- v0.24.1Latest
- v0.24.0
- v0.23.1
- v0.23.0
- v0.22.0
- v0.21.1
- v0.21.0
- v0.20.1
- v0.20.0
- v0.19.0
- v0.18.1
- v0.18.0
- v0.17.0
- v0.16.0
- v0.15.1
- v0.15.0
- intercept-v0.14.1
- v0.14.0
- v0.13.0
- v0.5.0
- v0.4.0
- v0.3.0
- v0.2.0
- v0.1.1
- v0.1.0
- v0.0.27
- v0.0.26
- v0.0.25
- v0.0.24
- v0.0.23
- v0.0.22
- v0.0.21
- v0.0.20
- v0.0.19
- v0.0.18
- v0.0.17
- v0.0.16
- v0.0.15
- v0.0.14
- v0.0.13
- v0.0.12
- v0.0.11
- v0.0.10
- v0.0.9
- v0.0.8
- v0.0.7
- v0.0.6
- v0.0.5
- v0.0.4
- v0.0.3
- v0.0.2
- v0.0.1
deno_http_fns
NOTE: This is still fairly experimental.
A collection of functions for HTTP.
- Based on Request => Response functions
- Works with
Deno.serve
- Handlers for routing based on various criteria
- URLPattern
- Method
- Media Type
- Request and Response helper functions
- Generate router module from filesystem based handlers
- Static or dynamic imports
- Build time or runtime discovery
- Request/Response interceptor function chains
- Logging
- CORS
Deno.serve
options helper fns for various hosting scenarios- Development on localhost (including https support)
- Deno Deploy
Read the blog.
Examples
See the examples.
You can run them after cloning this repo, for example:
deno run -A --import-map=examples/import_map.json examples/logging.ts
or (using a task defined in the deno.json file)
deno task example examples/logging.ts
(NOTE: The above will map the imports to use the local http_fns modules rather than fetching from deno.land)
or directly from deno.land:
deno run -A https://deno.land/x/http_fns/examples/logging.ts
or directly from GitHub:
deno run -A https://raw.githubusercontent.com/jollytoad/deno_http_fns/main/examples/logging.ts
Request Handlers
Most functions could be considered as handler factories, in that they create and return a Request handler function, generally of the form:
(req: Request, data: unknown) => Response
Response can also be in a Promise, and in many case may also be null
to
indicate that the Request cannot be handled and it should be delegated to
another handler.
Here is a very simple example of how the functions can be composed into a server:
await serve(
handle([
byPattern(
"/",
byMethod({
GET: () => ok("Hello"),
}),
),
byPattern(
"/foo",
byMethod({
GET: () => ok("Foo"),
}),
),
]),
);
Routing
handle
handle(handlers, fallback) => Handler
This is the top-level function you’ll use to form a router.
You pass it a list of handlers, each handler may return either a Response
or a
null
. If the handler returns null
, the next handler is called until a
Response
is returned, or it will end by calling the optional fallback
handler which must return a Response
.
The default fallback is to return a 404 Not Found
response.
(handle
is actually just a shortcut for cascade
& withFallback
, discussed
later)
byPattern
byPattern(pattern, handler) => Handler
Every router needs a way to delegate by actual path or URL. byPattern
provides
that using the standard
URLPattern.
It can take a pattern or array of patterns, and the handler to be called on a successful match.
The pattern can be a string (to match just the path), a URLPatternInit
which
can declare patterns for other parts of the URL, or a pre-constructed
URLPattern
itself.
The handler created will attempt to match the Request URL against each given
pattern in order until one matches, and then call the delegate handler (passed
in the 2nd arg of byPattern), with the Request and the URLPatternResult
:
(req: Request, match: URLPatternResult) => Response | null | Promise<Response | null>
If no pattern matches, the handler returns null
, allowing the request to
cascade to the next handler in the array of handlers passed to handle
(or
cascade
).
bySubPattern
bySubPattern(pattern, handler) => Handler
Match a child route pattern after already matching a parent pattern.
byMethod
byMethod({ METHOD: handler }, fallback) => Handler
Select a handler based on the request method.
byMediaType
byMediaType({ "media/type": handler }, fallbackExt, fallbackAccept) => Handler
Select the most appropriate handler based on the desired media-type of the request.
Delegation
cascade
cascade(...handlers) => Handler
Attempt each handler in turn until one returns a Response.
withFallback
withFallback(handler, fallback) => Handler
Provide a fallback Response should the handler ‘skip’ (ie. return no response).
lazy
lazy(module url or loader) => Handler
Dynamically load a handler when first required.
Handlers
staticRoute
staticRoute(pattern, fileRootUrl, options) => Handler
Serve static files.
Middleware
intercept
intercept(handler, ...interceptors) => Handler
Modify the Request and/or Response around the handler, and handle errors.
interceptResponse
interceptResponse(handler, ...responseInterceptors) => Handler
Modify the Response from a handler.
skip
skip(...status) => ResponseInterceptor
Use with interceptResponse
to convert Responses of the given status to a
‘skipped’ response.
byStatus
byStatus(status, interceptor) => ResponseInterceptor
Create a Response Interceptor that matches the status of the Response.
loggers
logging() => Interceptors
A set of standard logging interceptors.
cors
cors(options) => ResponseInterceptor
A response intercept that adds the appropriate CORS headers, and handles the OPTIONS request.
Filesystem based handlers
Route discovery
Walk the filesystem discovering potential routes and handlers modules.
Router module generation
Module | Example script | Example of generated routes | Example router
Generate a TypeScript module that exports a routing handler of discovered
modules, using byPattern
.
Dynamic runtime router
dynamicRoute(options) => Handler
A handler that performs route discovery dynamically at runtime.
Utilities
Request
TODO
Response
TODO