Last active
November 19, 2018 09:29
-
-
Save andywer/4e6ce06c782874f05aa983a8d7bc96f8 to your computer and use it in GitHub Desktop.
Better node server API - An attempt based on Koa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { createApp, respond, route } from "koax" | |
| import pkg from "../package.json" | |
| const app = createApp() | |
| app.get("/", async () => { | |
| const body = { | |
| name: pkg.name, | |
| version: pkg.version | |
| } | |
| return respond(body, { | |
| status: 200, | |
| headers: {} | |
| }) | |
| }) | |
| //////////////////////// | |
| // Low-level equivalent | |
| app.use(route("GET", "/", async () => { | |
| return respond("{}", { | |
| status: 200, | |
| headers: { | |
| "Content-Length": 2, | |
| "Content-Type": "application/json" | |
| }, | |
| body: "{}" | |
| }) | |
| })) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Concept of server framework: | |
| * - Instead of passing request and mutable response, | |
| * pass request into handler which returns the response | |
| * - Can throw a response as an error escape-hatch | |
| * - Here the alternative server framework API is a separate package | |
| * - But could just be implemented as a Koa middleware | |
| * | |
| * Concept of route file: | |
| * - Little code per route in router file to easily get an overview over routes | |
| * - Take path params out of request and pass explicitly to keep path & params in one place | |
| * | |
| * Benefits: | |
| * - No need to pass Koa context to route handlers, containing all kinds of stuff and util methods | |
| * - Route handler only needs the request object, path params and the static `respond()` function import | |
| * - HTTP-aware error handling all goes in route handler files | |
| */ | |
| import { createApp, respond } from "koax" | |
| import config from "./config" | |
| import { queryPostByID } from "./database" | |
| const app = createApp() | |
| app.get("/posts/:id", async ({ params, request }) => | |
| // Keep everything path-related together in this file | |
| getPostByID(params.id, request.query, new URL("/posts/:id", config.baseURL)) | |
| ) | |
| /////////////////////////////////////////////// | |
| // Route handler, can be put in separate file: | |
| async function getPostByID(id: string, query: { ignoreLegacy?: boolean }, href: string) { | |
| const post = await queryPostByID(id, query) | |
| if (!post) { | |
| return respond(404, `Post not found: ${id}`) | |
| // You can also throw a response: | |
| // (remotely inspired by how React suspense does it in the frontend) | |
| throw respond(404, `Post not found: ${id}`) | |
| } | |
| const body = { | |
| _links: { | |
| self: { href } | |
| }, | |
| ...post | |
| } | |
| return respond(body) | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment