Projektstart
This commit is contained in:
189
backend/node_modules/light-my-request/lib/response.js
generated
vendored
Normal file
189
backend/node_modules/light-my-request/lib/response.js
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
'use strict'
|
||||
|
||||
const http = require('node:http')
|
||||
const { Writable, Readable } = require('node:stream')
|
||||
const util = require('node:util')
|
||||
|
||||
const setCookie = require('set-cookie-parser')
|
||||
|
||||
function Response (req, onEnd, reject) {
|
||||
http.ServerResponse.call(this, req)
|
||||
|
||||
this._lightMyRequest = { headers: null, trailers: {}, payloadChunks: [] }
|
||||
// This forces node@8 to always render the headers
|
||||
this.setHeader('foo', 'bar'); this.removeHeader('foo')
|
||||
|
||||
this.assignSocket(getNullSocket())
|
||||
|
||||
this._promiseCallback = typeof reject === 'function'
|
||||
|
||||
let called = false
|
||||
const onEndSuccess = (payload) => {
|
||||
// no need to early-return if already called because this handler is bound `once`
|
||||
called = true
|
||||
if (this._promiseCallback) {
|
||||
return process.nextTick(() => onEnd(payload))
|
||||
}
|
||||
process.nextTick(() => onEnd(null, payload))
|
||||
}
|
||||
|
||||
const onEndFailure = (err) => {
|
||||
if (called) return
|
||||
called = true
|
||||
if (this._promiseCallback) {
|
||||
return process.nextTick(() => reject(err))
|
||||
}
|
||||
process.nextTick(() => onEnd(err, null))
|
||||
}
|
||||
|
||||
this.once('finish', () => {
|
||||
const res = generatePayload(this)
|
||||
res.raw.req = req
|
||||
onEndSuccess(res)
|
||||
})
|
||||
|
||||
this.connection.once('error', onEndFailure)
|
||||
|
||||
this.once('error', onEndFailure)
|
||||
|
||||
this.once('close', onEndFailure)
|
||||
}
|
||||
|
||||
util.inherits(Response, http.ServerResponse)
|
||||
|
||||
Response.prototype.setTimeout = function (msecs, callback) {
|
||||
this.timeoutHandle = setTimeout(() => {
|
||||
this.emit('timeout')
|
||||
}, msecs)
|
||||
this.on('timeout', callback)
|
||||
return this
|
||||
}
|
||||
|
||||
Response.prototype.writeHead = function () {
|
||||
const result = http.ServerResponse.prototype.writeHead.apply(this, arguments)
|
||||
|
||||
copyHeaders(this)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Response.prototype.write = function (data, encoding, callback) {
|
||||
if (this.timeoutHandle) {
|
||||
clearTimeout(this.timeoutHandle)
|
||||
}
|
||||
http.ServerResponse.prototype.write.call(this, data, encoding, callback)
|
||||
this._lightMyRequest.payloadChunks.push(Buffer.from(data, encoding))
|
||||
return true
|
||||
}
|
||||
|
||||
Response.prototype.end = function (data, encoding, callback) {
|
||||
if (data) {
|
||||
this.write(data, encoding)
|
||||
}
|
||||
|
||||
http.ServerResponse.prototype.end.call(this, callback)
|
||||
|
||||
this.emit('finish')
|
||||
|
||||
// We need to emit 'close' otherwise stream.finished() would
|
||||
// not pick it up on Node v16
|
||||
|
||||
this.destroy()
|
||||
}
|
||||
|
||||
Response.prototype.destroy = function (error) {
|
||||
if (this.destroyed) return
|
||||
this.destroyed = true
|
||||
|
||||
if (error) {
|
||||
process.nextTick(() => this.emit('error', error))
|
||||
}
|
||||
|
||||
process.nextTick(() => this.emit('close'))
|
||||
}
|
||||
|
||||
Response.prototype.addTrailers = function (trailers) {
|
||||
for (const key in trailers) {
|
||||
this._lightMyRequest.trailers[key.toLowerCase().trim()] = trailers[key].toString().trim()
|
||||
}
|
||||
}
|
||||
|
||||
function generatePayload (response) {
|
||||
// This seems only to happen when using `fastify-express` - see https://github.com/fastify/fastify-express/issues/47
|
||||
/* istanbul ignore if */
|
||||
if (response._lightMyRequest.headers === null) {
|
||||
copyHeaders(response)
|
||||
}
|
||||
serializeHeaders(response)
|
||||
// Prepare response object
|
||||
const res = {
|
||||
raw: {
|
||||
res: response
|
||||
},
|
||||
headers: response._lightMyRequest.headers,
|
||||
statusCode: response.statusCode,
|
||||
statusMessage: response.statusMessage,
|
||||
trailers: {},
|
||||
get cookies () {
|
||||
return setCookie.parse(this)
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare payload and trailers
|
||||
const rawBuffer = Buffer.concat(response._lightMyRequest.payloadChunks)
|
||||
res.rawPayload = rawBuffer
|
||||
|
||||
// we keep both of them for compatibility reasons
|
||||
res.payload = rawBuffer.toString()
|
||||
res.body = res.payload
|
||||
res.trailers = response._lightMyRequest.trailers
|
||||
|
||||
// Prepare payload parsers
|
||||
res.json = function parseJsonPayload () {
|
||||
return JSON.parse(res.payload)
|
||||
}
|
||||
|
||||
// Provide stream Readable for advanced user
|
||||
res.stream = function streamPayload () {
|
||||
return Readable.from(response._lightMyRequest.payloadChunks)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Throws away all written data to prevent response from buffering payload
|
||||
function getNullSocket () {
|
||||
return new Writable({
|
||||
write (chunk, encoding, callback) {
|
||||
setImmediate(callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function serializeHeaders (response) {
|
||||
const headers = response._lightMyRequest.headers
|
||||
|
||||
for (const headerName of Object.keys(headers)) {
|
||||
const headerValue = headers[headerName]
|
||||
if (Array.isArray(headerValue)) {
|
||||
headers[headerName] = headerValue.map(value => '' + value)
|
||||
} else {
|
||||
headers[headerName] = '' + headerValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copyHeaders (response) {
|
||||
response._lightMyRequest.headers = Object.assign({}, response.getHeaders())
|
||||
|
||||
// Add raw headers
|
||||
;['Date', 'Connection', 'Transfer-Encoding'].forEach((name) => {
|
||||
const regex = new RegExp('\\r\\n' + name + ': ([^\\r]*)\\r\\n')
|
||||
const field = response._header.match(regex)
|
||||
if (field) {
|
||||
response._lightMyRequest.headers[name.toLowerCase()] = field[1]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = Response
|
||||
Reference in New Issue
Block a user