HTTP Application
An HTTP application is what you build to handle requests and send responses to those requests. In Drash, you build HTTP applications using the HTTP module’s Application class. Specifically, you use the Application.builder() method. You give it resources and middleware to handle requests. You respond to those requests through your resources and middleware.
What Application Assembles Under Its Hood
HTTP Request Chain
Under the hood, Application assembles an HTTP request chain — a chain of handlers (see Concepts > Chains to learn more). You do not have to think about the chain to use it, but the pages here explain what it is doing so you understand the underpinnings of the Drash code you are using.
Handlers
Its handlers are assembled in this strict order:
| # | Handler | What it does |
|---|---|---|
| 1 | RequestValidator | Rejects inputs lacking a readable url or method field. |
| 2 | ResourcesIndex | Matches input.url against each resource’s paths using URLPattern or a polyfilled URLPattern. |
| 3 | ResourceNotFoundHandler | Throws HTTPError(404) when the ResourcesIndex handler cannot find a matching resource. |
| 4 | RequestParamsParser | Defines a non-enumerable params property on the request. Access it via request.params. |
| 5 | ResourceCaller | Invokes resource[METHOD](request) (e.g., UsersResource.GET(request)). |
The order is not configurable. What you control is the set of resources or resource groups you provide. For example:
const app = Application
.builder() // Assembles all handlers above
.resources(/* ... */) // Your resources come after so they can be called by `ResourceCaller`
.build() // Builds the chain in the above orderThe Data It Processes
The Application’s chain processes the data you give it, so you are in charge of defining what goes into it and what comes out. Its handlers pass along the input you give them, not a fixed request type — which is why one chain can take a Web Request in Deno and another can take a context object in Node, and both work.
Handler Requirements
The handlers expect the following:
-
The data it receives must be a single object.
-
The object must have a
url: stringproperty, and it must be a fully qualified URL:// Good const url: string = "http://localhost:1447/accounts/1337"; // Bad const url: string = "/accounts/1337"; -
The object must have a
method: stringproperty that is a valid HTTP request method :// Uppercase is OK const method: string = "GET"; // Lowercase is also OK const method: string = "get";
Given the above, the single data object could look like:
const input = {
url: "http://localhost:1447/accounts/1337",
method: "get",
//
// ... other fields
//
}The RequestValidator handler validates the above shape and throws HTTPError(422) with one of the following error messages if that shape is not met:
- Request could not be read
- Request HTTP method could not be read
- Request URL could not be read
Examples of Correct Data
The minimum:
const minimal = {
url: "http://localhost:1447/accounts/1337",
method: "get",
};In Node, you might find yourself using something like:
const context = {
url: "http://localhost:1447/accounts/1337",
method: "get",
request, // IncomingMessage
response, // ServerResponse
// ... add as many fields as you wish
};Errors Propagate to You
app.handle() returns a Promise. Errors thrown anywhere in the chain — including a resource method — reject that promise. Drash writes nothing to the socket, so your .catch() is the only thing standing between an error and the client.
app
.handle<Response>(request)
.catch((error) => {
// You decide what the client sees.
});This is deliberate: translating an error into a response is runtime-specific, and Drash does not own your response object. See HTTPError.
Path Matching
The ResourcesIndex handler appends {/}? to every path before compiling it, so /users matches /users/ too. Match results are cached by fully-qualified URL.
Because matching is URLPattern-based, path parameters use URLPattern syntax:
class Users extends Resource {
paths = ["/users/:id?"];
}You can access request params via request.params.
See Resources > Creating a Resource > Dynamic Paths for the full syntax.