UNPKG

3.47 kBJavaScriptView Raw
1'use strict'
2
3const proxyAddr = require('proxy-addr')
4const semver = require('semver')
5const warning = require('./warnings')
6
7function Request (id, params, req, query, log, context) {
8 this.id = id
9 this.context = context
10 this.params = params
11 this.raw = req
12 this.query = query
13 this.log = log
14 this.body = null
15}
16
17function getTrustProxyFn (tp) {
18 if (typeof tp === 'function') {
19 return tp
20 }
21 if (tp === true) {
22 // Support plain true/false
23 return function () { return true }
24 }
25 if (typeof tp === 'number') {
26 // Support trusting hop count
27 return function (a, i) { return i < tp }
28 }
29 if (typeof tp === 'string') {
30 // Support comma-separated tps
31 const vals = tp.split(',').map(it => it.trim())
32 return proxyAddr.compile(vals)
33 }
34 return proxyAddr.compile(tp)
35}
36
37function buildRequest (R, trustProxy) {
38 if (trustProxy) {
39 return buildRequestWithTrustProxy(R, trustProxy)
40 }
41
42 return buildRegularRequest(R)
43}
44
45function buildRegularRequest (R) {
46 function _Request (id, params, req, query, log, context) {
47 this.id = id
48 this.context = context
49 this.params = params
50 this.raw = req
51 this.query = query
52 this.log = log
53 this.body = null
54 }
55 _Request.prototype = new R()
56
57 return _Request
58}
59
60function buildRequestWithTrustProxy (R, trustProxy) {
61 const _Request = buildRegularRequest(R)
62 const proxyFn = getTrustProxyFn(trustProxy)
63
64 Object.defineProperties(_Request.prototype, {
65 ip: {
66 get () {
67 return proxyAddr(this.raw, proxyFn)
68 }
69 },
70 ips: {
71 get () {
72 return proxyAddr.all(this.raw, proxyFn)
73 }
74 },
75 hostname: {
76 get () {
77 if (this.ip !== undefined && this.headers['x-forwarded-host']) {
78 return this.headers['x-forwarded-host']
79 }
80 return this.headers.host || this.headers[':authority']
81 }
82 },
83 protocol: {
84 get () {
85 if (this.headers['x-forwarded-proto']) {
86 const proto = this.headers['x-forwarded-proto']
87 // we use the last one if the header is set more than once
88 const lastIndex = proto.lastIndexOf(',')
89 return lastIndex === -1 ? proto.trim() : proto.slice(lastIndex + 1).trim()
90 }
91 return this.socket.encrypted ? 'https' : 'http'
92 }
93 }
94 })
95
96 return _Request
97}
98
99Object.defineProperties(Request.prototype, {
100 req: {
101 get () {
102 warning.emit('FSTDEP001')
103 return this.raw
104 }
105 },
106 url: {
107 get () {
108 return this.raw.url
109 }
110 },
111 method: {
112 get () {
113 return this.raw.method
114 }
115 },
116 routerPath: {
117 get () {
118 return this.context.config.url
119 }
120 },
121 routerMethod: {
122 get () {
123 return this.context.config.method
124 }
125 },
126 is404: {
127 get () {
128 return this.context.config.url === undefined
129 }
130 },
131 connection: {
132 get () {
133 if (semver.gte(process.versions.node, '13.0.0')) {
134 warning.emit('FSTDEP005')
135 }
136 return this.raw.connection
137 }
138 },
139 socket: {
140 get () {
141 return this.raw.socket
142 }
143 },
144 ip: {
145 get () {
146 return this.socket.remoteAddress
147 }
148 },
149 hostname: {
150 get () {
151 return this.raw.headers.host || this.raw.headers[':authority']
152 }
153 },
154 protocol: {
155 get () {
156 return this.socket.encrypted ? 'https' : 'http'
157 }
158 },
159 headers: {
160 get () {
161 return this.raw.headers
162 }
163 }
164})
165
166module.exports = Request
167module.exports.buildRequest = buildRequest