[uWSGI] http proxying in response-route

mathieu lacage mathieu.lacage at alcmeon.com
Wed May 29 11:46:22 UTC 2019


Hi,

In case anyone stumbles upon this question, I eventually found a working
solution, documented below. FYI, I am going to use 2. upon production
deployments.

1. "standard" HTTP headers: this is the solution I tried to get to work
earlier without understanding that:
   - the rewrite plugin rewrites the variables, not the input HTTP request
   - the http router plugin supports a third undocumented argument that is
the PATH argument that will be injected in the forwarded query
   - uwsgi does not support the syntax "route = http:${VAR}" where
VAR=val1,val2,val3. Instead, it requires "route =
http:${VAR1},${VAR2},${VAR3}"

The application side:
222         handler.response.headers['X-Sendurl'] = 'true'
223         handler.response.headers['X-Sendurl-IP'] =  '%s:%d' %
(socket.gethostbyname(url.hostname), url.port if url.port is not None else
80)
224         handler.response.headers['X-Sendurl-Host'] = url.hostname
225         handler.response.headers['X-Sendurl-Path-Query'] = "%s?%s" %
(url.path, url.query)

The configuration file:
 29 collect-header = X-Sendurl X_SENDURL
 30 response-route-if-not = empty:${X_SENDURL} goto:xsendurl
 32 response-route-run = last:

 45 response-route-label = xsendurl
 46 collect-header = X-Sendurl-IP X_SENDURL_IP
 47 collect-header = X-Sendurl-Host X_SENDURL_HOST
 48 collect-header = X-Sendurl-Path-Query X_SENDURL_PATH_QUERY
 49 response-route-run =
http:${X_SENDURL_IP},${X_SENDURL_HOST},${X_SENDURL_PATH_QUERY}
 51 response-route-run = last:

2. "variables". It is possible to shorten slightly the above to this:

The application side:
216         import uwsgi
217         uwsgi.add_var("SEND_URL", "y")
218         uwsgi.add_var("SEND_URL_IP", '%s:%d' %
(socket.gethostbyname(url.hostname), url.port if url.port is not None else
80))
219         uwsgi.add_var("SEND_URL_HOST", url.hostname)
220         uwsgi.add_var("SEND_URL_PATH_QUERY", "%s?%s" % (url.path,
url.query))

The configuration side:

 31 response-route-if = equal:${SEND_URL};y goto:xsendurl
 32 response-route-run = last:
 44
 45 response-route-label = xsendurl
 50 response-route-run =
http:${SEND_URL_IP},${SEND_URL_HOST},${SEND_URL_PATH_QUERY}
 51 response-route-run = last:

3. Sadly, the even shorter version below does not work because of issue
#1041 (https://github.com/unbit/uwsgi/issues/1041) which appears to be
fixed by the unmerged patch:
https://github.com/unbit/uwsgi/pull/1473/commits/b71dc90b82c1e8e640d0c449d535171b19a08d9d

The application side:
216         import uwsgi
221         uwsgi.route("http", "%s:%d,%s,%s?%s" %
(socket.gethostbyname(url.hostname), url.port if url.port is not None else
80, url.hostname, url.path, url.query))

The configuration side: none

I hope this help,
Mathieu


Le mar. 28 mai 2019 à 15:29, mathieu lacage <mathieu.lacage at alcmeon.com> a
écrit :

> hi,
>
> I am trying to implement X-sendurl in my application using uwsgi. I
> modified my app to generate a couple of http headers:
>
> 215         handler.response.headers['X-Sendurlhost'] = '%s:%d,%s' %
> (socket.gethostbyname(url.hostname), url.port if url.port is not None else
> 80, url.hostname)
> 216         handler.response.headers['X-Sendurlpathqs'] = "%s?%s" %
> (url.path, url.query)
> 217         handler.response.set_status(200)
>
> and I configured my uwsgi server as follows:
>
>  29 collect-header = X-Sendurlpathqs X_SENDURLPATHQS
>  30 collect-header = X-Sendurlhost X_SENDURLHOST
>  31 response-route-if-not = empty:${X_SENDURLPATHQS} goto:xsendurl
>  32 response-route-run = last:
>
>  [snip]
>
>  45 response-route-label = xsendurl
>  46 response-route-run = rewrite:${X_SENDURLPATHQS}
>  48 response-route-run = http:${X_SENDURLHOST}
>  49 response-route-run = last:
>
> The above configuration appears to hit and execute correctly line 48 above
>
> with the following values:
>
> X_SENDURLHOST=137.74.127.78:80,storage.gra3.cloud.ovh.net
>
> X_SENDURLPATHQS=/v1/AUTH_7542981824cf4bcb883cf4c4321195ae/prod/companies/8/users-profile-attachments/4165024?temp_url_sig=49d3ec9ee9d5fd5aa447fc70162e6fb72c564e99&temp_url_expires=1559049647
>
> I read very carefully the documentation at
> https://uwsgi-docs.readthedocs.io/en/latest/InternalRouting.html and I
> would expect the above to forward an HTTP request to IP 137.74.127.78 on
> port 80 with HTTP header HOST=storage.gra3.cloud.ovh.net and
> PATH=/v1/AUTH_7542981824cf4...
>
> However, tcpdump shows instead the following request:
>
> GET
> /admin/8/users-profile-attachments/?user_id=5172075&site_id=154&site_type=2
> HTTP/1.0
> Host: localhost:9090
> ...
>
> HTTP/1.1 401 Unauthorized
> Content-Length: 131
> Content-Type: text/html; charset=UTF-8
> Www-Authenticate: Swift realm="8"
> WWW-Authenticate: Keystone uri='https://auth.cloud.ovh.net/'
> ...
>
> So, uwsgi is connecting to the right IP and port, but it's not sending
> what I would expect for the HOST HTTP header and HTTP PATH.
>
> Is there something I should adjust in my uwsgi configuration to make it
> forward the Host+PATH headers I want ?
>
> Mathieu
> --
> Mathieu Lacage <mathieu.lacage at alcmeon.com>
>


-- 
Mathieu Lacage <mathieu.lacage at alcmeon.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.unbit.it/pipermail/uwsgi/attachments/20190529/ec784286/attachment.html>


More information about the uWSGI mailing list