summaryrefslogtreecommitdiff
path: root/alarm/node_modules/polka
diff options
context:
space:
mode:
Diffstat (limited to 'alarm/node_modules/polka')
-rw-r--r--alarm/node_modules/polka/index.js102
-rw-r--r--alarm/node_modules/polka/package.json19
-rw-r--r--alarm/node_modules/polka/readme.md643
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: &mdash; 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 &mdash; 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 &mdash; 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)