Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am using nginx as reverse proxy and I have 2 rules like:

location ~ ^/indirect {
  rewrite ^/indirect(.*) /foobar$1;

location ~ ^/foobar {
  set $url$scheme://$host$uri;
  proxy_pass $url;

So, as you can see I'm passing the $uri variable as a parameter to the proxied page (the $uri variable is an nginx one, see the http core module documentation).

Problem is, if I visit, the $uri variable contains /foobar/hello world (as you see, the %20 has been substituted with its url-decoded value, a space). And then, nginx returns http status code 400 (bad request) before executing the proxy_pass line (the backend there is not contacted).

There is also available the variable $request_uri, which holds the original request URI as issued by the client, so in this case it would hold the correct value, with the %20 sequence. But I cannot use this because if a client goes through the /indirect path, $request_uri would contain /indirect/... while I want that the access param passed to the backend be always /foobar/....

There are multiple indirect-like rules (this is for a DAV/calDAV/cardDAV server, and there are multiple clients out there that connect to multiple paths, so I need these indirect-like rules), so it is not feasible to do the proxy_pass there, and there are clients that go directly to the /foobar path.

So is there any way to get $uri without url-decoding it?

possible things that aren't acceptable:

  • sending the request double-encoded, as the request may come from a client I have no control of
  • specifying the final url multiple times in eacy indirect rule and also in the "direct" one, as it causes maintenance problems.
share|improve this question
This whole setup is its own maintenance problem. So I'm not sure why you would reject a solution because it might be a "maintenance problem". – Michael Hampton Nov 5 '12 at 16:52
@MichaelHampton yes, you are right, but if it's possible I don't want to make it even less maintainable – Carlos Campderrós Nov 6 '12 at 8:15
Finally I ended doing external 301 redirects from all the indirect uri's to the direct one, and only having the proxy_pass there. Should I answer my own question with this workaround? – Carlos Campderrós Nov 12 '12 at 9:39

The only way I found is to use the HttpSetMiscModule like so:

location ~
 ^/indirect {
  set_escape_uri $key $1;
  rewrite ^/indirect(.*) /foobar$key;

location ~ ^/foobar {
  set_escape_uri $key $uri;
  set $url$scheme://$host$key;
  proxy_pass $url;

If anyone knows of a better way (without having to compile nginx with external modules, because I don't have root access) please let me know!

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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