koa 3.0.0-alpha.3 → 3.0.0-alpha.5
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/lib/application.js +6 -4
- package/lib/context.js +0 -3
- package/lib/is-stream.js +20 -0
- package/lib/request.js +6 -6
- package/lib/response.js +10 -14
- package/package.json +4 -3
package/lib/application.js
CHANGED
|
@@ -16,6 +16,7 @@ const Emitter = require('events')
|
|
|
16
16
|
const util = require('util')
|
|
17
17
|
const Stream = require('stream')
|
|
18
18
|
const http = require('http')
|
|
19
|
+
const isStream = require('./is-stream.js')
|
|
19
20
|
const only = require('./only.js')
|
|
20
21
|
const { HttpError } = require('http-errors')
|
|
21
22
|
|
|
@@ -55,7 +56,7 @@ module.exports = class Application extends Emitter {
|
|
|
55
56
|
* @param {string} [options.proxyIpHeader] Proxy IP header, defaults to X-Forwarded-For
|
|
56
57
|
* @param {number} [options.maxIpsCount] Max IPs read from proxy IP header, default to 0 (means infinity)
|
|
57
58
|
* @param {function} [options.compose] Function to handle middleware composition
|
|
58
|
-
* @param {boolean} [options.asyncLocalStorage]
|
|
59
|
+
* @param {boolean} [options.asyncLocalStorage] Enable AsyncLocalStorage, default to false
|
|
59
60
|
*
|
|
60
61
|
*/
|
|
61
62
|
|
|
@@ -258,9 +259,10 @@ function respond (ctx) {
|
|
|
258
259
|
// allow bypassing koa
|
|
259
260
|
if (ctx.respond === false) return
|
|
260
261
|
|
|
261
|
-
if (!ctx.writable) return
|
|
262
|
-
|
|
263
262
|
const res = ctx.res
|
|
263
|
+
|
|
264
|
+
if (!ctx.writable) return res.end()
|
|
265
|
+
|
|
264
266
|
let body = ctx.body
|
|
265
267
|
const code = ctx.status
|
|
266
268
|
|
|
@@ -303,10 +305,10 @@ function respond (ctx) {
|
|
|
303
305
|
|
|
304
306
|
if (Buffer.isBuffer(body)) return res.end(body)
|
|
305
307
|
if (typeof body === 'string') return res.end(body)
|
|
306
|
-
if (body instanceof Stream) return body.pipe(res)
|
|
307
308
|
if (body instanceof Blob) return Stream.Readable.from(body.stream()).pipe(res)
|
|
308
309
|
if (body instanceof ReadableStream) return Stream.Readable.from(body).pipe(res)
|
|
309
310
|
if (body instanceof Response) return Stream.Readable.from(body?.body || '').pipe(res)
|
|
311
|
+
if (isStream(body)) return body.pipe(res)
|
|
310
312
|
|
|
311
313
|
// body: json
|
|
312
314
|
body = JSON.stringify(body)
|
package/lib/context.js
CHANGED
|
@@ -150,9 +150,6 @@ const proto = module.exports = {
|
|
|
150
150
|
|
|
151
151
|
let statusCode = err.status || err.statusCode
|
|
152
152
|
|
|
153
|
-
// ENOENT support
|
|
154
|
-
if (err.code === 'ENOENT') statusCode = 404
|
|
155
|
-
|
|
156
153
|
// default to 500
|
|
157
154
|
if (typeof statusCode !== 'number' || !statuses.message[statusCode]) statusCode = 500
|
|
158
155
|
|
package/lib/is-stream.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Stream = require('stream')
|
|
4
|
+
|
|
5
|
+
// TODO: use a third party library for this
|
|
6
|
+
|
|
7
|
+
module.exports = (stream) => {
|
|
8
|
+
return (
|
|
9
|
+
stream instanceof Stream ||
|
|
10
|
+
(stream !== null &&
|
|
11
|
+
typeof stream === 'object' &&
|
|
12
|
+
!!stream.readable &&
|
|
13
|
+
typeof stream.pipe === 'function' &&
|
|
14
|
+
typeof stream.read === 'function' &&
|
|
15
|
+
typeof stream.readable === 'boolean' &&
|
|
16
|
+
typeof stream.readableObjectMode === 'boolean' &&
|
|
17
|
+
typeof stream.destroy === 'function' &&
|
|
18
|
+
typeof stream.destroyed === 'boolean')
|
|
19
|
+
)
|
|
20
|
+
}
|
package/lib/request.js
CHANGED
|
@@ -89,14 +89,14 @@ module.exports = {
|
|
|
89
89
|
},
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
* Get origin
|
|
92
|
+
* Get the origin header.
|
|
93
93
|
*
|
|
94
94
|
* @return {String}
|
|
95
95
|
* @api public
|
|
96
96
|
*/
|
|
97
97
|
|
|
98
98
|
get origin () {
|
|
99
|
-
return
|
|
99
|
+
return this.req.headers.origin || null
|
|
100
100
|
},
|
|
101
101
|
|
|
102
102
|
/**
|
|
@@ -109,7 +109,7 @@ module.exports = {
|
|
|
109
109
|
get href () {
|
|
110
110
|
// support: `GET http://example.com/foo`
|
|
111
111
|
if (/^https?:\/\//i.test(this.originalUrl)) return this.originalUrl
|
|
112
|
-
return this.
|
|
112
|
+
return this.protocol + '://' + this.host + this.originalUrl
|
|
113
113
|
},
|
|
114
114
|
|
|
115
115
|
/**
|
|
@@ -288,7 +288,7 @@ module.exports = {
|
|
|
288
288
|
if (!this.memoizedURL) {
|
|
289
289
|
const originalUrl = this.originalUrl || '' // avoid undefined in template string
|
|
290
290
|
try {
|
|
291
|
-
this.memoizedURL = new URL(`${this.
|
|
291
|
+
this.memoizedURL = new URL(`${this.protocol}://${this.host}${originalUrl}`)
|
|
292
292
|
} catch (err) {
|
|
293
293
|
this.memoizedURL = Object.create(null)
|
|
294
294
|
}
|
|
@@ -732,6 +732,6 @@ if (util.inspect.custom) {
|
|
|
732
732
|
* @param {number} [limit] - The maximum number of values to return.
|
|
733
733
|
* @returns {string[]} An array of values from the comma-separated string.
|
|
734
734
|
*/
|
|
735
|
-
function splitCommaSeparatedValues(value, limit) {
|
|
736
|
-
return value.split(',', limit).map(v => v.trim())
|
|
735
|
+
function splitCommaSeparatedValues (value, limit) {
|
|
736
|
+
return value.split(',', limit).map(v => v.trim())
|
|
737
737
|
}
|
package/lib/response.js
CHANGED
|
@@ -14,10 +14,10 @@ const destroy = require('destroy')
|
|
|
14
14
|
const assert = require('assert')
|
|
15
15
|
const extname = require('path').extname
|
|
16
16
|
const vary = require('vary')
|
|
17
|
+
const isStream = require('./is-stream.js')
|
|
17
18
|
const only = require('./only.js')
|
|
18
19
|
const util = require('util')
|
|
19
20
|
const encodeUrl = require('encodeurl')
|
|
20
|
-
const Stream = require('stream')
|
|
21
21
|
const deprecate = require('depd')('koa')
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -172,7 +172,7 @@ module.exports = {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// stream
|
|
175
|
-
if (val
|
|
175
|
+
if (isStream(val)) {
|
|
176
176
|
onFinish(this.res, destroy.bind(null, val))
|
|
177
177
|
if (original !== val) {
|
|
178
178
|
val.once('error', err => this.ctx.onerror(err))
|
|
@@ -211,7 +211,7 @@ module.exports = {
|
|
|
211
211
|
|
|
212
212
|
// json
|
|
213
213
|
this.remove('Content-Length')
|
|
214
|
-
this.type = 'json'
|
|
214
|
+
if (!this.type || !/\bjson\b/i.test(this.type)) this.type = 'json'
|
|
215
215
|
},
|
|
216
216
|
|
|
217
217
|
/**
|
|
@@ -240,7 +240,7 @@ module.exports = {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
const { body } = this
|
|
243
|
-
if (!body || body
|
|
243
|
+
if (!body || isStream(body)) return undefined
|
|
244
244
|
if (typeof body === 'string') return Buffer.byteLength(body)
|
|
245
245
|
if (Buffer.isBuffer(body)) return body.length
|
|
246
246
|
return Buffer.byteLength(JSON.stringify(body))
|
|
@@ -309,7 +309,7 @@ module.exports = {
|
|
|
309
309
|
if (this.ctx.accepts('html')) {
|
|
310
310
|
url = escape(url)
|
|
311
311
|
this.type = 'text/html; charset=utf-8'
|
|
312
|
-
this.body = `Redirecting to
|
|
312
|
+
this.body = `Redirecting to ${url}.`
|
|
313
313
|
return
|
|
314
314
|
}
|
|
315
315
|
|
|
@@ -513,22 +513,18 @@ module.exports = {
|
|
|
513
513
|
* this.set('Accept', 'application/json');
|
|
514
514
|
* this.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
|
|
515
515
|
*
|
|
516
|
-
* @param {String|
|
|
517
|
-
* @param {
|
|
516
|
+
* @param {String|{ [k: string]: any }} field
|
|
517
|
+
* @param {any} [val]
|
|
518
518
|
* @api public
|
|
519
519
|
*/
|
|
520
520
|
|
|
521
521
|
set (field, val) {
|
|
522
|
-
if (this.headerSent) return
|
|
522
|
+
if (this.headerSent || !field) return
|
|
523
523
|
|
|
524
|
-
if (
|
|
525
|
-
if (Array.isArray(val)) val = val.map(v => typeof v === 'string' ? v : String(v))
|
|
526
|
-
else if (typeof val !== 'string') val = String(val)
|
|
524
|
+
if (typeof field === 'string') {
|
|
527
525
|
this.res.setHeader(field, val)
|
|
528
526
|
} else {
|
|
529
|
-
|
|
530
|
-
this.set(key, field[key])
|
|
531
|
-
}
|
|
527
|
+
Object.keys(field).forEach(header => this.res.setHeader(header, field[header]))
|
|
532
528
|
}
|
|
533
529
|
},
|
|
534
530
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koa",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"tag": "experimental"
|
|
6
6
|
},
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"on-finished": "^2.3.0",
|
|
56
56
|
"parseurl": "^1.3.2",
|
|
57
57
|
"statuses": "^2.0.1",
|
|
58
|
-
"type-is": "^
|
|
58
|
+
"type-is": "^2.0.1",
|
|
59
59
|
"vary": "^1.1.2"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
@@ -70,5 +70,6 @@
|
|
|
70
70
|
"files": [
|
|
71
71
|
"dist",
|
|
72
72
|
"lib"
|
|
73
|
-
]
|
|
73
|
+
],
|
|
74
|
+
"homepage": "https://koajs.com"
|
|
74
75
|
}
|