Hello, fellow developers!
I have created an open-sourced library for those who want to route requests with ease using Cloudflare Workers. Originally the plan was to use this only for myself, but as I didn’t find other routers that I liked, I wanted to bring it to the public
You can find the GitHub repository here:
Features
What’s so great about Cloudflare-router? Here are some of the reasons:
- You can use Cloudflare-router very similarly to express apps
- It’s written in TypeScript
- You can have middlewares
- (WIP) The repository is tied with continuous integration which runs the tests and ensures things are working properly
- Easily testable to ensure expected functionality
- It’s very easy to use and flexible to your needs
Installing
Pretty easy, run the following command:
npm install cloudflare-router --save
Usage
Also very easy, with very little boilerplate code required to make it work. Here’s a short example:
TypeScript version
import { Router } from "cloudflare-router";
const router = new Router();
router.get("/", (_request, response) => {
return response.text(`Hello, world, from TypeScript!`);
});
addEventListener("fetch", event => {
event.respondWith(
router.serve(event.request)
.then(returned => returned.response)
);
});
JavaScript version
const { Router } = require("cloudflare-router");
const router = new Router();
router.get("/", (request, response) => {
response.text(`Hello, world, from JavaScript!`);
});
addEventListener("fetch", event => {
event.respondWith(
router.serve(event.request)
.then(returned => returned.response)
);
});
Examples
Some examples that are working right off the bat (only TypeScript here):
Middlewares
const router = new Router();
// Note that middlewares are working on ALL methods
router.use("/", async (request, response) => {
// The request instance has a separate "data" Map
// so that it's easier to pass on arguments to the final handler
// For example if you were to retrieve something from the database from the request
const exampleRequest = await fetch("url");
request.data.isAuthenticated = true;
});
router.get("/", (request, response) => {
if (!data.isAuthenticated) {
return response.statusCode(403)
.json({
error: "Not authenticated"
});
}
response.text("You are authenticated :)");
});
Testing your application
const router = new Router({
// Used for turning the data received into a Response instance
// Instead, as we're testing the code, we're returning the plain
// object.
customResponseTransformer: a => a
});
const request = (url, method, options = {}) => router.serve({
url,
method,
headers: [],
...options
});
// Middleware
router.use("/*", (req, res) => {
req.data.set("hello", "world");
});
router.get("/", (req, res) => {
res.text("hello!");
});
// Assuming this is a test with Jest
describe("testing application", () => {
it("should return a string in the body", async () => {
const response = await request("https://domain.com/", "GET");
// Testing the middleware
expect(response.routerRequest.data.get("hello"))
.toBe("world");
// Testing the response body
expect(response)
.toMatchObject({
response: {
body: "hello!"
}
});
});
});
Splitting into multiple files
// File: apiRouter.ts
const router = new Router();
router.get("/", (_request, response) => {
response.json({
status: "OK",
message: "API is operational"
});
});
router.get("/greet/:name", (request, response) => {
response.json({
success: true,
message: `Hello, ${request.params!.name}`
});
});
export default router;
// File: index.ts
import apiRouter from "./apiRouter";
const router = new Router();
// Routing all /api requests to the apiRouter
router.use("/api", router);
router.get("/", (_request, response) => {
response.text("Welcome the our service! Go to /api to use the API!");
});
addEventListener("fetch", event => {
event.respondWith(
router.serve(event.request)
.then(response => response.response)
);
});
Issues, Bugs or Features?
Please file an issue, or even better, file a pull request and help contribute to the project!
I’m still yet to create tests that cover more of the library, but they’re coming
That’s it
I hope you find the library useful, if something’s wrong, keep in mind it was created by an 18-year old in high school