Learn JavaScript The Right Way Javascript Icon

JavaScript is complex, unless you have all the answers...

Making Http GET Requests with Deno

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 and TypeScript 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 no package.json. Instead, we just import 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.

Angular Directives In-Depth eBook Cover

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.

  • Green Tick Icon Observables and Async Pipe
  • Green Tick Icon Identity Checking and Performance
  • Green Tick Icon Web Components <ng-template> syntax
  • Green Tick Icon <ng-container> and Observable Composition
  • Green Tick Icon Advanced Rendering Patterns
  • Green Tick Icon Setters and Getters for Styles and Class Bindings

Stay tuned as we grow this server to handle POST, PUT and DELETE requests as well!

Related blogs 🚀

Free eBooks:

Angular Directives In-Depth eBook Cover

JavaScript Array Methods eBook Cover

NestJS Build a RESTful CRUD API eBook Cover