1 | var expect = require('chai').expect;
|
2 | var proxyMiddleware = require('../index');
|
3 | var http = require('http');
|
4 | var express = require('express');
|
5 |
|
6 | describe('http-proxy-middleware creation', function() {
|
7 | it('should create a middleware', function() {
|
8 | var middleware;
|
9 | middleware = proxyMiddleware('/api', {target: 'http://localhost:8000'});
|
10 | expect(middleware).to.be.a('function');
|
11 | });
|
12 | });
|
13 |
|
14 | describe('context matching', function() {
|
15 | describe('do not proxy', function() {
|
16 | var isSkipped;
|
17 |
|
18 | beforeEach(function() {
|
19 | isSkipped = false;
|
20 |
|
21 | var middleware;
|
22 |
|
23 | var mockReq = {url: '/foo/bar'};
|
24 | var mockRes = {};
|
25 | var mockNext = function() {
|
26 |
|
27 | isSkipped = true;
|
28 | };
|
29 |
|
30 | middleware = proxyMiddleware('/api', {target: 'http://localhost:8000'});
|
31 | middleware(mockReq, mockRes, mockNext);
|
32 | });
|
33 |
|
34 | it('should not proxy requests when request url does not match context' , function() {
|
35 | expect(isSkipped).to.be.true;
|
36 | });
|
37 |
|
38 | });
|
39 | });
|
40 |
|
41 | describe('http-proxy-middleware in actual server', function() {
|
42 |
|
43 | describe('basic setup, requests to target', function() {
|
44 | var proxyServer, targetServer;
|
45 | var targetHeaders;
|
46 | var targetUrl;
|
47 | var responseBody;
|
48 |
|
49 | beforeEach(function(done) {
|
50 | var mw_proxy = proxyMiddleware('/api', {target: 'http://localhost:8000'});
|
51 |
|
52 | var mw_target = function(req, res, next) {
|
53 | targetUrl = req.url;
|
54 | targetHeaders = req.headers;
|
55 | res.write('HELLO WEB');
|
56 | res.end();
|
57 | };
|
58 |
|
59 | proxyServer = createServer(3000, mw_proxy);
|
60 | targetServer = createServer(8000, mw_target);
|
61 |
|
62 | http.get('http://localhost:3000/api/b/c/d;p?q=1&r=[2,3]#s"', function(res) {
|
63 | res.on('data', function(chunk) {
|
64 | responseBody = chunk.toString();
|
65 | done();
|
66 | });
|
67 | });
|
68 | });
|
69 |
|
70 | afterEach(function() {
|
71 | proxyServer.close();
|
72 | targetServer.close();
|
73 | });
|
74 |
|
75 | it('should have the same headers.host value', function() {
|
76 | expect(targetHeaders.host).to.equal('localhost:3000');
|
77 | });
|
78 |
|
79 | it('should have proxied the uri-path and uri-query, but not the uri-hash', function() {
|
80 | expect(targetUrl).to.equal('/api/b/c/d;p?q=1&r=[2,3]');
|
81 | });
|
82 |
|
83 | it('should have response body: "HELLO WEB"', function() {
|
84 | expect(responseBody).to.equal('HELLO WEB');
|
85 | });
|
86 | });
|
87 |
|
88 | describe('multi path', function() {
|
89 | var proxyServer, targetServer;
|
90 | var targetHeaders;
|
91 | var response, responseBody;
|
92 |
|
93 | beforeEach(function() {
|
94 | var mw_proxy = proxyMiddleware(['/api', '/ajax'], {target: 'http://localhost:8000'});
|
95 |
|
96 | var mw_target = function(req, res, next) {
|
97 | res.write(req.url);
|
98 | res.end();
|
99 | };
|
100 |
|
101 | proxyServer = createServer(3000, mw_proxy);
|
102 | targetServer = createServer(8000, mw_target);
|
103 | });
|
104 |
|
105 | afterEach(function() {
|
106 | proxyServer.close();
|
107 | targetServer.close();
|
108 | });
|
109 |
|
110 | describe('request to path A, configured', function() {
|
111 | beforeEach(function(done) {
|
112 | http.get('http://localhost:3000/api/some/endpoint', function(res) {
|
113 | response = res;
|
114 | res.on('data', function(chunk) {
|
115 | responseBody = chunk.toString();
|
116 | done();
|
117 | });
|
118 | });
|
119 | });
|
120 |
|
121 | it('should proxy to path A', function() {
|
122 | expect(response.statusCode).to.equal(200);
|
123 | expect(responseBody).to.equal('/api/some/endpoint');
|
124 | });
|
125 | });
|
126 |
|
127 | describe('request to path B, configured', function() {
|
128 | beforeEach(function(done) {
|
129 | http.get('http://localhost:3000/ajax/some/library', function(res) {
|
130 | response = res;
|
131 | res.on('data', function(chunk) {
|
132 | responseBody = chunk.toString();
|
133 | done();
|
134 | });
|
135 | });
|
136 | });
|
137 |
|
138 | it('should proxy to path B', function() {
|
139 | expect(response.statusCode).to.equal(200);
|
140 | expect(responseBody).to.equal('/ajax/some/library');
|
141 | });
|
142 | });
|
143 |
|
144 | describe('request to path C, not configured', function() {
|
145 | beforeEach(function(done) {
|
146 | http.get('http://localhost:3000/lorum/ipsum', function(res) {
|
147 | response = res;
|
148 | res.on('data', function(chunk) {
|
149 | responseBody = chunk.toString();
|
150 | done();
|
151 | });
|
152 | });
|
153 | });
|
154 |
|
155 | it('should not proxy to this path', function() {
|
156 | expect(response.statusCode).to.equal(404);
|
157 | });
|
158 | });
|
159 |
|
160 | });
|
161 |
|
162 | describe('wildcard path matching', function() {
|
163 | var proxyServer, targetServer;
|
164 | var targetHeaders;
|
165 | var response, responseBody;
|
166 |
|
167 | beforeEach(function() {
|
168 | var mw_proxy = proxyMiddleware('/api/**', {target: 'http://localhost:8000'});
|
169 |
|
170 | var mw_target = function(req, res, next) {
|
171 | res.write(req.url);
|
172 | res.end();
|
173 | };
|
174 |
|
175 | proxyServer = createServer(3000, mw_proxy);
|
176 | targetServer = createServer(8000, mw_target);
|
177 | });
|
178 |
|
179 | beforeEach(function(done) {
|
180 | http.get('http://localhost:3000/api/some/endpoint', function(res) {
|
181 | response = res;
|
182 | res.on('data', function(chunk) {
|
183 | responseBody = chunk.toString();
|
184 | done();
|
185 | });
|
186 | });
|
187 | });
|
188 |
|
189 | afterEach(function() {
|
190 | proxyServer.close();
|
191 | targetServer.close();
|
192 | });
|
193 |
|
194 | it('should proxy to path', function() {
|
195 | expect(response.statusCode).to.equal(200);
|
196 | expect(responseBody).to.equal('/api/some/endpoint');
|
197 | });
|
198 | });
|
199 |
|
200 | describe('multi glob wildcard path matching', function() {
|
201 | var proxyServer, targetServer;
|
202 | var targetHeaders;
|
203 | var responseA, responseBodyA;
|
204 | var responseB, responseBodyB;
|
205 |
|
206 | beforeEach(function() {
|
207 | var mw_proxy = proxyMiddleware(['/**.html', '!**.json'], {target: 'http://localhost:8000'});
|
208 |
|
209 | var mw_target = function(req, res, next) {
|
210 | res.write(req.url);
|
211 | res.end();
|
212 | };
|
213 |
|
214 | proxyServer = createServer(3000, mw_proxy);
|
215 | targetServer = createServer(8000, mw_target);
|
216 | });
|
217 |
|
218 | beforeEach(function(done) {
|
219 | http.get('http://localhost:3000/api/some/endpoint/index.html', function(res) {
|
220 | responseA = res;
|
221 | res.on('data', function(chunk) {
|
222 | responseBodyA = chunk.toString();
|
223 | done();
|
224 | });
|
225 | });
|
226 | });
|
227 |
|
228 | beforeEach(function(done) {
|
229 | http.get('http://localhost:3000/api/some/endpoint/data.json', function(res) {
|
230 | responseB = res;
|
231 | res.on('data', function(chunk) {
|
232 | responseBodyB = chunk.toString();
|
233 | done();
|
234 | });
|
235 | });
|
236 | });
|
237 |
|
238 | afterEach(function() {
|
239 | proxyServer.close();
|
240 | targetServer.close();
|
241 | });
|
242 |
|
243 | it('should proxy to paths ending with *.html', function() {
|
244 | expect(responseA.statusCode).to.equal(200);
|
245 | expect(responseBodyA).to.equal('/api/some/endpoint/index.html');
|
246 | });
|
247 |
|
248 | it('should not proxy to paths ending with *.json', function() {
|
249 | expect(responseB.statusCode).to.equal(404);
|
250 | });
|
251 | });
|
252 |
|
253 | describe('option.headers - additional request headers', function() {
|
254 | var proxyServer, targetServer;
|
255 | var targetHeaders;
|
256 |
|
257 | beforeEach(function(done) {
|
258 | var mw_proxy = proxyMiddleware('/api', {target: 'http://localhost:8000', headers: {host: 'foobar.dev'}});
|
259 |
|
260 | var mw_target = function(req, res, next) {
|
261 | targetHeaders = req.headers;
|
262 | res.end();
|
263 | };
|
264 |
|
265 | proxyServer = createServer(3000, mw_proxy);
|
266 | targetServer = createServer(8000, mw_target);
|
267 |
|
268 | http.get('http://localhost:3000/api/', function(res) {
|
269 | done();
|
270 | });
|
271 | });
|
272 |
|
273 | afterEach(function() {
|
274 | proxyServer.close();
|
275 | targetServer.close();
|
276 | });
|
277 |
|
278 | it('should send request header "host" to target server', function() {
|
279 | expect(targetHeaders.host).to.equal('foobar.dev');
|
280 | });
|
281 | });
|
282 |
|
283 | describe('legacy option.proxyHost', function() {
|
284 | var proxyServer, targetServer;
|
285 | var targetHeaders;
|
286 |
|
287 | beforeEach(function(done) {
|
288 | var mw_proxy = proxyMiddleware('/api', {target: 'http://localhost:8000', proxyHost: 'foobar.dev'});
|
289 |
|
290 | var mw_target = function(req, res, next) {
|
291 | targetHeaders = req.headers;
|
292 | res.end();
|
293 | };
|
294 |
|
295 | proxyServer = createServer(3000, mw_proxy);
|
296 | targetServer = createServer(8000, mw_target);
|
297 |
|
298 | http.get('http://localhost:3000/api/', function(res) {
|
299 | done();
|
300 | });
|
301 | });
|
302 |
|
303 | afterEach(function() {
|
304 | proxyServer.close();
|
305 | targetServer.close();
|
306 | });
|
307 |
|
308 | it('should proxy host header to target server', function() {
|
309 | expect(targetHeaders.host).to.equal('foobar.dev');
|
310 | });
|
311 | });
|
312 |
|
313 | describe('option.onError - Error handling', function() {
|
314 | var proxyServer, targetServer;
|
315 | var response, responseBody;
|
316 |
|
317 | describe('default', function() {
|
318 | beforeEach(function(done) {
|
319 | var mw_proxy = proxyMiddleware('/api', {target: 'http://localhost:666'});
|
320 | var mw_target = function(req, res, next) {next();};
|
321 |
|
322 | proxyServer = createServer(3000, mw_proxy);
|
323 | targetServer = createServer(8000, mw_target);
|
324 |
|
325 | http.get('http://localhost:3000/api/', function(res) {
|
326 | response = res;
|
327 | done();
|
328 | });
|
329 | });
|
330 |
|
331 | afterEach(function() {
|
332 | proxyServer.close();
|
333 | targetServer.close();
|
334 | });
|
335 |
|
336 | it('should handle errors when host is not reachable', function() {
|
337 | expect(response.statusCode).to.equal(500);
|
338 | });
|
339 | });
|
340 |
|
341 | describe('custom', function() {
|
342 | beforeEach(function(done) {
|
343 | var customOnError = function(err, req, res) {
|
344 | res.writeHead(418);
|
345 | res.end('I\'m a teapot');
|
346 | };
|
347 |
|
348 | var mw_proxy = proxyMiddleware('/api', {target: 'http://localhost:666', onError: customOnError});
|
349 | var mw_target = function(req, res, next) {next();};
|
350 |
|
351 | proxyServer = createServer(3000, mw_proxy);
|
352 | targetServer = createServer(8000, mw_target);
|
353 |
|
354 | http.get('http://localhost:3000/api/', function(res) {
|
355 | response = res;
|
356 | res.on('data', function(chunk) {
|
357 | responseBody = chunk.toString();
|
358 | done();
|
359 | });
|
360 | });
|
361 | });
|
362 |
|
363 | afterEach(function() {
|
364 | proxyServer.close();
|
365 | targetServer.close();
|
366 | });
|
367 |
|
368 | it('should respond with custom http status code', function() {
|
369 | expect(response.statusCode).to.equal(418);
|
370 | });
|
371 |
|
372 | it('should respond with custom status message', function() {
|
373 | expect(responseBody).to.equal('I\'m a teapot');
|
374 | });
|
375 | });
|
376 | });
|
377 |
|
378 | describe('option.onProxyRes', function() {
|
379 | var proxyServer, targetServer;
|
380 | var response, responseBody;
|
381 |
|
382 | beforeEach(function(done) {
|
383 | var fnOnProxyRes = function(proxyRes, req, res) {
|
384 | proxyRes.headers['x-added'] = 'foobar';
|
385 | delete proxyRes.headers['x-removed'];
|
386 | };
|
387 |
|
388 | var mw_proxy = proxyMiddleware('/api', {
|
389 | target: 'http://localhost:8000',
|
390 | onProxyRes: fnOnProxyRes
|
391 | });
|
392 | var mw_target = function(req, res, next) {
|
393 | res.setHeader('x-removed', 'remove-header');
|
394 | res.write(req.url);
|
395 | res.end();
|
396 | };
|
397 |
|
398 | proxyServer = createServer(3000, mw_proxy);
|
399 | targetServer = createServer(8000, mw_target);
|
400 |
|
401 | http.get('http://localhost:3000/api/foo/bar', function(res) {
|
402 | response = res;
|
403 | res.on('data', function(chunk) {
|
404 | responseBody = chunk.toString();
|
405 | done();
|
406 | });
|
407 | });
|
408 | });
|
409 |
|
410 | afterEach(function() {
|
411 | proxyServer.close();
|
412 | targetServer.close();
|
413 | });
|
414 |
|
415 | it('should add `x-added` as custom header to response"', function() {
|
416 | expect(response.headers['x-added']).to.equal('foobar');
|
417 | });
|
418 |
|
419 | it('should remove `x-removed` field from response header"', function() {
|
420 | expect(response.headers['x-removed']).to.equal(undefined);
|
421 | });
|
422 | });
|
423 |
|
424 | describe('option.onProxyReq', function() {
|
425 | var proxyServer, targetServer;
|
426 | var receivedRequest;
|
427 |
|
428 | beforeEach(function(done) {
|
429 | var fnOnProxyReq = function(proxyReq, req, res) {
|
430 | proxyReq.setHeader('x-added', 'foobar');
|
431 | };
|
432 |
|
433 | var mw_proxy = proxyMiddleware('/api', {
|
434 | target: 'http://localhost:8000',
|
435 | onProxyReq: fnOnProxyReq
|
436 | });
|
437 |
|
438 | var mw_target = function(req, res, next) {
|
439 | receivedRequest = req;
|
440 | res.write(req.url);
|
441 | res.end();
|
442 | };
|
443 |
|
444 | proxyServer = createServer(3000, mw_proxy);
|
445 | targetServer = createServer(8000, mw_target);
|
446 |
|
447 | http.get('http://localhost:3000/api/foo/bar', function() {
|
448 | done();
|
449 | });
|
450 | });
|
451 |
|
452 | afterEach(function() {
|
453 | proxyServer.close();
|
454 | targetServer.close();
|
455 | });
|
456 |
|
457 | it('should add `x-added` as custom header to request"', function() {
|
458 | expect(receivedRequest.headers['x-added']).to.equal('foobar');
|
459 | });
|
460 | });
|
461 |
|
462 | describe('option.pathRewrite', function() {
|
463 | var proxyServer, targetServer;
|
464 | var responseBody;
|
465 |
|
466 | beforeEach(function(done) {
|
467 | var mw_proxy = proxyMiddleware('/api', {
|
468 | target: 'http://localhost:8000',
|
469 | pathRewrite: {
|
470 | '^/api': '/rest',
|
471 | '^/remove': ''
|
472 | }
|
473 | });
|
474 | var mw_target = function(req, res, next) {
|
475 | res.write(req.url);
|
476 | res.end();
|
477 | };
|
478 |
|
479 | proxyServer = createServer(3000, mw_proxy);
|
480 | targetServer = createServer(8000, mw_target);
|
481 |
|
482 | http.get('http://localhost:3000/api/foo/bar', function(res) {
|
483 | res.on('data', function(chunk) {
|
484 | responseBody = chunk.toString();
|
485 | done();
|
486 | });
|
487 | });
|
488 | });
|
489 |
|
490 | afterEach(function() {
|
491 | proxyServer.close();
|
492 | targetServer.close();
|
493 | });
|
494 |
|
495 | it('should have rewritten path from "/api/foo/bar" to "/rest/foo/bar"', function() {
|
496 | expect(responseBody).to.equal('/rest/foo/bar');
|
497 | });
|
498 | });
|
499 |
|
500 | describe('shorthand usage', function() {
|
501 | var proxyServer, targetServer;
|
502 | var responseBody;
|
503 |
|
504 | beforeEach(function(done) {
|
505 | var mw_proxy = proxyMiddleware('http://localhost:8000/api');
|
506 | var mw_target = function(req, res, next) {
|
507 | res.write(req.url);
|
508 | res.end();
|
509 | };
|
510 |
|
511 | proxyServer = createServer(3000, mw_proxy);
|
512 | targetServer = createServer(8000, mw_target);
|
513 |
|
514 | http.get('http://localhost:3000/api/foo/bar', function(res) {
|
515 | res.on('data', function(chunk) {
|
516 | responseBody = chunk.toString();
|
517 | done();
|
518 | });
|
519 | });
|
520 | });
|
521 |
|
522 | afterEach(function() {
|
523 | proxyServer.close();
|
524 | targetServer.close();
|
525 | });
|
526 |
|
527 | it('should have proxy with shorthand configuration', function() {
|
528 | expect(responseBody).to.equal('/api/foo/bar');
|
529 | });
|
530 | });
|
531 |
|
532 | describe('express with path + proxy', function() {
|
533 | var proxyServer, targetServer;
|
534 | var responseBody;
|
535 |
|
536 | beforeEach(function(done) {
|
537 | var mw_proxy = proxyMiddleware('http://localhost:8000');
|
538 | var mw_target = function(req, res, next) {
|
539 | res.write(req.url);
|
540 | res.end();
|
541 | };
|
542 |
|
543 | proxyServer = createServer(3000, mw_proxy, '/api');
|
544 | targetServer = createServer(8000, mw_target);
|
545 |
|
546 | http.get('http://localhost:3000/api/foo/bar', function(res) {
|
547 | res.on('data', function(chunk) {
|
548 | responseBody = chunk.toString();
|
549 | done();
|
550 | });
|
551 | });
|
552 | });
|
553 |
|
554 | afterEach(function() {
|
555 | proxyServer.close();
|
556 | targetServer.close();
|
557 | });
|
558 |
|
559 | it('should proxy to target with the baseUrl', function() {
|
560 | expect(responseBody).to.equal('/api/foo/bar');
|
561 | });
|
562 |
|
563 | });
|
564 |
|
565 | describe('option.logLevel & option.logProvider', function() {
|
566 | var proxyServer, targetServer;
|
567 | var responseBody;
|
568 | var logMessage;
|
569 |
|
570 | beforeEach(function(done) {
|
571 | var customLogger = function(message) {
|
572 | logMessage = message;
|
573 | };
|
574 |
|
575 | var mw_proxy = proxyMiddleware('http://localhost:8000/api', {
|
576 | logLevel: 'info',
|
577 | logProvider: function(provider) {
|
578 | provider.debug = customLogger;
|
579 | provider.info = customLogger;
|
580 | return provider;
|
581 | }
|
582 | });
|
583 | var mw_target = function(req, res, next) {
|
584 | res.write(req.url);
|
585 | res.end();
|
586 | };
|
587 |
|
588 | proxyServer = createServer(3000, mw_proxy);
|
589 | targetServer = createServer(8000, mw_target);
|
590 |
|
591 | http.get('http://localhost:3000/api/foo/bar', function(res) {
|
592 | res.on('data', function(chunk) {
|
593 | responseBody = chunk.toString();
|
594 | done();
|
595 | });
|
596 | });
|
597 | });
|
598 |
|
599 | afterEach(function() {
|
600 | proxyServer.close();
|
601 | targetServer.close();
|
602 | });
|
603 |
|
604 | it('should have logged messages', function() {
|
605 | expect(logMessage).not.to.equal(undefined);
|
606 | });
|
607 | });
|
608 |
|
609 | });
|
610 |
|
611 | function createServer(portNumber, middleware, path) {
|
612 | var app = express();
|
613 |
|
614 | if (middleware, path) {
|
615 | app.use(path, middleware);
|
616 | } else if (middleware) {
|
617 | app.use(middleware);
|
618 | }
|
619 |
|
620 | var server = app.listen(portNumber);
|
621 |
|
622 | return server;
|
623 | }
|