{"id":17312605,"url":"https://github.com/ndaidong/restfun","last_synced_at":"2026-04-29T08:01:51.057Z","repository":{"id":64911218,"uuid":"579350713","full_name":"ndaidong/restfun","owner":"ndaidong","description":"Minimal REST framework in 300 LOC for Node.js and Bun - No dependencies nor build step - Completely pure and native!","archived":false,"fork":false,"pushed_at":"2025-04-25T10:22:56.000Z","size":228,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-04T02:23:43.901Z","etag":null,"topics":["nodejs","rest-api"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/ndaidong.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,"zenodo":null}},"created_at":"2022-12-17T12:02:48.000Z","updated_at":"2025-04-25T10:22:09.000Z","dependencies_parsed_at":"2025-02-01T06:41:03.007Z","dependency_job_id":"03b892ed-382d-4228-a86c-bb5ae4906734","html_url":"https://github.com/ndaidong/restfun","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/ndaidong/restfun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndaidong%2Frestfun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndaidong%2Frestfun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndaidong%2Frestfun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndaidong%2Frestfun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ndaidong","download_url":"https://codeload.github.com/ndaidong/restfun/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndaidong%2Frestfun/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32416146,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T06:29:02.080Z","status":"ssl_error","status_checked_at":"2026-04-29T06:29:00.631Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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":["nodejs","rest-api"],"created_at":"2024-10-15T12:44:02.841Z","updated_at":"2026-04-29T08:01:51.052Z","avatar_url":"https://github.com/ndaidong.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# restfun\n\nTo run minimal and fast rest api on the edges.\n\n[![npm](https://img.shields.io/npm/v/restfun?color=green)](https://www.npmjs.com/package/restfun)\n[![CodeQL](https://github.com/ndaidong/restfun/workflows/CodeQL/badge.svg)](https://github.com/ndaidong/restfun/actions/workflows/codeql-analysis.yml)\n[![CI test](https://github.com/ndaidong/restfun/workflows/ci-test/badge.svg)](https://github.com/ndaidong/restfun/actions/workflows/ci-test.yml)\n\n## Install\n\n```bash\npnpm i restfun\nbun add restfun\n```\n\n## Usage\n\nCreate a server.js file as below:\n\n```js\nimport restfun from 'restfun'\n\nconst server = restfun()\n\nserver.get('/', (req, res) =\u003e {\n  res.html('Hello world')\n})\n\nserver.listen(3001)\n```\n\nRun with Node.js or Bun:\n\n```bash\nnode server.js\n# or\nbun run server\n```\n\n## APIs\n\n### `restfun`\n\n#### Syntax\n\n```ts\nrestfun()\nrestfun(Object options)\n```\n\n#### Parameters\n\n##### `options` *optional*\n\n- `cors`: object, headers for cors, default to `{}`\n- `noDelay`: bolean, default to `true`\n- `keepAlive`: bolean, default to `false`\n- `maxHeaderSize`: number, default to `16384`\n- `headersTimeout`: number, default to `60000`\n- `requestTimeout`: number, default to `300000`\n\nRegarding `cors`, by default, `restfun` enalbe CORS by auto adding the following headers:\n\n```bash\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Headers: authorization, token, x-token, apikey, x-api-key\n```\n\nDeveloper can modify, or add more via `cors` options, for example:\n\n```js\nimport restfun from 'restfun'\n\nexport const server = restfun({\n  cors: {\n    'Access-Control-Allow-Origin': 'https://myownfrontend.com', // overwrite\n    'Access-Control-Allow-Credentials': 'true'\n  }\n})\n```\n\nFor other options, refer [this link](https://nodejs.org/api/http.html#httpcreateserveroptions-requestlistener).\n\n#### Return\n\nReturn a `restfun` instance with the following methods:\n\n- `listen(port, host, callback)`: start listening at the specified port\n- `get(pattern, handler)`: routes GET request to the specified pattern\n- `post(pattern, handler)`: routes POST request to the specified pattern\n- `put(pattern, handler)`: routes PUT request to the specified pattern\n- `patch(pattern, handler)`: routes PATCH request to the specified pattern\n- `delete(pattern, handler)`: routes DELETE request to the specified pattern\n- `head(pattern, handler)`: routes HEAD request to the specified pattern\n- `options(pattern, handler)`: routes OPTIONS request to the specified pattern\n- `route(METHOD, pattern, handler`: another way to add router using any HTTP methods\n- `use(handler)`: insert a handler in the middle of request/response processing, before the router handlers\n- `notFound(handler)`: add handler to deal with 404 error\n- `onError(handler)`: add handler to deal with other errors\n\n##### `patterns`\n\nThis lib only support simple pattern, e.g,:\n\n- `/:category/:slug`\n- `/profile/:userid/`\n- `/accounts/:userid/settings`\n- `/search`\n- `/`\n\n\n##### `handler`\n\nA function that accepts an [IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage) (a.k.a `req`) and a [ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse) (a.k.a `res`).\n\nAlong with what are inherited from their prototype, `restfun` adds the following properties and methods to `req`/`res`:\n\n- `req.ip`\n- `req.params`\n- `req.query`\n- `req.body`\n- `req.getHeader()`\n- `res.type()`\n- `res.status()`\n- `res.json()`\n- `res.html()`\n- `res.send()`\n\nAn example:\n\n```js\nimport restfun from 'restfun'\n\nexport const server = restfun()\n\nconst PORT = 3001\nconst HOST = '0.0.0.0'\n\nserver.get('/', async (req, res) =\u003e {\n  const ua = req.getHeader('user-agent')\n  console.log(`${req.ip} ${req.method} ${req.path}: ${ua}`)\n  res.html('Hello restfun')\n})\n\nserver.listen(PORT, HOST, () =\u003e {\n  console.log(`Server started listening at http://${HOST}:${PORT}`)\n})\n````\n\n## Benchmark\n\nHere are the result by [oha](https://github.com/hatoo/oha) after the following command:\n\n```bash\noha -n 5000 -c 8 -z 30s --disable-keepalive http://0.0.0.0:3001\n```\n\n- restfun with Node.js v22.14.0:\n\n```bash\nSummary:\n  Success rate: 100.00%\n  Total:  30.0002 secs\n  Slowest:  0.0130 secs\n  Fastest:  0.0001 secs\n  Average:  0.0004 secs\n  Requests/sec: 20592.5155\n\n  Total data: 7.66 MiB\n  Size/request: 13 B\n  Size/sec: 261.42 KiB\n```\n\n- restfun with Bun v1.2.10:\n\n```bash\nSummary:\n  Success rate: 100.00%\n  Total:  30.0004 secs\n  Slowest:  0.0189 secs\n  Fastest:  0.0000 secs\n  Average:  0.0002 secs\n  Requests/sec: 37074.3614\n\n  Total data: 13.79 MiB\n  Size/request: 13 B\n  Size/sec: 470.67 KiB\n```\n\nSystem specs:\n\n- 12th Gen Intel(R) Core(TM) i5-12450HX (12) @ 4.40 GHz\n- RAM DDR5 4800 MT/s 24GB\n\nUnder the same conditions, we also tested some other alternatives:\n\n| Library/Framework | Node.js v22.14.0 | Bun v1.2.10 | Deno v2.2.12 |\n|--|--|--|--|\n| restfun@0.0.18 | 20,592 | 37,074 | 6,645 |\n| fastify@5.3.2 | 22,815 | 42,978 | 7,199 |\n| koa@2.16.1 | 19,359 | 39,288 | 7,263 |\n| polka@1.0.0-next.28 | 21,840 | 16,189 | 3,392 |\n| nitro@2.11.9 | 15,450 | 14,596 | 6,580 |\n| express@5.1.0 | 11,237 | 37,832 | 6,170 |\n| hono@4.7.7 | 20,045 | 50,292 | 41,513 |\n| elysia@1.2.25 | 22,738 | 50,209 | 7,165 |\n| ultimate-express@1.4.6 | 48,377 | not support | not support |\n| hyper-express@6.17.3 | 49,427 | not support | not support |\n| Node HTTP module | 27,935 | 43,668 | 7,184  |\n| Bun.serve | not support | 53,702 | not support |\n| Deno.serve | not support | not support | 42,447 |\n\n* elysia run on Deno with `@elysiajs/node`\n* Node, Bun, Deno all have built-in server, but only Bun supports routers\n\nLooking into the above table, we can see that `restfun` is just for fun. Until now, I mainly use `hyper-express` in my projects. But I'm slowly switching to Bun as its built-in server is very cool. For the teams, I recommend to use a mix between `express` and `ultimate-express` then it has both standard and performance, dev friendly and production ready. If your project must work on Bun and Deno, `hono` is still the best choice.\n\n## Test\n\n```bash\ngit clone https://github.com/ndaidong/restfun.git\ncd restfun\npnpm i\npnpm test\n```\n\n## License\nThe MIT License (MIT)\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fndaidong%2Frestfun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fndaidong%2Frestfun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fndaidong%2Frestfun/lists"}