koa 2.14.0 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![gitter][gitter-image]][gitter-url]
4
4
  [![NPM version][npm-image]][npm-url]
5
- [![build status][travis-image]][travis-url]
5
+ [![build status][github-action-image]][github-action-url]
6
6
  [![Test coverage][coveralls-image]][coveralls-url]
7
7
  [![OpenCollective Backers][backers-image]](#backers)
8
8
  [![OpenCollective Sponsors][sponsors-image]](#sponsors)
@@ -17,7 +17,7 @@
17
17
 
18
18
  ## Installation
19
19
 
20
- Koa requires __node v7.6.0__ or higher for ES2015 and async function support.
20
+ Koa requires __node v12.17.0__ or higher for ES2015 and async function support.
21
21
 
22
22
  ```
23
23
  $ npm install koa
@@ -40,9 +40,7 @@ app.listen(3000);
40
40
  ## Getting started
41
41
 
42
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
-
43
+ - [Guide](docs/guide.md) - Go straight to the docs.
46
44
 
47
45
  ## Middleware
48
46
 
@@ -181,6 +179,7 @@ See [AUTHORS](AUTHORS).
181
179
 
182
180
  ## Community
183
181
 
182
+ - [KoaJS Slack Group](https://join.slack.com/t/koa-js/shared_invite/zt-5pjgthmb-1JeKDbByqqcARtlPbtf~vQ)
184
183
  - [Badgeboard](https://koajs.github.io/badgeboard) and list of official modules
185
184
  - [Examples](https://github.com/koajs/examples)
186
185
  - [Middleware](https://github.com/koajs/koa/wiki) list
@@ -276,8 +275,8 @@ Become a sponsor and get your logo on our README on Github with a link to your s
276
275
 
277
276
  [npm-image]: https://img.shields.io/npm/v/koa.svg?style=flat-square
278
277
  [npm-url]: https://www.npmjs.com/package/koa
279
- [travis-image]: https://img.shields.io/travis/koajs/koa/master.svg?style=flat-square
280
- [travis-url]: https://travis-ci.org/koajs/koa
278
+ [github-action-image]: https://github.com/koajs/koa/actions/workflows/node.js.yml/badge.svg
279
+ [github-action-url]: https://github.com/koajs/koa/actions/workflows/node.js.yml
281
280
  [coveralls-image]: https://img.shields.io/codecov/c/github/koajs/koa.svg?style=flat-square
282
281
  [coveralls-url]: https://codecov.io/github/koajs/koa?branch=master
283
282
  [backers-image]: https://opencollective.com/koajs/backers/badge.svg?style=flat-square
@@ -1,27 +1,38 @@
1
1
 
2
- 'use strict';
2
+ 'use strict'
3
3
 
4
4
  /**
5
5
  * Module dependencies.
6
6
  */
7
7
 
8
- const isGeneratorFunction = require('is-generator-function');
9
- const debug = require('debug')('koa:application');
10
- const onFinished = require('on-finished');
11
- const assert = require('assert');
12
- const response = require('./response');
13
- const compose = require('koa-compose');
14
- const context = require('./context');
15
- const request = require('./request');
16
- const statuses = require('statuses');
17
- const Emitter = require('events');
18
- const util = require('util');
19
- const Stream = require('stream');
20
- const http = require('http');
21
- const only = require('only');
22
- const convert = require('koa-convert');
23
- const deprecate = require('depd')('koa');
24
- const { HttpError } = require('http-errors');
8
+ const debug = require('debug')('koa:application')
9
+ const assert = require('assert')
10
+ const onFinished = require('on-finished')
11
+ const response = require('./response')
12
+ const compose = require('koa-compose')
13
+ const context = require('./context')
14
+ const request = require('./request')
15
+ const statuses = require('statuses')
16
+ const Emitter = require('events')
17
+ const util = require('util')
18
+ const Stream = require('stream')
19
+ const http = require('http')
20
+ const only = require('only')
21
+ const { HttpError } = require('http-errors')
22
+
23
+ /** @typedef {typeof import ('./context') & {
24
+ * app: Application
25
+ * req: import('http').IncomingMessage
26
+ * res: import('http').ServerResponse
27
+ * request: KoaRequest
28
+ * response: KoaResponse
29
+ * state: any
30
+ * originalUrl: string
31
+ * }} Context */
32
+
33
+ /** @typedef {typeof import('./request')} KoaRequest */
34
+
35
+ /** @typedef {typeof import('./response')} KoaResponse */
25
36
 
26
37
  /**
27
38
  * Expose `Application` class.
@@ -47,29 +58,30 @@ module.exports = class Application extends Emitter {
47
58
  *
48
59
  */
49
60
 
50
- constructor(options) {
51
- super();
52
- options = options || {};
53
- this.proxy = options.proxy || false;
54
- this.subdomainOffset = options.subdomainOffset || 2;
55
- this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For';
56
- this.maxIpsCount = options.maxIpsCount || 0;
57
- this.env = options.env || process.env.NODE_ENV || 'development';
58
- if (options.keys) this.keys = options.keys;
59
- this.middleware = [];
60
- this.context = Object.create(context);
61
- this.request = Object.create(request);
62
- this.response = Object.create(response);
61
+ constructor (options) {
62
+ super()
63
+ options = options || {}
64
+ this.proxy = options.proxy || false
65
+ this.subdomainOffset = options.subdomainOffset || 2
66
+ this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For'
67
+ this.maxIpsCount = options.maxIpsCount || 0
68
+ this.env = options.env || process.env.NODE_ENV || 'development'
69
+ this.compose = options.compose || compose
70
+ if (options.keys) this.keys = options.keys
71
+ this.middleware = []
72
+ this.context = Object.create(context)
73
+ this.request = Object.create(request)
74
+ this.response = Object.create(response)
63
75
  // util.inspect.custom support for node 6+
64
76
  /* istanbul ignore else */
65
77
  if (util.inspect.custom) {
66
- this[util.inspect.custom] = this.inspect;
78
+ this[util.inspect.custom] = this.inspect
67
79
  }
68
80
  if (options.asyncLocalStorage) {
69
- const { AsyncLocalStorage } = require('async_hooks');
70
- assert(AsyncLocalStorage, 'Requires node 12.17.0 or higher to enable asyncLocalStorage');
71
- this.ctxStorage = new AsyncLocalStorage();
72
- this.use(createAsyncCtxStorage(this));
81
+ const { AsyncLocalStorage } = require('async_hooks')
82
+ assert(AsyncLocalStorage, 'Requires node 12.17.0 or higher to enable asyncLocalStorage')
83
+ this.ctxStorage = new AsyncLocalStorage()
84
+ this.use(this.createAsyncCtxStorageMiddleware())
73
85
  }
74
86
  }
75
87
 
@@ -79,14 +91,14 @@ module.exports = class Application extends Emitter {
79
91
  * http.createServer(app.callback()).listen(...)
80
92
  *
81
93
  * @param {Mixed} ...
82
- * @return {Server}
94
+ * @return {import('http').Server}
83
95
  * @api public
84
96
  */
85
97
 
86
- listen(...args) {
87
- debug('listen');
88
- const server = http.createServer(this.callback());
89
- return server.listen(...args);
98
+ listen (...args) {
99
+ debug('listen')
100
+ const server = http.createServer(this.callback())
101
+ return server.listen(...args)
90
102
  }
91
103
 
92
104
  /**
@@ -97,12 +109,12 @@ module.exports = class Application extends Emitter {
97
109
  * @api public
98
110
  */
99
111
 
100
- toJSON() {
112
+ toJSON () {
101
113
  return only(this, [
102
114
  'subdomainOffset',
103
115
  'proxy',
104
116
  'env'
105
- ]);
117
+ ])
106
118
  }
107
119
 
108
120
  /**
@@ -112,8 +124,8 @@ module.exports = class Application extends Emitter {
112
124
  * @api public
113
125
  */
114
126
 
115
- inspect() {
116
- return this.toJSON();
127
+ inspect () {
128
+ return this.toJSON()
117
129
  }
118
130
 
119
131
  /**
@@ -121,22 +133,16 @@ module.exports = class Application extends Emitter {
121
133
  *
122
134
  * Old-style middleware will be converted.
123
135
  *
124
- * @param {Function} fn
136
+ * @param {(context: Context) => Promise<any | void>} fn
125
137
  * @return {Application} self
126
138
  * @api public
127
139
  */
128
140
 
129
- use(fn) {
130
- if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
131
- if (isGeneratorFunction(fn)) {
132
- deprecate('Support for generators will be removed in v3. ' +
133
- 'See the documentation for examples of how to convert old middleware ' +
134
- 'https://github.com/koajs/koa/blob/master/docs/migration.md');
135
- fn = convert(fn);
136
- }
137
- debug('use %s', fn._name || fn.name || '-');
138
- this.middleware.push(fn);
139
- return this;
141
+ use (fn) {
142
+ if (typeof fn !== 'function') throw new TypeError('middleware must be a function!')
143
+ debug('use %s', fn._name || fn.name || '-')
144
+ this.middleware.push(fn)
145
+ return this
140
146
  }
141
147
 
142
148
  /**
@@ -147,24 +153,24 @@ module.exports = class Application extends Emitter {
147
153
  * @api public
148
154
  */
149
155
 
150
- callback() {
151
- const fn = compose(this.middleware);
156
+ callback () {
157
+ const fn = this.compose(this.middleware)
152
158
 
153
- if (!this.listenerCount('error')) this.on('error', this.onerror);
159
+ if (!this.listenerCount('error')) this.on('error', this.onerror)
154
160
 
155
161
  const handleRequest = (req, res) => {
156
- const ctx = this.createContext(req, res);
157
- return this.handleRequest(ctx, fn);
158
- };
162
+ const ctx = this.createContext(req, res)
163
+ return this.handleRequest(ctx, fn)
164
+ }
159
165
 
160
- return handleRequest;
166
+ return handleRequest
161
167
  }
162
168
 
163
169
  /**
164
- * return currnect contenxt from async local storage
170
+ * return current context from async local storage
165
171
  */
166
- get currentContext() {
167
- if (this.ctxStorage) return this.ctxStorage.getStore();
172
+ get currentContext () {
173
+ if (this.ctxStorage) return this.ctxStorage.getStore()
168
174
  }
169
175
 
170
176
  /**
@@ -173,13 +179,13 @@ module.exports = class Application extends Emitter {
173
179
  * @api private
174
180
  */
175
181
 
176
- handleRequest(ctx, fnMiddleware) {
177
- const res = ctx.res;
178
- res.statusCode = 404;
179
- const onerror = err => ctx.onerror(err);
180
- const handleResponse = () => respond(ctx);
181
- onFinished(res, onerror);
182
- return fnMiddleware(ctx).then(handleResponse).catch(onerror);
182
+ handleRequest (ctx, fnMiddleware) {
183
+ const res = ctx.res
184
+ res.statusCode = 404
185
+ const onerror = err => ctx.onerror(err)
186
+ const handleResponse = () => respond(ctx)
187
+ onFinished(res, onerror)
188
+ return fnMiddleware(ctx).then(handleResponse).catch(onerror)
183
189
  }
184
190
 
185
191
  /**
@@ -188,19 +194,22 @@ module.exports = class Application extends Emitter {
188
194
  * @api private
189
195
  */
190
196
 
191
- createContext(req, res) {
192
- const context = Object.create(this.context);
193
- const request = context.request = Object.create(this.request);
194
- const response = context.response = Object.create(this.response);
195
- context.app = request.app = response.app = this;
196
- context.req = request.req = response.req = req;
197
- context.res = request.res = response.res = res;
198
- request.ctx = response.ctx = context;
199
- request.response = response;
200
- response.request = request;
201
- context.originalUrl = request.originalUrl = req.url;
202
- context.state = {};
203
- return context;
197
+ createContext (req, res) {
198
+ /** @type {Context} */
199
+ const context = Object.create(this.context)
200
+ /** @type {KoaRequest} */
201
+ const request = context.request = Object.create(this.request)
202
+ /** @type {KoaResponse} */
203
+ const response = context.response = Object.create(this.response)
204
+ context.app = request.app = response.app = this
205
+ context.req = request.req = response.req = req
206
+ context.res = request.res = response.res = res
207
+ request.ctx = response.ctx = context
208
+ request.response = response
209
+ response.request = request
210
+ context.originalUrl = request.originalUrl = req.url
211
+ context.state = {}
212
+ return context
204
213
  }
205
214
 
206
215
  /**
@@ -210,20 +219,20 @@ module.exports = class Application extends Emitter {
210
219
  * @api private
211
220
  */
212
221
 
213
- onerror(err) {
222
+ onerror (err) {
214
223
  // When dealing with cross-globals a normal `instanceof` check doesn't work properly.
215
224
  // See https://github.com/koajs/koa/issues/1466
216
225
  // We can probably remove it once jest fixes https://github.com/facebook/jest/issues/2549.
217
226
  const isNativeError =
218
227
  Object.prototype.toString.call(err) === '[object Error]' ||
219
- err instanceof Error;
220
- if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err));
228
+ err instanceof Error
229
+ if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err))
221
230
 
222
- if (404 === err.status || err.expose) return;
223
- if (this.silent) return;
231
+ if (err.status === 404 || err.expose) return
232
+ if (this.silent) return
224
233
 
225
- const msg = err.stack || err.toString();
226
- console.error(`\n${msg.replace(/^/gm, ' ')}\n`);
234
+ const msg = err.stack || err.toString()
235
+ console.error(`\n${msg.replace(/^/gm, ' ')}\n`)
227
236
  }
228
237
 
229
238
  /**
@@ -231,78 +240,80 @@ module.exports = class Application extends Emitter {
231
240
  * @see https://github.com/koajs/koa/issues/1513
232
241
  */
233
242
 
234
- static get default() {
235
- return Application;
243
+ static get default () {
244
+ return Application
245
+ }
246
+
247
+ createAsyncCtxStorageMiddleware () {
248
+ const app = this
249
+ return async function asyncCtxStorage (ctx, next) {
250
+ await app.ctxStorage.run(ctx, async () => {
251
+ return await next()
252
+ })
253
+ }
236
254
  }
237
- };
238
-
239
- function createAsyncCtxStorage(app) {
240
- return async function asyncCtxStorage(ctx, next) {
241
- await app.ctxStorage.run(ctx, async() => {
242
- return await next();
243
- });
244
- };
245
255
  }
246
256
 
247
257
  /**
248
258
  * Response helper.
249
259
  */
250
260
 
251
- function respond(ctx) {
261
+ function respond (ctx) {
252
262
  // allow bypassing koa
253
- if (false === ctx.respond) return;
263
+ if (ctx.respond === false) return
254
264
 
255
- if (!ctx.writable) return;
265
+ if (!ctx.writable) return
256
266
 
257
- const res = ctx.res;
258
- let body = ctx.body;
259
- const code = ctx.status;
267
+ const res = ctx.res
268
+ let body = ctx.body
269
+ const code = ctx.status
260
270
 
261
271
  // ignore body
262
272
  if (statuses.empty[code]) {
263
273
  // strip headers
264
- ctx.body = null;
265
- return res.end();
274
+ ctx.body = null
275
+ return res.end()
266
276
  }
267
277
 
268
- if ('HEAD' === ctx.method) {
278
+ if (ctx.method === 'HEAD') {
269
279
  if (!res.headersSent && !ctx.response.has('Content-Length')) {
270
- const { length } = ctx.response;
271
- if (Number.isInteger(length)) ctx.length = length;
280
+ const { length } = ctx.response
281
+ if (Number.isInteger(length)) ctx.length = length
272
282
  }
273
- return res.end();
283
+ return res.end()
274
284
  }
275
285
 
276
286
  // status body
277
- if (null == body) {
287
+ if (body == null) {
278
288
  if (ctx.response._explicitNullBody) {
279
- ctx.response.remove('Content-Type');
280
- ctx.response.remove('Transfer-Encoding');
281
- return res.end();
289
+ ctx.response.remove('Content-Type')
290
+ ctx.response.remove('Transfer-Encoding')
291
+ ctx.length = 0
292
+ return res.end()
282
293
  }
283
294
  if (ctx.req.httpVersionMajor >= 2) {
284
- body = String(code);
295
+ body = String(code)
285
296
  } else {
286
- body = ctx.message || String(code);
297
+ body = ctx.message || String(code)
287
298
  }
288
299
  if (!res.headersSent) {
289
- ctx.type = 'text';
290
- ctx.length = Buffer.byteLength(body);
300
+ ctx.type = 'text'
301
+ ctx.length = Buffer.byteLength(body)
291
302
  }
292
- return res.end(body);
303
+ return res.end(body)
293
304
  }
294
305
 
295
306
  // responses
296
- if (Buffer.isBuffer(body)) return res.end(body);
297
- if ('string' === typeof body) return res.end(body);
298
- if (body instanceof Stream) return body.pipe(res);
307
+ if (Buffer.isBuffer(body)) return res.end(body)
308
+ if (typeof body === 'string') return res.end(body)
309
+ if (body instanceof Stream) return body.pipe(res)
299
310
 
300
311
  // body: json
301
- body = JSON.stringify(body);
312
+ body = JSON.stringify(body)
302
313
  if (!res.headersSent) {
303
- ctx.length = Buffer.byteLength(body);
314
+ ctx.length = Buffer.byteLength(body)
304
315
  }
305
- res.end(body);
316
+ res.end(body)
306
317
  }
307
318
 
308
319
  /**
@@ -310,4 +321,4 @@ function respond(ctx) {
310
321
  * have a direct dependency upon `http-errors`
311
322
  */
312
323
 
313
- module.exports.HttpError = HttpError;
324
+ module.exports.HttpError = HttpError
package/lib/context.js CHANGED
@@ -1,18 +1,18 @@
1
1
 
2
- 'use strict';
2
+ 'use strict'
3
3
 
4
4
  /**
5
5
  * Module dependencies.
6
6
  */
7
7
 
8
- const util = require('util');
9
- const createError = require('http-errors');
10
- const httpAssert = require('http-assert');
11
- const delegate = require('delegates');
12
- const statuses = require('statuses');
13
- const Cookies = require('cookies');
8
+ const util = require('util')
9
+ const createError = require('http-errors')
10
+ const httpAssert = require('http-assert')
11
+ const delegate = require('delegates')
12
+ const statuses = require('statuses')
13
+ const Cookies = require('cookies')
14
14
 
15
- const COOKIES = Symbol('context#cookies');
15
+ const COOKIES = Symbol('context#cookies')
16
16
 
17
17
  /**
18
18
  * Context prototype.
@@ -28,9 +28,9 @@ const proto = module.exports = {
28
28
  * @api public
29
29
  */
30
30
 
31
- inspect() {
32
- if (this === proto) return this;
33
- return this.toJSON();
31
+ inspect () {
32
+ if (this === proto) return this
33
+ return this.toJSON()
34
34
  },
35
35
 
36
36
  /**
@@ -45,7 +45,7 @@ const proto = module.exports = {
45
45
  * @api public
46
46
  */
47
47
 
48
- toJSON() {
48
+ toJSON () {
49
49
  return {
50
50
  request: this.request.toJSON(),
51
51
  response: this.response.toJSON(),
@@ -54,7 +54,7 @@ const proto = module.exports = {
54
54
  req: '<original node req>',
55
55
  res: '<original node res>',
56
56
  socket: '<original node socket>'
57
- };
57
+ }
58
58
  },
59
59
 
60
60
  /**
@@ -93,8 +93,8 @@ const proto = module.exports = {
93
93
  * @api public
94
94
  */
95
95
 
96
- throw(...args) {
97
- throw createError(...args);
96
+ throw (...args) {
97
+ throw createError(...args)
98
98
  },
99
99
 
100
100
  /**
@@ -104,81 +104,81 @@ const proto = module.exports = {
104
104
  * @api private
105
105
  */
106
106
 
107
- onerror(err) {
107
+ onerror (err) {
108
108
  // don't do anything if there is no error.
109
109
  // this allows you to pass `this.onerror`
110
110
  // to node-style callbacks.
111
- if (null == err) return;
111
+ if (err == null) return
112
112
 
113
113
  // When dealing with cross-globals a normal `instanceof` check doesn't work properly.
114
114
  // See https://github.com/koajs/koa/issues/1466
115
115
  // We can probably remove it once jest fixes https://github.com/facebook/jest/issues/2549.
116
116
  const isNativeError =
117
117
  Object.prototype.toString.call(err) === '[object Error]' ||
118
- err instanceof Error;
119
- if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err));
118
+ err instanceof Error
119
+ if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err))
120
120
 
121
- let headerSent = false;
121
+ let headerSent = false
122
122
  if (this.headerSent || !this.writable) {
123
- headerSent = err.headerSent = true;
123
+ headerSent = err.headerSent = true
124
124
  }
125
125
 
126
126
  // delegate
127
- this.app.emit('error', err, this);
127
+ this.app.emit('error', err, this)
128
128
 
129
129
  // nothing we can do here other
130
130
  // than delegate to the app-level
131
131
  // handler and log.
132
132
  if (headerSent) {
133
- return;
133
+ return
134
134
  }
135
135
 
136
- const { res } = this;
136
+ const { res } = this
137
137
 
138
138
  // first unset all headers
139
139
  /* istanbul ignore else */
140
140
  if (typeof res.getHeaderNames === 'function') {
141
- res.getHeaderNames().forEach(name => res.removeHeader(name));
141
+ res.getHeaderNames().forEach(name => res.removeHeader(name))
142
142
  } else {
143
- res._headers = {}; // Node < 7.7
143
+ res._headers = {} // Node < 7.7
144
144
  }
145
145
 
146
146
  // then set those specified
147
- this.set(err.headers);
147
+ this.set(err.headers)
148
148
 
149
149
  // force text/plain
150
- this.type = 'text';
150
+ this.type = 'text'
151
151
 
152
- let statusCode = err.status || err.statusCode;
152
+ let statusCode = err.status || err.statusCode
153
153
 
154
154
  // ENOENT support
155
- if ('ENOENT' === err.code) statusCode = 404;
155
+ if (err.code === 'ENOENT') statusCode = 404
156
156
 
157
157
  // default to 500
158
- if ('number' !== typeof statusCode || !statuses[statusCode]) statusCode = 500;
158
+ if (typeof statusCode !== 'number' || !statuses[statusCode]) statusCode = 500
159
159
 
160
160
  // respond
161
- const code = statuses[statusCode];
162
- const msg = err.expose ? err.message : code;
163
- this.status = err.status = statusCode;
164
- this.length = Buffer.byteLength(msg);
165
- res.end(msg);
161
+ const code = statuses[statusCode]
162
+ const msg = err.expose ? err.message : code
163
+ this.status = err.status = statusCode
164
+ this.length = Buffer.byteLength(msg)
165
+ res.end(msg)
166
166
  },
167
167
 
168
- get cookies() {
168
+ get cookies () {
169
169
  if (!this[COOKIES]) {
170
170
  this[COOKIES] = new Cookies(this.req, this.res, {
171
171
  keys: this.app.keys,
172
172
  secure: this.request.secure
173
- });
173
+ })
174
174
  }
175
- return this[COOKIES];
175
+ return this[COOKIES]
176
176
  },
177
177
 
178
- set cookies(_cookies) {
179
- this[COOKIES] = _cookies;
178
+ set cookies (_cookies) {
179
+ this[COOKIES] = _cookies
180
180
  }
181
- };
181
+ }
182
182
 
183
183
  /**
184
184
  * Custom inspection implementation for newer Node.js versions.
@@ -189,7 +189,7 @@ const proto = module.exports = {
189
189
 
190
190
  /* istanbul ignore else */
191
191
  if (util.inspect.custom) {
192
- module.exports[util.inspect.custom] = module.exports.inspect;
192
+ module.exports[util.inspect.custom] = module.exports.inspect
193
193
  }
194
194
 
195
195
  /**
@@ -213,7 +213,7 @@ delegate(proto, 'response')
213
213
  .access('lastModified')
214
214
  .access('etag')
215
215
  .getter('headerSent')
216
- .getter('writable');
216
+ .getter('writable')
217
217
 
218
218
  /**
219
219
  * Request delegation.
@@ -248,4 +248,4 @@ delegate(proto, 'request')
248
248
  .getter('stale')
249
249
  .getter('fresh')
250
250
  .getter('ips')
251
- .getter('ip');
251
+ .getter('ip')