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
- Complete the instructions outlined on the Prerequisites page
- Read our concepts on chains and resources
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. Thiscontext
object contains theurl
andmethod
fields required by chains. These fields are mentioned in Concepts > Chains > What Data Does It Process?.
Steps
-
Build the chain.
path/to/your/project/app.tsimport { 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.
-
Add a resource to the chain.
path/to/your/project/app.tsimport { 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
andOrders
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.
-
Plug the chain into the server.
path/to/your/project/app.tsimport { 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:
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
- Handle request path params
- Handle request query params
- Learn how to handle errors in a more robust manner