Stop automatic trailing slash addition

I was wondering if it’s possible to have separate namespaces for ‘/test’
and /test/’. For example:

  location /test {
      root         /usr/share/nginx/test;
    }

     location /test/ {
       root         /usr/share/nginx/test-slash;
       try_files $uri default.txt;
    }

I tried above configuration, but nginx adds trailing slash to all
‘/test’
requests before they get processed by location directives. So all
requests
are going to ‘/test/’ location.

Is there any way to get separate namespace for /test and /test/ ? This
not
for real world website. I am trying to learn more about location
directive.

  • N

On Sat, Dec 13, 2014 at 9:00 AM, neubyr [email protected] wrote:

       root         /usr/share/nginx/test-slash;
       try_files $uri default.txt;
    }

I tried above configuration, but nginx adds trailing slash to all ‘/test’
requests before they get processed by location directives. So all requests
are going to ‘/test/’ location.

Is there any way to get separate namespace for /test and /test/ ? This not
for real world website. I am trying to learn more about location directive.

try reloading your nginx server.

Either that or you have directory /usr/share/nginx/test/test.

(or browser’s cache)

On Fri, Dec 12, 2014 at 04:00:29PM -0800, neubyr wrote:

Hi there,

I was wondering if it’s possible to have separate namespaces for ‘/test’
and /test/'.

They are different requests, and different request prefixes, so yes,
they can be handled in different location{}s.

requests before they get processed by location directives. So all requests
are going to ‘/test/’ location.

Have you evidence of this unexpected behaviour?

A trailing slash should not be added by nginx before
location{}-matching.

Is there any way to get separate namespace for /test and /test/ ? This not
for real world website. I am trying to learn more about location directive.

What you have should do it. But I am not clear on what precisely you
wish to happen.

What request do you make? (Presumably something like “curl -i
http://localhost/test” or “curl -i http://localhost/testA”)

What response do you get? (A http redirect? Or perhaps the content of
a particular file on your filesystem?)

What response do you want? (The content of a different file on your
filesystem? Name the files, so it is clear where the expectation and
the result are different)

For what it’s worth, enabling the debug log can show lots about what
the location-matching engine is actually doing during a request.

f

Francis D. [email protected]

On Saturday 13 December 2014 15:53:32 neubyr wrote:
[…]

Hope my understanding of debugging log is correct. Let me know if I am
missing anything.
[…]

From the debug log it looks like that you have the try_files directive
in your “/test” location block. And the config you have mentioned
before
isn’t the one you are actually using.

wbr, Valentin V. Bartenev

On Sat, Dec 13, 2014 at 12:00 AM, Francis D. [email protected]
wrote:

requests before they get processed by location directives. So all
directive.
What response do you want? (The content of a different file on your
filesystem? Name the files, so it is clear where the expectation and
the result are different)

For what it’s worth, enabling the debug log can show lots about what
the location-matching engine is actually doing during a request.

Thank you for pointing out debugging log. I think that helped in
explaining
this behavior.

It seems like nginx is adding slash as uri name matches with
corresponding
directory and not file name. I thought nginx will return 404 in this
case,
but it adds trailing slash when matching directory is found.

After adding trailing slash uri becomes /test/ and hence it matches next
location block.

Hope my understanding of debugging log is correct. Let me know if I am
missing anything.

Below is a snippet from debug log.

2014/12/13 23:20:00 [debug] 15839#0: epoll: fd:6 ev:0001
d:00007F0AB9F9E010
2014/12/13 23:20:00 [debug] 15839#0: accept on 0.0.0.0:80, ready: 0
2014/12/13 23:20:00 [debug] 15839#0: posix_memalign:
00007F0ABBA0C440:256
@16
2014/12/13 23:20:00 [debug] 15839#0: *6 accept: 50.136.134.241 fd:3
2014/12/13 23:20:00 [debug] 15839#0: posix_memalign:
00007F0ABBA27070:256
@16
2014/12/13 23:20:00 [debug] 15839#0: *6 event timer add: 3:
60000:1418512860643
2014/12/13 23:20:00 [debug] 15839#0: *6 reusable connection: 1
2014/12/13 23:20:00 [debug] 15839#0: *6 epoll add event: fd:3 op:1
ev:80002001
2014/12/13 23:20:00 [debug] 15839#0: timer delta: 129801
2014/12/13 23:20:00 [debug] 15839#0: posted events 0000000000000000
2014/12/13 23:20:00 [debug] 15839#0: worker cycle
2014/12/13 23:20:00 [debug] 15839#0: epoll timer: 60000
2014/12/13 23:20:00 [debug] 15839#0: epoll: fd:3 ev:0001
d:00007F0AB9F9E1C1
2014/12/13 23:20:00 [debug] 15839#0: *6 http wait request handler
2014/12/13 23:20:00 [debug] 15839#0: *6 malloc: 00007F0ABB99BC90:1024
2014/12/13 23:20:00 [debug] 15839#0: *6 recv: fd:3 77 of 1024
2014/12/13 23:20:00 [debug] 15839#0: *6 reusable connection: 0
2014/12/13 23:20:00 [debug] 15839#0: *6 posix_memalign:
00007F0ABB9E6EE0:4096 @16
2014/12/13 23:20:00 [debug] 15839#0: *6 http process request line
2014/12/13 23:20:00 [debug] 15839#0: *6 http request line: “GET /test
HTTP/1.1”
2014/12/13 23:20:00 [debug] 15839#0: *6 http uri: “/test”
2014/12/13 23:20:00 [debug] 15839#0: *6 http args: “”
2014/12/13 23:20:00 [debug] 15839#0: *6 http exten: “”
2014/12/13 23:20:00 [debug] 15839#0: *6 http process request header line
2014/12/13 23:20:00 [debug] 15839#0: *6 http header: “User-Agent:
curl/7.30.0”
2014/12/13 23:20:00 [debug] 15839#0: *6 http header: “Host: example.org
2014/12/13 23:20:00 [debug] 15839#0: *6 http header: “Accept: /
2014/12/13 23:20:00 [debug] 15839#0: *6 http header done
2014/12/13 23:20:00 [debug] 15839#0: *6 event timer del: 3:
1418512860643
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 0
2014/12/13 23:20:00 [debug] 15839#0: *6 rewrite phase: 1
2014/12/13 23:20:00 [debug] 15839#0: *6 test location: “/50x.html”
2014/12/13 23:20:00 [debug] 15839#0: *6 test location: “/test”
2014/12/13 23:20:00 [debug] 15839#0: *6 using configuration “/test”
2014/12/13 23:20:00 [debug] 15839#0: *6 http cl:-1 max:1048576
2014/12/13 23:20:00 [debug] 15839#0: *6 rewrite phase: 3
2014/12/13 23:20:00 [debug] 15839#0: *6 post rewrite phase: 4
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 5
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 6
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 7
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 8
2014/12/13 23:20:00 [debug] 15839#0: *6 access phase: 9
2014/12/13 23:20:00 [debug] 15839#0: *6 access phase: 10
2014/12/13 23:20:00 [debug] 15839#0: *6 post access phase: 11
2014/12/13 23:20:00 [debug] 15839#0: *6 try files phase: 12
2014/12/13 23:20:00 [debug] 15839#0: *6 http script var: “/test”
2014/12/13 23:20:00 [debug] 15839#0: *6 trying to use file: “/test”
“/usr/share/nginx/test/test”
2014/12/13 23:20:00 [debug] 15839#0: *6 trying to use file:
“/test/default.txt” “/usr/share/nginx/test/test/default.txt”
2014/12/13 23:20:00 [debug] 15839#0: *6 internal redirect:
“/test/default.txt?”
2014/12/13 23:20:00 [debug] 15839#0: *6 rewrite phase: 1
2014/12/13 23:20:00 [debug] 15839#0: *6 test location: “/50x.html”
2014/12/13 23:20:00 [debug] 15839#0: *6 test location: “/test”
2014/12/13 23:20:00 [debug] 15839#0: *6 test location: “/”
2014/12/13 23:20:00 [debug] 15839#0: *6 using configuration “/test/”
2014/12/13 23:20:00 [debug] 15839#0: *6 http cl:-1 max:1048576
2014/12/13 23:20:00 [debug] 15839#0: *6 rewrite phase: 3
2014/12/13 23:20:00 [debug] 15839#0: *6 post rewrite phase: 4
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 5
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 6
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 7
2014/12/13 23:20:00 [debug] 15839#0: *6 generic phase: 8
2014/12/13 23:20:00 [debug] 15839#0: *6 access phase: 9
2014/12/13 23:20:00 [debug] 15839#0: *6 access phase: 10
2014/12/13 23:20:00 [debug] 15839#0: *6 post access phase: 11
2014/12/13 23:20:00 [debug] 15839#0: *6 try files phase: 12
2014/12/13 23:20:00 [debug] 15839#0: *6 posix_memalign:
00007F0ABB9A8200:4096 @16
2014/12/13 23:20:00 [debug] 15839#0: *6 http script var:
“/test/default.txt”
2014/12/13 23:20:00 [debug] 15839#0: *6 trying to use file:
“/test/default.txt” “/usr/share/nginx/test-slash/test/default.txt”
2014/12/13 23:20:00 [debug] 15839#0: *6 try file uri:
“/test/default.txt”
2014/12/13 23:20:00 [debug] 15839#0: *6 content phase: 13
2014/12/13 23:20:00 [debug] 15839#0: *6 content phase: 14
2014/12/13 23:20:00 [debug] 15839#0: *6 content phase: 15
2014/12/13 23:20:00 [debug] 15839#0: *6 content phase: 16
2014/12/13 23:20:00 [debug] 15839#0: *6 content phase: 17
2014/12/13 23:20:00 [debug] 15839#0: *6 content phase: 18
2014/12/13 23:20:00 [debug] 15839#0: *6 http filename:
“/usr/share/nginx/test-slash/test/default.txt”
2014/12/13 23:20:00 [debug] 15839#0: *6 add cleanup: 00007F0ABB9A8260
2014/12/13 23:20:00 [debug] 15839#0: *6 http static fd: 10
2014/12/13 23:20:00 [debug] 15839#0: *6 http set discard body
2014/12/13 23:20:00 [debug] 15839#0: *6 xslt filter header
2014/12/13 23:20:00 [debug] 15839#0: *6 HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Sat, 13 Dec 2014 23:20:00 GMT
Content-Type: text/plain
Content-Length: 19
Last-Modified: Sat, 13 Dec 2014 23:17:22 GMT
Connection: keep-alive
ETag: “548cc902-13”
Accept-Ranges: bytes

2014/12/13 23:20:00 [debug] 15839#0: *6 write new buf t:1 f:0
00007F0ABB9A8430, pos 00007F0ABB9A8430, size: 236 file: 0, size: 0
2014/12/13 23:20:00 [debug] 15839#0: *6 http write filter: l:0 f:0 s:236
2014/12/13 23:20:00 [debug] 15839#0: *6 http output filter
“/test/default.txt?”
2014/12/13 23:20:00 [debug] 15839#0: *6 http copy filter:
“/test/default.txt?”
2014/12/13 23:20:00 [debug] 15839#0: *6 image filter
2014/12/13 23:20:00 [debug] 15839#0: *6 xslt filter body


Thanks,

  • N

On Sat, Dec 13, 2014 at 4:25 PM, Valentin V. Bartenev [email protected]
wrote:

case,
in your “/test” location block. And the config you have mentioned before
isn’t the one you are actually using.

wbr, Valentin V. Bartenev

Thanks for pointing it out. It’s giving same result even without
try_files
directive in ‘/test’ location block.

2014/12/14 07:33:09 [debug] 16414#0: epoll: fd:6 ev:0001
d:00007F1B949F4010
2014/12/14 07:33:09 [debug] 16414#0: accept on 0.0.0.0:80, ready: 0
2014/12/14 07:33:09 [debug] 16414#0: posix_memalign:
00007F1B965F9440:256
@16
2014/12/14 07:33:09 [debug] 16414#0: *2 accept: 50.136.134.241 fd:3
2014/12/14 07:33:09 [debug] 16414#0: posix_memalign:
00007F1B96614070:256
@16
2014/12/14 07:33:09 [debug] 16414#0: *2 event timer add: 3:
60000:1418542449679
2014/12/14 07:33:09 [debug] 16414#0: *2 reusable connection: 1
2014/12/14 07:33:09 [debug] 16414#0: *2 epoll add event: fd:3 op:1
ev:80002001
2014/12/14 07:33:09 [debug] 16414#0: timer delta: 112608
2014/12/14 07:33:09 [debug] 16414#0: posted events 0000000000000000
2014/12/14 07:33:09 [debug] 16414#0: worker cycle
2014/12/14 07:33:09 [debug] 16414#0: epoll timer: 60000
2014/12/14 07:33:09 [debug] 16414#0: epoll: fd:3 ev:0001
d:00007F1B949F41C1
2014/12/14 07:33:09 [debug] 16414#0: *2 http wait request handler
2014/12/14 07:33:09 [debug] 16414#0: *2 malloc: 00007F1B96588C90:1024
2014/12/14 07:33:09 [debug] 16414#0: *2 recv: fd:3 77 of 1024
2014/12/14 07:33:09 [debug] 16414#0: *2 reusable connection: 0
2014/12/14 07:33:09 [debug] 16414#0: *2 posix_memalign:
00007F1B965D3EE0:4096 @16
2014/12/14 07:33:09 [debug] 16414#0: *2 http process request line
2014/12/14 07:33:09 [debug] 16414#0: *2 http request line: “GET /test
HTTP/1.1”
2014/12/14 07:33:09 [debug] 16414#0: *2 http uri: “/test”
2014/12/14 07:33:09 [debug] 16414#0: *2 http args: “”
2014/12/14 07:33:09 [debug] 16414#0: *2 http exten: “”
2014/12/14 07:33:09 [debug] 16414#0: *2 http process request header line
2014/12/14 07:33:09 [debug] 16414#0: *2 http header: “User-Agent:
curl/7.30.0”
2014/12/14 07:33:09 [debug] 16414#0: *2 http header: “Host: example.org
2014/12/14 07:33:09 [debug] 16414#0: *2 http header: “Accept: /
2014/12/14 07:33:09 [debug] 16414#0: *2 http header done
2014/12/14 07:33:09 [debug] 16414#0: *2 event timer del: 3:
1418542449679
2014/12/14 07:33:09 [debug] 16414#0: *2 generic phase: 0
2014/12/14 07:33:09 [debug] 16414#0: *2 rewrite phase: 1
2014/12/14 07:33:09 [debug] 16414#0: *2 test location: “/50x.html”
2014/12/14 07:33:09 [debug] 16414#0: *2 test location: “/test”
2014/12/14 07:33:09 [debug] 16414#0: *2 using configuration “/test”
2014/12/14 07:33:09 [debug] 16414#0: *2 http cl:-1 max:1048576
2014/12/14 07:33:09 [debug] 16414#0: *2 rewrite phase: 3
2014/12/14 07:33:09 [debug] 16414#0: *2 post rewrite phase: 4
2014/12/14 07:33:09 [debug] 16414#0: *2 generic phase: 5
2014/12/14 07:33:09 [debug] 16414#0: *2 generic phase: 6
2014/12/14 07:33:09 [debug] 16414#0: *2 generic phase: 7
2014/12/14 07:33:09 [debug] 16414#0: *2 generic phase: 8
2014/12/14 07:33:09 [debug] 16414#0: *2 access phase: 9
2014/12/14 07:33:09 [debug] 16414#0: *2 access phase: 10
2014/12/14 07:33:09 [debug] 16414#0: *2 post access phase: 11
2014/12/14 07:33:09 [debug] 16414#0: *2 try files phase: 12
2014/12/14 07:33:09 [debug] 16414#0: *2 content phase: 13
2014/12/14 07:33:09 [debug] 16414#0: *2 content phase: 14
2014/12/14 07:33:09 [debug] 16414#0: *2 content phase: 15
2014/12/14 07:33:09 [debug] 16414#0: *2 content phase: 16
2014/12/14 07:33:09 [debug] 16414#0: *2 content phase: 17
2014/12/14 07:33:09 [debug] 16414#0: *2 content phase: 18
2014/12/14 07:33:09 [debug] 16414#0: *2 http filename:
“/usr/share/nginx/test/test”
2014/12/14 07:33:09 [debug] 16414#0: *2 add cleanup: 00007F1B965D4E98
2014/12/14 07:33:09 [debug] 16414#0: *2 http static fd: -1
2014/12/14 07:33:09 [debug] 16414#0: *2 http dir
2014/12/14 07:33:09 [debug] 16414#0: *2 posix_memalign:
00007F1B96595200:4096 @16
2014/12/14 07:33:09 [debug] 16414#0: *2 http finalize request: 301,
“/test?” a:1, c:1
2014/12/14 07:33:09 [debug] 16414#0: *2 http special response: 301,
“/test?”
2014/12/14 07:33:09 [debug] 16414#0: *2 http set discard body
2014/12/14 07:33:09 [debug] 16414#0: *2 xslt filter header
2014/12/14 07:33:09 [debug] 16414#0: *2 HTTP/1.1 301 Moved Permanently
Server: nginx/1.6.2
Date: Sun, 14 Dec 2014 07:33:09 GMT
Content-Type: text/html
Content-Length: 184
Location: http://example.org/test/
Connection: keep-alive

2014/12/14 07:33:09 [debug] 16414#0: *2 write new buf t:1 f:0
00007F1B965952A0, pos 00007F1B965952A0, size: 196 file: 0, size: 0
2014/12/14 07:33:09 [debug] 16414#0: *2 http write filter: l:0 f:0 s:196
2014/12/14 07:33:09 [debug] 16414#0: *2 http output filter “/test?”
2014/12/14 07:33:09 [debug] 16414#0: *2 http copy filter: “/test?”
2014/12/14 07:33:09 [debug] 16414#0: *2 image filter
2014/12/14 07:33:09 [debug] 16414#0: *2 xslt filter body

  • N

On Sat, Dec 13, 2014 at 03:53:32PM -0800, neubyr wrote:

On Sat, Dec 13, 2014 at 12:00 AM, Francis D. [email protected] wrote:

On Fri, Dec 12, 2014 at 04:00:29PM -0800, neubyr wrote:

Hi there,

  location /test {
      root         /usr/share/nginx/test;
    }

     location /test/ {
       root         /usr/share/nginx/test-slash;
       try_files $uri default.txt;
    }

What request do you make? (Presumably something like “curl -i
http://localhost/test” or “curl -i http://localhost/testA”)

What response do you get? (A http redirect? Or perhaps the content of
a particular file on your filesystem?)

What response do you want? (The content of a different file on your
filesystem? Name the files, so it is clear where the expectation and
the result are different)

Those questions still need answers, if you want someone else to be able
to tell you how to configure nginx to do your non-standard thing. (If
such a thing is even possible without extra coding.)

The “standard” thing is: requests that map directly to the filesystem
that match a directory that omit a trailing slash get a http 301
response
to include the trailing slash. That is usually what is wanted.

If you want something else, you’ll have to be very clear about what it
is that you want.

The machine will do exactly what you configure it to do, not what you
hope it will do.

It seems like nginx is adding slash as uri name matches with corresponding
directory and not file name. I thought nginx will return 404 in this case,
but it adds trailing slash when matching directory is found.

I’m not sure why you expected a 404 if a non-slash request names an
existing directory by default. That’s not the common thing to want.

You can get that by using (for example)

try_files $uri =404;

but that probably will not do what you want if the request does end
in a slash.

After adding trailing slash uri becomes /test/ and hence it matches next
location block.

One request is handled in one location.

Depending on what actual configuration you used, the “/test/” url might
count as a new subrequest and start a new location search, or it
might not. See the documentation for whatever directive you are using
(explicitly or implicitly.)

For example using,

try_files $uri $uri/index.html =404;

in both /test and /test/ locations, a request for /test would send you
the contents of the file

/usr/share/nginx/test/test/index.html

if it exists (unless other configuration says not to), while a request
for /test/ would send you the contents of the file

/usr/share/nginx/test-slash/test/index.html

if it exists.

(Your “try_files $uri default.txt;” is unlikely to give you a useful
result.)

Good luck with it,

f

Francis D. [email protected]