I came down to ask here since I am troubleshooting this for days without any success. What I try to accomplish is to set up a reverse proxy to the nodejs/Express backend using apache2. Proxying the http and websocket connections work fine, however, enabling CORS does not work. I need it as the Application provides a widget that will be imported by the client on the external host. The curcial information here is that cors should be handled by the cors() middleware by expressjs, and all related headers / requests should simply be proxied forth and back to this backend server via apache2. Here is my current configuration with some comments on how I understand the different directives:
<VirtualHost my.domain.name:80>
# redirecting all requests to https (works fine)
</VirtualHost>
<VirtualHost my.domain.name>
LogLevel debug # does not log any information regarding the headers
ServerName my.domain.name
ServerAdmin [email protected]
## SSL directives removed for clarity
## logfile directives removed for clarity
# forward requests to proxy =>
ProxyPreserveHost On # Not sure if this is required as I forward the Origin header
<Location "/"> # proxy all requests
RequestHeader set Origin %{HTTP:Origin}e
ProxyPass "http://localhost:3333/" # location of the backend server
ProxyPassReverse "http://localhost:3333/" # required
</Location>
#ProxyRequest Off # Throws an error (unknown directive), but disabled by default, so not required
# forward socket.io requests removed for calrity
## Required headers for CORS:
# crucial CORS-related header that indicates the origin of the requesting domain
RequestHeader set Origin "%{ORIGIN}e"
# used in CORS preflight requests to indicate the HTTP method
RequestHeader set Access-Control-Request-Method "%{REQUEST_METHOD}e"
# used in CORS preflight requests to indicate the requested headers
RequestHeader set Access-Control-Request-Headers "%{HTTP_ACCESS_CONTROL_REQUEST_HEADERS}e"
</VirtualHost>
Locally I used nginx to test the widget behind a reverse Proxy and it is working fine (including CORS from another port):
server {
# omitted meta and SSL specific directives for clarity
location / {
proxy_pass http://127.0.0.1:3333;
# enable websocket passthrough
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
I see that nginx is not setting the origin or anything related to the OPTIONS preflight request. Also, Host and X-Real-IP are not directly related to cors, as far as I can tell. I wonder why this was working. Note that I included the X-Forwarded-* headers in the apache2 config before (to no avail) to ensure that the cors middleware in express does not complain about missing information when it discovers a proxied request. My brain is melting from reading the apache2 docs regarding mod_proxy and mod_headers as well as searching the web for information about how to do this, and I really hope you can enlighten me what I am missing / doing wrong here. Thank you in advance !
Edit
To be more specific about my question: How can I debug what headers apache modifies, if any? I started to dig into the cors middleware and print out headers on the Express Server side, but for now, I am not much smarter. I will have more time at the weekend I hope, and will further update this question.
Edit2
I added a middleware to the expressjs backend to log the request headers:
app.use((req, res, next) => {
console.log("Request Headers:", req.headers);
next();
});
And it turns out that the "origin" header, although set by the original request, indeed was not correctly passed to the backend:
Request Headers: {
// ...
origin: '(null)',
// ...
}
It took me a while to figure out how to access the Origin header value and pass it to the backend, but I found a solution for the origin (I got goosebumps like crazy when I did, ha(!)). I will post my solution as an answer for future reference. (Spoiler: Neither the HTTP:Origin
nor the Origin
or ORIGIN
environment variables were set..).