I'm trying to build a Node/Express server that essentially acts as a middleman server and logs any requests that come in, then forwards the request to the destination server, and forwards back any responses that come from the destination server. The goal is to be as "transparent as possible, making it seem as if there is no middleman server at all.
The problem I'm having is that my express server seems to be dumping in a bunch of unnecessary headers in the response from the destination server.
In my app.js I have some (a lot of) middlewares that are useful for my app in general but seems to inject headers in the response:
app.use(rateLimiter);
app.use(helmet());
app.use(xss());
app.use(mongoSanitize());
app.use(nocache());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
Then I have my middleware endpoint that receives the request, forwards it, and returns the response:
exports.createLink = async (req, res, next) => {
try {
const url = 'https://destination-endpoint.com';
const options = {
url: url,
};
request( options, function(err, remoteResponse, remoteBody) {
res.writeHead(remoteResponse.statusCode, {...remoteResponse.headers});
return res.end(remoteBody);
});
} catch (error) {
console.log(error);
next(error);
}
};
If I hit my middleman I get the response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Vary: Accept-Encoding
Access-Control-Allow-Credentials: true
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
date: Sun, 24 Jan 2021 05:23:07 GMT
X-RateLimit-Reset: 1611465796
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
X-DNS-Prefetch-Control: off
Expect-CT: max-age=0
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: no-referrer
X-XSS-Protection: 0
Surrogate-Control: no-store
cache-control: no-cache, private
Pragma: no-cache
Expires: 0
server: nginx/1.14.2
content-type: text/plain; charset=UTF-8
transfer-encoding: chunked
connection: close
x-request-id: 864b8443-5fe2-498e-8e88-662035afe6c7
x-token-id: d0cb94e2-9c87-4d6e-b32a-11fcc698ad2c
set-cookie: laravel_session=tBlSCeel0OFIR5pL9C6f02JfXGqoyg3SN6BH6jjG; expires=Sun, 24-Jan-2021 07:23:07 GMT; Max-Age=7200; path=/; httponly
{
"foo": "bar"
}%
While if I hit the endpoint directly I just get this:
HTTP/1.1 200 OK
Server: nginx/1.14.2
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Request-Id: 1f033b57-4a2f-48a1-82b3-41bce6e2d748
X-Token-Id: d0cb94e2-9c87-4d6e-b32a-11fcc698ad2c
Cache-Control: no-cache, private
Date: Sun, 24 Jan 2021 05:24:28 GMT
Set-Cookie: laravel_session=MdOGJ18iDU28XLmNYXf5T2RxSa25KxqFisxzCBzR; expires=Sun, 24-Jan-2021 07:24:28 GMT; Max-Age=7200; path=/; httponly
{
"foo": "bar"
}%
As you can see there is a lot of extra stuff added to the header. Some of it may be solvable by removing middlewares/etc. but I think the bigger issue is that I want to return the response from the destination server AS IS no matter what. I found that I can delete the current headers before sending it like this:
request( options, function(err, remoteResponse, remoteBody) {
const headers = res.getHeaders();
for (const head in headers){
res.removeHeader(head);
}
res.writeHead(remoteResponse.statusCode, {...remoteResponse.headers});
return res.end(remoteBody);
});
But that seems very heavy handed, there has to be an easier way to overwrite/set all response headers to exactly what I need. So my overall question is: How do I return the response from the request to the destination server EXACTLY as is?