Redirection problem again in new rules.
Francis Daly
francis at daoine.org
Sat Apr 16 12:36:21 UTC 2016
On Sat, Apr 16, 2016 at 12:22:46PM +0500, Muhammad Yousuf Khan wrote:
Hi there,
> location ~ \.php$ {
> location ~*
> \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|woff|woff2)$
> location / {
> try_files $uri $uri/ /index.php?q=$request_uri;
> autoindex off;
> rewrite ^/([^_]*)_([^_]*_.*)\.html /$1-$2;
> rewrite ^/([^_]*)_([^_]*)\.html$ /$1-$2.html redirect;
> }
> if ( $request_filename ~ /action/cycling/cycling-is-best-for-health ) {
> rewrite ^ /action/cycling/cycling-is-best-for-health.html? permanent;
> }
To recap:
A loop is when the second (redirected) request is handled in the same
way as the first request. So to avoid or break the loop, the second
request must not get the same response as the first one.
You know that
location /x { rewrite ^ /x.html redirect; }
fails because "location /x" will match /x.html, so the second request
will match the same location as the first one and the same redirect will
happen again; and one way to avoid the loop is to make the "location"
only match exactly "/x".
Based on that, can you guess what the "~" in
if ( $request_filename ~ /action/cycling/cycling-is-best-for-health ) {
means, in the context of "matching both the first request and the second
request"?
http://nginx.org/r/if
One way to avoid the loop is the make the "if" only match exactly the
first request.
Also, you know that
rewrite ^ /x.html redirect;
fails because the first argument to "rewrite" is a pattern, and both
your original /x and your rewritten /x.html match it; so another way
to avoid the loop is to make the "rewrite" only match exactly "/x".
So you could try that approach instead.
http://nginx.org/r/rewrite
Anyhow: since your example redirect is static, not depending on anything
other than the first request, what you probably want here is a series
of exact location matches, of the form
location = /action/cycling/cycling-is-best-for-health {
return 301 /action/cycling/cycling-is-best-for-health.html;
}
But *if* what you want is always-and-only serve the file of "the original
request with .html on the end", then you don't necessarily need a redirect
at all. Depending on what the full requirements are, you might be able
to get away with adjusting your try_files line instead:
> try_files $uri $uri/ /index.php?q=$request_uri;
Make that
try_files $uri $uri.html $uri/ /index.php?q=$request_uri;
and it might do what you want without any redirects.
(Whether the new $uri.html goes before or after "$uri/" depends on
the requirements.)
> here is the test run of curl -i
> http://mydomain.com/action/cycling/cycling-is-best-for-health
>
>
> HTTP/1.1 301 Moved Permanently
> Server: nginx/1.6.2
> Date: Sat, 16 Apr 2016 07:10:33 GMT
> Content-Type: text/html
> Content-Length: 184
> Location: http://mydomain.com/action/cycling/cycling-is-best-for-health.html
> Connection: keep-alive
We know from the config that that is handled directly by nginx;
additionally, if it were handled by PHP or wordpress, there would probably
be an extra header in there to indicate that.
> test run with ".html" at the end.
> curl -i http://mydomain.com/action/cycling/cycling-is-best-for-health.html
>
> HTTP/1.1 301 Moved Permanently
> Server: nginx/1.6.2
> Date: Sat, 16 Apr 2016 07:10:37 GMT
> Content-Type: text/html
> Content-Length: 184
> Location: http://mydomain.com/action/cycling/cycling-is-best-for-health.html
> Connection: keep-alive
Since that extra PHP-or-wordpress header is not there, we can suspect
that it is also handled directly by nginx.
(To be sure, you would have to check the headers for a wordpress response
as well.)
But from the analysis above, we already now that it is handled directly
by nginx, because your "if/rewrite" configuration is the loop.
Cheers,
f
--
Francis Daly francis at daoine.org
More information about the nginx
mailing list