Redirection problem again in new rules

Hi,

there are multiple apache redirection rules that were working
successfully.
for example something like this

Redirect 301 /aaaa/bbbbbbb /aaaaa/bbbbbb.html

Now i have converted this rule in nginx like this

location /aaaa/bbbbbbbb {
rewrite ^(.*)$ /aaaa/bbbbbbbbbb.html redirect;
}

i also tried adding “permanent” and rewrite line but also didn;t wrok.

now all redirection rules are keep giving error “redirection loops”.
and when i disable the rule things back to normal. there is no
duplication
happening as far as config is concern. i can confirm.

can you guys please advice how can i troubleshoot this and fix the
issue.

your friendly advice is highly appreciated.

Thanks,
Yousuf

Le 14 avr. 2016 16:03, Muhammad Yousuf K. [email protected] a crit :

Redirect 301 /aaaa/bbbbbbb /aaaaa/bbbbbb.html

Now i have converted this rule in nginx like this

location /aaaa/bbbbbbbb {
rewrite ^(.*)$ /aaaa/bbbbbbbbbb.html redirect;
}

You should use break instead redirect :
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite

On Thu, Apr 14, 2016 at 07:03:19PM +0500, Muhammad Yousuf K. wrote:

Hi there,

there are multiple apache redirection rules that were working successfully.
for example something like this

Redirect 301 /aaaa/bbbbbbb /aaaaa/bbbbbb.html

Now i have converted this rule in nginx like this

location /aaaa/bbbbbbbb {
rewrite ^(.*)$ /aaaa/bbbbbbbbbb.html redirect;
}

You have different numbers of a:s and b:s there, which makes it quite
difficult to know what it is that you actually want to do.

now all redirection rules are keep giving error “redirection loops”.
and when i disable the rule things back to normal. there is no duplication
happening as far as config is concern. i can confirm.

Do note that “location /x” can match anything that starts with /x; and
if a request for /x.html returns a redirect to /x.html, you’ve got a
loop.

Possibly you want your “rewrite/redirect” to only happen for specific
requests; in that case, set the first argument to “rewrite” to be as
specific as you want. Or leave the “rewrite” applying to everything,
but have it in an exact-match location{}.

(And if you are doing the same “rewrite…redirect” for all inputs,
“return” may be a better directive to use instead.)

can you guys please advice how can i troubleshoot this and fix the issue.

“troubleshoot” is “turn on the debug log to see, or otherwise work out,
what you have asked nginx to do”. Then compare that with what you want
nginx to do.

Good luck with it,

f

Francis D. [email protected]

Hi All,

Thanks for your help. Ph. Gras and Francis for your support and advice i
really appreciate that.

Ph. Gras, i tried “break” but now it is showing 404.

Francis,

Sorry for the mistake in a’s and b’s i was typing that in general
because
the context was not the URL but the problem.

Do note that “location /x” can match anything that starts with /x; and
if a request for /x.html returns a redirect to /x.html, you’ve got a loop.

Yes , i have double checked but my redirection rules are not created
wrong.
so i am sure no loop is happening there.

BTW just to update you guys. i am using wordpress.

i am doing two redirections , one domain base and second URL base.

domain base is working fine however URL redirections are giving me
issues.

could this be related to wordpress?

Thanks,
MYK

On Fri, Apr 15, 2016 at 12:27:11PM +0500, Muhammad Yousuf K. wrote:

Hi there,

Sorry for the mistake in a’s and b’s i was typing that in general because
the context was not the URL but the problem.

If you can show one specific url which does show the problem, then it
makes it much easier to see what is going on.

If you can also include one small but complete config file that shows
the problem, that makes it much easier for someone else to repeat your
experiment.

(And sometimes, the act of making a small config that shows the problem,
will show you what the fix is.)

Do note that “location /x” can match anything that starts with /x; and
if a request for /x.html returns a redirect to /x.html, you’ve got a loop.

Yes , i have double checked but my redirection rules are not created wrong.
so i am sure no loop is happening there.

Part of the point of you asking the question, is that you do not know
where the problem is.

So usually, the best thing is to run a test nginx with your config, then
remove as much as possible while still showing the problem. Maybe that
config will just have two location{} blocks, and the loop will be
obvious.

BTW just to update you guys. i am using wordpress.

i am doing two redirections , one domain base and second URL base.

domain base is working fine however URL redirections are giving me issues.

Use “curl” to test your broken url and see what exactly is returned.

Do something like

curl -i http://your-server/aaaa/bbbbbbbb

and you should get a http 301 response, with something in the Location:
header.

Then do “curl -i” against that url, and see if you get the loop.

The rest of the headers may show that PHP was, or was not, involved
in the redirections.

could this be related to wordpress?

It could be.

If the “curl” responses show that PHP is involved, then it probably is.

f

Francis D. [email protected]

Here is our nginx default configuration file.

server {
server_name www.mydomain.com;
return 301 $scheme://mydomain.com$request_uri;
}

server {
server_name mydomain.com;
#listen 80;
root /var/www/html/mydomain/public_html;
index index.php info.php;

access_log /var/log/nginx/mydomain/access.log;
error_log /var/log/nginx/mydomain/error.log;

    location ~ \.php$ {
            include fastcgi_params;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            #fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_pass  127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            }

    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)$
{
add_header Access-Control-Allow-Origin mydomain.com;
}

    location / {
            try_files $uri $uri/ /index.php?q=$request_uri;
             autoindex off;
            rewrite ^/([^_]*)_([^_]*_.*)\.html /$1-$2;
            rewrite ^/([^_]*)_([^_]*)\.html$ /$1-$2.html redirect;
            #if (!-e $request_filename){
            #rewrite ^(.*)$ /index.php redirect;
            #}
            }

if ( $request_filename ~ /action/cycling/cycling-is-best-for-health ) {
rewrite ^ /action/cycling/cycling-is-best-for-health.html? permanent;
}

Server HTTP End
}

Thanks for your troubleshooting tip. the redirection rule is working
great
however but the.html link again redirection to the .html link. i can not
get this thing. where is the second 301 rule once the link is redirected
why again html is redirecting.

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

301 Moved Permanently

301 Moved Permanently


nginx/1.6.2

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

301 Moved Permanently

301 Moved Permanently


nginx/1.6.2

what i found out is that 2nd test on .html is again redirecting to
.html.
now what is causing this second redirection i have no clue.

any advice would be highly appreciated.

Thanks,
Yousuf

On Sat, Apr 16, 2016 at 12:22:46PM +0500, Muhammad Yousuf K. 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.)

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 D. [email protected]

Thanks alot Francis D. :). the try_file option worked for me and
location
tip also worked but try_file seems more better approach.

Btw, can you please explain this paragraph. actually i am really sorry
for
this newbie type question. actually i have been working as ssytem admin
for
last 5 years. now my Firewall concepts of rules are collapsing with
nginx
rules.

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

can you please explain how the second request creates the loop. if i use
break instead of redirect?

On Mon, Apr 18, 2016 at 06:37:59PM +0500, Muhammad Yousuf K. wrote:

Hi there,

Thanks alot Francis D. :). the try_file option worked for me and location
tip also worked but try_file seems more better approach.

I’m glad you got it working for you.

Btw, can you please explain this paragraph. actually i am really sorry for
this newbie type question. actually i have been working as ssytem admin for
last 5 years. now my Firewall concepts of rules are collapsing with nginx
rules.

No worries - nginx config follows its own rules, which are generally
consistent but not necessarily the same as any other program.

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

can you please explain how the second request creates the loop. if i use
break instead of redirect?

I don’t understand the question.

What break, and what loop?

I thought you had said that when you used “break” instead of “redirect”
in the above “location /x”, you got a 404. And that is what I would
expect if the file $document_root/x.html does not exist. 404 is not a
loop.

Can you start with one specific configuration, and use the documentation
(probably at Module ngx_http_rewrite_module, since that seems to be the
troublesome one) to work out what will happen?

Note: when a request arrives, the server-level “rewrite”-module
directives
(basically: if and rewrite) are used; if that does not complete the
request, then the location is chosen, and the “rewrite”-modules
directives
in that location are used.

If a “rewrite” leads to an external redirect, that completes the
request; and the browser may then come back with a whole new request
that is handled afresh.

If the “rewrite” leads to an internal rewrite (to a new url), then the
“subrequest” of the new url is handled according to the docs – possibly
with a whole new selection of the location to use, depending on the
arguments given to the rewrite.

So: show your (simplified, but complete) config; show your http request;
show your http response; and if appropriate, describe the response that
you wanted to get instead.

“break” does exactly what it says in the documentation. If that is
unclear, let’s fix the documentation.

f

Francis D. [email protected]

Thanks Alot Francis D., actually i was trying to understand the
working
of rewrite and location rules how they handle the query. you explain it
very well. Thanks again for sharing such useful and detailed
explanation. i
really appreciate that. :slight_smile: