A thin, testable routing library designed to sit on top of Deno's standard HTTP module
Repository
Current version released
4 years ago
Dependencies
jspm.dev
sinon@7.5.0
std
Versions
- v2.0.105Latest
- v2.0.104
- v2.0.103
- v2.0.102
- v2.0.101
- v2.0.100
- v2.0.99
- v2.0.98
- v2.0.97
- v2.0.96
- v2.0.95
- v2.0.94
- v2.0.93
- v2.0.92
- v2.0.91
- v2.0.90
- v2.0.89
- v2.0.88
- v2.0.87
- v2.0.86
- v2.0.85
- v2.0.83
- v2.0.81
- v2.0.80
- v2.0.79
- v2.0.78
- v2.0.77
- v2.0.76
- v2.0.75
- v2.0.74
- v2.0.73
- v2.0.72
- v2.0.71
- v2.0.71
- v2.0.71
- v2.0.71
- v2.0.71
- v2.0.70
- v2.0.69
- v2.0.68
- v2.0.67
- v2.0.66
- v2.0.65
- v2.0.64
- v2.0.63
- v2.0.62
- v2.0.61
- v2.0.60
- v2.0.59
- v2.0.58
- v2.0.57
- v2.0.56
- v2.0.55
- v2.0.54
- v2.0.53
- v2.0.52
- v2.0.51
- v2.0.50
- v2.0.49
- v2.0.48
- v2.0.47
- v2.0.46
- v2.0.45
- v2.0.44
- v2.0.43
- v2.0.42
- v2.0.41
- v2.0.40
- v2.0.39
- v2.0.38
- v2.0.37
- v2.0.36
- v2.0.35
- v2.0.34
- v2.0.33
- v2.0.32
- v2.0.31
- v2.0.30
- v2.0.29
- v2.0.28
- v2.0.27
- v2.0.26
- v2.0.25
- v2.0.24
- v2.0.23
- v2.0.22
- v2.0.21
- v2.0.20
- v2.0.19
- v2.0.18
- v2.0.17
- v2.0.16
- v2.0.15
- v2.0.14
- v2.0.13
- v2.0.12
- v2.0.11
- v2.0.10
- v2.0.9
- v2.0.8
- v2.0.7
- v2.0.6
- vv2.0.5
- vv2.0.4
- vv2.0.3
- vv
- v2.0.0
- v1.3.16
- v1.3.15
- v1.3.14
- v1.3.13
- v1.3.12
- v1.3.11
- v1.3.10
- v1.3.9
- v1.3.8
- v1.3.7
- v1.3.6
- v1.3.5
- v1.3.4
- v1.3.3
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.4
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.1
- v1.1.0
- v1.0.1
- v1.0.0
- v1.0.0-alpha.3
- v1.0.0-alpha.2
- v1.0.0-alpha.1
- v0.7.0
- v0.6.4
- v0.6.3
- v0.6.2
- v0.6.1
- v0.6.0
- v0.5.1
- v0.5.0
- v0.4.0
- v0.3.0
- v0.2.0
- v0.1.0
- v0.0.2
- v0.0.1
Reno
Reno is a thin routing library designed to sit on top of Deno’s standard HTTP module.
Overview
import { listenAndServe } from "https://deno.land/std@v0.51.0/http/server.ts";
import {
createRouter,
AugmentedRequest,
createRouteMap,
textResponse,
jsonResponse,
streamResponse,
} from "https://deno.land/x/reno@v1.0.0-alpha.1/reno/mod.ts";
export const routes = createRouteMap([
["/home", () => textResponse("Hello world!")],
// Supports RegExp routes for further granularity
[/^\/api\/swanson\/?([0-9]?)$/, async (req: AugmentedRequest) => {
const [quotesCount = "1"] = req.routeParams;
const res = await fetch(
`https://ron-swanson-quotes.herokuapp.com/v2/quotes/${quotesCount}`,
);
return jsonResponse(await res.json());
}],
// Supports Reader for streaming responses in chunks
["/streamed-response", () => streamResponse(
new ReactReader(<App />),
)],
]);
const notFound = (e: NotFoundError) => createErrorResponse(404, e);
const serverError = (e: Error) => createErrorResponse(500, e);
const mapToErrorResponse = (e: Error) =>
e instanceof NotFoundError ? notFound(e) : serverError(e);
const router = createRouter(routes);
(async () => {
console.log("Listening for requests...");
await listenAndServe(
":8001",
async (req: ServerRequest) => {
try {
const res = await router(req);
return req.respond(res);
} catch (e) {
return req.respond(mapToErrorResponse(e));
}
},
);
})();
Key Features
Responses are just Data Structures
This, along with request handlers being pure functions, makes unit testing Reno services a breeze:
import { jsonResponse, assertResponsesMatch } from "https://deno.land/x/reno@v1.0.0-alpha.1/reno/mod.ts";
import { createRonSwansonQuoteHandler } from "./routes.ts";
const createFetchStub = (response: string[]) =>
sinon.stub().resolves({
json: sinon.stub().resolves(response),
});
test({
name: "ronSwansonQuoteHandler should fetch a quote from an API and return it",
async fn() {
const quotes = ["Some Ron Swanson Quote"];
const fetchStub = createFetchStub(quotes);
const ronSwansonQuoteHandler = createRonSwansonQuoteHandler(fetchStub);
const req = {
routeParams: []
};
const response = await ronSwansonQuoteHandler(req);
assertResponsesMatch(response, jsonResponse(quotes, {
"X-Foo": "bar"
}));
}
});
pipe()
- An Alternative to Middleware
Reno emulates the middleware pattern, found in Express, by favouring function piping to create reusable, higher-order route handlers:
import { createRouteMap, jsonResponse, pipe } from "https://deno.land/x/reno@v1.0.0-alpha.1/reno/mod.ts";
const withCaching = pipe(
(req, res) => {
/* Mutate the response returned by
* the inner route handler... */
res.headers.append("Cache-Control", "max-age=86400");
},
/* ...or go FP and return a new
* response reference entirely. */
(req, res) => ({
...res,
cookies: new Map<string, string>([["requested_proto", req.proto]])
})
);
const home = withCaching(() =>
jsonResponse({
foo: "bar",
isLol: true
})
);
export const routes = createRouteMap([["/", home]]);
API Documentation
Consult docs/API.md for comprehensive documentation on Reno’s API.
Local Development
Once you’ve cloned the repository, you’ll need to ensure you’re running the version of Deno against which this project is developed; this is stored in .deno-version
. To install the correct version, run:
$ curl -fsSL https://deno.land/x/install/install.sh | sh -s $(cat .deno-version)
You should also run ./tools/install-types.sh
to install the TypeScript definitions for Deno and any other third-party dependencies.
Then you can run:
deno run --allow-net example/index.ts
- starts the example serverdeno test
- runs the unit tests
Functionality Checklist
- Path routing
- Async-compatible route handlers
- Error handling
- Route params
- Query params
- Response helpers
- JSON
- Custom headers
- Request bodies
- Cookies
- Streaming responses with
Reader
- Streaming request bodies