Rewrite last using variable

Hi,

consider the following simplified nginx config snippet:

set $var “/url?par=val”;
location = /a {
rewrite ^ $var redirect;
}
location = /b {
rewrite ^ $var last;
}
location = /url {
proxy_pass http://some_backend;
}

For location a the redirect goes via the client and everything works
just fine.
For location b the redirect is internal and now the backend cannot
process the request anymore.

I found out that it in the 2nd case the backend sees a URL encoded form
of the contents of $var. So the question mark has become %3F and
naturally the backend can’t find the request parameters.
I guess that the URL encoding also takes place in the first case, but
here the client decodes the URL and thus everything is ok again.

So here is my question:
Is it possible in nginx to make rewrites with variables where the
variable contains a URL with parameters like in the example? If yes,
what do I need to change? If no, what other options do I have?

Cheers, Ingo =;->

On Mon, Oct 28, 2013 at 01:56:16AM +0100, Ingo Schmidt wrote:

Hi there,

set $var “/url?par=val”;
location = /b {
rewrite ^ $var last;
}

For location b the redirect is internal and now the backend cannot
process the request anymore.

I guess that the URL encoding also takes place in the first case, but
here the client decodes the URL and thus everything is ok again.

No; here what is sent to the client includes the bare ?.

Is it possible in nginx to make rewrites with variables where the
variable contains a URL with parameters like in the example? If yes,
what do I need to change? If no, what other options do I have?

I believe it is intended to be “no”, for internal rewrites at least.

You can do something like

set $var "/url";
set $vararg "par=val";
rewrite ^ $var?$vararg last;

Although you may need to be more subtle if you know that your backend
handles “/url” and “/url?” differently, in case $vararg is empty.

f

Francis D. [email protected]

Hi!

I believe it is intended to be “no”, for internal rewrites at least.
Hmm, any reason why it might be intended?
Also, it would be nice if the docs could mention this, because I find it
unintuitive, if rewrite behaves differently depending on the rewrite
type.

You can do something like set $var “/url”; set $vararg “par=val”;
rewrite ^ $var?$vararg last;
Well, in my case that is exactly what I am trying to avoid, because my
variable is set in a map and I would have to create two maps then, one
with the URLs, the other with arguments.
And, as you already pointed out, sometimes the argument is optional.

Hmm, but it looks like this is my only option right now.
Anyway, thanks for your answer!

Cheers, Ingo =;->

On Mon, Oct 28, 2013 at 09:36:20AM +0100, Ingo Schmidt wrote:

Hi there,

I was (partly) wrong when I said

“”"

I guess that the URL encoding also takes place in the first case, but
here the client decodes the URL and thus everything is ok again.

No; here what is sent to the client includes the bare ?.
“”"

Reading the code, the string does go through some uri-escaping and some
uri-unescaping within nginx, and the end result is that a ? in $var
remains a ? in what is written to the client. But it’s not a straight
copy of the string.

I believe it is intended to be “no”, for internal rewrites at least.
Hmm, any reason why it might be intended?

My guess? The value given must either be already uri-escaped, or not.
And
nginx chooses “not”.

Also, it would be nice if the docs could mention this, because I find it
unintuitive, if rewrite behaves differently depending on the rewrite type.

If you presume that the docs are in the directory called “src”, then
it’s mentioned there :wink: Anything "redirect"ed goes through an unescape.

I expect that a correct clarifying patch to the docs will be welcomed,
if you fancy writing one.

You can do something like set $var “/url”; set $vararg “par=val”;
rewrite ^ $var?$vararg last;
Well, in my case that is exactly what I am trying to avoid, because my
variable is set in a map and I would have to create two maps then, one
with the URLs, the other with arguments.

Generally in nginx, if there’s something that you can’t do in config,
you can do it in a module you write. Possibly you can do it in config
using one of the scripting language modules.

(Usually, config is simpler in the short term.)

Good luck with it,

f

Francis D. [email protected]