Verified Commit 13ec8098 authored by Aral Balkan's avatar Aral Balkan
Browse files

Merge branch '404-fallthrough'

parents 7a738ea2 30855cee
Pipeline #908 canceled with stages
......@@ -225,6 +225,9 @@ Providing an alternative way to decide which requests should be proxied; In case
}
```
- **option.fallthrough**: boolean, sets whether execution should fall through to middleware chain when a 404 is encountered at the proxy target. If set, calls `next()` on the middleware chain.
Default: `false`
- **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`
- **option.logProvider**: function, modify or replace log provider. Default: `console`.
......
......@@ -19,8 +19,13 @@ export class HttpProxyMiddleware {
this.config = createConfig(context, opts);
this.proxyOptions = this.config.options;
let httpProxyOptions = <any>{}
if (context.fallthrough) {
httpProxyOptions.fallthrough = true
}
// create proxy
this.proxy = httpProxy.createProxyServer({});
this.proxy = httpProxy.createProxyServer(httpProxyOptions);
this.logger.info(
`[HPM] Proxy created: ${this.config.context} -> ${this.proxyOptions.target}`
);
......@@ -48,6 +53,18 @@ export class HttpProxyMiddleware {
public middleware = async (req, res, next) => {
if (this.shouldProxy(this.config.context, req)) {
const activeProxyOptions = await this.prepareProxyRequest(req);
// fallthrough to the middleware chain if a resource
// cannot be found in the source being proxied
if (this.proxyOptions.fallthrough) {
this.proxy.once('proxyRes', (proxyRes) => {
if (proxyRes.statusCode === 404) {
this.logger.info('[HPM] Falling through to middleware chain on 404');
next();
}
});
}
this.proxy.web(req, res, activeProxyOptions);
} else {
next();
......
......@@ -16,3 +16,16 @@ export function createServer(portNumber, middleware, path?) {
return server;
}
export function createServerWithFallthrough(portNumber, middleware) {
const app = express();
app.use(middleware);
app.use((request, response, next) => {
response.end('fell through');
})
const server = app.listen(portNumber);
return server;
}
import * as http from 'http';
import { createServer, proxyMiddleware } from './_utils';
import { createServer, proxyMiddleware, createServerWithFallthrough } from './_utils';
describe('E2E http-proxy-middleware', () => {
describe('http-proxy-middleware creation', () => {
......@@ -658,5 +658,90 @@ describe('E2E http-proxy-middleware', () => {
expect(logMessage).not.toBeUndefined();
});
});
describe('404 fallthrough when requested', () => {
let proxyServer;
let targetServer;
let response;
let responseBody;
beforeEach(() => {
const mwProxy = proxyMiddleware('/', {
target: 'http://localhost:8000',
fallthrough: true
});
const mwTarget = (req, res, next) => {
// return 404 error
res.statusCode = 404;
res.end();
};
proxyServer = createServerWithFallthrough(3000, mwProxy);
targetServer = createServer(8000, mwTarget);
});
beforeEach(done => {
http.get('http://localhost:3000/', res => {
response = res;
res.on('data', chunk => {
responseBody = chunk.toString();
done();
});
});
});
afterEach(() => {
proxyServer.close();
targetServer.close();
});
it('should fall through', () => {
expect(response.statusCode).toBe(200);
expect(responseBody).toBe('fell through');
});
});
describe('404 do not fallthrough when not requested', () => {
let proxyServer;
let targetServer;
let response;
let responseBody;
beforeEach(() => {
const mwProxy = proxyMiddleware('/', {
target: 'http://localhost:8000',
});
const mwTarget = (req, res, next) => {
// return 404 error
res.statusCode = 404;
res.end('404 error');
};
proxyServer = createServerWithFallthrough(3000, mwProxy);
targetServer = createServer(8000, mwTarget);
});
beforeEach(done => {
http.get('http://localhost:3000/', res => {
response = res;
res.on('data', chunk => {
responseBody = chunk.toString();
done();
});
});
});
afterEach(() => {
proxyServer.close();
targetServer.close();
});
it('should not fall through', () => {
expect(response.statusCode).toBe(404);
expect(responseBody).toBe('404 error');
});
});
});
});
......@@ -494,10 +494,10 @@
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
"@types/http-proxy@^1.17.0":
version "1.17.0"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.0.tgz#baf82ff6aa2723fd29f90e3ba1384e665006863e"
integrity sha512-l+s0IoxSHqhLFJPDHRfO235kgrCkvFD8JmdV/T9C4BKBYPIjrQopGFH4r7h2e3jQqgJRCthRCAZIxDoFnj1zwQ==
"@types/http-proxy@^1.17.3":
version "1.17.3"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.3.tgz#348e1b808ff9585423cb909e9992d89ccdbf4c14"
integrity sha512-wIPqXANye5BbORbuh74exbwNzj+UWCwWyeEFJzUQ7Fq3W2NSAy+7x7nX1fgbEypr2/TdKqpeuxLnXWgzN533/Q==
dependencies:
"@types/node" "*"
......@@ -1840,10 +1840,10 @@ eventemitter3@1.x.x:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=
eventemitter3@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
eventemitter3@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
exec-sh@^0.3.2:
version "0.3.2"
......@@ -2393,6 +2393,13 @@ http-errors@~1.6.2:
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
http-proxy@../node-http-proxy/:
version "1.18.0"
dependencies:
eventemitter3 "^4.0.0"
follow-redirects "^1.0.0"
requires-port "^1.0.0"
http-proxy@1.15.2:
version "1.15.2"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.15.2.tgz#642fdcaffe52d3448d2bda3b0079e9409064da31"
......@@ -2401,15 +2408,6 @@ http-proxy@1.15.2:
eventemitter3 "1.x.x"
requires-port "1.x.x"
http-proxy@^1.17.0:
version "1.17.0"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a"
integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==
dependencies:
eventemitter3 "^3.0.0"
follow-redirects "^1.0.0"
requires-port "^1.0.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment