-
-
Notifications
You must be signed in to change notification settings - Fork 756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serve correct openapi spec basepath when path is altered by reverse-proxy #823
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2267f45
use url_for to reverse the route for openapi.json
dtkav 0892bae
modify spec base_path on request
dtkav 93fe858
add reverseproxy example
dtkav 2b23b75
add aiohttp reverse proxy example
dtkav c672c85
add tests for reverse proxies
dtkav a649697
Improve with PR comments
154d367
use yaml.BaseLoader in test to remove warning
dtkav 26249b9
fix yaml spec creation
dtkav d0efe57
fix deprecated logging.warn calls in reverse proxy examples
dtkav dd5f29b
remove check for python versions less than 3.5
dtkav e859609
Merge branch 'master' into dynamic_ui_path
dtkav File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#!/usr/bin/env python3 | ||
''' | ||
example of connexion running behind a path-altering reverse-proxy | ||
|
||
NOTE this demo is not secure by default!! | ||
dtkav marked this conversation as resolved.
Show resolved
Hide resolved
|
||
You'll want to make sure these headers are coming from your proxy, and not | ||
directly from users on the web! | ||
|
||
''' | ||
import logging | ||
|
||
import connexion | ||
|
||
|
||
# adapted from http://flask.pocoo.org/snippets/35/ | ||
class ReverseProxied(object): | ||
'''Wrap the application in this middleware and configure the | ||
reverse proxy to add these headers, to let you quietly bind | ||
this to a URL other than / and to an HTTP scheme that is | ||
different than what is used locally. | ||
|
||
In nginx: | ||
|
||
location /proxied { | ||
proxy_pass http://192.168.0.1:5001; | ||
proxy_set_header Host $host; | ||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||
proxy_set_header X-Scheme $scheme; | ||
proxy_set_header X-Forwarded-Path /proxied; | ||
} | ||
|
||
:param app: the WSGI application | ||
:param script_name: override the default script name (path) | ||
:param scheme: override the default scheme | ||
:param server: override the default server | ||
''' | ||
|
||
def __init__(self, app, script_name=None, scheme=None, server=None): | ||
self.app = app | ||
self.script_name = script_name | ||
self.scheme = scheme | ||
self.server = server | ||
|
||
def __call__(self, environ, start_response): | ||
logging.warning( | ||
"this demo is not secure by default!! " | ||
"You'll want to make sure these headers are coming from your proxy, " | ||
"and not directly from users on the web!" | ||
) | ||
script_name = environ.get('HTTP_X_FORWARDED_PATH', '') or self.script_name | ||
if script_name: | ||
environ['SCRIPT_NAME'] = "/" + script_name.lstrip("/") | ||
path_info = environ['PATH_INFO'] | ||
if path_info.startswith(script_name): | ||
environ['PATH_INFO_OLD'] = path_info | ||
environ['PATH_INFO'] = path_info[len(script_name):] | ||
scheme = environ.get('HTTP_X_SCHEME', '') or self.scheme | ||
if scheme: | ||
environ['wsgi.url_scheme'] = scheme | ||
server = environ.get('HTTP_X_FORWARDED_SERVER', '') or self.server | ||
if server: | ||
environ['HTTP_HOST'] = server | ||
return self.app(environ, start_response) | ||
|
||
|
||
def hello(): | ||
return "hello" | ||
|
||
|
||
if __name__ == '__main__': | ||
app = connexion.FlaskApp(__name__) | ||
app.add_api('openapi.yaml') | ||
flask_app = app.app | ||
proxied = ReverseProxied( | ||
flask_app.wsgi_app, | ||
script_name='/reverse_proxied/' | ||
) | ||
flask_app.wsgi_app = proxied | ||
app.run(port=8080) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
openapi: 3.0.0 | ||
info: | ||
title: Path-Altering Reverse Proxy Example | ||
version: '1.0' | ||
paths: | ||
/hello: | ||
get: | ||
summary: say hi | ||
operationId: app.hello | ||
responses: | ||
'200': | ||
description: hello | ||
content: | ||
text/plain: | ||
schema: | ||
type: string |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] aiohttp-remotes | ||
$ ./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" | ||
} | ||
} | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In line 44 and here we do similar formatting for the register and to get the URL for the endpoint. Maybe we can do it once? I would like to avoid duplicated "..._openapi_json" string. Something could tie this two together closer, so we don't break things later. I know we have tests covering this, but if possible would be nice to remove this duplication. Sorry if this seems over-engineering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @rafaelcaricio - really appreciate your comments.
I agree with your point here, but I couldn't come up with a good idea for how to make it happen. Maybe you could provide a more specific example of what you have in mind?