2

I am trying to implement a zero downtime deploy strategy for a static website using an .htaccess file. I'd like to access at http://example.com/__staging__ the staging enviroinment redirecting internally all the requests to the path containing the actual data uploaded (i.e. http://example.com/__private__/abcdefgh where abcdefgh is the hash of the commit). In the meantime opening directly anything under http://example.com/__private__ should be forbidden.

This is the .htaccess file I have written so far (which does not work):

RewriteEngine On

# This line seems to work correctly.
RewriteRule "__staging__(.*)$" "__private__$1" [PT,E=__staging__:1]

# These directives always forbid the access while, to my understanding, should
# trigger after a rewrite from 
RewriteCond %{ENV:__staging__} "!=1"
RewriteRule "__private__" "-" [F]

I've read https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html, https://httpd.apache.org/docs/2.4/env.html and https://httpd.apache.org/docs/2.4/rewrite/.. I have surely missed something, I am stuck. Thank you very much!

2
1

Try something like the following instead:

RewriteEngine On

# Block direct access to __private__
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^__private__ - [F]

# Rewrite requests from __staging__ to __private__
RewriteRule ^__staging__(.*) __private__$1 [L]

There's no need to set the __staging__ environment variable, unless you are using this for something else? (But you can always determine this from the requested URL in your app.)

The condition that checks the REDIRECT_STATUS env var ensures we don't get a redirect loop. This is empty on the initial request and set to "200" (as in 200 OK HTTP status) after the first successful rewrite.

You should use a start-of-string anchor (^) to avoid potential conflicts. Regex is greedy by default, so the trailing $ (end-of-string anchor) is superfluous on the RewriteRule pattern.

The surrounding double-quotes on the arguments are only strictly necessary if you have spaces in the argument values (even then they can be backslash escaped instead). So, whether you use double quotes here is just personal preference.


# These directives always forbid the access while, to my understanding, should
# trigger after a rewrite from 
RewriteCond %{ENV:__staging__} "!=1"
RewriteRule "__private__" "-" [F]

Because the PT flag (implies L) causes the rewrite engine to start over. At this point the environment variable __staging__ is renamed to REDIRECT___staging__ (REDIRECT_ prefix - so that's 3 underscores in the resulting env var). So, the __staging__ env var is never actually set at the time the rule is evaluated and the request is always blocked.

However, the method outlined above is the more usual way to handle this - no env var is required.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.