Skip to content
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

SpectacularSwaggerView behind a proxy #211

Closed
maximebel opened this issue Nov 25, 2020 · 8 comments
Closed

SpectacularSwaggerView behind a proxy #211

maximebel opened this issue Nov 25, 2020 · 8 comments

Comments

@maximebel
Copy link

Hello

SpectacularSwaggerView is using request.get_full_path() but it is not enough I think for servers behind a proxy.

It should either rely on x_forwarded headers or integrate FORCE_SCRIPT_NAME if defined.

My current issue is that Swagger can't load the script because the generated path is not complete.

No issue for redoc though

Regards

@tfranzel
Copy link
Owner

Hi @maximebel,

ahh a proxy, i see. so first of all, all URLs should be relative, but i guess this is not sufficient in your case. i'm assuming you have some kind of prefix from your proxy. if thats not the case, can you make a (anonymized) example to make the analysis easier?

that would mean you are already using the url param for SpectacularSwaggerView? and that param is not used for generating the "self-referential" second url, which looks like the core problem. can you confirm that?

i guess that other feature request generated more problems than it solved.

@maximebel
Copy link
Author

Hello yes you're right but it is not enough. The first issue is with the <script src="{{script_url|safe}}"></script> in the template.

script_url is request.get_full_path() which is not using FORCE_SCRIPT_NAME (or anything else) so the generated url lacks the proxy prefix.

@ronek22
Copy link

ronek22 commented Dec 15, 2020

I have the same problem,

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accounts.urls')),
    path('upc/', include('upc.urls')),
    path('schema/', SpectacularAPIView.as_view(), name='schema'),
    path('docs/', SpectacularSwaggerView.as_view(template_name="swagger-ui.html", url_name="schema"), name="swagger-ui"),
]

For backend endpoints was added /api prefix in nginx

upstream backend {
    server backend:8000;
}

server {
    listen 80;

    gzip on;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html =404;
    }

    location /static/ {
        alias /var/www/static/;
        autoindex on;
    }

    location /api {
        rewrite /api/(.*) /$1 break;
        proxy_pass http://backend;
    }
}

In Swagger Api calls doesn't have /api prefix

image

@tfranzel
Copy link
Owner

@maximebel your problem should be fixed now as SpectacularSwaggerView now behaves again like redoc (1 request). the split request version is till available for people with CSP issues (SpectacularSwaggerSplitView).

regarding your second point. FORCE_SCRIPT_NAME was in fact working for me as expected. both reverse() and get_full_path() contained the prefix from FORCE_SCRIPT_NAME. tested it with FORCE_SCRIPT_NAME="/foo/".

@ronek22 your problem is a separate but related one i believe. @maximebel was not referring to a missing prefix in the schema, but a broken swagger UI.

your problem is that django needs to be aware that it is prefixed. FORCE_SCRIPT_NAME might be a solution, but it is currently unused for schema generation i believe. what you can do is defining a server in the schema with:

SPECTACULAR_SETTINGS = {
   'SERVERS': [{'url': 'http://localhost:8081/api/'}],
    ...
}

then Swagger UI should probably work as expected.

@tfranzel
Copy link
Owner

this looks resolved to me. feel free to comment if not

@kiran-4444
Copy link

I'm facing a similar issue. I'm serving my backend through Nginx reverse proxy. The problem is when I try to hit server-domain/subdomain/schema/swagger-ui it's calling /schema and this is getting redirected to server-domain/schema. But instead, it should get redirected to server-domain/subdomain/schema.

@tfranzel
Copy link
Owner

If django does not know about your path, it cannot reverse a correct link to the schema. The swagger and the schema are 2 requests.

regarding your second point. FORCE_SCRIPT_NAME was in fact working for me as expected. both reverse() and get_full_path() contained the prefix from FORCE_SCRIPT_NAME. tested it with FORCE_SCRIPT_NAME="/foo/".

You need to make Django aware of your routing as mentioned above: https://docs.djangoproject.com/en/4.2/ref/settings/#force-script-name
In your case it should probably be /subdomain.

@kiran-4444
Copy link

Thanks for that! But now I get this when I hit /schema/swagger-ui:

😱 Could not render Hn, see the console.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants