@fastify/reply-from 8.1.0 → 8.2.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/.github/workflows/ci.yml +2 -0
- package/README.md +2 -2
- package/example.js +2 -2
- package/index.d.ts +1 -1
- package/index.js +15 -5
- package/lib/errors.js +13 -0
- package/lib/request.js +9 -4
- package/package.json +5 -5
- package/test/http-invalid-target.js +1 -0
- package/test/http-timeout.js +1 -0
- package/test/http2-invalid-target.js +1 -0
- package/test/http2-target-crash.js +1 -0
- package/test/http2-target-multi-crash.js +1 -0
- package/test/http2-timeout.js +2 -0
- package/test/on-error.js +8 -2
- package/test/undici-timeout.js +1 -0
- package/test/unexpected-error.js +1 -0
package/.github/workflows/ci.yml
CHANGED
package/README.md
CHANGED
|
@@ -47,12 +47,12 @@ proxy.get('/', (request, reply) => {
|
|
|
47
47
|
reply.from('/')
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
target.listen(3001, (err) => {
|
|
50
|
+
target.listen({ port: 3001 }, (err) => {
|
|
51
51
|
if (err) {
|
|
52
52
|
throw err
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
proxy.listen(3000, (err) => {
|
|
55
|
+
proxy.listen({ port: 3000 }, (err) => {
|
|
56
56
|
if (err) {
|
|
57
57
|
throw err
|
|
58
58
|
}
|
package/example.js
CHANGED
|
@@ -23,12 +23,12 @@ proxy.get('/', (request, reply) => {
|
|
|
23
23
|
reply.from('/')
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
target.listen(3001, (err) => {
|
|
26
|
+
target.listen({ port: 3001 }, (err) => {
|
|
27
27
|
if (err) {
|
|
28
28
|
throw err
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
proxy.listen(3000, (err) => {
|
|
31
|
+
proxy.listen({ port: 3000 }, (err) => {
|
|
32
32
|
if (err) {
|
|
33
33
|
throw err
|
|
34
34
|
}
|
package/index.d.ts
CHANGED
|
@@ -85,7 +85,7 @@ export interface FastifyReplyFromOptions {
|
|
|
85
85
|
base?: string;
|
|
86
86
|
cacheURLs?: number;
|
|
87
87
|
disableCache?: boolean;
|
|
88
|
-
http?: HttpOptions;
|
|
88
|
+
http?: HttpOptions | boolean;
|
|
89
89
|
http2?: Http2Options | boolean;
|
|
90
90
|
undici?: Pool.Options;
|
|
91
91
|
contentTypesToEncode?: string[];
|
package/index.js
CHANGED
|
@@ -4,7 +4,6 @@ const fp = require('fastify-plugin')
|
|
|
4
4
|
const lru = require('tiny-lru')
|
|
5
5
|
const querystring = require('querystring')
|
|
6
6
|
const Stream = require('stream')
|
|
7
|
-
const createError = require('http-errors')
|
|
8
7
|
const buildRequest = require('./lib/request')
|
|
9
8
|
const {
|
|
10
9
|
filterPseudoHeaders,
|
|
@@ -13,7 +12,14 @@ const {
|
|
|
13
12
|
buildURL
|
|
14
13
|
} = require('./lib/utils')
|
|
15
14
|
|
|
16
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
TimeoutError,
|
|
17
|
+
ServiceUnavailableError,
|
|
18
|
+
GatewayTimeoutError,
|
|
19
|
+
ConnectionResetError,
|
|
20
|
+
UndiciSocketError,
|
|
21
|
+
InternalServerError
|
|
22
|
+
} = require('./lib/errors')
|
|
17
23
|
|
|
18
24
|
module.exports = fp(function from (fastify, opts, next) {
|
|
19
25
|
const contentTypesToEncode = new Set([
|
|
@@ -137,11 +143,15 @@ module.exports = fp(function from (fastify, opts, next) {
|
|
|
137
143
|
this.request.log.warn(err, 'response errored')
|
|
138
144
|
if (!this.sent) {
|
|
139
145
|
if (err.code === 'ERR_HTTP2_STREAM_CANCEL' || err.code === 'ENOTFOUND') {
|
|
140
|
-
onError(this, { error:
|
|
146
|
+
onError(this, { error: ServiceUnavailableError() })
|
|
141
147
|
} else if (err instanceof TimeoutError || err.code === 'UND_ERR_HEADERS_TIMEOUT') {
|
|
142
|
-
onError(this, { error: new
|
|
148
|
+
onError(this, { error: new GatewayTimeoutError() })
|
|
149
|
+
} else if (err.code === 'ECONNRESET') {
|
|
150
|
+
onError(this, { error: new ConnectionResetError() })
|
|
151
|
+
} else if (err.code === 'UND_ERR_SOCKET') {
|
|
152
|
+
onError(this, { error: new UndiciSocketError() })
|
|
143
153
|
} else {
|
|
144
|
-
onError(this, { error:
|
|
154
|
+
onError(this, { error: new InternalServerError(err.message) })
|
|
145
155
|
}
|
|
146
156
|
}
|
|
147
157
|
return
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const createError = require('@fastify/error')
|
|
4
|
+
|
|
5
|
+
module.exports.TimeoutError = createError('FST_REPLY_FROM_TIMEOUT', 'Timeout', 504)
|
|
6
|
+
module.exports.HttpRequestTimeoutError = createError('FST_REPLY_FROM_HTTP_REQUEST_TIMEOUT', 'HTTP request timed out', 504, module.exports.TimeoutError)
|
|
7
|
+
module.exports.Http2RequestTimeoutError = createError('FST_REPLY_FROM_HTTP2_REQUEST_TIMEOUT', 'HTTP/2 request timed out', 504, module.exports.TimeoutError)
|
|
8
|
+
module.exports.Http2SessionTimeoutError = createError('FST_REPLY_FROM_HTTP2_SESSION_TIMEOUT', 'HTTP/2 session timed out', 504, module.exports.TimeoutError)
|
|
9
|
+
module.exports.ServiceUnavailableError = createError('FST_REPLY_FROM_SERVICE_UNAVAILABLE', 'Service Unavailable', 503)
|
|
10
|
+
module.exports.GatewayTimeoutError = createError('FST_REPLY_FROM_GATEWAY_TIMEOUT', 'Gateway Timeout', 504)
|
|
11
|
+
module.exports.ConnectionResetError = createError('ECONNRESET', 'Connection Reset', 500)
|
|
12
|
+
module.exports.UndiciSocketError = createError('UND_ERR_SOCKET', 'Undici Socket Error', 500)
|
|
13
|
+
module.exports.InternalServerError = createError('FST_REPLY_FROM_INTERNAL_SERVER_ERROR', '%s', 500)
|
package/lib/request.js
CHANGED
|
@@ -9,7 +9,12 @@ const undici = require('undici')
|
|
|
9
9
|
const { stripHttp1ConnectionHeaders } = require('./utils')
|
|
10
10
|
const http2 = require('http2')
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const {
|
|
13
|
+
TimeoutError,
|
|
14
|
+
Http2RequestTimeoutError,
|
|
15
|
+
Http2SessionTimeoutError,
|
|
16
|
+
HttpRequestTimeoutError
|
|
17
|
+
} = require('./errors')
|
|
13
18
|
|
|
14
19
|
function shouldUseUndici (opts) {
|
|
15
20
|
if (opts.undici === false || opts.http || opts.http2) {
|
|
@@ -102,7 +107,7 @@ function buildRequest (opts) {
|
|
|
102
107
|
done(null, { statusCode: res.statusCode, headers: res.headers, stream: res })
|
|
103
108
|
})
|
|
104
109
|
req.once('timeout', () => {
|
|
105
|
-
const err = new
|
|
110
|
+
const err = new HttpRequestTimeoutError()
|
|
106
111
|
req.abort()
|
|
107
112
|
done(err)
|
|
108
113
|
})
|
|
@@ -183,13 +188,13 @@ function buildRequest (opts) {
|
|
|
183
188
|
end(req, opts.body, done)
|
|
184
189
|
}
|
|
185
190
|
req.setTimeout(http2Opts.requestTimeout, () => {
|
|
186
|
-
const err = new
|
|
191
|
+
const err = new Http2RequestTimeoutError()
|
|
187
192
|
req.close(http2.constants.NGHTTP2_CANCEL)
|
|
188
193
|
done(err)
|
|
189
194
|
})
|
|
190
195
|
req.once('close', () => {
|
|
191
196
|
if (sessionTimedOut) {
|
|
192
|
-
const err = new
|
|
197
|
+
const err = new Http2SessionTimeoutError()
|
|
193
198
|
done(err)
|
|
194
199
|
}
|
|
195
200
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastify/reply-from",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"description": "forward your HTTP request to another server, for fastify",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@fastify/formbody": "^7.0.1",
|
|
32
32
|
"@fastify/multipart": "^7.1.0",
|
|
33
|
+
"@fastify/pre-commit": "^2.0.2",
|
|
33
34
|
"@sinonjs/fake-timers": "^9.1.2",
|
|
34
35
|
"@types/node": "^18.0.0",
|
|
35
36
|
"@types/tap": "^15.0.7",
|
|
@@ -39,20 +40,19 @@
|
|
|
39
40
|
"h2url": "^0.2.0",
|
|
40
41
|
"msgpack5": "^6.0.1",
|
|
41
42
|
"nock": "^13.2.6",
|
|
42
|
-
"pre-commit": "^1.2.2",
|
|
43
43
|
"proxyquire": "^2.1.3",
|
|
44
44
|
"simple-get": "^4.0.1",
|
|
45
45
|
"snazzy": "^9.0.0",
|
|
46
46
|
"split2": "^4.1.0",
|
|
47
47
|
"standard": "^17.0.0",
|
|
48
48
|
"tap": "^16.2.0",
|
|
49
|
-
"tsd": "^0.
|
|
49
|
+
"tsd": "^0.22.0",
|
|
50
50
|
"typescript": "^4.7.3"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"@fastify/error": "^3.0.0",
|
|
53
54
|
"end-of-stream": "^1.4.4",
|
|
54
|
-
"fastify-plugin": "^
|
|
55
|
-
"http-errors": "^2.0.0",
|
|
55
|
+
"fastify-plugin": "^4.0.0",
|
|
56
56
|
"pump": "^3.0.0",
|
|
57
57
|
"semver": "^7.3.7",
|
|
58
58
|
"tiny-lru": "^8.0.2",
|
|
@@ -26,6 +26,7 @@ test('http invalid target', async (t) => {
|
|
|
26
26
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
27
27
|
t.same(JSON.parse(err.response.body), {
|
|
28
28
|
statusCode: 503,
|
|
29
|
+
code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
|
|
29
30
|
error: 'Service Unavailable',
|
|
30
31
|
message: 'Service Unavailable'
|
|
31
32
|
})
|
package/test/http-timeout.js
CHANGED
|
@@ -43,6 +43,7 @@ async function main () {
|
|
|
43
43
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
44
44
|
t.same(JSON.parse(err.response.body), {
|
|
45
45
|
statusCode: 504,
|
|
46
|
+
code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
|
|
46
47
|
error: 'Gateway Timeout',
|
|
47
48
|
message: 'Gateway Timeout'
|
|
48
49
|
})
|
|
@@ -27,6 +27,7 @@ test('http2 invalid target', async (t) => {
|
|
|
27
27
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
28
28
|
t.same(JSON.parse(err.response.body), {
|
|
29
29
|
statusCode: 503,
|
|
30
|
+
code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
|
|
30
31
|
error: 'Service Unavailable',
|
|
31
32
|
message: 'Service Unavailable'
|
|
32
33
|
})
|
|
@@ -44,6 +44,7 @@ test('http -> http2 crash', async (t) => {
|
|
|
44
44
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
45
45
|
t.same(JSON.parse(err.response.body), {
|
|
46
46
|
statusCode: 503,
|
|
47
|
+
code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
|
|
47
48
|
error: 'Service Unavailable',
|
|
48
49
|
message: 'Service Unavailable'
|
|
49
50
|
})
|
|
@@ -37,6 +37,7 @@ test('http -> http2 crash multiple times', async (t) => {
|
|
|
37
37
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
38
38
|
t.same(JSON.parse(err.response.body), {
|
|
39
39
|
statusCode: 503,
|
|
40
|
+
code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
|
|
40
41
|
error: 'Service Unavailable',
|
|
41
42
|
message: 'Service Unavailable'
|
|
42
43
|
})
|
package/test/http2-timeout.js
CHANGED
|
@@ -38,6 +38,7 @@ test('http2 request timeout', async (t) => {
|
|
|
38
38
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
39
39
|
t.same(JSON.parse(err.response.body), {
|
|
40
40
|
statusCode: 504,
|
|
41
|
+
code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
|
|
41
42
|
error: 'Gateway Timeout',
|
|
42
43
|
message: 'Gateway Timeout'
|
|
43
44
|
})
|
|
@@ -81,6 +82,7 @@ test('http2 session timeout', async (t) => {
|
|
|
81
82
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
82
83
|
t.same(JSON.parse(err.response.body), {
|
|
83
84
|
statusCode: 504,
|
|
85
|
+
code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
|
|
84
86
|
error: 'Gateway Timeout',
|
|
85
87
|
message: 'Gateway Timeout'
|
|
86
88
|
})
|
package/test/on-error.js
CHANGED
|
@@ -34,8 +34,13 @@ async function main () {
|
|
|
34
34
|
reply.from(`http://localhost:${target.server.address().port}/`,
|
|
35
35
|
{
|
|
36
36
|
onError: (reply, { error }) => {
|
|
37
|
-
t.
|
|
38
|
-
|
|
37
|
+
t.same(error, {
|
|
38
|
+
statusCode: 504,
|
|
39
|
+
name: 'FastifyError',
|
|
40
|
+
code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
|
|
41
|
+
message: 'Gateway Timeout'
|
|
42
|
+
})
|
|
43
|
+
reply.code(error.statusCode).send(error)
|
|
39
44
|
}
|
|
40
45
|
})
|
|
41
46
|
})
|
|
@@ -49,6 +54,7 @@ async function main () {
|
|
|
49
54
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
50
55
|
t.same(JSON.parse(err.response.body), {
|
|
51
56
|
statusCode: 504,
|
|
57
|
+
code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
|
|
52
58
|
error: 'Gateway Timeout',
|
|
53
59
|
message: 'Gateway Timeout'
|
|
54
60
|
})
|
package/test/undici-timeout.js
CHANGED
|
@@ -48,6 +48,7 @@ async function main () {
|
|
|
48
48
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
49
49
|
t.same(JSON.parse(err.response.body), {
|
|
50
50
|
statusCode: 504,
|
|
51
|
+
code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
|
|
51
52
|
error: 'Gateway Timeout',
|
|
52
53
|
message: 'Gateway Timeout'
|
|
53
54
|
})
|
package/test/unexpected-error.js
CHANGED
|
@@ -37,6 +37,7 @@ test('unexpected error renders 500', async (t) => {
|
|
|
37
37
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
38
38
|
t.same(JSON.parse(err.response.body), {
|
|
39
39
|
statusCode: 500,
|
|
40
|
+
code: 'FST_REPLY_FROM_INTERNAL_SERVER_ERROR',
|
|
40
41
|
error: 'Internal Server Error',
|
|
41
42
|
message: 'foo'
|
|
42
43
|
})
|