25

How do I get the value of request_uri without the args appended on the end. I know there is a uri variable but I need the original value as the Nginx documentation states:

request_uri

This variable is equal to the original request URI as received from the client including the args. It cannot be modified. Look at $uri for the post-rewrite/altered URI. Does not include host name. Example: "/foo/bar.php?arg=baz"

4 Answers 4

34

I use this map, which works without lua:

map $request_uri $request_uri_path {
  "~^(?P<path>[^?]*)(\?.*)?$"  $path;
}
4
  • can you explain what is happening here. first time I'm seeing regex like this.
    – user3905644
    Jan 16, 2018 at 6:36
  • 2
    ~ (denotes this is a regex) ^ (anchors to beginning of url) ( (group/capture) ?P<path> (capture this group into the variable $path) [^?]* (0 or more characters that are not '?') ) (end group) (\?.*)? (Maybe a querystring, starting with '?' and possible more characters after that) $ (anchor end of url)
    – Ryan Olson
    Jan 16, 2018 at 17:20
  • This is quite interesting, didn’t know nginx had named regex capture groups, unlike using $1
    – user3905644
    Jan 17, 2018 at 1:10
  • IMO this is a better answer because it works out-of-the-box without lua scripting, and for the same reason, I suspect it is faster - EDIT: just realised you already made that point, but I figure it's important enough to let the reinforcement stand
    – randomsock
    May 12, 2021 at 20:51
23

You're looking for $uri. It does not have $args. In fact, $request_uri is almost equivalent to $uri$args.

If you really want exactly $request_uri with the args stripped, you can do this.

local uri = string.gsub(ngx.var.request_uri, "?.*", "")

You will need to have lua available but that will do exactly what you're asking.

3
  • 6
    But as the question says, $uri may be modified by nginx (like when an error redirect occurs). So how to get the original request (such as in $request) but without args? Nov 30, 2015 at 19:28
  • 2
    This answer is incorrect, though the lua fragment is correct. In the event of rewrites or try_files, etc. $uri will be changed to the path that nginx is currently testing/evaluating. Feb 3, 2016 at 0:00
  • I was building my custom proxy cache key, this was useful.
    – user3905644
    Jan 16, 2018 at 6:35
3

The accepted answer pointed me in the right direction, but I had to figure out where to add that directive, After some time investigating I found set_by_lua_block

set_by_lua_block $request_uri_path {
    return string.gsub(ngx.var.request_uri, "?.*", "")
}

I hope it saves some time to those who comes here.

2

Ryan Olson's answer is really good but map cannot be used everywhere. It must be used in the http context.

If you need to get that information at a block level that does not accept the use of map, it can be done in a if statement. But remember that if is evil.

set $new_uri "";
if ($request_uri ~ "^([^?]*)(\?.*)?$") {
    set $new_uri $1;
}

This code works out of the box (it does not use Lua or anything else).

3
  • I don't understand the observation on map. Map is defined once in the http block, then one simply uses the output of the map, as map are evaluated only on call. Thus there is no need of any if or additional constructs. If you have map $request_uri $new_var then simply use $new_var where needed.
    – Pier A
    Sep 27, 2023 at 11:06
  • @PierA I added some context as to where the map instruction can be used. Depending on what you are doing, you might not have access to the http context, for instance. By the way, it is not "additional constructs", it is an alternative way to map if your context does not allow it.
    – Maxime
    Sep 28, 2023 at 17:50
  • 1
    I see, if one is not allowed to change the http block, then yes. Thank you for the clarification.
    – Pier A
    Sep 29, 2023 at 13:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.