Rewrite causing $ to be escaped

Hi,

We’re running Jenkins behind an Nginx reverse proxy and see issues where
Jenkins running in Tomcat returns 404 because it receives URLs that have
$
encoded as %24. From the Tomcat logs:
10.0.7.212 - - [15/Dec/2015:00:15:22 +0000] “POST
/%24stapler/bound/c43ae9fc-dcca-4fbe-b247-82279fa65d55/render HTTP/1.0”
404
992

If we access Tomcat directly, it does not return a 404 and $ is not
encoded:
10.0.7.212 - - [15/Dec/2015:00:16:54 +0000] “POST
/$stapler/bound/95ed7e0f-f703-458a-a456-8bf729670a4a/render HTTP/1.1”
200
437

When I log the $request_uri and $uri variables, it doesn’t look like the
$
is being encoded:
Dec 15 00:15:22 ip-10-0-7-212.us-west-2.compute.internal nginx[2732]:
ip-10-0-7-212.us-west-2.compute.internal nginx: [15/Dec/2015:00:15:22
+0000] Hi Sunil! Request URI:
/service/jenkins/$stapler/bound/c43ae9fc-dcca-4fbe-b247-82279fa65d55/render
is now URI: /$stapler/bound/c43ae9fc-dcca-4fbe-b247-82279fa65d55/render

However, it looks like the rewrite rule in our location block is causing
the $ to be encoded. If I comment out this block or change the regex so
it
doesn’t match, this works.

Here’s the relevant configuration block:
location ~ ^/service/jenkins/(?.) {
rewrite ^/service/jenkins/?.
$ /$path break;

        proxy_set_header        Host $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For

$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://10.0.0.63:10115;
        proxy_redirect http://$host/service/jenkins/ 

/service/jenkins/;
proxy_redirect http://$host/ /service/jenkins/;
}

Is there a way to bypass this encoding (an equivalent to Apache’s
noescape
https://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_ne flag?)?

Thanks in advance,

Sunil

Hello!

On Mon, Dec 14, 2015 at 04:26:33PM -0800, Sunil Shah wrote:

437
the $ to be encoded. If I comment out this block or change the regex so it
doesn’t match, this works.

Here’s the relevant configuration block:
location ~ ^/service/jenkins/(?.) {
rewrite ^/service/jenkins/?.
$ /$path break;

The ‘$’ character isn’t encoded by nginx on rewrites. If you see
it encoded - probably something else did it. Just tested it here,
and such a configuration sends the following request line to
upstream server:

GET /$stapler/bound/c43ae9fc-dcca-4fbe-b247-82279fa65d55/render HTTP/1.0

That is, ‘$’ is not escaped.

If in doubt, try looking into debug logs to see what nginx
actually sent to upstream server, see
A debugging log for details.

Note well that better solution for such URI change would be to use
static location and proxy_pass with URI component, like this:

location /service/jenkins/ {
    proxy_pass http://10.0.0.63:10115/;
    ...
}

(Note tralinig “/” in proxy_pass.)

No rewrites, no regular expressions, the same result. May need
adjustments if you use other conflicting regular expressions in
your config. See Module ngx_http_core_module for details on
location matching, and Module ngx_http_proxy_module for details
on proxy_pass.

[…]


Maxim D.
http://nginx.org/

Thanks Maxim! You’re right - we were looking in the wrong place - the
rewrite rule was just a red herring.