{"id":44573947,"url":"https://github.com/onlybrad/http-server-simple","last_synced_at":"2026-02-14T04:01:35.316Z","repository":{"id":144428774,"uuid":"505151035","full_name":"onlybrad/http-server-simple","owner":"onlybrad","description":"HTTP Server for Node JS with no dependencies, inpired by Express.","archived":false,"fork":false,"pushed_at":"2023-09-12T17:31:36.000Z","size":104,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-25T03:39:48.531Z","etag":null,"topics":["http","http-server","httpserver"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onlybrad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2022-06-19T15:41:22.000Z","updated_at":"2022-06-25T03:20:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"13e2f2ff-0716-4c42-a17c-f47f8ce484d0","html_url":"https://github.com/onlybrad/http-server-simple","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/onlybrad/http-server-simple","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onlybrad%2Fhttp-server-simple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onlybrad%2Fhttp-server-simple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onlybrad%2Fhttp-server-simple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onlybrad%2Fhttp-server-simple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onlybrad","download_url":"https://codeload.github.com/onlybrad/http-server-simple/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onlybrad%2Fhttp-server-simple/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29435361,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T03:34:37.767Z","status":"ssl_error","status_checked_at":"2026-02-14T03:34:09.092Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["http","http-server","httpserver"],"created_at":"2026-02-14T04:00:29.333Z","updated_at":"2026-02-14T04:01:35.308Z","avatar_url":"https://github.com/onlybrad.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"http-server-simple is an http server written in pure javascript for NodeJS. It has no dependencies. The syntaxe was inspired by the Express library.\n\nThe following methods are supported: GET, HEAD, OPTIONS, POST, PUT, PATCH, DELETE.\n\n## Usage\n\n```javascript\nconst {Server} = require(\"http-server-simple\");\nconst server = new Server();\n\n/* GET 127.0.0.1:5000/text */\nserver.get(\"/text\", (req,res) =\u003e {\n    return res.text(\"Sending a text/plain message\");\n})\n/* GET 127.0.0.1:5000/json */\n.get(\"/json\", (req,res) =\u003e {\n    return res.json({message: \"Sending an application/json message\"});\n})\n/* GET 127.0.0.1:5000/html */\n.get(\"/html\", (req,res) =\u003e {\n    return res.html(\"\u003ch1\u003eSending a text/html message\u003c/h1\u003e\");\n})\n/* POST 127.0.0.1:5000/ */\n.post(\"/\", (req,res) =\u003e {\n    return res.text(\"A post request to /\");\n})\n.listen(5000, \"127.0.0.1\");\n\n```\n\n## Router\n\nServer level routing done in the previous example will implicitly create a router with the \"/\" root, you can create your own router with a different root\n\n```javascript\n\nconst {Server, Router} = require(\"http-server-simple\");\nconst server = new Server();\nconst router = new Router();\nconst users = require(\"./data/users\");\n\n/* GET 127.0.0.1:5000/user */\nrouter.get(\"/\", (req,res) =\u003e {\n    return res.json(users);\n})\n/* GET 127.0.0.1:5000/user/:id */\n.get(\"/:id\", (req,res) =\u003e {\n    const id = req.params.id;\n    return res.json(user.id);\n})\n/* DELETE 127.0.0.1:5000/user/:id */\n.delete(\"/:id\", (req,res) =\u003e {\n    const id = req.params.id;\n    delete user.id;\n    return res.end();\n});\n\nserver.router(\"/user\",router).listen(5000,\"127.0.0.1\");\n\n```\n\n## Router prefix\n\nIn order to create routes within the router with the same prefix without having to repeat the prefix in each route, you can use Router.prefix()\n\n```javascript\nconst {Server, Router} = require(\"http-server-simple\");\nconst server = new Server();\nconst router = new Router();\nconst users = require(\"./data/users\");\nconst posts = require(\"./data/posts\");\n\nconst userRouter = Router.prefix(\"/user\", router =\u003e {\n    /* GET 127.0.0.1:5000/api/v1/user */\n    router.get(\"/\", (req,res) =\u003e res.json(users))\n\n    /* GET 127.0.0.1:5000/api/v1/user/:id */\n    .get(\"/:id\", (req,res) =\u003e res.json(users[req.params.id]));\n});\n\nconst postRouter = Router.prefix(\"/post\", router =\u003e {\n    /* GET 127.0.0.1:5000/api/v1/post */\n    router.get(\"/\", (req,res) =\u003e res.json(posts))\n\n    /* GET 127.0.0.1:5000/api/v1/post/:id */\n    .get(\"/:id\", (req,res) =\u003e res.json(posts[req.params.id]));\n});\n\n\nserver.router(\"/api/v1\",[userRouter, postRouter])\n    .listen(5000,\"127.0.0.1\");\n\n```\n\n## Middleware\n\nRoute handlers are considered middlewares too. The only difference between a middleware and a handler is the use of the next function. Handlers do not use the next function, middlewares do. Not calling next in the middle of the middleware chain will hang the server. To exit a middleware chain you have to return res.text(), res.html(), res.json() or res.end()\n\n```javascript \n\nconst {Server, Router} = require(\"http-server-simple\");\nconst server = new Server();\nconst router = new Router();\n\nserver.router(\"/router\",router,(req,res,next) =\u003e {\n    console.log(\"Router middlewares will execute before routes middlewares.\");\n    next();\n}).listen(5000,\"127.0.0.1\");\n\n/* 127.0.0.1:5000/router/get */\nrouter.get(\"/get\",\n(req,res,next) =\u003e {\n    console.log(\"Route middlewares execute after the router middlewares.\");\n\n    if(Math.random() \u003c 0.5) {\n        console.log(\"Call the next middleware.\");\n        return next();\n    } \n\n    console.log(\"Otherwise terminate the chain.\");\n    return res.end();\n    \n},\n(req,res) =\u003e {\n    console.log(\"This is the route handler, it's last in the middleware chain and doesn't use the next function.\");\n    return res.end();\n});\n\n/* GET 127.0.0.1:5000/ */\nserver.get(\"/\", (req,res,next) =\u003e {\n    console.log(\"Server level routing also supports middlewares.\");\n    next();\n},\n(req,res) =\u003e {\n    console.log(\"End of the chain = route handler.\");\n    return res.end();\n});\n\n```\n\n## Query Parameters\n\nUse the req.query function to get the query parameters from the url\n\n```javascript\n\nconst {Server} = require(\"http-server-simple\");\nconst server = new Server();\n\n/* GET 127.0.0.1:5000/?a=1\u0026b=2 */\nserver.get(\"/\", (req,res) =\u003e {\n    const queries = req.query(); // returns {a: \"1\", b: \"2\"}\n    const a = req.query(\"a\"); //returns \"1\"\n    const c = req.query(\"c\"); //returns null\n    return res.end();\n})\n.listen(5000,\"127.0.0.1\");\n\n```\n\n## Route parameters\n\nAccess the dictionary of route parameters with the req.params attribute\n\n```javascript\n\nconst {Server} = require(\"http-server-simple\");\nconst server = new Server();\n\n/* GET 127.0.0.1:5000/user/:id */\nserver.get(\"/user/:id\", (req,res) =\u003e {\n    const id = req.params.id;\n\n    return res.html(`\u003ch1\u003eThis is user ${id}\u003c/h1\u003e`);\n})\n.listen(5000,\"127.0.0.1\");\n\n```\n\n## Body parsing\n\nAccess the body of a POST,PUT or PATCH request with req.body. The body will be parsed depending on the Content-Type header. If the parsing failed, the Content-Type is invalid or no Content-Type was specified, req.body will be the raw data with the specified encoding.\n\n\u003cem\u003e**For all other methods, req.body returns undefined**\u003c/em\u003e\n\n\u003cspan style=\"text-decoration: underline\"\u003e***SERVER SIDE***\u003c/span\u003e\n\n```javascript\nconst {Server} = require(\"http-server-simple\");\nconst server = new Server();\nconst users = require(\"./data/users\");\n\n/* PUT 127.0.0.1:5000/user/:id */\nserver.put(\"/user/:id\", (req,res) =\u003e {\n    const id = req.params.id;\n\n    // {name: \"bob\", age: 10}\n    const newData = req.body;\n\n    users[id] = {...users[id], ...newData};\n\n    return res.json(users[id]);\n})\n.listen(5000,\"127.0.0.1\");\n```\n\n\u003cspan style=\"text-decoration: underline\"\u003e***CLIENT SIDE (using urlencoded)*** \u003c/span\u003e\n\n```javascript\nfetch(\"http://127.0.0.1:5000/user/1\", {\n    method: \"PUT\",\n    body: \"name=bob\u0026age=10\",\n    headers: {\n        \"Content-Type\": \"application/x-www-form-urlencoded\"\n    }\n});\n\n```\n\n## Unhandled exceptions\n\nA status code 500 and no content will be sent as a response if an uncaught exception happens in one of the middlewares or handlers\n\n\u003cspan style=\"text-decoration: underline\"\u003e***SERVER SIDE***\u003c/span\u003e\n\n```javascript\nconst {Server} = require(\"http-server-simple\");\nconst server = new Server();\n\n/* PUT 127.0.0.1:5000/exception */\nserver.get(\"/exception\", (req,res) =\u003e {\n    res.nonExistantFunction();\n})\n.listen(5000,\"127.0.0.1\");\n```\n\n\u003cspan style=\"text-decoration: underline\"\u003e***CLIENT SIDE*** \u003c/span\u003e\n\n```javascript\nconst res = await fetch(\"http://127.0.0.1:5000/exception\");\n\n//true\nconsole.log(res.status === 500);\n\n```\n\n## Download\nDownloading a file from the disk can be done in two ways. the \"low level\" way is with the **res.download** method and the \"high level\" way is with the **Download** class helper.\n\n**res.download** takes as argument a **File** object and, optionally, an object containing the start and end bytes that you would like to download.\n\n\u003cspan style=\"text-decoration: underline\"\u003e***SERVER SIDE***\u003c/span\u003e\n\n```javascript\nconst {Server, File} = require(\"http-server-simple\");\nconst server = new Server();\n\n/* PUT 127.0.0.1:5000/download */\nserver.get(\"/download\", (req,res) =\u003e {\n    //content of file: 0123456789\n    const file = new File(\"path/to/a/file/that/exists\");\n\n    opts = {};\n    if(req.query(\"start\")) {\n        opts.start = parseInt(req.query(\"start\"));\n    }\n    if(req.query(\"end\")) {\n        opts.end = parseInt(req.query(\"end\"));\n    }\n\n    return res.download(file, opts);\n})\n.listen(5000,\"127.0.0.1\");\n\n```\n\n\u003cspan style=\"text-decoration: underline\"\u003e***CLIENT SIDE*** \u003c/span\u003e\n\n```javascript\nlet res = await fetch(\"http://127.0.0.1:5000/download\");\nlet text = await res.text();\n\n//0123456789, or it will download the file on a browser that respect the Content-Disposition header\nconsole.log(text);\nconsole.log(res.status); //200\n\nres = await fetch(\"http://127.0.0.1:5000/download?start=2\");\ntext = await res.text();\n\nconsole.log(text); //23456789\nconsole.log(res.status); //206\n\nres = await fetch(\"http://127.0.0.1:5000/download?end=5\");\ntext = await res.text();\n\nconsole.log(text); //012345\nconsole.log(res.status); //206\n\nres = await fetch(\"http://127.0.0.1:5000/download?start=2\u0026end=5\");\ntext = await res.text();\n\nconsole.log(text); //23456\nconsole.log(res.status); //206\n\nres = await fetch(\"http://127.0.0.1:5000/download?start=100\");\n\n//416, invalid range\nconsole.log(res.status);\n\n```\n\nthe **Download** class however only takes a **File** object or a string representing its path as argument. It looks at the Range header to determine what bytes to send.\n \n \u003cspan style=\"text-decoration: underline\"\u003e***SERVER SIDE***\u003c/span\u003e\n\n```javascript\nconst {Server, Download} = require(\"http-server-simple\");\nconst server = new Server();\n\n/* PUT 127.0.0.1:5000/download */\nserver.get(\"/download\", (req,res) =\u003e {\n    //content of file: 0123456789\n    const file = \"path/to/a/file/that/exists\";\n    const downloader = new Download(req,res);\n\n    return downloader.download(file);\n})\n.get(\"/resumableDownload\", (req,res) =\u003e {\n    const file = \"path/to/a/file/that/exists\";\n    const downloader = new Download(req,res);\n\n    return downloader.resumableDownload(file);\n})\n.listen(5000,\"127.0.0.1\");\n\n```\n\u003cspan style=\"text-decoration: underline\"\u003e***CLIENT SIDE*** \u003c/span\u003e\n\n```javascript\nlet res = await fetch(\"http://127.0.0.1:5000/download\");\nlet text = await res.text();\n\nconsole.log(text); //0123456789\nconsole.log(res.status); //200\n\nres = await fetch(\"http://127.0.0.1:5000/download\", {\n    headers: {\n        \"Range\": \"bytes=2-\"\n    }\n});\ntext = await res.text();\n\n //0123456789, the Range header was ignored because downloader.download() does not support resuming therefore it downloads the whole file.\nconsole.log(text);\nconsole.log(res.status); //200\n\nres = await fetch(\"http://127.0.0.1:5000/resumableDownload\", {\n    headers: {\n        \"Range\": \"bytes=2-\"\n    }\n});\ntext = await res.text();\n\nconsole.log(text); //23456789\nconsole.log(res.status) //206\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonlybrad%2Fhttp-server-simple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonlybrad%2Fhttp-server-simple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonlybrad%2Fhttp-server-simple/lists"}