UNPKG

20.8 kBJavaScriptView Raw
1var expect = require('chai').expect;
2var proxyMiddleware = require('../index');
3var http = require('http');
4var express = require('express');
5
6describe('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
14describe('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 // mockNext will be called when request is not proxied
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
41describe('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; // store target url.
54 targetHeaders = req.headers; // store target headers.
55 res.write('HELLO WEB'); // respond with '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); // respond with 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); // respond with 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); // respond with 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'}); // unreachable host on port: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); // different error code
345 res.end('I\'m a teapot'); // no response body
346 };
347
348 var mw_proxy = proxyMiddleware('/api', {target: 'http://localhost:666', onError: customOnError}); // unreachable host on port:666
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'; // add custom header to response
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); // respond with 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'); // add custom header to request
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); // respond with 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); // respond with 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); // respond with 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); // respond with 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); // respond with 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
611function 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}