Skip to Content
Drash v3 is in beta. APIs may change.
DocsGetting StartedStep-By-Step Guide

Step-By-Step Guide

Building a tiny HTTP application

Overview

This guide helps you build a tiny HTTP application using the HTTP module’s Application class. If you want a finished app instead of a walkthrough, view the examples.

Objectives

To gain familiarity with:

  • the HTTP module’s Application class;
  • how Application can be used in different runtimes;
  • receiving and handling requests; and
  • responding to requests.

Instructions

End State

After completing the steps in this section, your project's directory should look similar to the directory tree below.

    • app.js

Before You Get Started

  • All of the code will be written in the same file for simplicity.
  • Each next step adds code to the step before it. The code that is highlighted is the code that is being added.
  • The code comments explain the code in a line-by-line manner. Please read them to gain a better understanding of the code.
  • The Node.js code blocks will show code that creates a context object. This context object contains the url and method fields the HTTP module’s Application requires. These fields are mentioned in Concepts > HTTP Application > Handler Requirements.
  • Deno and Cloudflare Workers provide a global URLPattern, so they use the native module. Node and Bun do not, so they use the polyfill module. The two modules are otherwise identical. See Concepts > Native vs. Polyfill.

Steps and Verification

Initialize Your Project

Terminal
npm init --yes npm install @drashland/drash

The --yes flag accepts all defaults for the package.json file the init command creates for you. Learn more about the --yes flag here .

Define Your Resource

A resource is a class that answers requests for one or more paths. You define one using the Resource class.

app.js
import { Resource, } from "@drashland/drash/modules/http.polyfill.js"; class Home extends Resource { paths = ["/"]; GET(context) { context.response.end("Oh so easy"); } }

Good to know

Node’s node:http server hands you an IncomingMessage and a ServerResponse — not a Web Request and Response. Because of that, this resource writes to context.response directly instead of returning a response. The context object is built in Step 4 - Add Your App to Your Server.

Build the Application

An application routes requests to the resources you give it. You build one using the Application class.

app.js
import { Application, Resource } from "@drashland/drash/modules/http.polyfill.js"; class Home extends Resource { paths = ["/"]; GET(context) { context.response.end("Oh so easy"); } } const app = Application .builder() // Get the app builder so we can build an app easily. .resources(Home) // Add the `Home` resource to the app. .build(); // Build the app.

Good to know

Drash uses the builder pattern to create objects. You will see build() calls many times throughout these documentation pages. See Concepts > Builders for why.

Add Your App to Your Server

Drash is not a server. Your runtime provides the server and you plug Drash into it to handle the request-response lifecycle.

app.js
import { Application, Resource } from "@drashland/drash/modules/http.polyfill.js"; import { createServer } from "node:http"; class Home extends Resource { paths = ["/"]; GET(context) { context.response.end("Oh so easy"); } } const app = Application .builder() // Get the app builder so we can build an app easily. .resources(Home) // Add the `Home` resource to the app. .build(); // Build the app. const hostname = "localhost"; const port = 1447; const server = createServer((request, response) => { const context = { // Build the context object the app will process. url: `http://${hostname}:${port}${request.url}`, // `url` must be absolute. `request.url` is path-only here. method: request.method, // `method` tells the app which resource method to call. request, // Passed along so resources can read the raw request. response, // Passed along so resources can write the response. }; return app // Let the app .handle(context) // handle the context object .catch(() => { // Catch errors and response.statusCode = 500; // send a 500 response response.end("Oops."); }); }); server.listen(port, hostname);

Run Your App

Terminal
node app.js

The file above uses import statements, so Node needs to treat it as an ES module. Either add "type": "module" to your package.json or rename the file to app.mjs.

With the app running, go to http://localhost:1447  in your browser. You should see something like:

Oh so easy

Known Behaviors

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"), // Use your runtime's file reading API here { status: 200, statusText: "OK", headers: { "content-type": "image/x-icon", } } );
Last updated on