1 | 'use strict'
|
2 |
|
3 | const proxyAddr = require('proxy-addr')
|
4 | const semver = require('semver')
|
5 | const warning = require('./warnings')
|
6 |
|
7 | function 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 |
|
17 | function getTrustProxyFn (tp) {
|
18 | if (typeof tp === 'function') {
|
19 | return tp
|
20 | }
|
21 | if (tp === true) {
|
22 |
|
23 | return function () { return true }
|
24 | }
|
25 | if (typeof tp === 'number') {
|
26 |
|
27 | return function (a, i) { return i < tp }
|
28 | }
|
29 | if (typeof tp === 'string') {
|
30 |
|
31 | const vals = tp.split(',').map(it => it.trim())
|
32 | return proxyAddr.compile(vals)
|
33 | }
|
34 | return proxyAddr.compile(tp)
|
35 | }
|
36 |
|
37 | function buildRequest (R, trustProxy) {
|
38 | if (trustProxy) {
|
39 | return buildRequestWithTrustProxy(R, trustProxy)
|
40 | }
|
41 |
|
42 | return buildRegularRequest(R)
|
43 | }
|
44 |
|
45 | function 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 |
|
60 | function 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 |
|
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 |
|
99 | Object.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 |
|
166 | module.exports = Request
|
167 | module.exports.buildRequest = buildRequest
|