1 | <img src="/docs/logo.png" alt="Koa middleware framework for nodejs"/>
|
2 |
|
3 | [![gitter][gitter-image]][gitter-url]
|
4 | [![NPM version][npm-image]][npm-url]
|
5 | [![build status][travis-image]][travis-url]
|
6 | [![Test coverage][coveralls-image]][coveralls-url]
|
7 | [![OpenCollective Backers][backers-image]](#backers)
|
8 | [![OpenCollective Sponsors][sponsors-image]](#sponsors)
|
9 | [![PR's Welcome][pr-welcoming-image]][pr-welcoming-url]
|
10 |
|
11 | Expressive HTTP middleware framework for node.js to make web applications and APIs more enjoyable to write. Koa's middleware stack flows in a stack-like manner, allowing you to perform actions downstream then filter and manipulate the response upstream.
|
12 |
|
13 | Only methods that are common to nearly all HTTP servers are integrated directly into Koa's small ~570 SLOC codebase. This
|
14 | includes things like content negotiation, normalization of node inconsistencies, redirection, and a few others.
|
15 |
|
16 | Koa is not bundled with any middleware.
|
17 |
|
18 | ## Installation
|
19 |
|
20 | Koa requires __node v7.6.0__ or higher for ES2015 and async function support.
|
21 |
|
22 | ```
|
23 | $ npm install koa
|
24 | ```
|
25 |
|
26 | ## Hello Koa
|
27 |
|
28 | ```js
|
29 | const Koa = require('koa');
|
30 | const app = new Koa();
|
31 |
|
32 | // response
|
33 | app.use(ctx => {
|
34 | ctx.body = 'Hello Koa';
|
35 | });
|
36 |
|
37 | app.listen(3000);
|
38 | ```
|
39 |
|
40 | ## Getting started
|
41 |
|
42 | - [Kick-Off-Koa](https://github.com/koajs/kick-off-koa) - An intro to Koa via a set of self-guided workshops.
|
43 | - [Workshop](https://github.com/koajs/workshop) - A workshop to learn the basics of Koa, Express' spiritual successor.
|
44 | - [Introduction Screencast](https://knowthen.com/episode-3-koajs-quickstart-guide/) - An introduction to installing and getting started with Koa
|
45 |
|
46 |
|
47 | ## Middleware
|
48 |
|
49 | Koa is a middleware framework that can take two different kinds of functions as middleware:
|
50 |
|
51 | * async function
|
52 | * common function
|
53 |
|
54 | Here is an example of logger middleware with each of the different functions:
|
55 |
|
56 | ### ___async___ functions (node v7.6+)
|
57 |
|
58 | ```js
|
59 | app.use(async (ctx, next) => {
|
60 | const start = Date.now();
|
61 | await next();
|
62 | const ms = Date.now() - start;
|
63 | console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
|
64 | });
|
65 | ```
|
66 |
|
67 | ### Common function
|
68 |
|
69 | ```js
|
70 | // Middleware normally takes two parameters (ctx, next), ctx is the context for one request,
|
71 | // next is a function that is invoked to execute the downstream middleware. It returns a Promise with a then function for running code after completion.
|
72 |
|
73 | app.use((ctx, next) => {
|
74 | const start = Date.now();
|
75 | return next().then(() => {
|
76 | const ms = Date.now() - start;
|
77 | console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
|
78 | });
|
79 | });
|
80 | ```
|
81 |
|
82 | ### Koa v1.x Middleware Signature
|
83 |
|
84 | The middleware signature changed between v1.x and v2.x. The older signature is deprecated.
|
85 |
|
86 | **Old signature middleware support will be removed in v3**
|
87 |
|
88 | Please see the [Migration Guide](docs/migration.md) for more information on upgrading from v1.x and
|
89 | using v1.x middleware with v2.x.
|
90 |
|
91 | ## Context, Request and Response
|
92 |
|
93 | Each middleware receives a Koa `Context` object that encapsulates an incoming
|
94 | http message and the corresponding response to that message. `ctx` is often used
|
95 | as the parameter name for the context object.
|
96 |
|
97 | ```js
|
98 | app.use(async (ctx, next) => { await next(); });
|
99 | ```
|
100 |
|
101 | Koa provides a `Request` object as the `request` property of the `Context`.
|
102 | Koa's `Request` object provides helpful methods for working with
|
103 | http requests which delegate to an [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
|
104 | from the node `http` module.
|
105 |
|
106 | Here is an example of checking that a requesting client supports xml.
|
107 |
|
108 | ```js
|
109 | app.use(async (ctx, next) => {
|
110 | ctx.assert(ctx.request.accepts('xml'), 406);
|
111 | // equivalent to:
|
112 | // if (!ctx.request.accepts('xml')) ctx.throw(406);
|
113 | await next();
|
114 | });
|
115 | ```
|
116 |
|
117 | Koa provides a `Response` object as the `response` property of the `Context`.
|
118 | Koa's `Response` object provides helpful methods for working with
|
119 | http responses which delegate to a [ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse)
|
120 | .
|
121 |
|
122 | Koa's pattern of delegating to Node's request and response objects rather than extending them
|
123 | provides a cleaner interface and reduces conflicts between different middleware and with Node
|
124 | itself as well as providing better support for stream handling. The `IncomingMessage` can still be
|
125 | directly accessed as the `req` property on the `Context` and `ServerResponse` can be directly
|
126 | accessed as the `res` property on the `Context`.
|
127 |
|
128 | Here is an example using Koa's `Response` object to stream a file as the response body.
|
129 |
|
130 | ```js
|
131 | app.use(async (ctx, next) => {
|
132 | await next();
|
133 | ctx.response.type = 'xml';
|
134 | ctx.response.body = fs.createReadStream('really_large.xml');
|
135 | });
|
136 | ```
|
137 |
|
138 | The `Context` object also provides shortcuts for methods on its `request` and `response`. In the prior
|
139 | examples, `ctx.type` can be used instead of `ctx.response.type` and `ctx.accepts` can be used
|
140 | instead of `ctx.request.accepts`.
|
141 |
|
142 | For more information on `Request`, `Response` and `Context`, see the [Request API Reference](docs/api/request.md),
|
143 | [Response API Reference](docs/api/response.md) and [Context API Reference](docs/api/context.md).
|
144 |
|
145 | ## Koa Application
|
146 |
|
147 | The object created when executing `new Koa()` is known as the Koa application object.
|
148 |
|
149 | The application object is Koa's interface with node's http server and handles the registration
|
150 | of middleware, dispatching to the middleware from http, default error handling, as well as
|
151 | configuration of the context, request and response objects.
|
152 |
|
153 | Learn more about the application object in the [Application API Reference](docs/api/index.md).
|
154 |
|
155 | ## Documentation
|
156 |
|
157 | - [Usage Guide](docs/guide.md)
|
158 | - [Error Handling](docs/error-handling.md)
|
159 | - [Koa for Express Users](docs/koa-vs-express.md)
|
160 | - [FAQ](docs/faq.md)
|
161 | - [API documentation](docs/api/index.md)
|
162 |
|
163 | ## Babel setup
|
164 |
|
165 | If you're not using `node v7.6+`, we recommend setting up `babel` with [`@babel/preset-env`](https://babeljs.io/docs/en/next/babel-preset-env):
|
166 |
|
167 | ```bash
|
168 | $ npm install @babel/register @babel/preset-env @babel/cli --save-dev
|
169 | ```
|
170 |
|
171 | In development, you'll want to use [`@babel/register`](https://babeljs.io/docs/en/next/babel-register):
|
172 |
|
173 | ```bash
|
174 | node --require @babel/register <your-entry-file>
|
175 | ```
|
176 |
|
177 | In production, you'll want to build your files with [`@babel/cli`](https://babeljs.io/docs/en/babel-cli). Suppose you are compiling a folder `src` and you wanted the output to go to a new folder `dist` with non-javascript files copied:
|
178 |
|
179 | ```bash
|
180 | babel src --out-dir dist --copy-files
|
181 | ```
|
182 |
|
183 | And have your `.babelrc` setup:
|
184 |
|
185 | ```json
|
186 | {
|
187 | "presets": [
|
188 | ["@babel/preset-env", {
|
189 | "targets": {
|
190 | "node": true
|
191 | }
|
192 | }]
|
193 | ]
|
194 | }
|
195 | ```
|
196 |
|
197 | ## Troubleshooting
|
198 |
|
199 | Check the [Troubleshooting Guide](docs/troubleshooting.md) or [Debugging Koa](docs/guide.md#debugging-koa) in
|
200 | the general Koa guide.
|
201 |
|
202 | ## Running tests
|
203 |
|
204 | ```
|
205 | $ npm test
|
206 | ```
|
207 |
|
208 | ## Reporting vulnerabilities
|
209 |
|
210 | To report a security vulnerability, please do not open an issue, as this notifies attackers
|
211 | of the vulnerability. Instead, please email [dead_horse](mailto:heyiyu.deadhorse@gmail.com) and [jonathanong](mailto:me@jongleberry.com) to
|
212 | disclose.
|
213 |
|
214 | ## Authors
|
215 |
|
216 | See [AUTHORS](AUTHORS).
|
217 |
|
218 | ## Community
|
219 |
|
220 | - [Badgeboard](https://koajs.github.io/badgeboard) and list of official modules
|
221 | - [Examples](https://github.com/koajs/examples)
|
222 | - [Middleware](https://github.com/koajs/koa/wiki) list
|
223 | - [Wiki](https://github.com/koajs/koa/wiki)
|
224 | - [G+ Community](https://plus.google.com/communities/101845768320796750641)
|
225 | - [Reddit Community](https://www.reddit.com/r/koajs)
|
226 | - [Mailing list](https://groups.google.com/forum/#!forum/koajs)
|
227 | - [中文文档 v1.x](https://github.com/guo-yu/koa-guide)
|
228 | - [中文文档 v2.x](https://github.com/demopark/koa-docs-Zh-CN)
|
229 | - __[#koajs]__ on freenode
|
230 |
|
231 | ## Job Board
|
232 |
|
233 | Looking for a career upgrade?
|
234 |
|
235 | <a href="https://astro.netlify.com/automattic"><img src="https://astro.netlify.com/static/automattic.png"></a>
|
236 | <a href="https://astro.netlify.com/segment"><img src="https://astro.netlify.com/static/segment.png"></a>
|
237 | <a href="https://astro.netlify.com/auth0"><img src="https://astro.netlify.com/static/auth0.png"/></a>
|
238 |
|
239 | ## Backers
|
240 |
|
241 | Support us with a monthly donation and help us continue our activities.
|
242 |
|
243 | <a href="https://opencollective.com/koajs/backer/0/website" target="_blank"><img src="https://opencollective.com/koajs/backer/0/avatar.svg"></a>
|
244 | <a href="https://opencollective.com/koajs/backer/1/website" target="_blank"><img src="https://opencollective.com/koajs/backer/1/avatar.svg"></a>
|
245 | <a href="https://opencollective.com/koajs/backer/2/website" target="_blank"><img src="https://opencollective.com/koajs/backer/2/avatar.svg"></a>
|
246 | <a href="https://opencollective.com/koajs/backer/3/website" target="_blank"><img src="https://opencollective.com/koajs/backer/3/avatar.svg"></a>
|
247 | <a href="https://opencollective.com/koajs/backer/4/website" target="_blank"><img src="https://opencollective.com/koajs/backer/4/avatar.svg"></a>
|
248 | <a href="https://opencollective.com/koajs/backer/5/website" target="_blank"><img src="https://opencollective.com/koajs/backer/5/avatar.svg"></a>
|
249 | <a href="https://opencollective.com/koajs/backer/6/website" target="_blank"><img src="https://opencollective.com/koajs/backer/6/avatar.svg"></a>
|
250 | <a href="https://opencollective.com/koajs/backer/7/website" target="_blank"><img src="https://opencollective.com/koajs/backer/7/avatar.svg"></a>
|
251 | <a href="https://opencollective.com/koajs/backer/8/website" target="_blank"><img src="https://opencollective.com/koajs/backer/8/avatar.svg"></a>
|
252 | <a href="https://opencollective.com/koajs/backer/9/website" target="_blank"><img src="https://opencollective.com/koajs/backer/9/avatar.svg"></a>
|
253 | <a href="https://opencollective.com/koajs/backer/10/website" target="_blank"><img src="https://opencollective.com/koajs/backer/10/avatar.svg"></a>
|
254 | <a href="https://opencollective.com/koajs/backer/11/website" target="_blank"><img src="https://opencollective.com/koajs/backer/11/avatar.svg"></a>
|
255 | <a href="https://opencollective.com/koajs/backer/12/website" target="_blank"><img src="https://opencollective.com/koajs/backer/12/avatar.svg"></a>
|
256 | <a href="https://opencollective.com/koajs/backer/13/website" target="_blank"><img src="https://opencollective.com/koajs/backer/13/avatar.svg"></a>
|
257 | <a href="https://opencollective.com/koajs/backer/14/website" target="_blank"><img src="https://opencollective.com/koajs/backer/14/avatar.svg"></a>
|
258 | <a href="https://opencollective.com/koajs/backer/15/website" target="_blank"><img src="https://opencollective.com/koajs/backer/15/avatar.svg"></a>
|
259 | <a href="https://opencollective.com/koajs/backer/16/website" target="_blank"><img src="https://opencollective.com/koajs/backer/16/avatar.svg"></a>
|
260 | <a href="https://opencollective.com/koajs/backer/17/website" target="_blank"><img src="https://opencollective.com/koajs/backer/17/avatar.svg"></a>
|
261 | <a href="https://opencollective.com/koajs/backer/18/website" target="_blank"><img src="https://opencollective.com/koajs/backer/18/avatar.svg"></a>
|
262 | <a href="https://opencollective.com/koajs/backer/19/website" target="_blank"><img src="https://opencollective.com/koajs/backer/19/avatar.svg"></a>
|
263 | <a href="https://opencollective.com/koajs/backer/20/website" target="_blank"><img src="https://opencollective.com/koajs/backer/20/avatar.svg"></a>
|
264 | <a href="https://opencollective.com/koajs/backer/21/website" target="_blank"><img src="https://opencollective.com/koajs/backer/21/avatar.svg"></a>
|
265 | <a href="https://opencollective.com/koajs/backer/22/website" target="_blank"><img src="https://opencollective.com/koajs/backer/22/avatar.svg"></a>
|
266 | <a href="https://opencollective.com/koajs/backer/23/website" target="_blank"><img src="https://opencollective.com/koajs/backer/23/avatar.svg"></a>
|
267 | <a href="https://opencollective.com/koajs/backer/24/website" target="_blank"><img src="https://opencollective.com/koajs/backer/24/avatar.svg"></a>
|
268 | <a href="https://opencollective.com/koajs/backer/25/website" target="_blank"><img src="https://opencollective.com/koajs/backer/25/avatar.svg"></a>
|
269 | <a href="https://opencollective.com/koajs/backer/26/website" target="_blank"><img src="https://opencollective.com/koajs/backer/26/avatar.svg"></a>
|
270 | <a href="https://opencollective.com/koajs/backer/27/website" target="_blank"><img src="https://opencollective.com/koajs/backer/27/avatar.svg"></a>
|
271 | <a href="https://opencollective.com/koajs/backer/28/website" target="_blank"><img src="https://opencollective.com/koajs/backer/28/avatar.svg"></a>
|
272 | <a href="https://opencollective.com/koajs/backer/29/website" target="_blank"><img src="https://opencollective.com/koajs/backer/29/avatar.svg"></a>
|
273 |
|
274 |
|
275 | ## Sponsors
|
276 |
|
277 | Become a sponsor and get your logo on our README on Github with a link to your site.
|
278 |
|
279 | <a href="https://opencollective.com/koajs/sponsor/0/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/0/avatar.svg"></a>
|
280 | <a href="https://opencollective.com/koajs/sponsor/1/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/1/avatar.svg"></a>
|
281 | <a href="https://opencollective.com/koajs/sponsor/2/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/2/avatar.svg"></a>
|
282 | <a href="https://opencollective.com/koajs/sponsor/3/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/3/avatar.svg"></a>
|
283 | <a href="https://opencollective.com/koajs/sponsor/4/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/4/avatar.svg"></a>
|
284 | <a href="https://opencollective.com/koajs/sponsor/5/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/5/avatar.svg"></a>
|
285 | <a href="https://opencollective.com/koajs/sponsor/6/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/6/avatar.svg"></a>
|
286 | <a href="https://opencollective.com/koajs/sponsor/7/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/7/avatar.svg"></a>
|
287 | <a href="https://opencollective.com/koajs/sponsor/8/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/8/avatar.svg"></a>
|
288 | <a href="https://opencollective.com/koajs/sponsor/9/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/9/avatar.svg"></a>
|
289 | <a href="https://opencollective.com/koajs/sponsor/10/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/10/avatar.svg"></a>
|
290 | <a href="https://opencollective.com/koajs/sponsor/11/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/11/avatar.svg"></a>
|
291 | <a href="https://opencollective.com/koajs/sponsor/12/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/12/avatar.svg"></a>
|
292 | <a href="https://opencollective.com/koajs/sponsor/13/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/13/avatar.svg"></a>
|
293 | <a href="https://opencollective.com/koajs/sponsor/14/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/14/avatar.svg"></a>
|
294 | <a href="https://opencollective.com/koajs/sponsor/15/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/15/avatar.svg"></a>
|
295 | <a href="https://opencollective.com/koajs/sponsor/16/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/16/avatar.svg"></a>
|
296 | <a href="https://opencollective.com/koajs/sponsor/17/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/17/avatar.svg"></a>
|
297 | <a href="https://opencollective.com/koajs/sponsor/18/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/18/avatar.svg"></a>
|
298 | <a href="https://opencollective.com/koajs/sponsor/19/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/19/avatar.svg"></a>
|
299 | <a href="https://opencollective.com/koajs/sponsor/20/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/20/avatar.svg"></a>
|
300 | <a href="https://opencollective.com/koajs/sponsor/21/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/21/avatar.svg"></a>
|
301 | <a href="https://opencollective.com/koajs/sponsor/22/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/22/avatar.svg"></a>
|
302 | <a href="https://opencollective.com/koajs/sponsor/23/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/23/avatar.svg"></a>
|
303 | <a href="https://opencollective.com/koajs/sponsor/24/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/24/avatar.svg"></a>
|
304 | <a href="https://opencollective.com/koajs/sponsor/25/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/25/avatar.svg"></a>
|
305 | <a href="https://opencollective.com/koajs/sponsor/26/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/26/avatar.svg"></a>
|
306 | <a href="https://opencollective.com/koajs/sponsor/27/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/27/avatar.svg"></a>
|
307 | <a href="https://opencollective.com/koajs/sponsor/28/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/28/avatar.svg"></a>
|
308 | <a href="https://opencollective.com/koajs/sponsor/29/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/29/avatar.svg"></a>
|
309 |
|
310 | # License
|
311 |
|
312 | [MIT](https://github.com/koajs/koa/blob/master/LICENSE)
|
313 |
|
314 | [npm-image]: https://img.shields.io/npm/v/koa.svg?style=flat-square
|
315 | [npm-url]: https://www.npmjs.com/package/koa
|
316 | [travis-image]: https://img.shields.io/travis/koajs/koa/master.svg?style=flat-square
|
317 | [travis-url]: https://travis-ci.org/koajs/koa
|
318 | [coveralls-image]: https://img.shields.io/codecov/c/github/koajs/koa.svg?style=flat-square
|
319 | [coveralls-url]: https://codecov.io/github/koajs/koa?branch=master
|
320 | [backers-image]: https://opencollective.com/koajs/backers/badge.svg?style=flat-square
|
321 | [sponsors-image]: https://opencollective.com/koajs/sponsors/badge.svg?style=flat-square
|
322 | [gitter-image]: https://img.shields.io/gitter/room/koajs/koa.svg?style=flat-square
|
323 | [gitter-url]: https://gitter.im/koajs/koa?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
324 | [#koajs]: https://webchat.freenode.net/?channels=#koajs
|
325 | [pr-welcoming-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
326 | [pr-welcoming-url]: https://github.com/koajs/koa/pull/new
|