Rewriting dynamic URLs

房东的猫 提交于 2019-12-17 20:09:07

问题


I' trying to rewrite 1 dynamic URL to another dynamic URL as follows;

/category?category=News to
/categorysearch/result/?q=news

I was wondering if anyone had an idea on how this can be done in htaccess?

Thanks.


回答1:


So the final EDITED solution is (for your linked .htaccess):

RewriteCond %{REQUEST_FILENAME} ethical [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)ethical(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=%3 [L,R]

If I use the 'category' terms like in this current question:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /categorysearch/result/?q=%3 [L,R]

But the first one is more clear, the word category is not used everywhere. If you want to add the lowercase transformation we'll even do:

# outside of a Directory section
RewriteMap lowercase int:tolower
# in a Directory section (not a .htaccess)
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%3} [L,R]

But as commented this last one with tolower could not work in a .htaccess -- anyway .htaccess are bad, really, for performances, you should really think about setting AllowOverride None and move all this stuff in a VirtualHost. And nice things such as rewriteMaps cannot work on .htaccess files.

So Now I'll explain the rules. First the main problem in your situation is that everything after the "?" is the query_string, not the requested filename. And most rewriteRules try to work on the requested filename. So I first check we're on the targeted quested filename:

RewriteCond %{REQUEST_FILENAME} category [NC]

Then we are going to work on the Query string (everything after the question mark). We could have written something quite simplier like that:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} ^category=(.+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%1} [L,R]

To catch everything after ?category= in a variable %1 available for the RewriteRule. But the QUERY_STRING parameter has several problems, let's try to have some fun with it:

  • url decoding is not yet done on this parameter
  • category is maybe not the first parameter in the list of parameters
  • it's maybe even not the last one (&foo=bar)
  • you could have some spaces before

EDITED:

My first answer was:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} [^|&|%26|%20][category](=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%2} [L,R]

With [^|&|%26|%20] catching the fact it could be the starting parameter or a parameter after an & or a space, %26 is an & urlencoded.

But this was wrong, thanks to @mootinator comment I've checked a little more, [category] is matching 'category' but also 'atcatcategory' and any combination of theses letters.

RewriteCond %{QUERY_STRING} category(=|%3D)([^&]+) [NC]

Is matching the 'category' argument, removing the ^ allows this argument to be placed anywhere. But this would also match an argument named subcategory. So the 1st letter must be a space or & (or the start of the query string).

This was the reason for [^|&|%26|%20], meaning for me start of chain OR & or space or & in urlencoded. But that was also wrong, the ^ inside [] means negate. So we need to use here as well matching parenthesis: (^|&|%26|%20), now it works, the only problem is that the value of the argument is now %3 and not %2

Then we catch the (category) word, to be really exact we should in fact catch it letter after letter with uppercase, lowercase, and urlencoded version of the letter in lower and uppercase, something like an awfull [c|C|%43|%63][a|A|%61|%41][t|T|%74|...]to be continued -- and I should maybe use parenthesis instead of brackets, hell, check urlencoded characters list here.

(=|%3D) is the '=' character urlencoded or not. I could have used [=|%3D] but the %3D is not matched well in this case, I don't understand why (mod_rewrite is a land of strange things). Because of this first matching parenthesis used we'll have to use %2 variable and not %1.

And then we have the nice ([^&]+) which means anything but not an '&'.

After theses conditions we apply the RewriteRule. We take everything (this is .*) and redirect it to /catalogsearch/result/?q=%2 where we use %3 and not $1 or $3 as we do not capture anything on the rewriteRule but on a condition before (%3 is the third captured data on the last condition so it's ([^&]+)). If you add the QSA flag ([L,R,QSA]) in the rewriteRule you will even get back other parameters on the final query string so that:

ethical?bar=toto& ethical=Foo&zorglub=titi 
=> is redirected to 
catalogsearch/result/?q=foo&bar=toto&%2520ethical=Foo&zorglub=titi

And if I play with a little url encoding:

ethical?bar=toto%26 ethical%3DFoo&zorglub=titi 
=> is redirected to 
catalogsearch/result/?q=foo&bar=toto%2526%2520ethical%253DFoo&zorglub=titi

But this is not the end of the play, I'll let you handle all the urlencoding problems you could have it you want to detect all variations on Foo value and mix them with the tolower (here it's broken). You will maybe not even have theses problems of encoded url in your parameters or extra attributes, but that was fun :-)




回答2:


Depending on what you're trying to do and how specific things need to be, there are two options.

The first is Rob W's solution, which should redirect the user from /category?category=News to /categorysearch/result/?q=News

If, as it appears, your URLs are case-sensitive, you might want to look at a PHP script like the following:

$matches = array();
if( preg_match( "/^/category\?category=(.+)/", $_SERVER['REQUEST_URI'], $matches ) ) {
    header( 'Location: http://' . $_SERVER['HTTP_HOST'] . '/categorysearch/result/?q= . strtolower($matches[1]) );
}
else {
    //ERROR HANDLING
}

Once that's settled, you can use a rule like the following to redirect using a fully lowercase parameter.

RewriteRule ^category\?category=(.+)$ redirect.php [L]

Put together, this solution would redirect /category?category=News to /categorysearch/result/?q=news




回答3:


I think

RewriteRule ^/category?category=(.*) /categorysearch/result/?q=news

Will do it.



来源:https://stackoverflow.com/questions/7703552/rewriting-dynamic-urls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!