Query part included in location match after rewrite (bug or feature?)

Hi,

According to documentation, “location” matches only against URI path,
ignoring query string. However, after “rewrite”, when using variables
containing “?” character (like $request_uri for illustration), query
becomes
part of $uri:

location /src/ {
rewrite ^ /dst$request_uri;
}

location /dst/ {

At this point, $uri contains query part from /src, like

/dst/src/?arg=val
add_header Content-Type text/plain;
return 200 “$request_uri $uri $args”;
}

For request like “/src/?arg=val” the output will be: /src/?arg=val
/dst/src/?arg=val arg=val

Thus, $uri (and matched part) contains query, and $args also contains
query (inherited from original request). All together, this may lead to
quite unexpected results in some configurations.

So, my question is - is this expected behavior (just undocumented) or is
a
bug? To me it looks like a bug - allowing matching anything past “?” in
location and making it part of $uri.

Posted at Nginx Forum:

On Fri, Sep 13, 2013 at 08:48:55AM -0400, aldem wrote:

Hi there,

According to documentation, “location” matches only against URI path,
ignoring query string. However, after “rewrite”, when using variables
containing “?” character (like $request_uri for illustration), query becomes
part of $uri:

My reading of this is that you must give rewrite an explicit ? to mark
the query string, so a ? within a variable is part of $uri if it comes
before a ?. If you want to have your own query string, or to lose the
original query string during the rewrite, you must use an explicit ?.

So, my question is - is this expected behavior (just undocumented) or is a
bug? To me it looks like a bug - allowing matching anything past “?” in
location and making it part of $uri.

? is a valid character in a normalised uri. ? is special in an escaped
uri, since it marks the query string. “rewrite” creates a normalised uri
(at least, when given variables to expand).

I’d say “expected”, unless there’s an example where “rewrite” does not
create a normalised uri.

f

Francis D. [email protected]

Well, this is where I am lost a bit - documentation only says
“replacement
string”, and from my understanding this includes possible expansion of
variables (like everywhere else), and it doesn’t mention (or I couldn’t
find, at least) that rewrite target is normalized URI (or that variables
could be processed differently). Probably, this is the only case where
expansion is processed differently from literal values.

On the other hand, if rewrite target expects a normalized URI, then
mangling
with arguments there should not be possible at all, as there could be
mixture of normalized and escaped values in single string.

Posted at Nginx Forum:

On Fri, Sep 13, 2013 at 09:48:05AM -0400, aldem wrote:

Hi there,

reading through ngx_http_rewrite_module.c and thinking about it some
more,
I believe I was wrong in my previous mail.

I tried to simplify too much.

Well, this is where I am lost a bit - documentation only says “replacement
string”, and from my understanding this includes possible expansion of
variables (like everywhere else), and it doesn’t mention (or I couldn’t
find, at least) that rewrite target is normalized URI (or that variables
could be processed differently). Probably, this is the only case where
expansion is processed differently from literal values.

The only true documentation for what the current version does is in the
directory called “src”. Anything else is someone’s interpretation. (In
many cases, the interpretation is correct; but there are often reasons
why some edge cases are not documented outside of the source.)

My understanding is that rewrite will populate $uri with its
“replacement”
argument up to the first ?, and will populate $args after that if
appropriate. While populating, it expands $variables.

For internal-to-nginx use, $uri and $args now have their values.

For external-to-nginx use, $uri and $args are concatenated with a
separating ? if appropriate, and it is up to whatever reads the complete
string to decide what to do with it.

On the other hand, if rewrite target expects a normalized URI, then mangling
with arguments there should not be possible at all, as there could be
mixture of normalized and escaped values in single string.

The general philosophy of the nginx configuration seems to be that
common
things are straightforward, and uncommon things are no more than a
module
or a local patch away.

And also, the administrator is trusted to know what they are doing,
so it is their responsibility to properly handle unescaped and escaped
values. In the specific case of escaping, nginx in general can’t guess
what the user wants.

It still looks like NOTABUG to me; but I’m not the one who wrote it.

f

Francis D. [email protected]

Francis, thank you for your time and looking through the source :slight_smile:

Though I still consider this issue as a “bug” (either in documentation
or in
consistence), what really matters is that understanding how it works is
very
helpful, and you did the perfect job explaining this.

Hopefully, someone, someday will describe this behavior in the
documentation

  • some things in nginx are not exactly intuitive…

Posted at Nginx Forum: