Opened 3 years ago

Last modified 7 weeks ago

#97 accepted defect

try_files and alias problems

Reported by: Maxim Dounin Owned by: somebody
Priority: minor Milestone:
Component: nginx-core Version:
Keywords: Cc:
Sensitive: no
uname -a: na
nginx -V: na

Description (last modified by Maxim Dounin)

# bug: request to "/test/x" will try "/tmp/x" (good) and
# "/tmp//test/y" (bad?)
location /test/ {
    alias /tmp/;
    try_files $uri /test/y =404;
}
# bug: request to "/test/x" will fallback to "fallback" instead of "/test/fallback"
location /test/ {
    alias /tmp/;
    try_files $uri /test/fallback?$args;
}
# bug: request to "/test/x" will try "/tmp/x/test/x" instead of "/tmp/x"
location ~ /test/(.*) {
    alias /tmp/$1;
    try_files $uri =403;
}

Or document special case for regexp locations with alias? See 3711bb1336c3.

# bug: request "/foo/test.gif" will try "/tmp//foo/test.gif"
location /foo/ {
    alias /tmp/;
    location ~ gif {
        try_files $uri =405;
    }
}

Change History (16)

comment:1 Changed 3 years ago by Maxim Dounin

  • Description modified (diff)
  • Status changed from new to accepted

comment:2 Changed 3 years ago by Maxim Dounin

  • Description modified (diff)

comment:3 Changed 3 years ago by Maxim Dounin

  • Description modified (diff)

Added case from ticket #176.

comment:4 Changed 2 years ago by Maxim Dounin

See also ticket #217.

comment:5 Changed 19 months ago by Maxim Dounin

  • Description modified (diff)
  • Sensitive unset

comment:6 Changed 14 months ago by Tuğrul Topuz

Also not works with rewrite. I tried to make fallback with rewrite.

comment:7 Changed 11 months ago by Bernard Rosset

I still confirm Maxim's reported bug 1st example of bug as of today with 1.6.0.

alias core function is to do precisely that, and its combination with try_files is one of the simplest I can think of.

Could its severity be incremented?

comment:8 Changed 9 months ago by Algirdas Grum

This bug is really annoying, simple task to have few sites in different locations under one vhost becomes problem...

comment:9 Changed 9 months ago by Christopher Monsanto

Could someone please fix this bug? I run into it fairly often. At this point it's one of the very oldest open tickets on this tracker.

comment:10 Changed 8 months ago by Sergey Kandaurov

Could you please try the following patch?

# HG changeset patch
# User Sergey Kandaurov <pluknet@nginx.com>
# Date 1401711096 -14400
#      Mon Jun 02 16:11:36 2014 +0400
# Node ID 5dc95efa0ea15bfeb0caf17a916c40ad8817211c
# Parent  790ba7484bb67d2a1e1a4ce55eeb0fe149ebd176
Changed try_files/alias behavior in prefix location (ticket #97).

When location matches the beginning of the try_files parameter, the matched
part is cut from the path to a file and substituted with alias like it always
worked for try_files with variables (in particular, try_files $uri).  Below,
the request to "/test/x" will try "/tmp/x" and "/tmp/y".

    location /test {
        alias /tmp;
        try_files $uri /test/y =404;
    }

The last try_files parameter now always ignores aliasing irrelevant to the
presence of variables in the directive configuration.  In the example below,
an internal redirect to "/test/fallback" is made.

    location /test/ {
        alias /tmp/;
        try_files $uri /test/fallback?$args;
    }

diff -r 790ba7484bb6 -r 5dc95efa0ea1 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c	Wed May 28 20:18:05 2014 +0400
+++ b/src/http/ngx_http_core_module.c	Mon Jun 02 16:11:36 2014 +0400
@@ -1286,17 +1286,19 @@ ngx_http_core_try_files_phase(ngx_http_r
             path.len = e.pos - path.data;
 
             *e.pos = '\0';
-
+        }
+
+        test_dir = tf->test_dir;
+
+        tf++;
+
+        if (tf->lengths || tf->name.len) {
             if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
                 ngx_memmove(name, name + alias, len - alias);
                 path.len -= alias;
             }
         }
 
-        test_dir = tf->test_dir;
-
-        tf++;
-
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "trying to use %s: \"%s\" \"%s\"",
                        test_dir ? "dir" : "file", name, path.data);

comment:11 Changed 4 months ago by Vladislav Rastrusny

Will it ever be fixed? :)

comment:12 Changed 4 months ago by Sergey Kandaurov

And did you ever try to test the proposed patch?

Due to the questionable nature of the behavior change this patch introduces,
it will not likely be committed without proper feedback and/or testing.

comment:13 Changed 4 months ago by Vladislav Rastrusny

I can test it on my test project. But I don't have test suite large enough to fully test it.

comment:14 Changed 2 months ago by Luke Howell

I have a work around for the issue until the bug is fixed. It is using the 'evil' if statements, but it does handle looking for files and directories before routing to index.

Code highlighting:

location /api { ## URL string to use for api ##
    alias /home/api/site_files/; ## Site root for api code ##

    ## Check for file existing and if there, stop ##
    if (-f $request_filename) {
        break;
    }

    ## Check for file existing and if there, stop ##
    if (-d $request_filename) {
        break;
    }

    ## If we get here then there is no file or directory matching request_filename ##
    rewrite (.*) /api/index.php?$query_string;

    ## Normal php block for processing ##
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}
Last edited 2 months ago by Luke Howell (previous) (diff)

comment:15 follow-up: Changed 7 weeks ago by Andrew Stoltz

I also ran into this bug, but for me it only occurs when $is_args$args is in the try_files. If I leave off $is_args$args, the try_files properly routes where expected.

A workaround is simply to double the path such as:

location /test/ {
    alias /tmp/;
    try_files $uri /test/test/fallback?$args;
}

comment:16 in reply to: ↑ 15 Changed 7 weeks ago by Luke Howell

This still doesn't seem to address directories that are in the alias location. Even if I change your code to try_files $uri $uri/ /test/test/fallback?$args; I don't get directory access when needed. If I have a file rules.txt in /tmp/docs/ I should be able to access that file from http://example.com/test/docs/rules.txt, however an attempt here only brings me back to the fallback.

With my solution above you can access existing files in the root of your alias as well as in subdirectories.

Replying to Andrew Stoltz:

I also ran into this bug, but for me it only occurs when $is_args$args is in the try_files. If I leave off $is_args$args, the try_files properly routes where expected.

A workaround is simply to double the path such as:

location /test/ {
    alias /tmp/;
    try_files $uri /test/test/fallback?$args;
}
Note: See TracTickets for help on using tickets.