1
1
'use strict' ;
2
2
3
3
const utility = require ( '2o3t-utility' ) ;
4
- const isFunction = utility . is . function ;
5
4
const httpProxy = require ( 'http-proxy' ) ;
6
- const logger = require ( './logger' ) ;
7
-
8
5
const createConfig = require ( './createConfig' ) ;
9
6
const handlers = require ( './handlers' ) ;
10
- const PathRewriter = require ( './path-rewriter' ) ;
11
7
const contextMatcher = require ( './context-matcher' ) ;
8
+ const PathRewriter = require ( './path-rewriter' ) ;
12
9
const Router = require ( './router' ) ;
10
+ const logger = require ( './logger' ) ;
11
+
12
+ const isFunction = utility . is . function ;
13
+
14
+ module . exports = Proxy ;
13
15
14
- function PROXY ( context , opts ) {
16
+ function Proxy ( context , opts ) {
15
17
// https://github.com/chimurai/http-proxy-middleware/issues/57
16
- const wsUpgradeDebounced = utility . debounce ( _handleUpgrade ) ;
18
+ const wsUpgradeDebounced = utility . debounce ( handleUpgrade ) ;
17
19
let wsInitialized = false ;
18
20
const config = createConfig ( context , opts ) ;
19
21
const proxyOptions = config . options ;
@@ -27,86 +29,89 @@ function PROXY(context, opts) {
27
29
handlers . init ( proxy , proxyOptions ) ;
28
30
29
31
// log errors for debug purpose
30
- proxy . on ( 'error' , _handleLogError ) ;
32
+ proxy . on ( 'error' , logError ) ;
31
33
32
34
// 新增加的功能
33
35
proxy . on ( 'proxyRes' , _handleProxyResBody ) ;
34
36
35
-
36
37
// https://github.com/chimurai/http-proxy-middleware/issues/19
37
38
// expose function to upgrade externally
38
39
middleware . upgrade = wsUpgradeDebounced ;
39
40
40
- function _handleLogError ( err , req /* res */ ) {
41
- const hostname = ( req . headers && req . headers . host ) || ( req . hostname || req . host ) ; // (websocket) || (node0.10 || node 4/5)
42
- const target = proxyOptions . target . host || proxyOptions . target ;
43
- const errorMessage = 'Error occurred while trying to proxy request %s from %s to %s (%s) (%s)' ;
44
- const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors' ; // link to Node Common Systems Errors page
41
+ return middleware ;
45
42
46
- logger . error ( errorMessage , req . url , hostname , target , err . code , errReference ) ;
47
- }
43
+ async function middleware ( ctx , next ) {
44
+ const req = ctx . req ;
45
+ const res = ctx . res ;
48
46
49
- function _handleProxyResBody ( proxyRes , req , res ) {
50
- const oriWrite = res . write ;
51
- const oriEnd = res . end ;
52
- const proxyBody = proxyOptions . proxyBody ;
53
- if ( proxyBody ) {
54
- const ctx = res . _ctx ;
55
- const jsonStrings = [ ] ;
56
- Object . assign ( res , {
57
- write ( chunk ) {
58
- jsonStrings . push ( chunk ) ;
59
- oriWrite . apply ( res , arguments ) ;
60
- } ,
61
- end ( ) {
62
- let buffer = jsonStrings . join ( ) ;
63
- try {
64
- if ( isFunction ( proxyBody ) ) {
65
- const oriJSONRes = JSON . parse ( buffer . toString ( ) ) ;
66
- const handledJSONRes = proxyBody ( oriJSONRes , proxyRes , req , res , ctx ) ;
67
- buffer = new Buffer ( JSON . stringify ( handledJSONRes ) ) ; // 一定要转成buffer,buffer长度和string长度不一样
68
- } else {
69
- ctx . body = JSON . parse ( buffer . toString ( ) ) ;
70
- }
71
- } catch ( error ) {
72
- logger . warn ( error ) ;
73
- }
74
- oriEnd . apply ( res , arguments ) ;
75
- } ,
76
- } ) ;
47
+ if ( proxyOptions . ws === true ) {
48
+ // use initial request to access the server object to subscribe to http upgrade event
49
+ catchUpgradeRequest ( req . connection . server ) ;
77
50
}
78
- if ( res . __resolve && isFunction ( res . __resolve ) ) {
79
- res . __resolve ( proxyRes ) ;
51
+
52
+ // function middleware(req, res, next) {
53
+ const proxyRes = await new Promise ( resolve => {
54
+ if ( shouldProxy ( config . context , req ) ) {
55
+ ctx . respond = false ;
56
+ ctx . status = 302 ;
57
+ const activeProxyOptions = prepareProxyRequest ( req ) ;
58
+ res . _ctx = ctx ;
59
+ res . _resolve = resolve ;
60
+ proxy . web ( req , res , activeProxyOptions ) ;
61
+ } else {
62
+ resolve ( ) ;
63
+ }
64
+ } ) ;
65
+
66
+ if ( proxyRes ) {
67
+ res . proxyRes = proxyRes ;
80
68
}
69
+
70
+ await next ( ) ;
81
71
}
82
72
83
- function _shouldProxy ( req ) {
84
- const context = config . context ;
85
- const path = ( req . originalUrl || req . url ) ;
86
- return contextMatcher . match ( context , path , req ) ;
73
+ function catchUpgradeRequest ( server ) {
74
+ // subscribe once; don't subscribe on every request...
75
+ // https://github.com/chimurai/http-proxy-middleware/issues/113
76
+ if ( ! wsInitialized ) {
77
+ server . on ( 'upgrade' , wsUpgradeDebounced ) ;
78
+ wsInitialized = true ;
79
+ }
87
80
}
88
81
89
- function _handleUpgrade ( req , socket , head ) {
82
+ function handleUpgrade ( req , socket , head ) {
90
83
// set to initialized when used externally
91
- _wsInitialized = true ;
84
+ wsInitialized = true ;
92
85
93
- if ( _shouldProxy ( req ) ) {
86
+ if ( shouldProxy ( config . context , req ) ) {
94
87
const activeProxyOptions = prepareProxyRequest ( req ) ;
95
88
proxy . ws ( req , socket , head , activeProxyOptions ) ;
96
89
logger . system ( 'Upgrading to WebSocket' ) ;
97
90
}
98
91
}
99
92
100
- function _catchUpgradeRequest ( server ) {
101
- // subscribe once; don't subscribe on every request...
102
- // https://github.com/chimurai/http-proxy-middleware/issues/113
103
- if ( ! _wsInitialized ) {
104
- server . on ( 'upgrade' , wsUpgradeDebounced ) ;
105
- _wsInitialized = true ;
106
- }
93
+ /**
94
+ * Determine whether request should be proxied.
95
+ *
96
+ * @private
97
+ * @param {String } context [description]
98
+ * @param {Object } req [description]
99
+ * @return {Boolean } bool
100
+ */
101
+ function shouldProxy ( context , req ) {
102
+ const path = ( req . originalUrl || req . url ) ;
103
+ return contextMatcher . match ( context , path , req ) ;
107
104
}
108
105
109
- function _prepareProxyRequest ( req ) {
106
+ /**
107
+ * Apply option.router and option.pathRewrite
108
+ * Order matters:
109
+ * Router uses original path for routing;
110
+ * NOT the modified path, after it has been rewritten by pathRewrite
111
+ * @param {Object } req req
112
+ * @return {Object } proxy options
113
+ */
114
+ function prepareProxyRequest ( req ) {
110
115
// https://github.com/chimurai/http-proxy-middleware/issues/17
111
116
// https://github.com/chimurai/http-proxy-middleware/issues/94
112
117
req . url = ( req . originalUrl || req . url ) ;
@@ -123,73 +128,78 @@ function PROXY(context, opts) {
123
128
return newProxyOptions ;
124
129
}
125
130
126
- middleware . upgrade = wsUpgradeDebounced ;
127
-
128
- logger . system ( 'inited...' ) ;
131
+ // Modify option.target when router present.
132
+ function __applyRouter ( req , options ) {
133
+ let newTarget ;
129
134
130
- return middleware ;
131
-
132
- async function middleware ( ctx , next ) {
133
- const req = ctx . req ;
134
- const res = ctx . res ;
135
+ if ( options . router ) {
136
+ newTarget = Router . getTarget ( req , options ) ;
135
137
136
- if ( proxyOptions . ws === true ) {
137
- // use initial request to access the server object to subscribe to http upgrade event
138
- _catchUpgradeRequest ( req . connection . server ) ;
138
+ if ( newTarget ) {
139
+ logger . system (
140
+ '[Proxy] Router new target: %s -> "%s"' ,
141
+ options . target ,
142
+ newTarget
143
+ ) ;
144
+ options . target = newTarget ;
145
+ }
139
146
}
147
+ }
140
148
141
- // function middleware(req, res, next) {
142
- const proxyRes = await new Promise ( resolve => {
143
- if ( _shouldProxy ( req ) ) {
144
- ctx . respond = false ;
145
- ctx . status = 302 ;
146
- const activeProxyOptions = _prepareProxyRequest ( req ) ;
147
- res . _ctx = ctx ;
148
- res . __resolve = resolve ;
149
+ // rewrite path
150
+ function __applyPathRewrite ( req , pathRewriter ) {
151
+ if ( pathRewriter ) {
152
+ const path = pathRewriter ( req . url , req ) ;
149
153
150
- proxy . web ( req , res , activeProxyOptions ) ;
154
+ if ( typeof path === 'string' ) {
155
+ req . url = path ;
151
156
} else {
152
- resolve ( ) ;
157
+ logger . system ( 'pathRewrite: No rewritten path found. (%s)' , req . url ) ;
153
158
}
154
- } ) ;
155
-
156
- if ( proxyRes ) {
157
- res . proxyRes = proxyRes ;
158
159
}
159
-
160
- await next ( ) ;
161
160
}
162
- }
163
161
164
- // Modify option.target when router present.
165
- function __applyRouter ( req , options ) {
166
- let newTarget ;
167
-
168
- if ( options . router ) {
169
- newTarget = Router . getTarget ( req , options ) ;
162
+ function logError ( err , req /* res */ ) {
163
+ const hostname = ( req . headers && req . headers . host ) || ( req . hostname || req . host ) ; // (websocket) || (node0.10 || node 4/5)
164
+ const target = proxyOptions . target . host || proxyOptions . target ;
165
+ const errorMessage = 'Error occurred while trying to proxy request %s from %s to %s (%s) (%s)' ;
166
+ const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors' ; // link to Node Common Systems Errors page
170
167
171
- if ( newTarget ) {
172
- logger . system (
173
- 'Router new target: %s -> "%s"' ,
174
- options . target ,
175
- newTarget
176
- ) ;
177
- options . target = newTarget ;
178
- }
168
+ logger . error ( errorMessage , req . url , hostname , target , err . code , errReference ) ;
179
169
}
180
- }
181
170
182
- // rewrite path
183
- function __applyPathRewrite ( req , pathRewriter ) {
184
- if ( pathRewriter ) {
185
- const path = pathRewriter ( req . url , req ) ;
171
+ function _handleProxyResBody ( proxyRes , req , res ) {
172
+ const oriWrite = res . write ;
173
+ const oriEnd = res . end ;
186
174
187
- if ( typeof path === 'string' ) {
188
- req . url = path ;
189
- } else {
190
- logger . system ( 'pathRewrite: No rewritten path found. (%s)' , req . url ) ;
175
+ const proxyBody = proxyOptions . proxyBody ;
176
+ if ( proxyBody ) {
177
+ const ctx = res . _ctx ;
178
+ const jsonStrings = [ ] ;
179
+ Object . assign ( res , {
180
+ write ( chunk ) {
181
+ jsonStrings . push ( chunk ) ;
182
+ oriWrite . apply ( res , arguments ) ;
183
+ } ,
184
+ end ( ) {
185
+ let buffer = jsonStrings . join ( ) ;
186
+ try {
187
+ if ( isFunction ( proxyBody ) ) {
188
+ const oriJSONRes = JSON . parse ( buffer . toString ( ) ) ;
189
+ const handledJSONRes = proxyBody ( oriJSONRes , proxyRes , req , res , ctx ) ;
190
+ buffer = new Buffer ( JSON . stringify ( handledJSONRes ) ) ; // 一定要转成buffer,buffer长度和string长度不一样
191
+ } else {
192
+ ctx . body = JSON . parse ( buffer . toString ( ) ) ;
193
+ }
194
+ } catch ( error ) {
195
+ logger . warn ( error ) ;
196
+ }
197
+ oriEnd . apply ( res , arguments ) ;
198
+ } ,
199
+ } ) ;
200
+ }
201
+ if ( res . _resolve && isFunction ( res . _resolve ) ) {
202
+ res . _resolve ( proxyRes ) ;
191
203
}
192
204
}
193
205
}
194
-
195
- module . exports = PROXY ;
0 commit comments