Skip to content

Commit

Permalink
add aiohttp reverse proxy example
Browse files Browse the repository at this point in the history
  • Loading branch information
dtkav committed Jan 24, 2019
1 parent c82daea commit 2fe0b0e
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 0 deletions.
58 changes: 58 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
=====================
Reverse Proxy Example
=====================

This example demonstrates how to run a connexion application behind a path-altering reverse proxy.

You can either set the path in your app, or set the ``X-Forwarded-Path`` header.

Running:

.. code-block:: bash
$ sudo pip3 install --upgrade connexion[swagger-ui] # install Connexion from PyPI
$ ./app.py
Now open your browser and go to http://localhost:8080/reverse_proxied/ui/ to see the Swagger UI.


You can also use the ``X-Forwarded-Path`` header to modify the reverse proxy path.
For example:

.. code-block:: bash
curl -H "X-Forwarded-Path: /banana/" http://localhost:8080/openapi.json
{
"servers" : [
{
"url" : "banana"
}
],
"paths" : {
"/hello" : {
"get" : {
"responses" : {
"200" : {
"description" : "hello",
"content" : {
"text/plain" : {
"schema" : {
"type" : "string"
}
}
}
}
},
"operationId" : "app.hello",
"summary" : "say hi"
}
}
},
"openapi" : "3.0.0",
"info" : {
"version" : "1.0",
"title" : "Path-Altering Reverse Proxy Example"
}
}
75 changes: 75 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
'''
example of aiohttp connexion running behind a path-altering reverse-proxy
'''

import json
import connexion
from yarl import URL
from aiohttp import web
from aiohttp_remotes.x_forwarded import XForwardedBase
from aiohttp_remotes.exceptions import RemoteError, TooManyHeaders

X_FORWARDED_PATH = "X-Forwarded-Path"


class XPathForwarded(XForwardedBase):

def __init__(self, num=1):
self._num = num

def get_forwarded_path(self, headers):
forwarded_host = headers.getall(X_FORWARDED_PATH, [])
if len(forwarded_host) > 1:
raise TooManyHeaders(X_FORWARDED_PATH)
return forwarded_host[0] if forwarded_host else None

@web.middleware
async def middleware(self, request, handler):
try:
overrides = {}
headers = request.headers

forwarded_for = self.get_forwarded_for(headers)
if forwarded_for:
overrides['remote'] = str(forwarded_for[-self._num])

proto = self.get_forwarded_proto(headers)
if proto:
overrides['scheme'] = proto[-self._num]

host = self.get_forwarded_host(headers)
if host is not None:
overrides['host'] = host

prefix = self.get_forwarded_path(headers)
if prefix is not None:
prefix = '/' + prefix.strip('/') + '/'
request_path = URL(request.path.lstrip('/'))
overrides['rel_url'] = URL(prefix).join(request_path)

request = request.clone(**overrides)

return await handler(request)
except RemoteError as exc:
exc.log(request)
await self.raise_error(request)


def hello(request):
ret = {
"host": request.host,
"scheme": request.scheme,
"path": request.path,
"_href": str(request.url)
}
return web.Response(text=json.dumps(ret), status=200)


if __name__ == '__main__':
app = connexion.AioHttpApp(__name__)
app.add_api('openapi.yaml', pass_context_arg_name='request')
aio = app.app
reverse_proxied = XPathForwarded()
aio.middlewares.append(reverse_proxied.middleware)
app.run(port=8080)
38 changes: 38 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
worker_processes 1;
error_log stderr;
daemon off;
pid nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;

keepalive_timeout 65;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
access_log access.log;
server {

listen localhost:9000;

location /reverse_proxied/ {
# Define the location of the proxy server to send the request to
proxy_pass http://localhost:8080/;
# Add prefix header
proxy_set_header X-Forwarded-Path /reverse_proxied/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto http;
}

}
}
18 changes: 18 additions & 0 deletions examples/openapi3/reverseproxy_aiohttp/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.0.0
info:
title: Path-Altering Reverse Proxy Example
version: '1.0'
servers:
- url: /api
paths:
/hello:
get:
summary: say hi
operationId: app.hello
responses:
'200':
description: hello
content:
text/plain:
schema:
type: string

0 comments on commit 2fe0b0e

Please sign in to comment.