简体   繁体   中英

RewriteRule to new URL and internally rewrite to old one

My goal is to redirect users from these paths:

/foo/index.php
/foo/

To

/index

And have /index load the original content from /foo/index.php .

Is this possible in .htaccess ?

So far I've tried:

RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L]
RewriteRule ^index$ /foo/index.php [QSA,L]

But this gets into an infinite redirection loop. I thought adding a RewriteCond for the URI would help, but from the docs :

Note: Conditions are being processed after the pattern of the RewriteRule has matched.

So apparently RewriteCond won't be of much use in my use case.

Looking through the Rewrite Flags docs , the S flag seems to be what I'm looking for:

This flag forces the rewriting engine to skip the next num rules in sequence, if the current rule matches. Use this to make pseudo if-then-else constructs: The last rule of the then-clause becomes skip=N, where N is the number of rules in the else-clause.

So I've tried:

RewriteRule ^index$ /foo/index.php [QSA,L,S=1]
RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L]

Though, as I have the L flag, the S flag seems a little redundant. Nevertheless, the logic seems correct in my view, though this is still in an infinite redirection loop.

Right now I'm using an workaround with PHP. First, Apache internally rewrites the new URL to the old one and then in the PHP I check if the $_SERVER['REQUEST_URI'] matches the new format in the beginning of the script, otherwise ensue a 301 redirect to the new URL.

Though, I'd like to know whether this possible to do with .htaccess solely? Or if anyone can explain how/why I'm getting an infinite loop with the rewrite rules above I will be grateful.

The trouble is that the rules are in a .htaccess file, and as docs say, this file is reparsed after every rewite loop, letst it might have been applicable to a .htaccess in a different directory. Thus your L flags are all in vain.

I have looked around, and if you really cannot place your rewrite rules in the main apache config, I can offer the following kludge: because the Server-Variables THE_REQUEST is not updated between the rewrite runs, one can conclude the "browser visible URL" from there and prevent rewriting in that case:

# external redirect to /index (unless browser already shows /index plus query params)
RewriteCond %{THE_REQUEST} !^\w+\ /index(\?.*)?\ HTTP/1..$
RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L]

# internal redirect for /index
RewriteRule ^index$ /foo/index.php [QSA,L]

I thought there is also another variable that remains unchanged, but right now I cannot find it. Maybe someone else ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM