@nxtedition/lib 23.6.20 → 23.7.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/http.js +73 -1
- package/package.json +1 -1
package/http.js
CHANGED
|
@@ -155,6 +155,78 @@ function noop() {}
|
|
|
155
155
|
|
|
156
156
|
const pendingSet = (globalThis._nxt_lib_http_pending ??= new Set())
|
|
157
157
|
|
|
158
|
+
export async function upgradeMiddleware(ctx, next) {
|
|
159
|
+
const { req, socket, logger } = ctx
|
|
160
|
+
const startTime = performance.now()
|
|
161
|
+
|
|
162
|
+
let aborted = false
|
|
163
|
+
|
|
164
|
+
req.on('error', noop)
|
|
165
|
+
socket.on('error', (err) => {
|
|
166
|
+
// NOTE: Special case where the client becomes unreachable.
|
|
167
|
+
if (err.message.startsWith('read ')) {
|
|
168
|
+
aborted = true
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
const isHealthcheck = req.url === '/healthcheck' || req.url === '/_up'
|
|
173
|
+
const reqLogger = isHealthcheck ? null : logger.child({ req })
|
|
174
|
+
|
|
175
|
+
pendingSet.add(ctx)
|
|
176
|
+
try {
|
|
177
|
+
if (req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS') {
|
|
178
|
+
req.resume() // Dump the body if there is one.
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
reqLogger?.debug('request started')
|
|
182
|
+
|
|
183
|
+
const thenable = next()
|
|
184
|
+
|
|
185
|
+
if (thenable?.then) {
|
|
186
|
+
await thenable
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
assert(socket.destroyed || socket.writableEnded, 'response not completed')
|
|
190
|
+
|
|
191
|
+
const elapsedTime = performance.now() - startTime
|
|
192
|
+
|
|
193
|
+
if (isHealthcheck) {
|
|
194
|
+
// Do nothing...
|
|
195
|
+
} else if (socket.errored) {
|
|
196
|
+
reqLogger?.error({ err: socket.errored, req, socket, elapsedTime }, 'request error')
|
|
197
|
+
} else if (!socket.writableEnded) {
|
|
198
|
+
reqLogger?.debug({ req, socket, elapsedTime }, 'request aborted')
|
|
199
|
+
} else if (socket.statusCode >= 500) {
|
|
200
|
+
reqLogger?.error({ req, socket, elapsedTime }, 'request error')
|
|
201
|
+
} else if (socket.statusCode >= 400) {
|
|
202
|
+
reqLogger?.warn({ req, socket, elapsedTime }, 'request failed')
|
|
203
|
+
} else {
|
|
204
|
+
reqLogger?.debug({ req, socket, elapsedTime }, 'request completed')
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
ctx[kAbortController]?.abort(err)
|
|
208
|
+
|
|
209
|
+
const statusCode = err.statusCode || err.$metadata?.httpStatusCode || 500
|
|
210
|
+
const elapsedTime = performance.now() - startTime
|
|
211
|
+
|
|
212
|
+
if (req.aborted || aborted || (!socket.errored && socket.closed) || err.name === 'AbortError') {
|
|
213
|
+
reqLogger?.debug({ socket, err, elapsedTime }, 'request aborted')
|
|
214
|
+
} else if (statusCode < 500) {
|
|
215
|
+
reqLogger?.warn({ socket, err, elapsedTime }, 'request failed')
|
|
216
|
+
} else {
|
|
217
|
+
reqLogger?.error({ socket, err, elapsedTime }, 'request error')
|
|
218
|
+
}
|
|
219
|
+
socket.destroy(err)
|
|
220
|
+
} finally {
|
|
221
|
+
pendingSet.delete(ctx)
|
|
222
|
+
|
|
223
|
+
if (!socket.writableEnded && !socket.destroyed) {
|
|
224
|
+
socket.destroy()
|
|
225
|
+
reqLogger?.warn('socket destroyed')
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
158
230
|
export async function requestMiddleware(ctx, next) {
|
|
159
231
|
const { req, res, logger } = ctx
|
|
160
232
|
const startTime = performance.now()
|
|
@@ -405,7 +477,7 @@ export class ServerResponse extends http.ServerResponse {
|
|
|
405
477
|
}
|
|
406
478
|
}
|
|
407
479
|
|
|
408
|
-
export class
|
|
480
|
+
export class Http2ServerRequest extends http2.Http2ServerRequest {
|
|
409
481
|
#target
|
|
410
482
|
#host
|
|
411
483
|
#url
|