1
+ var events = require ( 'events' ) ,
2
+ util = require ( 'util' ) ,
3
+ HttpProxy = require ( './http-proxy' ) . HttpProxy ,
4
+ ProxyTable = require ( './proxy-table' ) . ProxyTable ;
1
5
2
- var RoutingProxy = exports . RoutingProxy = function ( ) {
6
+ //
7
+ // ### function RoutingProxy (options)
8
+ // #### @options {Object} Options for this instance
9
+ // Constructor function for the RoutingProxy object, a higher level
10
+ // reverse proxy Object which can proxy to multiple hosts and also interface
11
+ // easily with a RoutingTable instance.
12
+ //
13
+ var RoutingProxy = exports . RoutingProxy = function ( options ) {
14
+ events . EventEmitter . call ( this ) ;
3
15
16
+ if ( options . router ) {
17
+ //
18
+ // TODO: Consume the RoutingTable for various things: `this.proxyTable`
19
+ //
20
+ }
21
+
22
+ //
23
+ // Create a set of `HttpProxy` objects to be used later on calls
24
+ // to `.proxyRequest()` and `.proxyWebSocketRequest()`.
25
+ //
26
+ this . proxies = { } ;
27
+ } ;
28
+
29
+
30
+ //
31
+ // Inherit from `events.EventEmitter`.
32
+ //
33
+ util . inherits ( RoutingProxy , events . EventEmitter ) ;
34
+
35
+ //
36
+ // ### function add (options)
37
+ // #### @options {Object} Options for the `HttpProxy` to add.
38
+ // Adds a new instance of `HttpProxy` to this `RoutingProxy` instance
39
+ // for the specified `options.host` and `options.port`.
40
+ //
41
+ RoutingProxy . prototype . add = function ( options ) {
42
+
43
+ } ;
44
+
45
+ //
46
+ // ### function remove (options)
47
+ // #### @options {Object} Options mapping to the `HttpProxy` to remove.
48
+ // Removes an instance of `HttpProxy` from this `RoutingProxy` instance
49
+ // for the specified `options.host` and `options.port` (if they exist).
50
+ //
51
+ RoutingProxy . prototype . remove = function ( options ) {
52
+
53
+ } ;
54
+
55
+ //
56
+ // ### function close()
57
+ // Cleans up any state left behind (sockets, timeouts, etc)
58
+ // associated with this instance.
59
+ //
60
+ RoutingProxy . prototype . close = function ( ) {
61
+ var self = this ;
62
+
63
+ if ( this . proxyTable ) {
64
+ //
65
+ // Close the `RoutingTable` associated with
66
+ // this instance (if any).
67
+ //
68
+ this . proxyTable . close ( ) ;
69
+ }
70
+
71
+ //
72
+ // Close all sockets for all `HttpProxy` object(s)
73
+ // associated with this instance.
74
+ //
75
+ Object . keys ( this . proxies ) . forEach ( function ( key ) {
76
+ self . proxies [ key ] . close ( ) ;
77
+ } ) ;
78
+ } ;
79
+
80
+ //
81
+ // ### function proxyRequest (req, res, [port, host, paused])
82
+ // #### @req {ServerRequest} Incoming HTTP Request to proxy.
83
+ // #### @res {ServerResponse} Outgoing HTTP Request to write proxied data to.
84
+ // #### @options {Object} Options for the outgoing proxy request.
85
+ //
86
+ // options.port {number} Port to use on the proxy target host.
87
+ // options.host {string} Host of the proxy target.
88
+ // options.buffer {Object} Result from `httpProxy.buffer(req)`
89
+ // options.https {Object|boolean} Settings for https.
90
+ //
91
+ RoutingProxy . prototype . proxyRequest = function ( req , res , options ) {
92
+ options = options || { } ;
93
+
94
+ //
95
+ // Check the proxy table for this instance to see if we need
96
+ // to get the proxy location for the request supplied. We will
97
+ // always ignore the proxyTable if an explicit `port` and `host`
98
+ // arguments are supplied to `proxyRequest`.
99
+ //
100
+ if ( this . proxyTable && ! options . host ) {
101
+ location = this . proxyTable . getProxyLocation ( req ) ;
102
+
103
+ //
104
+ // If no location is returned from the ProxyTable instance
105
+ // then respond with `404` since we do not have a valid proxy target.
106
+ //
107
+ if ( ! location ) {
108
+ try {
109
+ res . writeHead ( 404 ) ;
110
+ res . end ( ) ;
111
+ }
112
+ catch ( er ) {
113
+ console . error ( "res.writeHead/res.end error: %s" , er . message ) ;
114
+ }
115
+
116
+ return ;
117
+ }
118
+
119
+ //
120
+ // When using the ProxyTable in conjunction with an HttpProxy instance
121
+ // only the following arguments are valid:
122
+ //
123
+ // * `proxy.proxyRequest(req, res, { host: 'localhost' })`: This will be skipped
124
+ // * `proxy.proxyRequest(req, res, { buffer: buffer })`: Buffer will get updated appropriately
125
+ // * `proxy.proxyRequest(req, res)`: Options will be assigned appropriately.
126
+ //
127
+ options . port = location . port ;
128
+ options . host = location . host ;
129
+ }
130
+
131
+ var key = options . host + ':' + options . port ,
132
+ proxy = this . proxies [ key ] || this . _addTarget ( options ) ;
133
+
134
+ proxy . proxyRequest ( req , res , options . buffer ) ;
135
+ } ;
136
+
137
+ //
138
+ // ### function proxyWebSocketRequest (req, socket, head, options)
139
+ // #### @req {ServerRequest} Websocket request to proxy.
140
+ // #### @socket {net.Socket} Socket for the underlying HTTP request
141
+ // #### @head {string} Headers for the Websocket request.
142
+ // #### @options {Object} Options to use when proxying this request.
143
+ //
144
+ // options.port {number} Port to use on the proxy target host.
145
+ // options.host {string} Host of the proxy target.
146
+ // options.buffer {Object} Result from `httpProxy.buffer(req)`
147
+ // options.https {Object|boolean} Settings for https.
148
+ //
149
+ RoutingProxy . prototype . proxyWebSocketRequest = function ( req , socket , head , options ) {
150
+ options = options || { } ;
151
+
152
+ if ( this . proxyTable && ! options . host ) {
153
+ location = this . proxyTable . getProxyLocation ( req ) ;
154
+
155
+ if ( ! location ) {
156
+ return socket . destroy ( ) ;
157
+ }
158
+
159
+ options . port = location . port ;
160
+ options . host = location . host ;
161
+ }
162
+
163
+ var key = options . host + ':' + options . port ,
164
+ proxy = this . proxies [ key ] || this . _addTarget ( options ) ;
165
+
166
+ proxy . proxyWebSocketRequest ( req , socket , head , options . buffer ) ;
4
167
} ;
0 commit comments