Unable to use a GET url-param

Francis Daly francis at daoine.org
Mon Apr 17 08:02:01 UTC 2017

On Sun, Apr 16, 2017 at 09:49:09AM +0530, Ajay Garg wrote:
> On Sat, Apr 15, 2017 at 8:50 PM, Francis Daly <francis at daoine.org> wrote:
> > On Sat, Apr 15, 2017 at 02:47:26PM +0530, Ajay Garg wrote:

Hi there,

> Proxy-Server and Gateway are connected via a ssh-reverse-tunnel.
> The port over which they are connected remains the same, as long as the
> Gateway is same.
> So, $forwarded_port can be safely set in the map.


> Gateway and End-Server communicate via the "other end" of the
> ssh-reverse-tunnel.
> The End-Server here might change, and so the communication can either be
> over http or https.

I suspect that that is the piece that is breaking you now.

I think that it will be much easier to configure if the upstream is
http, or the upstream is https, and changing is a significant event,
which involves reconfiguring nginx.

> This information is passed as a GET-param, when making the request to the
> Proxy-Server.

As shown below, that design cannot work without more changes. If possible,
I suggest you remove that "changeable" desire. If not, you will need a
fuller design that accounts for it.

I would first suggest making all upstreams accessible over http. Failing
that, you may be able to build something based on cookies -- if the GET
param is present, set a cookie and use that value; else, if the cookie
is present, use that value; else do something appropriate -- perhaps
fail and tell the user why; perhaps assume http.

(If you can get a reliable "you used http instead of https" error code
from upstream, you might be able to use that information when setting
the cookie, so the thing can auto-tune.)
> I have already tried this via
> map $remote_user $forwarded_protocol {
>     ajay           $arg_upstream_protocol
> }

I was thinking more like

     ajay           http;

because $arg_upstream_protocol is not always present.

> > One request gets one response. If the response is a http 301, the next
> > request is a whole new request that should be considered separately.
> >
> > If at all possible, do not design things so that you need to edit the
> > upstream response body before sending it to the client.

> curl -v -k https://ajay:garg@

> > GET /?upstream_protocol=http HTTP/1.1
> > Authorization: Basic abcdefg

> < HTTP/1.1 200 Ok

> <script>
> <!--
>     window.location.href = "/cgi-bin/webproc";
> -->

So - the first request is handled as you want it to be. It includes
in its response body an invitation to the browser to make a new request,
to /cgi-bin/webproc.

Not to /cgi-bin/webproc?upstream_protocol=http.

Eventually, there will be a html page with many "a href" and "img src"
urls; none of them will include "?upstream_protocol=http" either. (Unless
you significantly change the upstream config to always include it --
which you do not want to do -- or you change the nginx config to edit
the upstream response body to always include it before returning it to
the client -- which you also do not want to do.)

> Strangely, when request is done by curl, absolutely nothing appears in
> /var/log/nignix/error.log, whereas when done through the browser, logs
> appear in /var/log/nginx/error.log as per my previous emails.

curl makes the one request that you ask it to make, and shows the
response. So you can see exactly what is happening.

Then, if you want to, you can use it to make the next one request that
the browser makes, so again you can see exactly what is happening.

I suspect that if you do

  curl -v -k https://ajay:garg@

you will see that same result in nginx as when the browser makes that

But now you know that the error message is not from the first request,
so you do not need to try to fix the first request.

And if you do

  curl -v -k https://ajay:garg@

(or if you use that url in a browser) you will see what comes back and
see the next problem.

> Things work fine if I hardcode http/https in proxy_pass directive.
> It's only when I need to use to parse-and-use "upstream_protocol" from the
> GET-param (which can only be equal to http/https) that I start facing
> problems.

Yes - you only face those problems when "upstream_protocol" is not
provided in the GET-params. So you must design things so that either
"upstream_protocol" is present in every request; or design things so
that the information that it carries is available in every request --
which probably means "always http" or "tied to authentication" or "tied
to a cookie".

Good luck with it,

Francis Daly        francis at daoine.org

More information about the nginx mailing list