Express redirect wrong url - node.js

When use express res function redirect(url), i'm redirected to the wrong url !
My website URL is mywebsite.com :
function myroute(app) {
app.get(/route, function(req, res) {
var url = getMyUrl();
console.log(url); // https://otherwebsite.com/foo?bar=baz [OK]
res.redirect(url); // redirect to https://mywebsite.com/foo?bar=baz [WRONG!]
});
}
I don't know why express redirect to mywebsite.com with good parameters instead of otherwebsite.com
No idea why...
This bug occurs on production. On my develop environment the redirect URL is the good url.
Thanks in advance
EDIT
I also tried with:
res.location(url);
and
res.setHeader(302, {Location: url});
But it always redirect to the wrong URL...
My url variable is good but I receive this header response:
HTTP/1.1 302 Found
X-Powered-By: Express
Location: https://mywebsite.com/foo?bar=baz
Vary: Accept\r\nContent-Type: text/html; charset=UTF-8
Content-Length: 170
Date: Fri, 13 Jul 2018 21:52:18 GMT
Connection: keep-alive
EDIT 2
Ok more tests here :
res.redirect("https://www.google.fr/toto?key=value"); // https://mywebsite.com/toto?key=value **[fail]**
res.redirect("https://www.google.fr/toto"); // https://mywebsite.com/toto **[fail]**
res.redirect("https://www.google.fr"); // https://www.google.fr **[success]**
It seems to not redirect to the domain I want if I add a path. Any idea ?
EDIT 3
Maybe it's caused by my vhost ?
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName mywebsite.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5001/
<Location />
ProxyPassReverse /
Order deny,allow
Allow from all
</Location>
SSLCertificateFile ...
SSLCertificateKeyFile ...
</VirtualHost>
</IfModule>

Providing an actual answer this time, as my previous one was (rightfully so) deleted.
The incorrect URL redirections are definitely caused by:
ProxyPassReverse /
As this is what such directive does:
"lets Apache httpd adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses."
In my case, removing this directive was causing other internal redirection issues in my application, so I was trying to find out a way to add exceptions to it.
However, it turns out I never needed ProxyPassReverse (only ProxyPass) if I adjust the 'mountpath' of my Express node js configuration to match the path of the proxy server. Not sure if this answer will help you as an actual solution, but it managed to solve it on my node application using Apache as reverse proxy.

I believe 301 needs to be included.
Try changing res.redirect(url) to res.status(301).redirect(url) and see if it fixes the issue.

Related

NodeJS + Apache Proxy, having trouble with routing a secured websocket through (apache config help please)

I've looked through countless of posts on here on how to do this, and I wasn't able to get this simple task working. I'm using Apache as a proxy that is suppose to encrypt/decrypt TSL packets, and then have an unsecured communication with the NodeJS server. The problem is that the web application loads fine, however the websocket fails with an error 404 (not found) and I've had an error 200 before (handshaking issue). I've tried many different configurations and it's not working.
This is what I have on the client side.
const connection = new WebSocket('wss://example.com/wss');
Using wss:// instead of ws:// here because I want to have a secured connection.
On the server side, I have just the standard
ws.on('connection', w => {
w.on('message', msg => {
var data = JSON.parse(msg);
// do something with the message ...
});
});
This is my Apache config file
ServerName www.example.com RewriteEngine on
RewriteCond %{HTTP:Upgrade}=websocket [NC]
RewriteRule /(.*) wss://127.0.0.1:3000/$1 [P,L]
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLProxyEngine on
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
ProxyPass /wss ws://127.0.0.1:3000/
ProxyPassReverse /wss ws://127.0.0.1:3000/
On the Apache side I'm not certain if I should have wss:// or ws:// for ProxyPass since it should be insecure between Apache and NodeJS. I put it as ws:// here but both ways didn't work. For this configuration I get 404 error.
Any help would be greatly appreciated! Thanks
I solved this problem with the Nginx reverse proxy,
The problem is the fact that I set up socket connection to be on the port 8080, but the proxy is set up for the port 3000. The issue should resolve if you put them on the same port.
i.e.
App server,
const ws = new WebSocket.Server({port: 3001});
Apache
ProxyPass /wss ws://127.0.0.1:3001/
ProxyPassReverse /wss ws://127.0.0.1:3001/

How to setup Gitlab EE with HTTPS on a DirectAdmin Server?

I already have setup an Omnibus Gitlab server on my Centos7 VPS (DirectAdmin) using this post:
how to install gitlab on a directadmin server
It worked great with HTTP requests.
For security reasons I want to setup HTTPS on GitLab subdomain gitlab.domain.com.
I want to use LetsEncrypt free SSL certificates. The problem is LetsEncrypt can't authenticate my domain using Certbot:
certbot certonly --webroot --webroot-path=/var/www/letsencrypt -d gitlab.domain.com
It fails with output:
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: gitlab.domain.com
Type: unauthorized
Detail: Invalid response from
http://gitlab.domain.com/.well-known/acme-challenge/8Xj5vc-KMfhHYgH7PhXCFEetcxzQBDk-puiA2tRfoB4:
"<!DOCTYPE html>\n<html class=\"devise-layout-html\">\n<head
prefix=\"og: http://ogp.me/ns#\">\n<meta charset=\"utf-8\">\n<meta
content=\"IE"
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address.
I googled for it and it seems LetsEncrypt have to reach a folder path:
http://gitlab.domain.com/.well-known/acme-challenge/xxxxxxxxxx
So I created the path and gave 777 permission and for test purposes put a test.html in it.
Now I have access to file using HTTP but I can’t get to it using HTTPS.
curl -I -k https://gitlab.domain.com/.well-known/acme-challenge/test.html
Output:
HTTP/1.1 301 Moved Permanently
Date: Wed, 06 Feb 2019 10:05:40 GMT
Server: Apache/2
Location: http://gitlab.domain.com/.well-known/acme-challenge/test.html
Content-Type: text/html; charset=iso-8859-1
I already have DirectAdmin on server and I can't figure out how to customize HTTPD.conf file of my subdomain so that everything works fine.
Custom HTTPD.conf section of direct admin:
ServerName gitlab.domain.com
ServerSignature Off
ProxyPreserveHost On
# Ensure that encoded slashes are not decoded but left in their encoded state.
# http://doc.gitlab.com/ce/api/projects.html#get-single-project
AllowEncodedSlashes NoDecode
<Location />
Order deny,allow
Allow from all
#Allow forwarding to gitlab-workhorse
ProxyPassReverse http://127.0.0.1:8181
ProxyPassReverse http://gitlab.domain.com/
</Location>
# Apache equivalent of nginx try files
# http://serverfault.com/questions/290784/what-is-apaches-equivalent-of-nginxs-try-files
# http://stackoverflow.com/questions/10954516/apache2-proxypass-for-rails-app-gitlab
RewriteEngine on
# Forward all requests to gitlab-workhorse except existing files like error documents
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_URI} ^/uploads/.* [NC,OR]
RewriteCond %{REQUEST_URI} !^.*/\.well-known/acme-challenge/.*$ [NC]
RewriteRule .* http://127.0.0.1:8181%{REQUEST_URI} [P,QSA,NE]
Alias /.well-known/acme-challenge/ /var/www/letsencrypt/
<Directory "/var/www/letsencrypt/">
Order allow,deny
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Allow from all
</Directory>
# needed for downloading attachments
DocumentRoot /opt/gitlab/embedded/service/gitlab-rails/public
It worth to mention that testing my domain using https://letsdebug.net/ with HTTP-01 and DNS-01 methods return that everything is OK.
I think if I could handle HTTPS requests to guarantee access of LetsEncrypt API to http://gitlab.domain.com/.well-known/acme-challenge/ URL over HTTP and HTTPS it will be ok.
As far as nobody respond to my question I worked on it and finally I found the answer.
Actually the problem was originated from two parts:
1.When you want to point to a path which contains special characters like '.', '\' or space in a string with a "..." you have to use it in '\.' format. I insist that it is applicable just in case you have a string surrounded by the double quotation marks not every parameters you have in your config file.
<Directory "/var/www/default/\.well-known/acme-challenge/">
So the correct form of Alias/Directory part is as below:
Alias /.well-known/acme-challenge/ /var/www/default/.well-known/acme-challenge/
<Directory "/var/www/default/\.well-known/acme-challenge/">
Options None
AllowOverride None
ForceType text/plain
RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"
</Directory>
You may get a "HTTP/1.1 302 Found" not a "HTTP/1.1 200 OK" when you call the URL of the test file by 'curl'. It returns 302 cause you somehow redirects request to somewhere else than you really see in the address bar. But it is OK for LetsEncrypt domain authorization.
curl -I http://example.com/.well-known/acme-challenge/test.html
2.When you call for certbot or letsencrypt command, in the webroot parameter it must point to the root of your ACME challenge directory (/var/www/default/) not the end destination of the certs (/var/www/default/.well-known/acme-challenge/) cause the acmetool itself makes directory path in every webroot you provided to it. So the correct form of certbot or letsencrypt command for above Alias/Directory should be like below:
letsencrypt certonly --webroot -w /var/www/default/ -d example.com -d www.example.com --renew-by-default
or
certbot certonly --webroot --webroot-path=/var/www/default/ -d example.com
I'm very new to the Apache configuration but as far as I searched for the problem it is a very popular problem to those who want to use LetsEncrypt over an Apache server.
So forgive me if it an elementary question to most of you guys.
Enjoy!

VirtualHost not redirecting

I am trying to redirect http://eamondev.com:3000 to https://omniatm.eamondev.com with a VirtualHost. I am using node to serve a site to http://eamondev.com:3000. I am using vhost with node like this:
app.use(vhost('omniatm.eamondev.com', express.static('/')));
I have never used vhost and it took me a while to figure this out without having to split up all my code like I was working with more than one site (when I am not), so I'm not sure if it is exactly how it should be for an Apache redirect to work.
In my apache conf file I have:
<VirtualHost *:80>
ServerName omniatm.eamondev.com
ProxyPreserveHost on
ProxyPass / http://localhost:3000/
</VirtualHost>
I am also using WHM on a VPS, I'm not sure if this is relevant or not, but the ServerName (with protocol, what I type into the browser) needs to be https://omniatm.eamondev.com.
I cannot serve node on port 80 of my server (and then redirect to subdomain) because my main site (http://eamondev.com) is running on port 80.
I have referenced most of the stackoverflow questions about this and nothing has worked. I should mention (although I'm not sure exactly how it is relevant, I just saw it in a stackoverflow question I looked at), my hosting support (bluehost) used WHM to set things up with a wildcard ssl certificate to make the omniatm.eamondev.com subdomain https.
How do I redirect http://eamondev.com:3000 to https://omniatm.eamondev.com using apache (or vhost)?
Proxy passing as given in the question will not do any redirects instead it will retain the URL as such and proxy the content from elsewhere. In Apache configuration, we have an option to do redirects, in the bellow sample, we are checking for the host and based on it issuing an redirect to the desired URL
<VirtualHost *:80>
ServerName omniatm.eamondev.com
Redirect / https://omniatm.eamondev.com
<If "%{HTTP_HOST} != 'eamondev.com:3000'">
Redirect "^/?(.*)" "https://omniatm.eamondev.com/$1"
</If>
</VirtualHost>

Ubuntu - Apache - Reverse Proxy - NodeJS 302 : moved permanently on post method

I have an application running on my VPS at http://localhost:3000.
I'm trying to make a reverse Proxy with Apache2 to make it accessible at node.mydomain.net.
With that virtualhost config :
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
ServerName node.mydomain.net
ServerAlias www.node.mydomain.net
</VirtualHost>
It's actually working with the welcome page, but when i'm trying to connect, the POST method to node.mydomain.net/authenticate, it's actually return in the web inspector :
request method : POST Status Code : 302 Moved Temporarily.
Im' not sure about the real problem and I found no solution by the moment. Can it a rewriting problem ? or a POST method not allowed problem ?
If anyone can send me on a serious trail, i'll be very happy.
Many thanks.

apache proxy HTTPS to HTTP with POST data

I have mobile a app uploading to https://mydomain.com/files/incoming_files.php and https://mydomain.com/api/v2/incoming_files.php
Ubuntu 11.04, Apache/2.2.17
Some of the uploads times out in the SSL handshake.
Therefore I'm trying to proxy POST upload requests to the PHP upload scripts from https:// to http:// and keep the POST data.
Throws these errors:
(70007)The timeout specified has expired: proxy: prefetch request body failed to 1.2.3.4:80
(103)Software caused connection abort: proxy: pass request body failed to 1.2.3.4:80
proxy: pass request body failed to 1.2.3.4:80
This is my config:
<VirtualHost 1.2.3.4:443>
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule ^/?files/incoming_files\.php http://%{SERVER_NAME}/files/incoming_files\.php [NC,P]
RewriteRule ^/?api/v2/incoming_files\.php http://%{SERVER_NAME}/api/v2/incoming_files\.php [NC,P]
SSLProxyEngine on
ProxyRequests Off
ProxyPreserveHost On
SetEnv proxy-sendchunked 1
SetEnv proxy-sendcl 0
ProxyPass /files/incoming_files.php http://mydomain.com/files/incoming_files.php
ProxyPassReverse /files/incoming_files.php http://mydomain.com/files/incoming_files.php
ProxyPass /api/v2/incoming_files.php http://mydomain.com/api/v2/incoming_files.php
ProxyPassReverse /api/v2/incoming_files.php http://mydomain.com/api/v2/incoming_files.php
Have tried to: Set Rewrite without ProxyPass. Set ProxyPass without Rewrite. Set with/without SetEnv proxy-sendchunked 1/proxysend-cl 0
Any idea what the best solution is, and what I'm doing wrong?
I'm seeing the same error messages in my apache access log:
[error] (103)Software caused connection abort: proxy: pass request body failed to X.X.X.X:Y (hostname)
[error] proxy: pass request body failed to X.X.X.X:Y (hostname) from Z.Z.Z.Z ()
with the only difference seeming to be that I'm running a tcServer (Tomcat) backend.
What I can tell you is that I'm also seeing a 502 response code associated with the upload request.
"POST /<path_to_target>/upload.do?_t=1407181458532 HTTP/1.1" 502 305
I think you might be on to something with the fact that your ProxyPass is redirecting HTTPS to HTTP and that is something I need to test.
One thing I would suggest is that you change update the ProxyRequests value to On.
ProxyRequests On

Resources