Step-By-Step Guide

Overview

In this guide, we will show you how to use the Request Chain module to create a tiny HTTP application that can receive requests and send responses.

Recommended Reading

Objectives

To gain familiarity with:

  • Drash's Request Chain (without using the await operator);
  • how it can be used in different runtimes;
  • how you can use resources to handle requests; and
  • how you can send responses based on those requests.

Instructions

End State

After completing the steps in this section, your project's directory should look like the directory tree below (based on the language you are using).

    • app.ts
  • Before You Get Started

    • The comments in the code explain the code in a line-by-line manner. Please read the comments to gain an understanding of the code.
    • Each code block adds code to the code block before it (if any). Code is highlighted to show the code that is being added.
    • The Node code blocks will show code that creates a context object. This context object contains the url and method fields required by chains. These fields are mentioned in Concepts > Chains > What Data Does It Process?.

    Steps

    1. Build the chain.

      path/to/your/project/app.ts
      import {
        Chain
      } from "npm:@drashland/drash@v3.0.0-beta.1/modules/chains/RequestChain/mod.native";
       
      const chain = Chain
        .builder()                    // Get the chain's builder so we can build the chain easily.
        .build();                     // Build the chain.
    2. Add a resource to the chain.

      path/to/your/project/app.ts
      import {
        Chain,
        Resource
      } from "npm:@drashland/drash@v3.0.0-beta.1/modules/chains/RequestChain/mod.native";
       
      class Home extends Resource {
        paths = ["/"];
       
        GET(request: Request) {
          const { method, url } = request;
          const date = new Date();
       
          return new Response(
            `Request received: ` +
            `${method} ${url}` +
            `\nWritten at: ${date}`
          );
        }
      }
       
      const chain = Chain
        .builder()                    // Get the chain's builder so we can build the chain easily.
        .resources(
          Home,                       // Add the `Home` resource to the chain.
        )
        .build();                     // Build the chain.
      Need to know how to add more resources? Click here

      In case you need to add more resources to your chain, you can do so in the same way shown above — you create a resource class and add it to your chain using chain.resources().

      Taking the above code as an example, if you wrote Users and Orders resource classes and wanted to add them, it would look like:

      const chain = Chain
        .builder()                    // Get the chain's builder so we can build the chain easily.
        .resources(
          Home,                       // Add the `Home` resource to the chain.
          Users,                      // Add the `Users` resource to the chain.
          Orders,                     // Add the `Orders` resource to the chain.
        )
        .build();                     // Build the chain.
    3. Plug the chain into the server.

      path/to/your/project/app.ts
      import {
        Chain,
        Resource
      } from "npm:@drashland/drash@v3.0.0-beta.1/modules/chains/RequestChain/mod.native";
       
      class Home extends Resource {
        paths = ["/"];
       
        GET(request: Request) {
          const { method, url } = request;
          const date = new Date();
       
          return new Response(        // This will be returned by the chain's `.handle()` method.
            `Request received: ` +
            `${method} ${url}` +
            `\nWritten at: ${date}`
          );
        }
      }
       
      const chain = Chain
        .builder()                    // Get the chain's builder so we can build the chain easily.
        .resources(
          Home,                       // Add the `Home` resource to the chain.
        )
        .build();                     // Build the chain.
       
      // Create and start the server
      Deno.serve({
        port: 1447,
        hostname: "localhost",
        handler: (                    // Define the request handler function that the server will use.
          req: Request                // This handler will receive a request. We will take this ...
                                      // ... request and use it below in the `chain.handle(req)` call.
       
        ): Promise<Response> => {     // We expect the chain to return a promised `Response` so we
                                      // define that return typing here.
       
          return chain                // As stated above, we can use the chain and ...
            .handle<Response>(req)    // ... call its `.handle()` method with the above request.
       
            .catch((e: Error) => {    // If the chain throws an error, we need to catch and handle it.
              console.log(e);         // In this case, we just log the error and ... 
              return new Response(    // ... return a generic error response.
                e.message,
                { status: 500 },
              );
            });
        },
      });

    Verification

    Run Your Code

    You will need to run your code before you can verify it works. Please refer to your chosen runtime's documentation pages for instructions on running the above app.ts file (or app.js file if you are using JavaScript).

    Need an example of what run your code looks like? Click here

    As an example, if you are using Deno v1.37.x, running the above app.ts file would look like:

    Terminal
    deno run --alow-net app.ts

    Tip: You might notice runtime documentation pages show their latest stable version's pages. Before reading documentation, we suggest you confirm the pages you are reading are for the version you are using. For example, if you are using Bun v.0x, then make sure you are reading Bun v0.x documentation, not v1.x or later.

    Verify Your Code

    Once your app is running, you can go to http://localhost:1447 in your browser.

    You should see something similar to the following:

    Request received: GET http://localhost:1447/
    Written at: Sun Aug 20 2023 19:47:48 GMT-0400 (Eastern Daylight Time)

    If the above check passed, then your app is working as expected.

    Troubleshooting

    If you do not see the issue you are facing below, know that you can always get help in our Discord server (opens in a new tab) (specifically the #help channel).

    Seeing HTTPError: Not Found messages? Click here

    If you see HTTPError: Not Found in the terminal where you are running your app, it is most likely from a favicon.ico request from your browser.

    You can ignore this error or (if you want to exercise your resource creation skills) you can create a resource that handles GET requests to the /favicon.ico path. From there, you can use your chosen runtime's reading APIs (e.g., readFile()) to send a favicon.ico file in the body of the response. For example, the favico.ico response you build could look something like:

    return new Response(
        await readFile("favicon.ico"),
        {
            status: 200,
            statusText: "OK",
            headers: {
                "content-type": "image/x-icon",
            }
        }
    );

    Next Steps

    Feel free to follow our recommendation or navigate the documentation pages at your leisure.

    Our Recommendations