-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from pmu-tech/feature_handle-cookie-and-body-f…
…or-proxy Fix Set-Cookie header and request body
- Loading branch information
Showing
5 changed files
with
160 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import express from 'express'; | ||
import http from 'http'; | ||
|
||
import { fixRequestBody } from './fixRequestBody'; | ||
|
||
const fakeProxyRequest = () => { | ||
const proxyRequest = new http.ClientRequest('http://some-host'); | ||
proxyRequest.emit = () => false; // Otherwise we get "Error: getaddrinfo ENOTFOUND some-host" | ||
|
||
return proxyRequest; | ||
}; | ||
|
||
test('should not write when body is undefined', () => { | ||
const proxyRequest = fakeProxyRequest(); | ||
|
||
jest.spyOn(proxyRequest, 'setHeader'); | ||
jest.spyOn(proxyRequest, 'write'); | ||
|
||
fixRequestBody(proxyRequest, { body: undefined } as express.Request); | ||
|
||
expect(proxyRequest.setHeader).not.toHaveBeenCalled(); | ||
expect(proxyRequest.write).not.toHaveBeenCalled(); | ||
}); | ||
|
||
test('should not write when body is empty', () => { | ||
const proxyRequest = fakeProxyRequest(); | ||
|
||
jest.spyOn(proxyRequest, 'setHeader'); | ||
jest.spyOn(proxyRequest, 'write'); | ||
|
||
fixRequestBody(proxyRequest, { body: {} } as express.Request); | ||
|
||
expect(proxyRequest.setHeader).not.toHaveBeenCalled(); | ||
expect(proxyRequest.write).not.toHaveBeenCalled(); | ||
}); | ||
|
||
test('should write when body is not empty and Content-Type is application/json', () => { | ||
const proxyRequest = fakeProxyRequest(); | ||
proxyRequest.setHeader('content-type', 'application/json; charset=utf-8'); | ||
|
||
jest.spyOn(proxyRequest, 'setHeader'); | ||
jest.spyOn(proxyRequest, 'write'); | ||
|
||
fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as express.Request); | ||
|
||
const expectedBody = JSON.stringify({ someField: 'some value' }); | ||
expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length); | ||
expect(proxyRequest.write).toHaveBeenCalledWith(expectedBody); | ||
}); | ||
|
||
test('should write when body is not empty and Content-Type is application/x-www-form-urlencoded', () => { | ||
const proxyRequest = fakeProxyRequest(); | ||
proxyRequest.setHeader('content-type', 'application/x-www-form-urlencoded'); | ||
|
||
jest.spyOn(proxyRequest, 'setHeader'); | ||
jest.spyOn(proxyRequest, 'write'); | ||
|
||
fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as express.Request); | ||
|
||
const expectedBody = 'someField=some+value'; | ||
expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length); | ||
expect(proxyRequest.write).toHaveBeenCalledWith(expectedBody); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import http from 'http'; | ||
|
||
/** | ||
* Fix proxied body if bodyParser is involved. | ||
* | ||
* @see https://github.com/chimurai/http-proxy-middleware/blob/v2.0.1/src/handlers/fix-request-body.ts | ||
* @see https://github.com/chimurai/http-proxy-middleware/issues/320 | ||
* @see https://github.com/chimurai/http-proxy-middleware/pull/492 | ||
*/ | ||
const fixRequestBody = (proxyReq: http.ClientRequest, req: http.IncomingMessage) => { | ||
const requestBody = (req as unknown as Request).body; | ||
|
||
if (!requestBody || Object.keys(requestBody).length === 0) { | ||
return; | ||
} | ||
|
||
const contentType = proxyReq.getHeader('Content-Type') as string; | ||
const writeBody = (bodyData: string) => { | ||
// deepcode ignore ContentLengthInCode: bodyParser fix | ||
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData)); | ||
proxyReq.write(bodyData); | ||
}; | ||
|
||
if (contentType && contentType.includes('application/json')) { | ||
writeBody(JSON.stringify(requestBody)); | ||
} | ||
|
||
if (contentType === 'application/x-www-form-urlencoded') { | ||
writeBody(new URLSearchParams(requestBody as unknown as string).toString()); | ||
} | ||
}; | ||
|
||
export { fixRequestBody }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { removeSecureFromSetCookie } from './removeSecureFromSetCookie'; | ||
|
||
test('should remove Secure attribute from Set-Cookie header', () => { | ||
const proxyRes = { | ||
headers: { | ||
'set-cookie': [ | ||
'cookie1=ZYADVSQYTDZA1; Secure; SameSite', | ||
'cookie2=ZYADVSQYTDZA2; Secure', | ||
'cookie3=ZYADVSQYTDZA3' | ||
] | ||
} | ||
}; | ||
|
||
removeSecureFromSetCookie(proxyRes); | ||
|
||
expect(proxyRes.headers['set-cookie']).toEqual([ | ||
'cookie1=ZYADVSQYTDZA1; SameSite', | ||
'cookie2=ZYADVSQYTDZA2', | ||
'cookie3=ZYADVSQYTDZA3' | ||
]); | ||
}); | ||
|
||
test('do nothing if no Set-Cookie header', () => { | ||
const proxyRes = { | ||
headers: {} | ||
}; | ||
|
||
removeSecureFromSetCookie(proxyRes); | ||
|
||
expect(proxyRes.headers).toEqual({}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import http from 'http'; | ||
|
||
/** | ||
* http-proxy does not remove 'Secure' attribute from Set-Cookie header. | ||
* | ||
* @see https://github.com/http-party/node-http-proxy/issues/1165 | ||
* @see https://github.com/http-party/node-http-proxy/pull/1166 | ||
*/ | ||
const removeSecureFromSetCookie = (proxyRes: { headers: http.IncomingHttpHeaders }) => { | ||
// ["Header names are lower-cased"](https://nodejs.org/dist/latest-v16.x/docs/api/http.html#messageheaders) | ||
|
||
if (proxyRes.headers['set-cookie']) { | ||
const cookies = proxyRes.headers['set-cookie'].map(cookie => cookie.replace(/; secure/gi, '')); | ||
/* eslint-disable no-param-reassign */ | ||
proxyRes.headers['set-cookie'] = cookies; | ||
/* eslint-enable no-param-reassign */ | ||
} | ||
}; | ||
|
||
export { removeSecureFromSetCookie }; |