title: Redirecting http traffic to https in Apache without using mod_rewrite
body: <p>I am trying a pretty simple thing that I would normally do using a RewriteRule (and which works perfectly when I do).</p>
  
  <p><strong>My goal:</strong>
  Force certain (not all) URLs to use the <code>https</code> protocol.</p>
  
  <p><strong>Caveats:</strong></p>
  
  <ul>
  <li>Apache is behind a crypto-offloader. We would like a single virtual host that deals with both the unencrypted and the decrypted traffic. The offloader forwards all traffic to the same port and sets the <code>X-Forwarded-Proto</code> header. (It also sets the new <code>Forwarded</code> header for future compatibility, but I will leave that out below for brevity.)</li>
  <li>Everything I have read lately suggests to use <code>Redirect</code> or <code>RedirectMatch</code> instead of <code>RewriteRule</code>. Accordingly, I would like to avoid <code>RewriteRule</code> if possible.</li>
  <li>The URLs I wish to force are reverse proxies that I have configured in a <code>&lt;LocationMatch&gt;</code> section within my virtual host.</li>
  <li>The virtual host has multiple <code>Alias</code> entries that all correspond to valid names that are included in the TLS certificate (i.e. I don't want/need to force users to use the canonical name)</li>
  <li>It seems that <code>Redirect</code> and <code>RedirectMatch</code> are unable to make use of the <code>%{HTTP_HOST}</code> server variable. This means I would need extra logic to have a different <code>RedirectMatch</code> line depending on the host that was use by the client (Messy).</li>
  <li>In the event that I NEED to use <code>mod_rewrite</code> for this, it would be good to have the <code>RewriteRule</code> inside the <code>&lt;LocationMatch&gt;</code> section to keep the configuration for that path/proxy in one place. However this also seems to cause problems.</li>
  </ul>
  
  <p>Time for some example code to help explain this. All of the following examples reside within a <code>VirtualHost</code> section as follows:</p>
  
  <pre><code>&lt;VirtualHost 192.168.0.1:80&gt;
      ServerName www.example.com
      ServerAlias example.com
      ServerAlias anothervalidalias.com
  </code></pre>
  
  <p><strong>Option 1</strong> - Using <code>RedirectMatch</code>. This works but forces the hostname.</p>
  
  <pre><code>&lt;LocationMatch "/backendcontextroot"&gt;
      ProxyPreserveHost on
      ProxyPass "http://192.168.0.2:8080/backendcontextroot"
      &lt;If "-z req('X-Forwarded-Proto')"&gt;
          RedirectMatch ^(.*) https://www.example.com/$1
      &lt;/If&gt;
  &lt;/LocationMatch&gt;
  </code></pre>
  
  <p><strong>Option 2</strong> - Using <code>RedirectMatch</code>. This would be my <strong>ideal</strong> solution, but the HTTP_HOST does not work. Apache sends no response back to the client.</p>
  
  <pre><code>&lt;LocationMatch "/backendcontextroot"&gt;
      ProxyPreserveHost on
      ProxyPass "http://192.168.0.2:8080/backendcontextroot"
      &lt;If "-z req('X-Forwarded-Proto')"&gt;
          RedirectMatch ^(.*) https://%{HTTP_HOST}/$1
      &lt;/If&gt;
  &lt;/LocationMatch&gt;
  </code></pre>
  
  <p><strong>Option 3</strong> - Using <code>RewriteRule</code> within a <code>LocationMatch</code> block. If I really cannot use <code>Redirect</code> and am forced to use <code>RewriteRule</code> then this would be my preferred method as it keeps the configuration for the <code>/backendcontextroot</code> reverse proxy together in one place. However, this produces some 'funky' redirects...</p>
  
  <pre><code>&lt;LocationMatch "/backendcontextroot"&gt;
      ProxyPreserveHost on
      ProxyPass "http://192.168.0.2:8080/backendcontextroot"
      RewriteEngine on
      RewriteCond %{HTTP:X-Forwarded-Proto} !https
      RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1
  &lt;/LocationMatch&gt;
  </code></pre>
  
  <p>This redirects to:
      <a href="https://www.example.com/proxy:http://192.168.0.2:8080/backendcontextroot" rel="nofollow">https://www.example.com/proxy:http://192.168.0.2:8080/backendcontextroot</a></p>
  
  <p><strong>Option 4</strong> - Using <code>RewriteRule</code> <em>outside</em> the <code>LocationMatch</code> block. This works, but the configuration for this reverse proxy is then 'spread around'. It also uses <code>RewriteRule</code> despite suggestions that I should avoid it if possible.</p>
  
  <pre><code>RewriteEngine on
  RewriteCond %{HTTP:X-Forwarded-Proto} !https
  RewriteCond %{REQUEST_URI} ^/backendcontextroot
  RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1
  
  &lt;LocationMatch "/backendcontextroot"&gt;
      ProxyPreserveHost on
      ProxyPass "http://192.168.0.2:8080/backendcontextroot"
  &lt;/LocationMatch&gt;
  </code></pre>
  
  <p>Am I stuck using option 4 or is there a more elegant way?</p>