I have a simple Express based Node.js web server that I'm using for development of a JavaScript application. I set up the server to use node-http-proxy to proxy API requests the application makes to a Jetty server that is running on a different domain and port. This setup has been working flawlessly until I started to run into problems with session management.
Upon authentication the application server returns a cookie with an auth token representing the server session. When I run the JS application off of my filesystem (file://) I can see that once client receives the cookie, it is sent in all the subsequent API requests. When I run the JS app on the node server and API calls are proxied through node-http-proxy (RoutingProxy) the request headers never include the cookie.
Is there something I need to handle manually to support this type of session persistence through the proxy? I've been digging through the node-http-proxy code but it is a little over my head because I am new to Node.
https://gist.github.com/2475547 or:
var express = require('express'),
routingProxy = require('http-proxy').RoutingProxy(),
app = express.createServer();
var apiVersion = 1.0,
apiHost = my.host.com,
apiPort = 8080;
function apiProxy(pattern, host, port) {
return function(req, res, next) {
if (req.url.match(pattern)) {
routingProxy.proxyRequest(req, res, {host: host, port: port});
} else {
next();
}
}
}
app.configure(function () {
// API proxy middleware
app.use(apiProxy(new RegExp('\/' + apiVersion + '\/.*'), apiHost, apiPort));
// Static content middleware
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(express.static(__dirname));
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
app.use(app.router);
});
app.listen(3000);
I did what you are asking by manually looking at the response, seeing if it is a set-cookie, snipping off the JSESSSIONID, storing it in a variable, and passing it on all subsequent requests as a header. This way the reverse proxy acts as a cookie.
enter code on('proxyReq', function(proxyReq){ proxyReq.setHeader('cookie', 'sessionid=' + cookieSnippedValue)
Hi @tomswift does your local server run on http protocol, but the session cookie receive from the remote server carry with Secure;
like:
'set-cookie':
[ 'JSESSIONID=COOKIEWITHSECURE98123; Path=/;HttpOnly;Secure;']
If so, before your local server response to the client, extract set-cookie
from the original response(response from remote server to local server) header, remove the Secure;
and put the rest of it into the proxy response (response from local server to client ) header like:
'set-cookie':
[ 'JSESSIONID=COOKIEWITHSECURE98123; Path=/;HttpOnly;']
then the client will take the session cookie automatically.
Hope it may help.
Ideally the job of a proxy is to just forward a request to the destination, and should not strip off critical headers like cookies, But if it is, i think you should file a issue against them here https://github.com/nodejitsu/node-http-proxy/issues.
Also you said the request headers never include the cookie, Is it possible the client never received it?
I found a way to implement this by forking and modifying node-http-proxy. It serves my current purpose which is a development environment. For any sort of serious consideration it needs to be fleshed out into a more legitimate solution.
The details can be found in the issue I filed in GitHub: https://github.com/nodejitsu/node-http-proxy/issues/236#issuecomment-5334457
I would love some input on this solution, especially if I'm going completely in the wrong direction.
I had similar problems that cookies were not passed forward to the client.
Solution:
- get cookie from proxy response
- set it in proxy request, with slightly modified value
let cookie;
const webpackConfig = {
proxy: {
'/api': {
...
onProxyReq: (proxyReq) => {
if(cookie) {
proxyReq.setHeader('Cookie', cookie);
}
},
onProxyRes: (proxyRes) => {
const sc = proxyRes.headers['set-cookie'];
const raw = sc.filter(s => s.startsWith('JSESSIONID'));
if(raw.length) {
cookie = raw[0].split(';')[0];
}
}
}
}
}