In this post you will learn how to make HTTP GET
requests with Deno. We’ll create a simple API with deno that can be accessed via HTTP GET events to retrieve some data!
Deno is a new
JavaScript
andTypeScript
runtime created by the creator of Node.Js. This post isn’t going to breakdown the background of deno, but I recommend checking out their v1 release blog for more details.
Let me introduce the http std lib, provided by the deno framework to build a simple HTTP server. We’re going to use this to setup our server to listen on port :8000
and accept GET requests - to return some data to the client!
We’re going to have one endpoint to retrieve a list of users: /api/user
Unlike node.js, which uses
npm
as a package manager, deno uses ES Modules (🙏 woo!) to import packages when they are needed. Yep, that means nopackage.json
. Instead, we justimport
the package we need via its url for Deno to resolve for us. Just beautiful 😭!
Okay let’s get started and build a typical “Hello world” example:
// ./src/server.ts
import { serve } from 'https://deno.land/[email protected]/http/server.ts';
const s = serve({ port: 8000 });
console.log('http://localhost:8000/'); // http://localhost:8000
// listen on all requests, response with 'Hello World'
for await (const req of s) {
req.respond({ body: 'Hello World\n' });
}
This for..of
loop simply listens for all requests happening, and later we’ll conditionally send a response
based on the request type (GET/POST/etc).
🕵️♀️ This step requires you have the deno cli and runtime installed. Checkout the install docs if you haven’t already!
Via the deno cli, we can then run the program:
# run our server
deno run --allow-net ./src/server.ts # plug the location of your server file here
An important aspect of deno: Security. When we want to access the network layer, we need to use the --allow-net
flag alongside our command. Without it, you’ll get a PermissionDenied
error:
error: Uncaught PermissionDenied: network access to "0.0.0.0:8000", run again with the --allow-net flag
Now we’re all setup and some gotchas are out the way, lets curl
it to see if we get a response:
curl http://localhost:8000 // Hello, world!
Awesome. Super easy and simple, right? Now let’s get this show on the road and handle some requests!
Here’s what I’ve come up with as a basic HTTP GET implementation with deno. Inside of our for..of
, we can check each req
object coming through and see if the method
property contains GET
. We can also throw in a url
property check if the user is also trying to access our API!
for await (const req: ServerRequest of s) {
if (req.method === 'GET' && req.url === '/api/user') {
handleGetUsersReq(req);
} else {
handleNotFound(req);
}
}
You could see how you could adapt this pattern using a higher level abstraction in a real-world environment.
Once we’ve passed our req
through, we can handle the responses accordingly:
const handleGetUsersReq = async (req: ServerRequest): Promise<void> => {
const users: User[] = await getUsers();
return req.respond({ status: Status.OK, body: JSON.stringify(users) });
};
const handleNotFound = async (req: ServerRequest): Promise<void> => {
return req.respond({
status: Status.NotFound,
body: JSON.stringify({ message: 'Request Not Found' }),
});
};
Add a few imports:
// ./src/server.ts
import {
serve,
ServerRequest,
} from 'https://deno.land/[email protected]/http/server.ts';
import { Status } from 'https://deno.land/[email protected]/http/http_status.ts';
import { getUsers } from './services/user.service.ts';
import { User } from './models/user.model.ts';
And boom, let’s start it up:
# run our server
deno run --allow-net ./src/server.ts # plug the location of your server file here
# server running on port 8000
Get a list of users:
curl http://localhost:8000/api/user # [{ id: 1, firstName: 'ultimate', lastName: 'courses', dob: '2020-01-01' }]
And, for sanity, lets check what we get when request a route that doesn’t exist:
curl http://localhost:8000/api/does/not/exist # Request Not Found
This is a super basic example that checks the method and url for a single request. Here’s the full code put together:
// ./src/server.ts
import {
serve,
ServerRequest,
} from 'https://deno.land/[email protected]/http/server.ts';
import { Status } from 'https://deno.land/[email protected]/http/http_status.ts';
import { getUsers } from './services/user.service.ts';
import { User } from './models/user.model.ts';
const handleGetUsersReq = async (req: ServerRequest): Promise<void> => {
const users: User[] = await getUsers();
return req.respond({ status: Status.OK, body: JSON.stringify(users) });
};
const handleNotFound = async (req: ServerRequest): Promise<void> => {
return req.respond({
status: Status.NotFound,
body: JSON.stringify({ message: 'Request Not Found' }),
});
};
for await (const req: ServerRequest of s) {
if (req.method === 'GET' && req.url === '/api/user') {
handleGetUsersReq(req);
} else {
handleNotFound(req);
}
}
The http
standard lib provided by deno
is pretty powerful and provides great building blocks to build out more complex APIs.

Free eBook
Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.
-
Observables and Async Pipe
-
Identity Checking and Performance
-
Web Components <ng-template> syntax
-
<ng-container> and Observable Composition
-
Advanced Rendering Patterns
-
Setters and Getters for Styles and Class Bindings
Stay tuned as we grow this server to handle POST
, PUT
and DELETE
requests as well!