{"id":16711772,"url":"https://github.com/lindsaykwardell/http-wrapper","last_synced_at":"2025-04-10T05:44:15.835Z","repository":{"id":98976113,"uuid":"263977011","full_name":"lindsaykwardell/http-wrapper","owner":"lindsaykwardell","description":"Simple Server/Router wrapper around Deno's HTTP module","archived":false,"fork":false,"pushed_at":"2020-05-30T03:01:39.000Z","size":91,"stargazers_count":12,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-08T02:08:05.242Z","etag":null,"topics":["deno","http-wrapper","router","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lindsaykwardell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-14T17:09:59.000Z","updated_at":"2023-07-22T01:54:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"f0e16121-27dd-448a-b6ba-a0a75b26b302","html_url":"https://github.com/lindsaykwardell/http-wrapper","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lindsaykwardell%2Fhttp-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lindsaykwardell%2Fhttp-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lindsaykwardell%2Fhttp-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lindsaykwardell%2Fhttp-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lindsaykwardell","download_url":"https://codeload.github.com/lindsaykwardell/http-wrapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239167064,"owners_count":19593147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","http-wrapper","router","typescript"],"created_at":"2024-10-12T20:26:25.536Z","updated_at":"2025-02-16T17:34:55.690Z","avatar_url":"https://github.com/lindsaykwardell.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deno HTTP Wrapper\n\n### _Simple Server/Router wrapper around Deno's HTTP module_\n\n[Example app using Vite and Deno](https://arcane-cove-31742.herokuapp.com/)\n\n[Example GitHub repo](https://github.com/lindsaykwardell/http-wrapper-example)\n\n## Intent\n\nI really like Deno as a concept, and I especially like the default HTTP library. I feel like it doesn't need all the abstraction put on top of it to build something pretty good.\n\nThe intent of this library is to build a lightweight wrapper around it that provides a more intuitive API around the `listenAndServe()` function.\n\nSome of the API is inspired by Express.js.\n\n## Install\n\nAs with all Deno modules, `http_wrapper` is imported via URL, and not with a package manager:\n\n```javascript\nimport {\n  Server,\n  Router,\n  Socket,\n} from \"https://deno.land/x/http_wrapper@v0.5.0/mod.ts\";\n```\n\n## Example\n\n```javascript\nimport {\n  Server,\n  Router,\n  Socket,\n} from \"https://deno.land/x/http_wrapper@v0.5.0/mod.ts\";\n\n// Create a new route\nconst router = new Router();\n\n// Add an endpoint to the route\n// Deno's default ServerRequest object is used\n\n// This endpoint will be accessible at /\nrouter.get(\"/\", async (req) =\u003e {\n  // Respond using default methods\n  req.respond({\n    status: 200,\n    headers: new Headers({\n      \"content-type\": \"text/html\",\n    }),\n    body: await Deno.open(\"./index.html\"),\n  });\n});\n\n// Create a second endpoint\nconst bobRouter = new Router(\"/bob\");\n\n// This endpoint will be accessible at /bob\nbobRouter.get(\"/\", (req) =\u003e {\n  req.respond({\n    status: 200,\n    headers: new Headers({\n      \"content-type\": \"application/json\",\n    }),\n    body: JSON.stringify({\n      test: \"This is a test\",\n    }),\n  });\n});\n\n// Create a web socket route at /ws\nconst socket = new Socket(\"/ws\");\n\n// Add a message event to listen for\nsocket.on(\"message\", (msg: Broadcast, connId: string): void =\u003e {\n  console.log(\"Received\");\n  socket.emit(\"message\", `[${connId}]: ${msg.body}`);\n});\n\n// Create the server\nconst app = new Server();\n\n// Add routes to server\napp.use(router.routes);\napp.use(bobRouter.routes);\napp.use(socket.routes);\n\n// Add static assets folder\napp.static(\"static\", \"/static\");\n\n// Start the server\napp\n  .start({ port: 3000 })\n  .then((config) =\u003e console.log(`Server running on localhost:${config.port}`));\n```\n\n## Use\n\nThere are two classes: `Server` and `Router`.\n\n### Router\n\n`Router` currently supports seven HTTP methods:\n\n- GET\n- POST\n- PUT\n- DELETE\n- PATCH\n- OPTIONS\n- HEAD\n\nNew routes are created as follows:\n\n```javascript\nconst router = new Router();\n```\n\n`new Router()` accepts a string for its constructor of new route (see example above).\n\nA new endpoint for the given route can be added by using its specific method:\n\n```javascript\nrouter.get(\"/\", (req) =\u003e {\n  // Perform actions on request\n});\n```\n\nThe `req` object is the standard `ServerRequest` object native to Deno. It is not modified in any way, and you can interact with it directly. The purpose of this library is to make it easy to work with, not to change the interface.\n\nThere are a couple of additional objects: `query` and `param`, generated by query and path parameters.\n\n```javascript\n// Example of query parameters\n// URL called: http://localhost:8000/?id=17\nrouter.get(\"/\", (req, { query }) =\u003e {\n  req.respond({ body: query.id });\n});\n\n// Example of path parameter\n// URL called: http://localhost:8000/user/17\nrouter.get(\"/user/{userId}\", (req, { param }) =\u003e {\n  req.respond({ body: param.userId });\n});\n\n```\n\n### Socket\n\nThe `Socket` class is a wrapper around `Router`, and is initialized the same way.\n\n```javascript\n// Create a new socket endpoint\nconst socket = new Socket(\"/ws\");\n```\n\nInternally, web socket connections to this endpoint are handled with Deno's standard library:\n\n- WebSocket\n- acceptable\n- acceptWebSocket\n- isWebSocketCloseEvent\n\nThis class wraps the above functionality, and acts as a router around certain events. Messages are stringified JSON, using the below structure:\n\n```javascript\ntype Broadcast = {\n  from?: string,\n  to?: string,\n  event?: string,\n  body: any,\n};\n```\n\nThere is currently no client developed to handle this object, just the server implementation, but it should be simple enough to write one.\n\nSocket events are implemented as follows:\n\n```javascript\nconst socket = new Socket(\"/ws\");\n\nsocket.on(\"message\", (msg: Broadcast, connId: string): void =\u003e {\n  console.log(\"Received\");\n  socket.emit(\"message\", `[${connId}]: ${msg.body}`);\n});\n```\n\nAn additional `to` or `from` value can be set as a third parameter:\n\n```javascript\nconst socket = new Socket(\"/ws\");\n\nsocket.on(\"message\", (msg: Broadcast, connId: string): void =\u003e {\n  console.log(\"Received\");\n  socket.emit(\"message\", `[${connId}]: ${msg.body}`, {\n    to: anotherUserId,\n    from: connId,\n  });\n});\n```\n\n### Server\n\nTo add a static file folder (useful for serving HTML/CSS/JS files), use the following:\n\n```javascript\nconst app = new Server();\n\n// First attribute is local folder where files are located, second is the route to load the files from\napp.static(\"static\", \"/static\");\n```\n\nWhen you are ready to apply your routes and start your server, run the following:\n\n```javascript\nconst app = new Server();\n\napp.use(router.routes); // router.routes is a getter, so you do not need to invoke it as a function.\napp.use(socket.routes); // Sockets are added to the server in the same way as routers.\n\n// Using promises to know when the server is up\napp\n  .start({ port: 3000 })\n  .then((config) =\u003e console.log(`Server running on localhost:${config.port}`));\n\n// Using await to know when the server is up\nawait app.start({ port: 3000 });\n\nconsole.log(\"Server running on localhost:3000\");\n```\n\nThe benefit of using promises is having the config object returned that you passed in, but it isn't important if you don't want to see it.\n\n## License\n\nThis project is MIT Licensed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flindsaykwardell%2Fhttp-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flindsaykwardell%2Fhttp-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flindsaykwardell%2Fhttp-wrapper/lists"}