What do you think? Discuss, post comments, or ask questions at the end of this article [More about me]

Skip to end of metadata
Go to start of metadata

Problem

So here was the situation: I decided to change the name (and sub-domain) of a web application I developed and maintain.  I needed to redirect traffic to my old domain to the new one.  However, the issue was that I provide a REST API in the application, and others (who use the web application) use my REST endpoint (which is accessed via the old subdomain name) in various custom applications and scripts.  Hence, I needed to maintain REST query access to the old subdomain (and provide it to new domain) while redirecting normal (browser) access to the new subdomain.

In short, I wanted to redirect everyone to the new domain BUT make sure REST calls to the old subdomain name still worked as before...

Now, the key problem here is I'm using Apache's mod_rewrite and RewriteRule does not pass authorization headers to the new domain (and auth headers are needed to authenticate on a secured REST endpoint).

Solution

The solution below essentially proxy passes REST API calls (to the old subdomain) directly to my web application, while redirecting other traffic to the new domain.

Below is my virtual host conf for the new domain:

<VirtualHost *:443>
    ServerName newdomain.jaytaala.com

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy <WEB-APP-SERVER-IP>

    ProxyPass / http://<WEB-APP-SERVER-IP:PORT>:/
    ProxyPassReverse / http:<WEB-APP-SERVER-IP:PORT>/

    SSLEngine On
    # Your SSL certificate information for this sub-domain can go here.
    # If you use certbot-auto, it will automatically add it here if you use the --apache flag.
    # See the following 'LetsEncrypt for SSL certificates' section for details.
</VirtualHost>

<VirtualHost *:80>
    ServerName newdomain.jaytaala.com
    Redirect Permanent / https://newdomain.jaytaala.com/
</VirtualHost>

This redirects non-https traffic to port 443 (HTTPS).  For HTTPS port, this will proxy-pass (reverse proxy) traffic to my web application.  ProxyPassing will preserve REST authorisation headers, and hence secured REST access and normal SSL secured browser access works fine.  See SSL certificates with cerbot - including wildcard SSL certificates for information on securing your site with SSL.

Now, let's add the virtual host config to the old subdomain (you can either add to the same file as the above or create a new conf file):

<VirtualHost *:443>
    ServerName olddomain.jaytaala.com

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy <WEB-APP-SERVER-IP>

    RewriteEngine On

    # if no auth header, then redirect
    RewriteCond %{HTTP:Authorization} !^(.+)$
    RewriteRule ^/(.*)$ https://newdomain.jaytaala.com/$1 [R=301,L]

    # if here then has auth headers, allow proxypass for REST API queries
    ProxyPass / http://<WEB-APP-SERVER-IP:PORT>/
    ProxyPassReverse / http://<WEB-APP-SERVER-IP:PORT>/

    SSLEngine On
    # Your SSL certificate information for this sub-domain can go here.
    # If you use certbot-auto, it will automatically add it here if you use the --apache flag.
    # See the following 'LetsEncrypt for SSL certificates' section for details.
</VirtualHost>

<VirtualHost *:80>
    ServerName olddomain.jaytaala.com
    Redirect Permanent / https://olddomain.jaytaala/
</VirtualHost>

This config uses RewriteCond to conditionally redirect (via RewriteRule) traffic without Authorization headers (queries to my REST endpoint has auth headers) directly to my newdomain vhost.  All other traffic (i.e traffic with auth headers) are proxy-passed (with auth headers) directly to my web application server to respond to.

References

  1. https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
  2. https://httpd.apache.org/docs/current/mod/mod_rewrite.html