# Rewrite last using variable

**URL:** <https://www.ruby-forum.com/t/rewrite-last-using-variable/237165>\
**Category:** NGINX\
**Created:** [October 28, 2013, 1:56am UTC](https://www.ruby-forum.com/t/rewrite-last-using-variable/237165 "2013-10-28T01:56:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Detlef\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/58f4c7/32.png) [@Detlef\_R](https://www.ruby-forum.com/u/Detlef_R)\
**Post date:** [October 28, 2013, 1:56am UTC](https://www.ruby-forum.com/t/rewrite-last-using-variable/237165/1 "2013-10-28T01:56:47Z")

</div>

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 =;-\>

---

<div class="post-metadata">

**Author:** ![Ingo\_Schmidt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/a88e57/32.png) [@Ingo\_Schmidt](https://www.ruby-forum.com/u/Ingo_Schmidt)\
**Post date:** [October 28, 2013, 9:10am UTC](https://www.ruby-forum.com/t/rewrite-last-using-variable/237165/2 "2013-10-28T09:10:15Z")

</div>

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. removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Ingo\_Schmidt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/a88e57/32.png) [@Ingo\_Schmidt](https://www.ruby-forum.com/u/Ingo_Schmidt)\
**Post date:** [October 28, 2013, 9:37am UTC](https://www.ruby-forum.com/t/rewrite-last-using-variable/237165/3 "2013-10-28T09:37:07Z")

</div>

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 =;-\>

---

<div class="post-metadata">

**Author:** ![Ingo\_Schmidt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/a88e57/32.png) [@Ingo\_Schmidt](https://www.ruby-forum.com/u/Ingo_Schmidt)\
**Post date:** [October 28, 2013, 10:57am UTC](https://www.ruby-forum.com/t/rewrite-last-using-variable/237165/4 "2013-10-28T10:57:44Z")

</div>

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 😉 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. removed\_email\_address@domain.invalid
