diff options
author | Minteck <contact@minteck.org> | 2022-10-18 08:59:09 +0200 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2022-10-18 08:59:09 +0200 |
commit | 2c4ae43e688a9873e86211ea0e7aeb9ba770dd77 (patch) | |
tree | 17848d95522dab25d3cdeb9c4a6450e2a234861f /alarm/node_modules/polka | |
parent | 108525534c28013cfe1897c30e4565f9893f3766 (diff) | |
download | pluralconnect-2c4ae43e688a9873e86211ea0e7aeb9ba770dd77.tar.gz pluralconnect-2c4ae43e688a9873e86211ea0e7aeb9ba770dd77.tar.bz2 pluralconnect-2c4ae43e688a9873e86211ea0e7aeb9ba770dd77.zip |
Update
Diffstat (limited to 'alarm/node_modules/polka')
-rw-r--r-- | alarm/node_modules/polka/index.js | 102 | ||||
-rw-r--r-- | alarm/node_modules/polka/package.json | 19 | ||||
-rw-r--r-- | alarm/node_modules/polka/readme.md | 643 |
3 files changed, 764 insertions, 0 deletions
diff --git a/alarm/node_modules/polka/index.js b/alarm/node_modules/polka/index.js new file mode 100644 index 0000000..f32a29c --- /dev/null +++ b/alarm/node_modules/polka/index.js @@ -0,0 +1,102 @@ +const http = require('http'); +const Router = require('trouter'); +const { parse } = require('querystring'); +const parser = require('@polka/url'); + +function lead(x) { + return x.charCodeAt(0) === 47 ? x : ('/' + x); +} + +function value(x) { + let y = x.indexOf('/', 1); + return y > 1 ? x.substring(0, y) : x; +} + +function mutate(str, req) { + req.url = req.url.substring(str.length) || '/'; + req.path = req.path.substring(str.length) || '/'; +} + +function onError(err, req, res, next) { + let code = (res.statusCode = err.code || err.status || 500); + res.end(err.length && err || err.message || http.STATUS_CODES[code]); +} + +class Polka extends Router { + constructor(opts={}) { + super(opts); + this.apps = {}; + this.wares = []; + this.bwares = {}; + this.parse = parser; + this.server = opts.server; + this.handler = this.handler.bind(this); + this.onError = opts.onError || onError; // catch-all handler + this.onNoMatch = opts.onNoMatch || this.onError.bind(null, { code:404 }); + } + + add(method, pattern, ...fns) { + let base = lead(value(pattern)); + if (this.apps[base] !== void 0) throw new Error(`Cannot mount ".${method.toLowerCase()}('${lead(pattern)}')" because a Polka application at ".use('${base}')" already exists! You should move this handler into your Polka application instead.`); + return super.add(method, pattern, ...fns); + } + + use(base, ...fns) { + if (typeof base === 'function') { + this.wares = this.wares.concat(base, fns); + } else if (base === '/') { + this.wares = this.wares.concat(fns); + } else { + base = lead(base); + fns.forEach(fn => { + if (fn instanceof Polka) { + this.apps[base] = fn; + } else { + let arr = this.bwares[base] || []; + arr.length > 0 || arr.push((r, _, nxt) => (mutate(base, r),nxt())); + this.bwares[base] = arr.concat(fn); + } + }); + } + return this; // chainable + } + + listen() { + (this.server = this.server || http.createServer()).on('request', this.handler); + this.server.listen.apply(this.server, arguments); + return this; + } + + handler(req, res, info) { + info = info || this.parse(req); + let fns=[], arr=this.wares, obj=this.find(req.method, info.pathname); + req.originalUrl = req.originalUrl || req.url; + let base = value(req.path = info.pathname); + if (this.bwares[base] !== void 0) { + arr = arr.concat(this.bwares[base]); + } + if (obj) { + fns = obj.handlers; + req.params = obj.params; + } else if (this.apps[base] !== void 0) { + mutate(base, req); info.pathname=req.path; //=> updates + fns.push(this.apps[base].handler.bind(null, req, res, info)); + } else if (fns.length === 0) { + fns.push(this.onNoMatch); + } + // Grab addl values from `info` + req.search = info.search; + req.query = parse(info.query); + // Exit if only a single function + let i=0, len=arr.length, num=fns.length; + if (len === i && num === 1) return fns[0](req, res); + // Otherwise loop thru all middlware + let next = err => err ? this.onError(err, req, res, next) : loop(); + let loop = _ => res.finished || (i < len) && arr[i++](req, res, next); + arr = arr.concat(fns); + len += num; + loop(); // init + } +} + +module.exports = opts => new Polka(opts); diff --git a/alarm/node_modules/polka/package.json b/alarm/node_modules/polka/package.json new file mode 100644 index 0000000..3a6cf11 --- /dev/null +++ b/alarm/node_modules/polka/package.json @@ -0,0 +1,19 @@ +{ + "name": "polka", + "version": "0.5.2", + "description": "A micro web server so fast, it'll make you dance! :dancers:", + "repository": "lukeed/polka", + "license": "MIT", + "files": [ + "*.js" + ], + "author": { + "name": "Luke Edwards", + "email": "luke@lukeed.com", + "url": "https://lukeed.com" + }, + "dependencies": { + "@polka/url": "^0.5.0", + "trouter": "^2.0.1" + } +} diff --git a/alarm/node_modules/polka/readme.md b/alarm/node_modules/polka/readme.md new file mode 100644 index 0000000..8c137fc --- /dev/null +++ b/alarm/node_modules/polka/readme.md @@ -0,0 +1,643 @@ +<div align="center"> + <img src="https://github.com/lukeed/polka/raw/master/polka.png" alt="Polka" width="400" height="300" /> +</div> + +<h1 align="center">Polka</h1> + +<div align="center"> + <a href="https://npmjs.org/package/polka"> + <img src="https://badgen.now.sh/npm/v/polka" alt="version" /> + </a> + <a href="https://travis-ci.org/lukeed/polka"> + <img src="https://badgen.now.sh/travis/lukeed/polka" alt="travis" /> + </a> + <a href="https://codecov.io/gh/lukeed/polka"> + <img src="https://badgen.now.sh/codecov/c/github/lukeed/polka" alt="codecov" /> + </a> + <a href="https://npmjs.org/package/polka"> + <img src="https://badgen.now.sh/npm/dm/polka" alt="downloads" /> + </a> + <a href="https://packagephobia.now.sh/result?p=polka"> + <img src="https://packagephobia.now.sh/badge?p=polka" alt="install size" /> + </a> +</div> + +<div align="center">A micro web server so fast, it'll make you dance! :dancers:</div> + +<br /> + +Polka is an extremely minimal, highly performant Express.js alternative. Yes, you're right, Express is _already_ super fast & not _that_ big :thinking: — but Polka shows that there was (somehow) room for improvement! + +Essentially, Polka is just a [native HTTP server](https://nodejs.org/dist/latest-v9.x/docs/api/http.html#http_class_http_server) with added support for routing, middleware, and sub-applications. That's it! :tada: + +And, of course, in mandatory bullet-point format: + +* 33-50% faster than Express for simple applications +* Middleware support, including Express middleware you already know & love +* Nearly identical application API & route pattern definitions +* ~90 LOC for Polka, 120 including [its router](https://github.com/lukeed/trouter) + + +## Install + +``` +$ npm install --save polka +``` + +## Usage + +```js +const polka = require('polka'); + +function one(req, res, next) { + req.hello = 'world'; + next(); +} + +function two(req, res, next) { + req.foo = '...needs better demo 😔'; + next(); +} + +polka() + .use(one, two) + .get('/users/:id', (req, res) => { + console.log(`~> Hello, ${req.hello}`); + res.end(`User: ${req.params.id}`); + }) + .listen(3000, err => { + if (err) throw err; + console.log(`> Running on localhost:3000`); + }); +``` + +## API + +Polka extends [Trouter](https://github.com/lukeed/trouter) which means it inherits its API, too! + +### polka(options) + +Returns an instance of Polka~! + +#### options.server +Type: `Server`<br> + +A custom, instantiated server that the Polka instance should attach its [`handler`](#handlerreq-res-parsed) to. This is useful if you have initialized a server elsewhere in your application and want Polka to use _it_ instead of creating a new `http.Server`. + +Polka _only_ updates the server when [`polka.listen`](#listen) is called. At this time, Polka will create a [`http.Server`](https://nodejs.org/api/http.html#http_class_http_server) if a server was not already provided via `options.server`. + +> **Important:** The `server` key will be `undefined` until `polka.listen` is invoked, unless a server was provided. + +#### options.onError +Type: `Function` + +A catch-all error handler; executed whenever a middleware throws an error. Change this if you don't like default behavior. + +Its signature is `(err, req, res, next)`, where `err` is the `String` or `Error` thrown by your middleware. + +> **Caution:** Use `next()` to bypass certain errors **at your own risk!** <br>You must be certain that the exception will be handled elsewhere or _can_ be safely ignored. <br>Otherwise your response will never terminate! + +#### options.onNoMatch +Type: `Function` + +A handler when no route definitions were matched. Change this if you don't like default behavior, which sends a `404` status & `Not found` response. + +Its signature is `(req, res)` and requires that you terminate the response. + + +### use(base, ...fn) + +Attach [middleware(s)](#middleware) and/or sub-application(s) to the server. These will execute _before_ your routes' [handlers](#handlers). + +**Important:** If a `base` pathname is provided, all functions within the same `use()` block will _only_ execute when the `req.path` matches the `base` path. + +#### base +Type: `String`<br> +Default: `undefined` + +The base path on which the following middleware(s) or sub-application should be mounted. + +#### fn +Type: `Function|Array` + +You may pass one or more functions at a time. Each function must have the standardized `(req, res, next)` signature. + +You may also pass a sub-application, which _must_ be accompanied by a `base` pathname. + +Please see [`Middleware`](#middleware) and [Express' middleware examples](http://expressjs.com/en/4x/api.html#middleware-callback-function-examples) for more info. + + +### parse(req) + +Returns: `Object` or `undefined` + +As of `v0.5.0`, this is an alias of the [`@polka/url`](/packages/url) module. For nearly all cases, you'll notice no changes. + +But, for whatever reason, you can quickly swap in [`parseurl`](https://github.com/pillarjs/parseurl) again: + +```js +const app = polka(); +app.parse = require('parseurl'); +//=> Done! +``` + +### listen() + +Returns: `Polka` + +Boots (or creates) the underlying [`http.Server`](https://nodejs.org/dist/latest-v9.x/docs/api/http.html#http_class_http_server) for the first time. All arguments are passed to [`server.listen`](https://nodejs.org/dist/latest-v9.x/docs/api/net.html#net_server_listen) directly with no changes. + +As of `v0.5.0`, this method no longer returns a Promise. Instead, the current Polka instance is returned directly, allowing for chained operations. + +```js +// Could not do this before 0.5.0 +const { server, handler } = polka().listen(); + +// Or this! +const app = polka().listen(PORT, onAppStart); + +app.use('users', require('./users')) + .get('/', (req, res) => { + res.end('Pretty cool!'); + }); +``` + +### handler(req, res, parsed) + +The main Polka [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) handler. It receives all requests and tries to match the incoming URL against known routes. + +If the `req.url` is not immediately matched, Polka will look for sub-applications or middleware groups matching the `req.url`'s [`base`](#base) path. If any are found, they are appended to the loop, running _after_ any global middleware. + +> **Note:** Any middleware defined within a sub-application is run _after_ the main app's (aka, global) middleware and _before_ the sub-application's route handler. + +At the end of the loop, if a middleware hasn't yet terminated the response (or thrown an error), the route handler will be executed, if found — otherwise a `(404) Not found` response is returned, configurable via [`options.onNoMatch`](#optionsonnomatch). + +#### req +Type: `IncomingMessage` + +#### res +Type: `ServerResponse` + +#### parsed +Type: `Object` + +Optionally provide a parsed [URL](https://nodejs.org/dist/latest-v9.x/docs/api/url.html#url_class_url) object. Useful if you've already parsed the incoming path. Otherwise, [`app.parse`](#parsereq) (aka [`parseurl`](https://github.com/pillarjs/parseurl)) will run by default. + + +## Routing + +Routes are used to define how an application responds to varying HTTP methods and endpoints. + +> If you're coming from Express, there's nothing new here!<br> However, do check out [Comparisons](#comparisons) for some pattern changes. + +### Basics + +Each route is comprised of a [path pattern](#patterns), a [HTTP method](#methods), and a [handler](#handlers) (aka, what you want to do). + +In code, this looks like: + +```js +app.METHOD(pattern, handler); +``` + +wherein: + +* `app` is an instance of `polka` +* [`METHOD`](#methods) is any valid HTTP/1.1 method, lowercased +* [`pattern`](#patterns) is a routing pattern (string) +* [`handler`](#handlers) is the function to execute when `pattern` is matched + +Also, a single pathname (or `pattern`) may be reused with multiple METHODs. + +The following example demonstrates some simple routes. + +```js +const app = polka(); + +app.get('/', (req, res) => { + res.end('Hello world!'); +}); + +app.get('/users', (req, res) => { + res.end('Get all users!'); +}); + +app.post('/users', (req, res) => { + res.end('Create a new User!'); +}); + +app.put('/users/:id', (req, res) => { + res.end(`Update User with ID of ${req.params.id}`); +}); + +app.delete('/users/:id', (req, res) => { + res.end(`CY@ User ${req.params.id}!`); +}); +``` + +### Patterns + +Unlike the very popular [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp), Polka uses string comparison to locate route matches. While [faster](https://github.com/lukeed/matchit#benchmarks) & more memory efficient, this does also prevent complex pattern matching. + +However, have no fear! :boom: All the basic and most commonly used patterns are supported. You probably only ever used these patterns in the first place. :wink: + +> See [Comparisons](#comparisons) for the list of `RegExp`-based patterns that Polka does not support. + +The supported pattern types are: + +* static (`/users`) +* named parameters (`/users/:id`) +* nested parameters (`/users/:id/books/:title`) +* optional parameters (`/users/:id?/books/:title?`) +* any match / wildcards (`/users/*`) + +### Parameters + +Any named parameters included within your route [`pattern`](#patterns) will be automatically added to your incoming `req` object. All parameters will be found within `req.params` under the same name they were given. + +> **Important:** Your parameter names should be unique, as shared names will overwrite each other! + +```js +app.get('/users/:id/books/:title', (req, res) => { + let { id, title } = req.params; + res.end(`User: ${id} && Book: ${title}`); +}); +``` + +```sh +$ curl /users/123/books/Narnia +#=> User: 123 && Book: Narnia +``` + +### Methods + +Any valid HTTP/1.1 method is supported! However, only the most common methods are used throughout this documentation for demo purposes. + +> **Note:** For a full list of valid METHODs, please see [this list](https://github.com/lukeed/trouter#method). + +### Handlers + +Request handlers accept the incoming [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) and the formulating [`ServerResponse`](https://nodejs.org/dist/latest-v9.x/docs/api/http.html#http_class_http_serverresponse). + +Every route definition must contain a valid `handler` function, or else an error will be thrown at runtime. + +> **Important:** You must _always_ terminate a `ServerResponse`! + +It's a **very good** practice to _always_ terminate your response ([`res.end`](https://nodejs.org/api/http.html#http_request_end_data_encoding_callback)) inside a handler, even if you expect a [middleware](#middleware) to do it for you. In the event a response is/was not terminated, the server will hang & eventually exit with a `TIMEOUT` error. + +> **Note:** This is a native `http` behavior. + +#### Async Handlers + +If using Node 7.4 or later, you may leverage native `async` and `await` syntax! :heart_eyes_cat: + +No special preparation is needed — simply add the appropriate keywords. + +```js +const app = polka(); + +const sleep = ms => new Promise(r => setTimeout(r, ms)); + +async function authenticate(req, res, next) { + let token = req.headers['authorization']; + if (!token) return (res.statusCode=401,res.end('No token!')); + req.user = await Users.find(token); // <== fake + next(); // done, woot! +} + +app + .use(authenticate) + .get('/', async (req, res) => { + // log middleware's findings + console.log('~> current user', req.user); + // force sleep, because we can~! + await sleep(500); + // send greeting + res.end(`Hello, ${req.user.name}`); + }); +``` + + +## Middleware + +Middleware are functions that run in between (hence "middle") receiving the request & executing your route's [`handler`](#handlers) response. + +> Coming from Express? Use any middleware you already know & love! :tada: + +The middleware signature receives the request (`req`), the response (`res`), and a callback (`next`). + +These can apply mutations to the `req` and `res` objects, and unlike Express, have access to `req.params`, `req.path`, `req.search`, and `req.query`! + +Most importantly, a middleware ***must*** either call `next()` or terminate the response (`res.end`). Failure to do this will result in a never-ending response, which will eventually crash the `http.Server`. + +```js +// Log every request +function logger(req, res, next) { + console.log(`~> Received ${req.method} on ${req.url}`); + next(); // move on +} + +function authorize(req, res, next) { + // mutate req; available later + req.token = req.headers['authorization']; + req.token ? next() : ((res.statusCode=401) && res.end('No token!')); +} + +polka().use(logger, authorize).get('*', (req, res) => { + console.log(`~> user token: ${req.token}`); + res.end('Hello, valid user'); +}); +``` + +```sh +$ curl / +# ~> Received GET on / +#=> (401) No token! + +$ curl -H "authorization: secret" /foobar +# ~> Received GET on /foobar +# ~> user token: secret +#=> (200) Hello, valid user +``` + +### Middleware Sequence + +In Polka, middleware functions are organized into tiers. + +Unlike Express, Polka middleware are tiered into "global", "filtered", and "route-specific" groups. + +* Global middleware are defined via `.use('/', ...fn)` or `.use(...fn)`, which are synonymous.<br>_Because_ every request's `pathname` begins with a `/`, this tier is always triggered. + +* Sub-group or "filtered" middleware are defined with a base `pathname` that's more specific than `'/'`. For example, defining `.use('/users', ...fn)` will run on any `/users/**/*` request.<br>These functions will execute _after_ "global" middleware but before the route-specific handler. + +* Route handlers match specific paths and execute last in the chain. They must also match the `method` action. + +Once the chain of middleware handler(s) has been composed, Polka will iterate through them sequentially until all functions have run, until a chain member has terminated the response early, or until a chain member has thrown an error. + +Contrast this with Express, which does not tier your middleware and instead iterates through your entire application in the sequence that you composed it. + +```js +// Express +express() + .get('/', get) + .use(foo) + .get('/users/123', user) + .use('/users', users) + +// Polka +Polka() + .get('/', get) + .use(foo) + .get('/users/123', user) + .use('/users', users) +``` + +```sh +$ curl {APP}/ +# Express :: [get] +# Polka :: [foo, get] + +$ curl {APP}/users/123 +# Express :: [foo, user] +# Polka :: [foo, users, user] +``` + + +### Middleware Errors + +If an error arises within a middleware, the loop will be exited. This means that no other middleware will execute & neither will the route handler. + +Similarly, regardless of `statusCode`, an early response termination will also exit the loop & prevent the route handler from running. + +There are three ways to "throw" an error from within a middleware function. + +> **Hint:** None of them use `throw` :joy_cat: + +1. **Pass any string to `next()`** + + This will exit the loop & send a `500` status code, with your error string as the response body. + + ```js + polka() + .use((req, res, next) => next('💩')) + .get('*', (req, res) => res.end('wont run')); + ``` + + ```sh + $ curl / + #=> (500) 💩 + ``` + +2. **Pass an `Error` to `next()`** + + This is similar to the above option, but gives you a window in changing the `statusCode` to something other than the `500` default. + + ```js + function oopsies(req, res, next) { + let err = new Error('Try again'); + err.code = 422; + next(err); + } + ``` + + ```sh + $ curl / + #=> (422) Try again + ``` + +3. **Terminate the response early** + + Once the response has been ended, there's no reason to continue the loop! + + This approach is the most versatile as it allows to control every aspect of the outgoing `res`. + + ```js + function oopsies(req, res, next) { + if (true) { + // something bad happened~ + res.writeHead(400, { + 'Content-Type': 'application/json', + 'X-Error-Code': 'Please dont do this IRL' + }); + let json = JSON.stringify({ error:'Missing CSRF token' }); + res.end(json); + } else { + next(); // never called FYI + } + } + ``` + + ```sh + $ curl / + #=> (400) {"error":"Missing CSRF token"} + ``` + + +## Benchmarks + +Quick comparison between various frameworks using [`wrk`](https://github.com/wg/wrk) on `Node v10.4.0`.<br> Results are taken with the following command, after one warm-up run: + +``` +$ wrk -t4 -c4 -d10s http://localhost:3000/users/123 +``` + +Additional benchmarks between Polka and Express (using various Node versions) can be [found here](/bench). + +> **Important:** Time is mostly spent in _your application code_ rather than Express or Polka code!<br> Switching from Express to Polka will (likely) not show such drastic performance gains. + +``` +Native + Thread Stats Avg Stdev Max +/- Stdev + Latency 1.96ms 119.06us 5.33ms 92.57% + Req/Sec 12.78k 287.46 13.13k 90.00% + 508694 requests in 10.00s, 50.45MB read + Requests/sec: 50867.22 + Transfer/sec: 5.05MB + +Polka + Thread Stats Avg Stdev Max +/- Stdev + Latency 1.98ms 119.26us 4.45ms 92.87% + Req/Sec 12.68k 287.74 13.05k 94.06% + 509817 requests in 10.10s, 50.56MB read + Requests/sec: 50475.67 + Transfer/sec: 5.01MB + +Rayo + Thread Stats Avg Stdev Max +/- Stdev + Latency 2.02ms 116.55us 6.66ms 92.55% + Req/Sec 12.43k 262.32 12.81k 91.58% + 499795 requests in 10.10s, 49.57MB read + Requests/sec: 49481.55 + Transfer/sec: 4.91MB + +Fastify + Thread Stats Avg Stdev Max +/- Stdev + Latency 2.10ms 138.04us 5.46ms 91.50% + Req/Sec 11.96k 414.14 15.82k 95.04% + 479518 requests in 10.10s, 66.31MB read + Requests/sec: 47476.75 + Transfer/sec: 6.57MB + +Koa + Thread Stats Avg Stdev Max +/- Stdev + Latency 2.95ms 247.10us 6.91ms 72.18% + Req/Sec 8.52k 277.12 9.09k 70.30% + 342518 requests in 10.10s, 47.36MB read + Requests/sec: 33909.82 + Transfer/sec: 4.69MB + +Express + Thread Stats Avg Stdev Max +/- Stdev + Latency 4.91ms 484.52us 10.65ms 89.71% + Req/Sec 5.11k 350.75 9.69k 98.51% + 204520 requests in 10.10s, 40.57MB read + Requests/sec: 20249.80 + Transfer/sec: 4.02MB +``` + + +## Comparisons + +Polka's API aims to be _very_ similar to Express since most Node.js developers are already familiar with it. If you know Express, you already know Polka! :dancer: + +There are, however, a few main differences. Polka does not support or offer: + +1) **Polka uses a tiered middleware system.** + + Express maintains the sequence of your route & middleware declarations during its runtime, which can pose a problem when composing sub-applications. Typically, this forces you to duplicate groups of logic. + + Please see [Middleware Sequence](#middleware-sequence) for an example and additional details. + +2) **Any built-in view/rendering engines.** + + Most templating engines can be incorporated into middleware functions or used directly within a route handler. + +3) **The ability to `throw` from within middleware.** + + However, all other forms of middleware-errors are supported. (See [Middleware Errors](#middleware-errors).) + + ```js + function middleware(res, res, next) { + // pass an error message to next() + next('uh oh'); + + // pass an Error to next() + next(new Error('🙀')); + + // send an early, customized error response + res.statusCode = 401; + res.end('Who are you?'); + } + ``` + +4) **Express-like response helpers... yet! (#14)** + + Express has a nice set of [response helpers](http://expressjs.com/en/4x/api.html#res.append). While Polka relies on the [native Node.js response methods](https://nodejs.org/dist/latest-v9.x/docs/api/http.html#http_class_http_serverresponse), it would be very easy/possible to attach a global middleware that contained a similar set of helpers. (_TODO_) + +5) **`RegExp`-based route patterns.** + + Polka's router uses string comparison to match paths against patterns. It's a lot quicker & more efficient. + + The following routing patterns **are not** supported: + + ```js + app.get('/ab?cd', _ => {}); + app.get('/ab+cd', _ => {}); + app.get('/ab*cd', _ => {}); + app.get('/ab(cd)?e', _ => {}); + app.get(/a/, _ => {}); + app.get(/.*fly$/, _ => {}); + ``` + + The following routing patterns **are** supported: + + ```js + app.get('/users', _ => {}); + app.get('/users/:id', _ => {}); + app.get('/users/:id?', _ => {}); + app.get('/users/:id/books/:title', _ => {}); + app.get('/users/*', _ => {}); + ``` + +6) **Polka instances are not (directly) the request handler.** + + Most packages in the Express ecosystem expect you to pass your `app` directly into the package. This is because `express()` returns a middleware signature directly. + + In the Polka-sphere, this functionality lives in your application's [`handler`](#handlerreq-res-parsed) instead. + + Here's an example with [`supertest`](https://github.com/visionmedia/supertest), a popular testing utility for Express apps. + + ```js + const request = require('supertest'); + const send = require('@polka/send-type'); + + const express = require('express')(); + const polka = require('polka')(); + + express.get('/user', (req, res) => { + res.status(200).json({ name: 'john' }); + }); + + polka.get('/user', (req, res) => { + send(res, 200, { name: 'john' }); + }); + + function isExpected(app) { + request(app) + .get('/user') + .expect('Content-Type', /json/) + .expect('Content-Length', '15') + .expect(200); + } + + // Express: Pass in the entire application directly + isExpected(express); + + // Polka: Pass in the application `handler` instead + isExpected(polka.handler); + ``` + + +## License + +MIT © [Luke Edwards](https://lukeed.com) |