You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
4.1 KiB
199 lines
4.1 KiB
'use strict'
|
|
|
|
const proxyAddr = require('proxy-addr')
|
|
const semver = require('semver')
|
|
const warning = require('./warnings')
|
|
|
|
function Request (id, params, req, query, log, context) {
|
|
this.id = id
|
|
this.context = context
|
|
this.params = params
|
|
this.raw = req
|
|
this.query = query
|
|
this.log = log
|
|
this.body = null
|
|
}
|
|
Request.props = []
|
|
|
|
function getTrustProxyFn (tp) {
|
|
if (typeof tp === 'function') {
|
|
return tp
|
|
}
|
|
if (tp === true) {
|
|
// Support plain true/false
|
|
return function () { return true }
|
|
}
|
|
if (typeof tp === 'number') {
|
|
// Support trusting hop count
|
|
return function (a, i) { return i < tp }
|
|
}
|
|
if (typeof tp === 'string') {
|
|
// Support comma-separated tps
|
|
const vals = tp.split(',').map(it => it.trim())
|
|
return proxyAddr.compile(vals)
|
|
}
|
|
return proxyAddr.compile(tp)
|
|
}
|
|
|
|
function buildRequest (R, trustProxy) {
|
|
if (trustProxy) {
|
|
return buildRequestWithTrustProxy(R, trustProxy)
|
|
}
|
|
|
|
return buildRegularRequest(R)
|
|
}
|
|
|
|
function buildRegularRequest (R) {
|
|
const props = [...R.props]
|
|
function _Request (id, params, req, query, log, context) {
|
|
this.id = id
|
|
this.context = context
|
|
this.params = params
|
|
this.raw = req
|
|
this.query = query
|
|
this.log = log
|
|
this.body = null
|
|
|
|
// eslint-disable-next-line no-var
|
|
var prop
|
|
// eslint-disable-next-line no-var
|
|
for (var i = 0; i < props.length; i++) {
|
|
prop = props[i]
|
|
this[prop.key] = prop.value
|
|
}
|
|
}
|
|
_Request.prototype = new R()
|
|
_Request.props = props
|
|
|
|
return _Request
|
|
}
|
|
|
|
function getLastEntryInMultiHeaderValue (headerValue) {
|
|
// we use the last one if the header is set more than once
|
|
const lastIndex = headerValue.lastIndexOf(',')
|
|
return lastIndex === -1 ? headerValue.trim() : headerValue.slice(lastIndex + 1).trim()
|
|
}
|
|
|
|
function buildRequestWithTrustProxy (R, trustProxy) {
|
|
const _Request = buildRegularRequest(R)
|
|
const proxyFn = getTrustProxyFn(trustProxy)
|
|
|
|
Object.defineProperties(_Request.prototype, {
|
|
ip: {
|
|
get () {
|
|
return proxyAddr(this.raw, proxyFn)
|
|
}
|
|
},
|
|
ips: {
|
|
get () {
|
|
return proxyAddr.all(this.raw, proxyFn)
|
|
}
|
|
},
|
|
hostname: {
|
|
get () {
|
|
if (this.ip !== undefined && this.headers['x-forwarded-host']) {
|
|
return getLastEntryInMultiHeaderValue(this.headers['x-forwarded-host'])
|
|
}
|
|
return this.headers.host || this.headers[':authority']
|
|
}
|
|
},
|
|
protocol: {
|
|
get () {
|
|
if (this.headers['x-forwarded-proto']) {
|
|
return getLastEntryInMultiHeaderValue(this.headers['x-forwarded-proto'])
|
|
}
|
|
if (this.socket) {
|
|
return this.socket.encrypted ? 'https' : 'http'
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
return _Request
|
|
}
|
|
|
|
Object.defineProperties(Request.prototype, {
|
|
req: {
|
|
get () {
|
|
warning.emit('FSTDEP001')
|
|
return this.raw
|
|
}
|
|
},
|
|
url: {
|
|
get () {
|
|
return this.raw.url
|
|
}
|
|
},
|
|
method: {
|
|
get () {
|
|
return this.raw.method
|
|
}
|
|
},
|
|
routerPath: {
|
|
get () {
|
|
return this.context.config.url
|
|
}
|
|
},
|
|
routerMethod: {
|
|
get () {
|
|
return this.context.config.method
|
|
}
|
|
},
|
|
is404: {
|
|
get () {
|
|
return this.context.config.url === undefined
|
|
}
|
|
},
|
|
connection: {
|
|
get () {
|
|
/* istanbul ignore next */
|
|
if (semver.gte(process.versions.node, '13.0.0')) {
|
|
warning.emit('FSTDEP005')
|
|
}
|
|
return this.raw.connection
|
|
}
|
|
},
|
|
socket: {
|
|
get () {
|
|
return this.raw.socket
|
|
}
|
|
},
|
|
ip: {
|
|
get () {
|
|
if (this.socket) {
|
|
return this.socket.remoteAddress
|
|
}
|
|
}
|
|
},
|
|
hostname: {
|
|
get () {
|
|
return this.raw.headers.host || this.raw.headers[':authority']
|
|
}
|
|
},
|
|
protocol: {
|
|
get () {
|
|
if (this.socket) {
|
|
return this.socket.encrypted ? 'https' : 'http'
|
|
}
|
|
}
|
|
},
|
|
headers: {
|
|
get () {
|
|
if (this.additionalHeaders) {
|
|
return Object.assign({}, this.raw.headers, this.additionalHeaders)
|
|
}
|
|
return this.raw.headers
|
|
},
|
|
set (headers) {
|
|
this.additionalHeaders = headers
|
|
}
|
|
},
|
|
server: {
|
|
value: null,
|
|
writable: true
|
|
}
|
|
})
|
|
|
|
module.exports = Request
|
|
module.exports.buildRequest = buildRequest
|