Skip to content

Commit 2b094eb

Browse files
committedMar 22, 2016
docs: update history and docs for v2
1 parent daf688b commit 2b094eb

File tree

6 files changed

+140
-95
lines changed

6 files changed

+140
-95
lines changed
 

‎History.md

+29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,33 @@
11

2+
2.0.0 /
3+
==================
4+
5+
* merge v1.1.2 and v1.2.0 changes
6+
* include `koa-convert` so that generator functions still work
7+
* NOTE: generator functions are deprecated in v2 and will be removed in v3
8+
* improve linting
9+
* improve docs
10+
11+
1.2.0 / 2016-03-03
12+
==================
13+
14+
* add support for `err.headers` in `ctx.onerror()`
15+
- see: https://github.com/koajs/koa/pull/668
16+
- note: you should set these headers in your custom error handlers as well
17+
- docs: https://github.com/koajs/koa/blob/master/docs/error-handling.md
18+
* fix `cookies`' detection of http/https
19+
- see: https://github.com/koajs/koa/pull/614
20+
* deprecate `app.experimental = true`. Koa v2 does not use this signature.
21+
* add a code of conduct
22+
* test against the latest version of node
23+
* add a lot of docs
24+
25+
1.1.2 / 2015-11-05
26+
==================
27+
28+
* ensure parseurl always working as expected
29+
* fix Application.inspect() – missing .proxy value.
30+
231
2.0.0-alpha.3 / 2015-11-05
332
==================
433

‎docs/api/context.md

+15-15
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
which would force middleware to re-implement this common functionality.
99

1010
A `Context` is created _per_ request, and is referenced in middleware
11-
as the receiver, or the `this` identifier, as shown in the following
11+
as the receiver, or the `ctx` identifier, as shown in the following
1212
snippet:
1313

1414
```js
15-
app.use(function * () {
16-
this; // is the Context
17-
this.request; // is a koa Request
18-
this.response; // is a koa Response
15+
app.use(async (ctx, next) => {
16+
ctx; // is the Context
17+
ctx.request; // is a koa Request
18+
ctx.response; // is a koa Response
1919
});
2020
```
2121

@@ -55,7 +55,7 @@ app.use(function * () {
5555
The recommended namespace for passing information through middleware and to your frontend views.
5656

5757
```js
58-
this.state.user = yield User.find(id);
58+
ctx.state.user = yield User.find(id);
5959
```
6060

6161
### ctx.app
@@ -90,13 +90,13 @@ koa uses the [cookies](https://github.com/jed/cookies) module where options are
9090
The following combinations are allowed:
9191

9292
```js
93-
this.throw(403);
94-
this.throw('name required', 400);
95-
this.throw(400, 'name required');
96-
this.throw('something exploded');
93+
ctx.throw(403);
94+
ctx.throw('name required', 400);
95+
ctx.throw(400, 'name required');
96+
ctx.throw('something exploded');
9797
```
9898

99-
For example `this.throw('name required', 400)` is equivalent to:
99+
For example `ctx.throw('name required', 400)` is equivalent to:
100100

101101
```js
102102
const err = new Error('name required');
@@ -113,8 +113,8 @@ throw err;
113113
You may optionally pass a `properties` object which is merged into the error as-is, useful for decorating machine-friendly errors which are reported to the requester upstream.
114114

115115
```js
116-
this.throw(401, 'access_denied', { user: user });
117-
this.throw('access_denied', { user: user });
116+
ctx.throw(401, 'access_denied', { user: user });
117+
ctx.throw('access_denied', { user: user });
118118
```
119119

120120
koa uses [http-errors](https://github.com/jshttp/http-errors) to create errors.
@@ -126,14 +126,14 @@ koa uses [http-errors](https://github.com/jshttp/http-errors) to create errors.
126126
method.
127127

128128
```js
129-
this.assert(this.state.user, 401, 'User not found. Please login!');
129+
ctx.assert(ctx.state.user, 401, 'User not found. Please login!');
130130
```
131131

132132
koa uses [http-assert](https://github.com/jshttp/http-assert) for assertions.
133133

134134
### ctx.respond
135135

136-
To bypass Koa's built-in response handling, you may explicitly set `this.respond = false;`. Use this if you want to write to the raw `res` object instead of letting Koa handle the response for you.
136+
To bypass Koa's built-in response handling, you may explicitly set `ctx.respond = false;`. Use this if you want to write to the raw `res` object instead of letting Koa handle the response for you.
137137

138138
Note that using this is __not__ supported by Koa. This may break intended functionality of Koa middleware and Koa itself. Using this property is considered a hack and is only a convenience to those wishing to use traditional `fn(req, res)` functions and middleware within Koa.
139139

‎docs/api/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
179179
with the `{ signed: true }` option:
180180

181181
```js
182-
this.cookies.set('name', 'tobi', { signed: true });
182+
ctx.cookies.set('name', 'tobi', { signed: true });
183183
```
184184

185185
## app.context

‎docs/api/request.md

+45-45
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
Get origin of URL, include `protocol` and `host`.
4545

4646
```js
47-
this.request.origin
47+
ctx.request.origin
4848
// => http://example.com
4949
```
5050

@@ -53,7 +53,7 @@ this.request.origin
5353
Get full request URL, include `protocol`, `host` and `url`.
5454

5555
```js
56-
this.request.href
56+
ctx.request.href
5757
// => http://example.com/foo/bar?q=1
5858
```
5959

@@ -96,7 +96,7 @@ this.request.href
9696
Get request `Content-Type` void of parameters such as "charset".
9797

9898
```js
99-
const ct = this.request.type
99+
const ct = ctx.request.type
100100
// => "image/png"
101101
```
102102

@@ -105,7 +105,7 @@ const ct = this.request.type
105105
Get request charset when present, or `undefined`:
106106

107107
```js
108-
this.request.charset
108+
ctx.request.charset
109109
// => "utf-8"
110110
```
111111

@@ -130,7 +130,7 @@ this.request.charset
130130
setter does _not_ support nested objects.
131131

132132
```js
133-
this.query = { next: '/login' }
133+
ctx.query = { next: '/login' }
134134
```
135135

136136
### request.fresh
@@ -140,18 +140,18 @@ this.query = { next: '/login' }
140140

141141
```js
142142
// freshness check requires status 20x or 304
143-
this.status = 200;
144-
this.set('ETag', '123');
143+
ctx.status = 200;
144+
ctx.set('ETag', '123');
145145

146146
// cache is ok
147-
if (this.fresh) {
148-
this.status = 304;
147+
if (ctx.fresh) {
148+
ctx.status = 304;
149149
return;
150150
}
151151

152152
// cache is stale
153153
// fetch new data
154-
this.body = yield db.find('something');
154+
ctx.body = yield db.find('something');
155155
```
156156

157157
### request.stale
@@ -165,7 +165,7 @@ this.body = yield db.find('something');
165165

166166
### request.secure
167167

168-
Shorthand for `this.protocol == "https"` to check if a request was
168+
Shorthand for `ctx.protocol == "https"` to check if a request was
169169
issued via TLS.
170170

171171
### request.ip
@@ -188,8 +188,8 @@ this.body = yield db.find('something');
188188
parts of the host. This can be changed by setting `app.subdomainOffset`.
189189

190190
For example, if the domain is "tobi.ferrets.example.com":
191-
If `app.subdomainOffset` is not set, this.subdomains is `["ferrets", "tobi"]`.
192-
If `app.subdomainOffset` is 3, this.subdomains is `["tobi"]`.
191+
If `app.subdomainOffset` is not set, `ctx.subdomains` is `["ferrets", "tobi"]`.
192+
If `app.subdomainOffset` is 3, `ctx.subdomains` is `["tobi"]`.
193193

194194
### request.is(types...)
195195

@@ -201,26 +201,26 @@ this.body = yield db.find('something');
201201

202202
```js
203203
// With Content-Type: text/html; charset=utf-8
204-
this.is('html'); // => 'html'
205-
this.is('text/html'); // => 'text/html'
206-
this.is('text/*', 'text/html'); // => 'text/html'
204+
ctx.is('html'); // => 'html'
205+
ctx.is('text/html'); // => 'text/html'
206+
ctx.is('text/*', 'text/html'); // => 'text/html'
207207

208208
// When Content-Type is application/json
209-
this.is('json', 'urlencoded'); // => 'json'
210-
this.is('application/json'); // => 'application/json'
211-
this.is('html', 'application/*'); // => 'application/json'
209+
ctx.is('json', 'urlencoded'); // => 'json'
210+
ctx.is('application/json'); // => 'application/json'
211+
ctx.is('html', 'application/*'); // => 'application/json'
212212

213-
this.is('html'); // => false
213+
ctx.is('html'); // => false
214214
```
215215

216216
For example if you want to ensure that
217217
only images are sent to a given route:
218218

219219
```js
220-
if (this.is('image/*')) {
220+
if (ctx.is('image/*')) {
221221
// process
222222
} else {
223-
this.throw(415, 'images only!');
223+
ctx.throw(415, 'images only!');
224224
}
225225
```
226226

@@ -247,45 +247,45 @@ In the case of missing accept headers where any type is acceptable, the first ty
247247

248248
```js
249249
// Accept: text/html
250-
this.accepts('html');
250+
ctx.accepts('html');
251251
// => "html"
252252

253253
// Accept: text/*, application/json
254-
this.accepts('html');
254+
ctx.accepts('html');
255255
// => "html"
256-
this.accepts('text/html');
256+
ctx.accepts('text/html');
257257
// => "text/html"
258-
this.accepts('json', 'text');
258+
ctx.accepts('json', 'text');
259259
// => "json"
260-
this.accepts('application/json');
260+
ctx.accepts('application/json');
261261
// => "application/json"
262262

263263
// Accept: text/*, application/json
264-
this.accepts('image/png');
265-
this.accepts('png');
264+
ctx.accepts('image/png');
265+
ctx.accepts('png');
266266
// => false
267267

268268
// Accept: text/*;q=.5, application/json
269-
this.accepts(['html', 'json']);
270-
this.accepts('html', 'json');
269+
ctx.accepts(['html', 'json']);
270+
ctx.accepts('html', 'json');
271271
// => "json"
272272

273273
// No Accept header
274-
this.accepts('html', 'json');
274+
ctx.accepts('html', 'json');
275275
// => "html"
276-
this.accepts('json', 'html');
276+
ctx.accepts('json', 'html');
277277
// => "json"
278278
```
279279

280-
You may call `this.accepts()` as many times as you like,
280+
You may call `ctx.accepts()` as many times as you like,
281281
or use a switch:
282282

283283
```js
284-
switch (this.accepts('json', 'html', 'text')) {
284+
switch (ctx.accepts('json', 'html', 'text')) {
285285
case 'json': break;
286286
case 'html': break;
287287
case 'text': break;
288-
default: this.throw(406, 'json, html, or text only');
288+
default: ctx.throw(406, 'json, html, or text only');
289289
}
290290
```
291291

@@ -295,10 +295,10 @@ switch (this.accepts('json', 'html', 'text')) {
295295

296296
```js
297297
// Accept-Encoding: gzip
298-
this.acceptsEncodings('gzip', 'deflate', 'identity');
298+
ctx.acceptsEncodings('gzip', 'deflate', 'identity');
299299
// => "gzip"
300300

301-
this.acceptsEncodings(['gzip', 'deflate', 'identity']);
301+
ctx.acceptsEncodings(['gzip', 'deflate', 'identity']);
302302
// => "gzip"
303303
```
304304

@@ -307,7 +307,7 @@ this.acceptsEncodings(['gzip', 'deflate', 'identity']);
307307

308308
```js
309309
// Accept-Encoding: gzip, deflate
310-
this.acceptsEncodings();
310+
ctx.acceptsEncodings();
311311
// => ["gzip", "deflate", "identity"]
312312
```
313313

@@ -320,10 +320,10 @@ this.acceptsEncodings();
320320

321321
```js
322322
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
323-
this.acceptsCharsets('utf-8', 'utf-7');
323+
ctx.acceptsCharsets('utf-8', 'utf-7');
324324
// => "utf-8"
325325

326-
this.acceptsCharsets(['utf-7', 'utf-8']);
326+
ctx.acceptsCharsets(['utf-7', 'utf-8']);
327327
// => "utf-8"
328328
```
329329

@@ -332,7 +332,7 @@ this.acceptsCharsets(['utf-7', 'utf-8']);
332332

333333
```js
334334
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
335-
this.acceptsCharsets();
335+
ctx.acceptsCharsets();
336336
// => ["utf-8", "utf-7", "iso-8859-1"]
337337
```
338338

@@ -343,10 +343,10 @@ this.acceptsCharsets();
343343

344344
```js
345345
// Accept-Language: en;q=0.8, es, pt
346-
this.acceptsLanguages('es', 'en');
346+
ctx.acceptsLanguages('es', 'en');
347347
// => "es"
348348

349-
this.acceptsLanguages(['en', 'es']);
349+
ctx.acceptsLanguages(['en', 'es']);
350350
// => "es"
351351
```
352352

@@ -355,7 +355,7 @@ this.acceptsLanguages(['en', 'es']);
355355

356356
```js
357357
// Accept-Language: en;q=0.8, es, pt
358-
this.acceptsLanguages();
358+
ctx.acceptsLanguages();
359359
// => ["es", "pt", "en"]
360360
```
361361

‎docs/api/response.md

+24-24
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ so you can make a correction.
104104
### response.length
105105

106106
Return response Content-Length as a number when present, or deduce
107-
from `this.body` when possible, or `undefined`.
107+
from `ctx.body` when possible, or `undefined`.
108108

109109
### response.body
110110

@@ -149,7 +149,7 @@ If `response.status` has not been set, Koa will automatically set the status to
149149
const PassThrough = require('stream').PassThrough;
150150

151151
app.use(function * (next) {
152-
this.body = someHTTPStream.on('error', this.onerror).pipe(PassThrough());
152+
ctx.body = someHTTPStream.on('error', ctx.onerror).pipe(PassThrough());
153153
});
154154
```
155155

@@ -162,30 +162,30 @@ app.use(function * (next) {
162162
Get a response header field value with case-insensitive `field`.
163163

164164
```js
165-
const etag = this.get('ETag');
165+
const etag = ctx.get('ETag');
166166
```
167167

168168
### response.set(field, value)
169169

170170
Set response header `field` to `value`:
171171

172172
```js
173-
this.set('Cache-Control', 'no-cache');
173+
ctx.set('Cache-Control', 'no-cache');
174174
```
175175

176176
### response.append(field, value)
177177
Append additional header `field` with value `val`.
178178

179179
```js
180-
this.append('Link', '<http://127.0.0.1/>');
180+
ctx.append('Link', '<http://127.0.0.1/>');
181181
```
182182

183183
### response.set(fields)
184184

185185
Set several response header `fields` with an object:
186186

187187
```js
188-
this.set({
188+
ctx.set({
189189
'Etag': '1234',
190190
'Last-Modified': date
191191
});
@@ -200,7 +200,7 @@ this.set({
200200
Get response `Content-Type` void of parameters such as "charset".
201201

202202
```js
203-
const ct = this.type;
203+
const ct = ctx.type;
204204
// => "image/png"
205205
```
206206

@@ -209,10 +209,10 @@ const ct = this.type;
209209
Set response `Content-Type` via mime string or file extension.
210210

211211
```js
212-
this.type = 'text/plain; charset=utf-8';
213-
this.type = 'image/png';
214-
this.type = '.png';
215-
this.type = 'png';
212+
ctx.type = 'text/plain; charset=utf-8';
213+
ctx.type = 'image/png';
214+
ctx.type = '.png';
215+
ctx.type = 'png';
216216
```
217217

218218
Note: when appropriate a `charset` is selected for you, for
@@ -222,7 +222,7 @@ this.type = 'png';
222222

223223
### response.is(types...)
224224

225-
Very similar to `this.request.is()`.
225+
Very similar to `ctx.request.is()`.
226226
Check whether the response type is one of the supplied types.
227227
This is particularly useful for creating middleware that
228228
manipulate responses.
@@ -236,13 +236,13 @@ const minify = require('html-minifier');
236236
app.use(function * minifyHTML(next) {
237237
yield next;
238238

239-
if (!this.response.is('html')) return;
239+
if (!ctx.response.is('html')) return;
240240

241-
let body = this.body;
241+
let body = ctx.body;
242242
if (!body || body.pipe) return;
243243

244244
if (Buffer.isBuffer(body)) body = body.toString();
245-
this.body = minify(body);
245+
ctx.body = minify(body);
246246
});
247247
```
248248

@@ -255,19 +255,19 @@ app.use(function * minifyHTML(next) {
255255
is not present `alt` or "/" is used.
256256

257257
```js
258-
this.redirect('back');
259-
this.redirect('back', '/index.html');
260-
this.redirect('/login');
261-
this.redirect('http://google.com');
258+
ctx.redirect('back');
259+
ctx.redirect('back', '/index.html');
260+
ctx.redirect('/login');
261+
ctx.redirect('http://google.com');
262262
```
263263

264264
To alter the default status of `302`, simply assign the status
265265
before or after this call. To alter the body, assign it after this call:
266266

267267
```js
268-
this.status = 301;
269-
this.redirect('/cart');
270-
this.body = 'Redirecting to shopping cart';
268+
ctx.status = 301;
269+
ctx.redirect('/cart');
270+
ctx.body = 'Redirecting to shopping cart';
271271
```
272272

273273
### response.attachment([filename])
@@ -291,7 +291,7 @@ this.body = 'Redirecting to shopping cart';
291291
You can either set it as a `Date` or date string.
292292

293293
```js
294-
this.response.lastModified = new Date();
294+
ctx.response.lastModified = new Date();
295295
```
296296

297297
### response.etag=
@@ -300,7 +300,7 @@ this.response.lastModified = new Date();
300300
Note that there is no corresponding `response.etag` getter.
301301

302302
```js
303-
this.response.etag = crypto.createHash('md5').update(this.body).digest('hex');
303+
ctx.response.etag = crypto.createHash('md5').update(ctx.body).digest('hex');
304304
```
305305

306306
### response.vary(field)

‎docs/error-handling.md

+26-10
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
## Try-Catch
44

5-
Using generators means that you can try-catch `next`. For example,
6-
this example prepends all error messages with "Error: "
5+
Using async functions means that you can try-catch `next`.
6+
This example adds a `.status` to all errors:
77

88
```js
99
app.use(async (ctx, next) => {
1010
try {
1111
await next();
12-
} catch (error) {
13-
error.message = 'Error: ' + error.message;
14-
throw error;
12+
} catch (err) {
13+
err.status = err.statusCode || err.status || 500;
14+
throw err;
1515
}
1616
});
1717
```
@@ -32,13 +32,29 @@
3232
will then be set. You can use a try-catch, as specified
3333
above, to add a header to this list.
3434

35+
Here is an example of creating your own error handler:
36+
37+
```js
38+
app.use(async (ctx, next) => {
39+
try {
40+
await next();
41+
} catch (err) {
42+
// will only respond with JSON
43+
this.status = err.statusCode || err.status || 500;
44+
this.body = {
45+
message: err.message
46+
};
47+
}
48+
})
49+
```
50+
3551
## The Error Event
3652

37-
Error handlers can be specified with `app.on('error')`.
38-
If no error handler is specified, a default error handler
39-
is used. Error handlers recieve all errors that make their
53+
Error event listeners can be specified with `app.on('error')`.
54+
If no error listener is specified, a default error listener
55+
is used. Error listener receive all errors that make their
4056
way back through the middleware chain, if an error is caught
41-
and not thrown again, it will not be handled by the error
42-
handler. If not error event handler is specified, then
57+
and not thrown again, it will not be passed to the error
58+
listener. If no error event listener is specified, then
4359
`app.onerror` will be used, which simply log the error if
4460
`error.expose` is true and `app.silent` is false.

0 commit comments

Comments
 (0)
Please sign in to comment.