I went through questions/solutions found here, tried numerous approaches (including the [L] directive) but nothing really did the trick.
Situation Overview
Debian running Apache 2.2 proxying through nginx
Goal
Redirect everything to /index.php
and assure a trailing slash, always.
Exclude the following directories from the rule:
- js_static
- media
Exclude all .css files from the rule.
The Problem
Apache/nginx lead to a 301
redirect loop when i call www.url.com/js_static
. (Problem occurs also with trailing slash – makes no difference)
Current Solution Approach
nginx is configured like this:
gzip_proxied any;
rewrite ^/(.*)/$ /$1;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:AES256+EDH';
Apache is configured this way:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !^.+\.(css)
RewriteCond %{REQUEST_URI} !^.+js_static
RewriteCond %{REQUEST_URI} !^.+media
RewriteRule ^(.*)$ /index.php/$1
AllowEncodedSlashes On
I fail to see where the problem is. A theory i had was that the combination of nginx/apache rewrites would create the problem, so i fiddled around with the configuration, but to no avail, unfortunately.
Can someone pinpoint the issue here?
Best Answer
tl;dr "The problem" is likely to be caused by mod_dir (Apache) automatically appending the slash when requesting a physical directory. However, disabling mod_dir (ie.
DirectorySlash Off
) is not necessarily the answer.In your Nginx config (your frontend proxy), you are unconditionally stripping the trailing slash from all URLs (including directories) via an internal rewrite. So, whether you include the trailing slash on the initial request, it will indeed make no difference.
Apache mod_dir (by default) will automatically append a slash when requesting a physical directory (that does not already have a trailing slash) via an external 301 redirect. It does this in order to "fix" the URL. "A directory" is not strictly a valid resource (what would you expect to be returned?). Once "fixed", mod_dir then tries to return the directory index document (eg.
index.html
) in that directory:example.com/directory
301 redirect toexample.com/directory/
example.com/directory/
internal rewrite toexample.com/directory/index.html
(or whateverDirectoryIndex
document is found). Or a 403 Forbidden if there is no directory index (unless auto-directory indexes are enabled - not recommended.)However, after the redirect to
example.com/directory/
, the request hits your Nginx proxy again which strips the trailing slash.... etc. etc. 301 redirect loop.My personal preference is to always leave the trailing slash on physical directories. However, if you do want to remove the trailing slash from all URLs then you need to disable mod_dir's automatic behaviour and manually append the trailing slash yourself via an internal rewrite (because requesting a bare directory with no trailing slash is not strictly valid in this instance).
Try changing your Apache config to the following
I assume this is in your server config (and not .htaccess)? However, your previous
RewriteRule
would have resulted in a double slash in the substitution when used in the server config. This should still have resolved correctly, however, it could break some things.I've also made this more "generic". Rather than specifically checking for
.css
files and URLs containingjs_static
ormedia
, this simply checks to make sure the request is not for a physical file. This is far more common (and flexible) as a "front-controller". However, you can change this back if you specifically need to (but there are potential problems if you do).Aside: I wouldn't expect this to be a valid request anyway?
Just to echo TeroKilkanen's concerns in the comments. Using both Nginx and Apache for related rewrites is not recommended.