{"id":13623225,"url":"https://github.com/lukeed/polkadot","last_synced_at":"2025-10-09T18:24:27.588Z","repository":{"id":44427139,"uuid":"167855877","full_name":"lukeed/polkadot","owner":"lukeed","description":"The tiny HTTP server that gets out of your way!     ・  ","archived":false,"fork":false,"pushed_at":"2020-05-05T00:56:04.000Z","size":189,"stargazers_count":324,"open_issues_count":2,"forks_count":9,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-14T04:45:52.831Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://discord.gg/xrRvfYV","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/lukeed.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}},"created_at":"2019-01-27T20:36:14.000Z","updated_at":"2025-03-07T02:41:13.000Z","dependencies_parsed_at":"2022-09-17T00:41:10.081Z","dependency_job_id":null,"html_url":"https://github.com/lukeed/polkadot","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fpolkadot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fpolkadot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fpolkadot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeed%2Fpolkadot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukeed","download_url":"https://codeload.github.com/lukeed/polkadot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249088999,"owners_count":21210900,"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":[],"created_at":"2024-08-01T21:01:29.319Z","updated_at":"2025-10-09T18:24:22.570Z","avatar_url":"https://github.com/lukeed.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" alt=\"polkadot\" height=\"260\" /\u003e\n\u003c/div\u003e\n\n\u003ch1 align=\"center\"\u003ePolkadot\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://npmjs.org/package/polkadot\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/v/polkadot\" alt=\"version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://travis-ci.org/lukeed/polkadot\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/travis/lukeed/polkadot\" alt=\"travis\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/lukeed/polkadot\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/codecov/c/github/lukeed/polkadot\" alt=\"codecov\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://npmjs.org/package/polkadot\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/dm/polkadot\" alt=\"downloads\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://packagephobia.now.sh/result?p=polkadot\"\u003e\n    \u003cimg src=\"https://badgen.net/packagephobia/install/polkadot\" alt=\"install size\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003eThe tiny HTTP server that gets out of your way~!\u003c/div\u003e\n\n## Features\n\n* **Intentionally Minimal**\u003cbr\u003e\n    _Build your own stack! Polkadot doesn't even include a router._\u003cbr\u003e\n    _Polkadot can accommodate any \u0026 all of your preferences. This is **your** app._\n\n* **Extremely Lightweight**\u003cbr\u003e\n    _Even with all dependencies, Polkadot weighs less than 15kB!_\u003cbr\u003e\n    _It's the perfect candidate for serverless environments._\n\n* **Simple yet Flexible**\u003cbr\u003e\n    _You can learn the \"framework\" during lunch and deploy before the day's end._\u003cbr\u003e\n    _There's no limit to what you can do – [nor how you can do it](#handlers)._\n\n* **Highly Performant**\u003cbr\u003e\n    _Because Polkadot does so little, it's as [\"blazing fast\"](/bench) as they come._\n\n* **Async Support**\u003cbr\u003e\n    _It's the 2020s – time to `await` all the things~!_\n\n\n\n## Install\n\n```\n$ npm install --save polkadot\n```\n\n\n## Usage: CLI\n\nJust specify an entry file – that's it! :tada:\u003cbr\u003e\nIf you do not provide one, then `index.js` is assumed.\n\nCustomize the port by setting the `PORT` environment variable.\u003cbr\u003e\nThe `PORT` will default to `3000` if left undeclared.\n\n\u003e **Important:** An error will be thrown if the `PORT` is in use.\n\n```sh\n# Examples:\n\n$ polkadot\n$ polkadot app.js\n$ PORT=8080 polkadot app.js\n```\n\n```js\n// index.js\nconst { get } = require('httpie');\n\nmodule.exports = async (req, res) =\u003e {\n  let uri = `https://jsonplaceholder.typicode.com/posts`;\n  if (req.query.id) {\n    uri += `/${req.query.id}`;\n  }\n  let res = await get(uri);\n  return res.data;\n}\n```\n\n\n## Usage: Programmatic\n\nFor those who need to control the lifecycle and/or lifespan of their server(s), a [programmatic API](#api) is available.\u003cbr\u003e\nSimilarly, this is the only way to customize the underlying `server` itself (see the [`with-https`](https://github.com/lukeed/polkadot/tree/master/examples/with-https) example).\n\n```js\nconst { get } = require('httpie');\nconst polkadot = require('polkadot');\n\nconst app = polkadot(async (req, res) =\u003e {\n  let uri = `https://jsonplaceholder.typicode.com/posts`;\n  if (req.query.id) {\n    uri += `/${req.query.id}`;\n  }\n  let res = await get(uri);\n  return res.data;\n});\n\napp.listen(3000, err =\u003e {\n  if (err) throw err;\n  console.log('\u003e Running on localhost:3000');\n});\n```\n\n## API\n\n\u003e **Note:** The following pertains to [Programmatic Usage](#usage-programmatic) only\n\n### polkadot.handler(req, res)\nReturns: `Function`\n\nThe main `polkadot` handler.\n\nIt parses the `req` (see [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)) and assigns value to the `path`, `query`, and `search` keys\u003csup\u003e1\u003c/sup\u003e.\u003cbr\u003e\nIt also waits until the `res` (see [`ServerResponse`](https://nodejs.org/api/http.html#http_class_http_serverresponse)) has been terminated or until data is returned.\u003csup\u003e2\u003c/sup\u003e\n\n\u003e _\u003csup\u003e1\u003c/sup\u003e See [`@polka/url`](https://github.com/lukeed/polka/tree/master/packages/url) for further details._\u003cbr\u003e\n\u003e _\u003csup\u003e2\u003c/sup\u003e See [Handlers](#handlers) for varying return types._\n\n### polkadot.listen()\nReturns: `http.Server`\n\nBoots (or creates) the underlying [`http.Server`](https://nodejs.org/api/http.html#http_class_http_server) for the first time.\u003cbr\u003e\nAll arguments are passed directly to [`server.listen`](https://nodejs.org/api/net.html#net_server_listen) with no changes.\n\n\n## Handlers\n\nEvery handler receives a `req` ([`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)) and a `res` ([`ServerResponse`](https://nodejs.org/api/http.html#http_class_http_serverresponse)) pair of arguments.\u003cbr\u003e\nThese are the true, mostly unfettered\u003csup\u003e1\u003c/sup\u003e instances that the `http.Server` created, so you have full access to all native APIs.\n\n\u003e _\u003csup\u003e1\u003c/sup\u003e Before calling your handler(s), [`@polka/url`](https://github.com/lukeed/polka/tree/master/packages/url) assigns value to `req.path`, `req.query`, and `req.search` keys._\n\nThere are multiple ways to format or return the server response. You may mix and match them, as you are not restricted to a particular format in your application(s).\n\n### 1. Use Native APIs\n\nBecause you have direct access to `res` (see [`ServerResponse`](https://nodejs.org/api/http.html#http_class_http_serverresponse)), you can set headers, the statusCode, and/or write response data with the core Node.js methods:\n\n```js\nmodule.exports = function (req, res) {\n  res.statusCode = 400;\n  res.setHeader('Content-Type', 'application/json');\n  res.end('{\"error\":\"Bad Request\"}');\n}\n```\n\n### 2. The `@polka/send-type` library\n\nThe [`@polka/send-type`](https://github.com/lukeed/polka/tree/master/packages/send-type) library is a utility function that composes your response through a simple API. It also inspects your response data and will auto-set its `Content-Type` (if unspecified) and `Content-Length` headers for you. Additionally, it will stringify Objects into JSON on your behalf!\n\n\u003e **Note:** Check out its [Data Detections](https://github.com/lukeed/polka/tree/master/packages/send-type#data-detections) documentation.\n\nBecause the [`@polka/send-type`](https://github.com/lukeed/polka/tree/master/packages/send-type) library is already a dependency of `polkadot`, using it comes at _no extra cost_!\n\n```js\nconst send = require('@polka/send-type');\n\nmodule.exports = function (req, res) {\n  send(res, 400, {\n    error: 'Bad Request'\n  });\n}\n```\n\n### 3. Return data\n\nPolka uses the [`@polka/send-type`](https://github.com/lukeed/polka/tree/master/packages/send-type) library internally, which allows you to `return` data directly from your function handler instead of using the native APIs to format the response manually.\n\nBecause of this, `@polka/send-type` can inspect your outgoing data and determine its `Content-Type` (if unspecified) and `Content-Length` response headers on your behalf. Similarly, it will automatically convert Objects into JSON strings.\n\n\u003e **Note:** Check out its [Data Detections](https://github.com/lukeed/polka/tree/master/packages/send-type#data-detections) documentation.\n\n```js\nmodule.exports = function (req, res) {\n  res.statusCode = 400;\n  return {\n    error: 'Bad Request'\n  };\n};\n```\n\n### 4. Async Returns\n\nPolkadot works great with asynchronous functions!\u003cbr\u003e\nYou can certainly fetch data from external APIs, interact with databases, ...etc without any problems.\n\nOf course, your asynchronous chain(s) may also use native `res` APIs, the `@polka/send-type` helper, or may return data directly. All options are always available!\n\nThe **only** rule is that if your handler _ends_ in a `Promise` or `AsyncFunction`, that function **must be returned** so that Polkadot can resolve it on your behalf.\n\n\u003e **Important:** The use of `AsyncFunction` is only supported in Node versions `7.4` and above.\n\n```js\n// For demo, not required\nconst send = require('@polka/send-type');\n\n// Using Promises\nmodule.exports = function (req, res) {\n  // must `return` the Promise\n  return isUser(req).then(user =\u003e {\n    if (user) {\n      send(res, 200, { user });\n    } else {\n      send(res, 401, 'You must be logged in');\n    }\n  });\n};\n\n// Using AsyncFunctions\nmodule.exports = async function (req, res) {\n  const user = await isUser(req);\n  if (user) {\n    send(res, 200, { user });\n  } else {\n    send(res, 401, 'You must be logged in');\n  }\n}\n```\n\n## Routing\n\nBefore your handler is called, Polkadot will parse the request to provide you with some core information.\u003cbr\u003e\nIt will use [`@polka/url`](https://github.com/lukeed/polka/tree/master/packages/url) to make `req.path`, `req.search`, and `req.query` available.\n\nWhile polkadot _does not_ include a router, you can create your own or import **any** router of your choosing!\u003cbr\u003e\nPlease check out the [`with-router`](https://github.com/lukeed/polkadot/tree/master/examples/with-router) example that uses [Trouter](https://github.com/lukeed/trouter) to build a full JSON resource.\n\nBelow is a simple example that serves images \u0026 video files based on the incoming path:\n\n```js\nconst fs = require('fs');\nconst { join } = require('path');\nconst mime = require('mime/lite');\n\nconst assets = join(__dirname, 'assets');\n\nfunction sendfile(res, dir, filename) {\n  const file = join(assets, dir, filename);\n  if (fs.existsSync(file)) {\n    res.setHeader('Content-Type', mime.getType(file));\n    fs.createReadStream(file).pipe(res);\n  } else {\n    res.statusCode = 404;\n    res.end('File not found');\n  }\n}\n\n// Supports: /images?filename=foobar.jpg\n// Supports: /videos?filename=foobar.mp4\nmodule.exports = function (req, res) {\n  const { filename } = req.query;\n  if (req.path === '/images') {\n    sendfile(res, 'images', filename);\n  } else if (req.path === '/videos') {\n    sendfile(res, 'videos', filename);\n  } else {\n    res.statusCode = 404;\n    res.end('Unknown filetype');\n  }\n}\n```\n\n\n## Error Handling\n\nYou must handle your own errors. This is because Polkadot will not dictate your application design nor its behavior – and _how_ an application responds to and handles errors is a large, important part of its design!\n\n\u003e Please visit the [`with-middleware`](https://github.com/lukeed/polkadot/tree/master/examples/with-middleware) or the [`with-router`](https://github.com/lukeed/polkadot/tree/master/examples/with-router) examples.\u003cbr\u003e They are both more complex demonstrations that handle errors while chaining or composing functions together.\n\nFor simple endpoints, it's very straightforward (as it should be):\n\n```js\n// Send 404 if unknown path\nmodule.exports = function (req, res) {\n  if (req.path !== '/') {\n    res.statusCode = 404;\n    return 'Page not found';\n  }\n  return 'OK';\n}\n\n// ---\n\nconst { get } = require('httpie');\n\n// Send 404 if ID unknown to external API\nmodule.exports = async function (req, res) {\n  try {\n    const ID = req.query.id;\n    let { data } = await get(`https://example.com/users/${ID}`);\n    send(res, 200, { user:data });\n  } catch (err) {\n    const code = err.statusCode || 404;\n    const message = err.data || 'User not found';\n    console.error('Error: ', req.query.id, code, message);\n    send(res, code, message);\n  }\n}\n```\n\n\n## Benchmarks\n\nFor performance results and comparisons, please check out the [`bench`](/bench) directory.\n\n\n## Prior Art\n\nPolkadot is the \"little sibling\" to [Polka](https://github.com/lukeed/polka). It's effectively the core of Polka, stripped of all routing, middleware sequencing, and Express compatibility layers. While Polka is already leaner than most everything else, there was an opportunity to further satisfy the minimalists and make a microscopic version of Polka – hence, polka•_dot_.\n\nAdditionally, Polkadot follows in the footsteps of [`micro`](https://github.com/zeit/micro), which was the first HTTP framework of our kind (to my knowledge).\n\n\n## License\n\nMIT © [Luke Edwards](https://lukeed.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukeed%2Fpolkadot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukeed%2Fpolkadot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukeed%2Fpolkadot/lists"}