API reference: fresco.middleware

class fresco.middleware.XForwarded(app: Callable[[dict[str, Any], Callable[[str, list[tuple[str, str]], tuple[type[BaseException], BaseException, TracebackType] | None], Callable[[bytes], object]]], Iterable[bytes]], trusted: Iterable[str] | None = None, force_https: bool | None = None)[source]

Modify the WSGI environment so that the X_FORWARDED_* headers are observed and generated URIs are correct in a proxied environment.

Use this whenever the WSGI application server is sitting behind Apache or another proxy server.

It is easy for clients to spoof the X-Forwarded-For header. You can largely protect against this by listing all trusted proxy server addresses in trusted. See http://en.wikipedia.org/wiki/X-Forwarded-For for more details.

HTTP_X_FORWARDED_FOR is substituted for REMOTE_ADDR and HTTP_X_FORWARDED_HOST for SERVER_NAME. If HTTP_X_FORWARDED_SSL is set, then the wsgi.url_scheme is modified to https and HTTPS is set to on.

Parameters:
  • trusted – List of IP addresses trusted to set the HTTP_X_FORWARDED_* headers

  • force_https – If True, the following environ keys will be set unconditionally: "HTTPS": "on" and "wsgi.url_scheme": "https" will be set

Example:

>>> from fresco import FrescoApp, context, GET, Response
>>> from flea import Agent
>>> app = FrescoApp()
>>> @app.route('/', GET)
... def view():
...     return Response(["URL is ", context.request.url,
...                      "; REMOTE_ADDR is ",
...                      context.request.remote_addr])
...
>>> r = Agent(XForwarded(app))
>>> response = r.get('/',
...     SERVER_NAME='wsgiserver-name',
...     SERVER_PORT='8080',
...     HTTP_HOST='wsgiserver-name:8080',
...     REMOTE_ADDR='127.0.0.1',
...     HTTP_X_FORWARDED_HOST='real-name:81',
...     HTTP_X_FORWARDED_FOR='1.2.3.4'
... )
>>> response.body
u'URL is http://real-name:81/; REMOTE_ADDR is 1.2.3.4'
>>> response = r.get('/',
...     SERVER_NAME='wsgiserver-name',
...     SERVER_PORT='8080',
...     HTTP_HOST='wsgiserver-name:8080',
...     REMOTE_ADDR='127.0.0.1',
...     HTTP_X_FORWARDED_HOST='real-name:443',
...     HTTP_X_FORWARDED_FOR='1.2.3.4',
...     HTTP_X_FORWARDED_SSL='on'
... )
>>> response.body
u'URL is https://real-name/; REMOTE_ADDR is 1.2.3.4'