Skip to content

Commit 439832f

Browse files
committed
feat: try to keep body even after body-parser middleware
1 parent f77121f commit 439832f

File tree

6 files changed

+67
-5
lines changed

6 files changed

+67
-5
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"@types/micromatch": "^4.0.1",
5656
"@types/node": "^14.11.8",
5757
"@types/supertest": "^2.0.10",
58+
"body-parser": "^1.19.0",
5859
"browser-sync": "^2.26.12",
5960
"connect": "^3.7.0",
6061
"express": "^4.17.1",

src/http-proxy-middleware.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as express from 'express';
2+
import { ClientRequest } from 'http';
23
import * as httpProxy from 'http-proxy';
34
import * as _ from 'lodash';
5+
import * as querystring from 'querystring';
46
import { createConfig } from './config-factory';
57
import * as contextMatcher from './context-matcher';
68
import * as handlers from './handlers';
@@ -33,6 +35,9 @@ export class HttpProxyMiddleware {
3335
// log errors for debug purpose
3436
this.proxy.on('error', this.logError);
3537

38+
// fix proxied body if bodyParser is involved
39+
this.proxy.on('proxyReq', this.fixBody);
40+
3641
// https://github.com/chimurai/http-proxy-middleware/issues/19
3742
// expose function to upgrade externally
3843
(this.middleware as any).upgrade = (req, socket, head) => {
@@ -174,4 +179,24 @@ export class HttpProxyMiddleware {
174179

175180
this.logger.error(errorMessage, req.url, hostname, target, err.code || err, errReference);
176181
};
182+
183+
private fixBody = (proxyReq: ClientRequest, req: Request) => {
184+
if (!req.body || !Object.keys(req.body).length) {
185+
return;
186+
}
187+
188+
const contentType = proxyReq.getHeader('Content-Type');
189+
const writeBody = (bodyData: string) => {
190+
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
191+
proxyReq.write(bodyData);
192+
};
193+
194+
if (contentType === 'application/json') {
195+
writeBody(JSON.stringify(req.body));
196+
}
197+
198+
if (contentType === 'application/x-www-form-urlencoded') {
199+
writeBody(querystring.stringify(req.body));
200+
}
201+
};
177202
}

test/e2e/_utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import * as express from 'express';
22

33
export { createProxyMiddleware } from '../../dist/index';
44

5-
export function createApp(middleware) {
5+
export function createApp(...middleware) {
66
const app = express();
7-
app.use(middleware);
7+
app.use(...middleware);
88
return app;
99
}
1010

test/e2e/express-router.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { createProxyMiddleware } from './_utils';
44
import { Options } from '../../src/index';
55

66
describe('Usage in Express', () => {
7-
let app;
8-
let server;
7+
let app: express.Express;
8+
let server: http.Server;
99

1010
beforeEach(() => {
1111
app = express();

test/e2e/http-proxy-middleware.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createProxyMiddleware, createApp, createAppWithPath } from './_utils';
22
import * as request from 'supertest';
33
import { Mockttp, getLocal, CompletedRequest } from 'mockttp';
4+
import * as bodyParser from 'body-parser';
45

56
describe('E2E http-proxy-middleware', () => {
67
describe('http-proxy-middleware creation', () => {
@@ -84,6 +85,41 @@ describe('E2E http-proxy-middleware', () => {
8485
});
8586
});
8687

88+
describe('basic setup with configured body-parser', () => {
89+
it('should proxy request body from form', async () => {
90+
agent = request(
91+
createApp(
92+
bodyParser.urlencoded({ extended: false }),
93+
createProxyMiddleware('/api', {
94+
target: `http://localhost:${mockTargetServer.port}`,
95+
})
96+
)
97+
);
98+
99+
await mockTargetServer.post('/api').thenCallback((request) => {
100+
expect(request.body.text).toBe('foo=bar&bar=baz');
101+
return { status: 200 };
102+
});
103+
await agent.post('/api').send('foo=bar').send('bar=baz').expect(200);
104+
});
105+
it('should proxy request body from json', async () => {
106+
agent = request(
107+
createApp(
108+
bodyParser.urlencoded({ extended: false }),
109+
createProxyMiddleware('/api', {
110+
target: `http://localhost:${mockTargetServer.port}`,
111+
})
112+
)
113+
);
114+
115+
await mockTargetServer.post('/api').thenCallback((request) => {
116+
expect(request.body.json).toEqual({ foo: 'bar', bar: 'baz' });
117+
return { status: 200 };
118+
});
119+
await agent.post('/api').send({ foo: 'bar', bar: 'baz' }).expect(200);
120+
});
121+
});
122+
87123
describe('custom context matcher/filter', () => {
88124
it('should have response body: "HELLO WEB"', async () => {
89125
const filter = (path, req) => {

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,7 @@ blob@0.0.5:
13331333
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
13341334
integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
13351335

1336-
body-parser@1.19.0, body-parser@^1.15.2:
1336+
body-parser@1.19.0, body-parser@^1.15.2, body-parser@^1.19.0:
13371337
version "1.19.0"
13381338
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
13391339
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==

0 commit comments

Comments
 (0)