6.6 KiB
Installation
Koa requires node v4.0.0 or higher for (partial) ES2015 support.
You can quickly install a supposed version of node with your favorite version manager:
$ nvm install v4.0.0
$ npm i koa
$ node my-koa-app.js
Async Functions with Babel
To use async
functions in Koa, we recommend using babel's require hook.
require('babel-core/register');
// require the rest of the app that needs to be transpiled after the hook
const app = require('./app');
To parse and transpile async functions,
you should at a minimum have the transform-async-to-generator
or transform-async-to-module-method plugins.
For example, in your .babelrc
file, you should have:
{
"plugins": ["transform-async-to-generator"]
}
You can also use the stage-3 preset instead.
Application
A Koa application is an object containing an array of middleware functions which are composed and executed in a stack-like manner upon request. Koa is similar to many other middleware systems that you may have encountered such as Ruby's Rack, Connect, and so on - however a key design decision was made to provide high level "sugar" at the otherwise low-level middleware layer. This improves interoperability, robustness, and makes writing middleware much more enjoyable.
This includes methods for common tasks like content-negotiation, cache freshness, proxy support, and redirection among others. Despite supplying a reasonably large number of helpful methods Koa maintains a small footprint, as no middleware are bundled.
The obligatory hello world application:
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
Cascading
Koa middleware cascade in a more traditional way as you may be used to with similar tools - this was previously difficult to make user friendly with node's use of callbacks. However with async functions we can achieve "true" middleware. Contrasting Connect's implementation which simply passes control through series of functions until one returns, Koa invoke "downstream", then control flows back "upstream".
The following example responds with "Hello World", however first the request flows through
the x-response-time
and logging
middleware to mark when the request started, then continue
to yield control through the response middleware. When a middleware invokes next()
the function suspends and passes control to the next middleware defined. After there are no more
middleware to execute downstream, the stack will unwind and each middleware is resumed to perform
its upstream behaviour.
const Koa = require('koa');
const app = new Koa();
// x-response-time
app.use(async function (ctx, next){
const start = new Date;
await next();
const ms = new Date - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// logger
app.use(async function (ctx, next){
const start = new Date;
await next();
const ms = new Date - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});
// response
app.use((ctx) => {
ctx.body = 'Hello World';
});
app.listen(3000);
Settings
Application settings are properties on the app
instance, currently
the following are supported:
app.name
optionally give your application a nameapp.env
defaulting to the NODE_ENV or "development"app.proxy
when true proxy header fields will be trustedapp.subdomainOffset
offset of.subdomains
to ignore [2]
app.listen(...)
A Koa application is not a 1-to-1 representation of a HTTP server. One or more Koa applications may be mounted together to form larger applications with a single HTTP server.
Create and return an HTTP server, passing the given arguments to
Server#listen()
. These arguments are documented on nodejs.org. The following is a useless Koa application bound to port 3000
:
const Koa = require('koa');
const app = new Koa();
app.listen(3000);
The app.listen(...)
method is simply sugar for the following:
const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
This means you can spin up the same application as both HTTP and HTTPS or on multiple addresses:
const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
http.createServer(app.callback()).listen(3001);
app.callback()
Return a callback function suitable for the http.createServer()
method to handle a request.
You may also use this callback function to mount your koa app in a
Connect/Express app.
app.use(function)
Add the given middleware function to this application. See Middleware for more information.
app.keys=
Set signed cookie keys.
These are passed to KeyGrip,
however you may also pass your own KeyGrip
instance. For
example the following are acceptable:
app.keys = ['im a newer secret', 'i like turtle'];
app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
These keys may be rotated and are used when signing cookies
with the { signed: true }
option:
this.cookies.set('name', 'tobi', { signed: true });
app.context
The recommended namespace to extend with information that's useful throughout the lifetime of your application, as opposed to a per request basis.
app.context.db = db();
Error Handling
By default outputs all errors to stderr unless NODE_ENV is "test" or app.silent
is true
.
The default error handler also won't outputs errors when err.status
is 404
or err.expose
is true
.
To perform custom error-handling logic such as centralized logging you can add an "error" event listener:
app.on('error', function(err){
log.error('server error', err);
});
If an error is in the req/res cycle and it is not possible to respond to the client, the Context
instance is also passed:
app.on('error', function(err, ctx){
log.error('server error', err, ctx);
});
When an error occurs and it is still possible to respond to the client, aka no data has been written to the socket, Koa will respond appropriately with a 500 "Internal Server Error". In either case an app-level "error" is emitted for logging purposes.