I am working on a Symfony 3.4 application which has public and private parts. However, I am currently setting up a staging system for this application which should only be accessed by authorized users, so I put an .htaccess basic authentication in front of the entire application.

There is a single route in the application which needs to be accessed by an external app which does not supply authentication. I want to disable .htaccess authentication for this single route only. All URLs for this route are of the form /api/post-result/123 where 123 is an arbitrary ID.

After searching around for a bit, I tried to solve this via a Require expr entry in my .htaccess which would simply match the URL. However, as Symfony does URL rewriting, REQUEST_URI always appears as "app.php" to the server (and my condition). I have tried other variables, such as QUERY_STRING or PATH_INFO, but none of them seem to contain my actual request URI. I have then tried to put the matched URI into an environment variable using a rewrite rule. However, it seems that this cannot be read by the expression.

Here is my .htaccess file

DirectoryIndex app.php

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .? - [L]

    RewriteRule ^(.*)$ %{ENV:BASE}/app.php [L,E=SFURI:$1] # <-- env variable is set here

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        RedirectMatch 302 ^/$ /app.php/

<Files "*.php">
  AuthUserFile /srv/my/app/.htuser
  AuthName "Authentication Required"
  AuthType Basic

  # allow access to post-result api without authentication
  # THIS DOES NOT WORK as reqenv('SFURI') is always empty
  Require expr "reqenv('SFURI') =~ m#/api/post-result/.*$#"
  # require authentication for everything else
  Require valid-user

Looking at the Apache log, the environment variable is set correctly:

[rewrite:trace5] [pid 11010] mod_rewrite.c(476): [...] setting env variable 'SFURI' to 'api/post-result/123'

[rewrite:trace1] [pid 12755] mod_rewrite.c(476): [...] internal redirect with /app.php [INTERNAL REDIRECT]

However, for some reason the variable is empty when I try to access it later. Could it be possible that all environment variables are cleared on the internal redirect caused by the last rewrite rule? The log shows that the condition doesn't match and when I change the condition so it checks whether the variable is empty, the condition comes back as true. I have also tried using the env function instead of reqenv, but the behavior is the same.

[authz_core:trace4] [pid 11010] util_expr_eval.c(860): [...] Evaluation of expression from /srv/my/app/.htaccess:36 gave: 0

[authz_core:debug] [pid 11010] mod_authz_core.c(809): [...] AH01626: authorization result of Require expr "reqenv('SFURI') =~ m#/api/post-result/.*$#": denied

What can I do to make my expression find the environment variable set by the rewrite rule?


It turns out that the internal redirect caused by the last rewrite rule prefixes all variables with REDIRECT_. In order to access the variable in the expression, it needs to be accessed as REDIRECT_SFURI.

This problem was also covered at StackOverflow: When setting environment variables in Apache RewriteRule directives, what causes the variable name to be prefixed with “REDIRECT_”?

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.