nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.29k stars 325 forks source link

starletted app hosted by unit -- unable to properly resolve routes to https using request.url_for #943

Closed sandeep-gh closed 9 months ago

sandeep-gh commented 10 months ago

My setup is following: a starlette app is driven by unit which is sitting behind nginx server.

What I need that starlette api request.url_for to resolve to https address instead of http. When starlette is hosted by uvicorn server, the config required is

--forwarded-allow-ips=domain.com
 server {
        server_name example.com
        location / {
            proxy_redirect     off;
# These are the critical headers needed by uvicorn to honor HTTPS in url_for :
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Proto $scheme;
# These are just some other headers you may find useful
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-Host $server_name;

           ...
        }

    listen 443 ssl; 

as described here ,

How to achieve the same for the nginx-unit setup: I have following in nginx.conf file:

  upstream webworks_monallabs_unit {
    # fail_timeout=0 means we always retry an upstream even if it failed
    server [2001:19f0:1000:25ca:5400:04ff:fe6d:2abc]:160 fail_timeout=0;

    }

    server {
    listen         *:443 ssl;
    server_name    webworks.monallabs.in www.webworks.monallabs.in;
    ssl_certificate /etc/nginx/conf.d/webworks.monallabs.in.crt;
    ssl_certificate_key /etc/nginx/conf.d/webworks.monallabs.in.key;
    location / {
         proxy_pass http://webworks_monallabs_unit;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "Upgrade";
         proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

and following on unit configuration

{
            "listeners": {
                "[2001:19f0:1000:25ca:5400:04ff:fe6d:2abc]:160": {
                    "pass": "routes",
                        "forwarded": {                 
                                    "protocol": "X-Forwarded-Proto",    
                                     "client_ip": "X-Forwarded-For",     
                                      "source": ["0.0.0.0/0"  ] 
            }
                }
            },

There have several discussions on starlette as well, so this seems involved. I can provide more links if needed.

tippexs commented 10 months ago

Thanks for reaching out! The https can be taken from the X-Forwarded-Porto. This looks right. I would limit the source IPs to match the IP from your nginx proxy server. This should not matter in this case but will follow the best practice. We will need to dig into the framework and see why it is not doing the right thing.

Are you able to share an example application using a very minimalistic setup?

Ashrafmohdiit commented 10 months ago

I will check it later so we can test it later