htaccess Silent Redirect to Subdirectory: Subdirectory showing when no trailing '/'

后端 未结 2 2062
借酒劲吻你
借酒劲吻你 2021-02-10 08:45

I have dug high and low around Google and StackOverflow to try and figure out my problem, trying countless solutions but nothing has completely worked.

I\'m looking to m

相关标签:
2条回答
  • 2021-02-10 08:52

    Jon Lin's answer was very helpful in determining what was causing the problem in my very similar setup. For completeness I will include the relevant information from his answer:

    This is probably happening because mod_dir (the module that automatically redirects the browser if a request for a directory is missing a trailing slash to the same thing with a trailing slash. See the DirectorySlash directive in mod_dir

    What's happening is:

    1. You request: mydomain.com/Contact
    2. mod_dir doesn't touch this since /Contact isn't a directory
    3. /Contact gets rewritten to /subdir/Contact and internally redirected
    4. mod_dir sees that /subdir/Contact is a directory and missing the trailing slash so it redirects the browser to mydomain.com/subdir/Contact/
    5. So now, your browser's location bar has the /subdir/ in it.

    In my case, I had requests being redirected to /subdir with a few exceptions and didn't want to have to re-enable DirectorySlash for each of those exceptions.

    By allowing RewriteEngine to continue after the initial redirect to /subdir, it's possible to mimic what mod_dir would be doing while also taking /subdir into account, before mod_dir gets to see it.

    RewriteEngine on
    
    RewriteCond %{REQUEST_URI} !^/exception1|exception2|...
    RewriteRule ^(.*)$ /subdir/$1
    
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteCond %{REQUEST_URI} !(.*)/$
    RewriteRule ^subdir/(.*) $1/ [R,L]
    

    Note: You may need to be careful about allowing RewriteEngine to continue if there are further rules. Not matching the second rule will continue on to any further rules which may produce a different result.

    This can be avoided by using a third rule to stop RewriteEngine processing if the redirect into /subdir has happened:

    RewriteCond %{REQUEST_URI} ^subdir
    RewriteRule .* - [L]
    
    0 讨论(0)
  • 2021-02-10 09:04

    This is probably happening because mod_dir (the module that automatically redirects the browser if a request for a directory is missing a trailing slash to the same thing with a trailing slash. See the DirectorySlash directive in mod_dir

    What's happening is:

    1. You request: mydomain.com/Contact
    2. mod_dir doesn't touch this since /Contact isn't a directory
    3. /Contact gets rewritten to /subdir/Contact and internally redirected
    4. mod_dir sees that /subdir/Contact is a directory and missing the trailing slash so it redirects the browser to mydomain.com/subdir/Contact/
    5. So now, your browser's location bar has the /subdir/ in it.

    You can add DirectorySlash off in your .htaccess to turn off mod_dir from redirecting. But if you want directories to have trailing slashes, you can add a separate condition for it. Based on what you already have, we can expand it to this:

    RewriteEngine on
    
    # Has a trailing slash, don't append one when rewriting
    RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
    RewriteCond %{REQUEST_URI} !^/subdir/
    RewriteCond %{THE_REQUEST} ./\ HTTP/1\.[01]$ [OR]
    # OR if it's a file that ends with one of these extensions
    RewriteCond %{REQUEST_URI} \.(php|html?|jpg|gif|css)$
    RewriteRule ^(.*)$ /subdir/$1 [L]
    
    # Missing trailing slash, append one
    RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
    RewriteCond %{REQUEST_URI} !^/subdir/
    RewriteCond %{THE_REQUEST} [^/]\ HTTP/1\.[01]$
    # But only if it's not a file that ends with one of these extensions
    RewriteCond %{REQUEST_URI} !\.(php|html?|jpg|gif|css)$
    RewriteRule ^(.*)$ /subdir/$1/ [L]
    

    Note: I changed !^/mydomain/ to !^/subdir/, figured it was a typo because without it, mod_rewrite would loop internally indefinitely (foo -> /subdir/foo -> /subdir/subdir/foo -> /subdir/subdir/subdir/foo, etc). If I got that wrong, you can change it back.

    Edit: See my additions of RewriteCond's matching against \.(php|html?|jpg|gif|css). These are the file extensions that get passed through without getting trailing slashes added. You can add/remove to suit your needs.

    0 讨论(0)
提交回复
热议问题