How to create a routing process in Deno's Oak

overview

Oak provides the ability to easily define routes. Routing is defined by specifying endpoints for handling HTTP requests.

Below, we’ll explore routing concepts, defining routes, creating route handlers, handling routing parameters, and options for routes in more detail.

Here, we will explain the routing method using the following versions.

Deno v1.18.0
Oak v9.0.0

Also, all the code I’ve created so far is listed below. https://github.com/wiblok/Deno-Oak

Routing concepts

Routing defines how an Oak application handles requests from clients when they reach a particular endpoint.

Routing is defined by a combination of HTTP methods (GET, POST, PUT, DELETE, etc.) and paths (URLs).

How to define routing

Here’s how to use routing:

import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const router = new Router();
router.<HTTP method>('<path>', (context) => {
  // handling routes
});

const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());

  • HTTP method: Specify the HTTP request method (eg get, post, put, delete, etc.).
  • Path: Specifies the URL path that requests from clients will match.

From the heading below, write the code.

How to use routing objects

app.ts

import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const router = new Router();

router.get("/hello", (context) => {
  context.response.body = "Hello, Oak!";
});

router.post("/users", async (context) => {
 

 const user = await context.request.body().value;
  // user creation, etc...
  context.response.body = { id: 1, name: user.name };
});

router. put("/users/:id", async (context) => {
  if (context.params && context.params.id && context.request.hasBody) {
    const userId = context.params.id;
    const user = await context.request.body().value;
    // user updates, etc...
    context.response.body = { id: userId, name: user.name };
  }
});

router.delete("/users/:id", (context) => {
  if (context.params && context.params.id) {
    const userId = context.params.id;
    // user deletion etc...
    context.response.body = { message: `User ${userId} has been deleted.` };
  }
});

const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 3000 });
console.log("Server started on port 3000");

This code uses Oak to define multiple path handlers for different HTTP methods and registers them with the Oak application.

Each handler receives a request, performs appropriate processing, and returns a response.

Commentary

  • Import and application of Oak modules, create a router
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const router = new Router();

This part loads Deno’s Oak module and creates a new Oak application instance and a router instance.

  • GET request handler
router.get("/hello", (context) => {
  context.response.body = "Hello, Oak!";
});

This will cause the server to respond to a GET request to “/hello” with “Hello, Oak!”.

  • POST request handler
router.post("/users", async (context) => {
  const user = await context.request.body().value;
  // user creation, etc...
  context.response.body = { id: 1, name: user.name };
});

With this, a POST request to “/users” will attempt to create a new user and, if successful, return the user information in JSON format.

  • PUT request handler
router. put("/users/:id", async (context) => {
  if (context.params && context.params.id && context.request.hasBody) {
    const userId = context.params.id;
    const user = await context.request.body().value;
    // user updates, etc...
    context.response.body = { id: userId, name: user.name };
  }
});

With this, a PUT request to “/users/:id” will attempt to update the user with the specified id, and upon success will return the updated user information in JSON format.

  • DELETE request handler
router.delete("/users/:id", (context) => {
  if (context.params && context.params.id) {
    const userId = context.params.id;
    // user deletion etc...
    context.response.body = { message: `User ${userId} has been deleted.` };
  }
});

With this, a DELETE request to “/users/:id” will attempt to delete the user with the specified id and, if successful, will return a message in JSON format stating that the user has been deleted.

  • apply router and start server
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 3000 });

This part applies a router to the application and configures the server to listen on port 3000. When the server boots, the console will display “Server started on port 3000”.

test

# test GET request
curl -X GET http://localhost:3000/hello
# test the POST request
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:3000/users
# test the PUT request
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:3000/users/1
# test DELETE request
curl -X DELETE http://localhost:3000/users/1

How to use root chain

chain.ts

import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const router = new Router();

router
  .get("/hello", (context) => {
    context.response.body = "Hello, Oak!";
  })
  .post("/users", async (context) => {
    const user = await context.request.body().value;
    // user creation, etc...
    context.response.body = { id: 1, name: user.name };
  })
  .put("/users/:id", async (context) => {
    if (context.params && context.params.id && context.request.hasBody) {
      const userId = context.params.id;
      const user = await context.request.body().value;
      // user updates, etc...
      context.response.body = { id: userId, name: user.name };
    }
  })
  .delete("/users/:id", (context) => {
    if (context.params && context.params.id) {
      const userId = context.params.id;
      // user deletion etc...
      context.response.body = { message: `User ${userId} has been deleted.` };
    }
  });

const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 3000 });

Commentary

  • Import and application of Oak modules, create a router
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const router = new Router();

This part loads Deno’s Oak module and creates a new Oak application instance and a router instance.

  • route setting
router
  .get("/hello", (context) => {
    context.response.body = "Hello, Oak!";
  })
  .post("/users", async (context) => {
    const user = await context.request.body().value;
    // user creation, etc...
    context.response.body = { id: 1, name: user.name };
  })
  .put("/users/:id", async (context) => {
    if (context.params && context.params.id && context.request.hasBody) {
      const userId = context.params.id;
      const user = await context.request.body().value;
      // user updates, etc...
      context.response.body = { id: userId, name: user.name };
    }
  })
  .delete("/users/:id", (context) => {
    if (context.params && context.params.id) {
      const userId = context.params.id;
      // user deletion etc...
      context.response.body = { message: `User ${userId} has been deleted.` };
    }
  });

Each HTTP method route is chained together. Each route reacts to a specific URL path and HTTP method. Handles GET requests to “/hello”, POST requests to “/users”, PUT and DELETE requests to “/users/:id”.

  • apply router and start server
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 3000 });

This part applies a router to the application and configures the server to listen on port 3000. After the server starts, you should see the message “Server started on port 3000” on the console.

test

# test GET request
curl -X GET http://localhost:3000/hello
# test the POST request
curl -X POST -H "Content-Type: application/json" -d '{"name":"John Doe"}' http://localhost:3000/users
# test the PUT request
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Jane Smith"}' http://localhost:3000/users/1
# test DELETE request
curl -X DELETE http://localhost:3000/users/1

The code above defines endpoints for each HTTP method (GET, POST, PUT, DELETE). Each endpoint performs different processing and returns results to the client. The specific user creation, update, and deletion processes are omitted here, but these are the parts that typically involve interaction with the database.

summary

In this article, we’ve shown how to do routing using Deno’s Oak framework. Below are the main points:

  • Using Router Objects: Oak creates a Router object and defines each route and its handler functions within it. This gives you the flexibility to use responses for different HTTP methods and paths.
  • Define handler function: Define a handler function for each route. A handler function receives a request, performs appropriate processing, and returns a response. This processing typically involves operations such as retrieving and updating data.
  • Using route parameters: Oak allows you to extract specific values ​​from the URL using route parameters. This allows the same path to behave differently depending on the parameter.
  • Start Oak Server: Configure the Oak Server to listen on the specified port. It then applies the defined route and starts the server.

Oak makes it easy to create HTTP servers with Deno and manage routing efficiently. By properly designing the handler function for each route, you can have fine-grained control over your application’s behavior.