Description
I have noticed that swagger.json fails to load behind an HTTPS proxy (say, a kubernetes ingress controller) when using gunicorn to serve, but not uWSGI. This happens regardless of passing header X-Forwarded-Proto
as recommended in the gunicorn documentation. While the issue probably lies with gunicorn, I have been able to make a slight change to the library which makes it work with gunicorn and uWSGI.
Changing api.specs_url
to not use _external
on url_for
, allows it to return just the relative path to swagger.json, instead of a complete URI (/api/v1/swagger.json
vs http://host.com/api/v1/swagger.json
) and subsequently allows the JS to load swagger.json. This also falls in line with the behavior of other Django REST middlewares, as well as FastAPI.
flask-restx/flask_restx/api.py
Line 510 in 66d884f
Repro Steps
- Run a basic Flask App with Flask-RESTX using gunicorn, and access it from an HTTPS reverse proxy.
Expected Behavior
Ability to load the SwaggerUI from behind an HTTPS reverse proxy using gunicorn. Having the JS load path instead of URI by rendering out api.specs_url not using _external
. Ergo, a relative path to swagger.json being passed to the swagger-ui template.
Actual Behavior
RESTX renders out the entire URI using HTTP (because the connection from proxy to gunicorn is HTTP) for the JS to load swagger.json for the SwaggerUI, thus causing a broken SwaggerUI because its trying to load insecure content on a secure site.
Error Messages/Stack Trace
Mixed Content: The page at 'https://host.com/api/v1/' was loaded over HTTPS, but requested an insecure resource 'http://host.com/api/v1/swagger.json'. This request has been blocked; the content must be served over HTTPS.
Environment
- Python version 3.8
- Flask version 1.1.2
- Flask-RESTX version 0.2.0
- Other installed Flask extensions None
Additional Context
Generally, websites use relative paths for their own content.
All of the other static content loaded by the SwaggerUI (CSS, JS bundles, etc) load with relative paths and work. Only swagger.json does not. This is because the swagger_static
template filter does not use _external
on url_for
flask-restx/flask_restx/apidoc.py
Line 33 in 66d884f