Score:0

Why can I write one set of URLs but not others with NGINX?

in flag

I've set up NGINX, version 1.18.0, as reverse proxy for my Apache Superset 1.4.0 installation.

I'm trying to capture some URL patterns, and rewrite them by adding standalone=1 at the end.

The following NGINX configuration works as expected:

location /superset/explore/ {
        if ($args ~* "(.*?)slice_id%22%3A133(.*)$") {
            rewrite ^/superset/explore/(.*)$ /superset/explore/$1?standalone=1 break;
        }

        proxy_pass http://127.0.0.1:8087;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

Because when I visit (with Chrome) a URL such as http://192.168.239.40:8088/superset/explore/?form_data=%7B%22viz_type%22%3A%22echarts_timeseries_line%22%2C%22datasource%22%3A%2233__table%22%2C%22slice_id%22%3A133%2C ..., I can see that it's replaced by the original plus &standalone=1 added to the URL when I check Chrome address bar.

But when I try to do something similar for another URL pattern for Apache Superset, such as the following:

   location /dashboard/list/ {
        rewrite ^/dashboard/list/(.*)$ /dashboard/list/$1?standalone=1 break;

        proxy_pass http://127.0.0.1:8087;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

and I request http://192.168.239.40:8088/dashboard/list/ with Chrome, I see the address bar replaced with http://192.168.239.40:8088/dashboard/list/?pageIndex=0&sortColumn=changed_on_delta_humanized&sortOrder=desc&viewMode=table but I don't see any any &standalone=1 appended.

I also checked Superset logs to see what it serves after I request http://192.168.239.40:8088/dashboard/list/ and I see that ?standalone=1 is actually appended!

Feb 10 14:09:19 dashboard-server python[34169]: 2022-02-10 14:09:19,482:INFO:werkzeug:127.0.0.1 - - [10/Feb/2022 14:09:19] "GET /dashboard/list/?standalone=1 HTTP/1.0" 200 -
Feb 10 14:09:20 dashboard-server python[34169]: 2022-02-10 14:09:20,729:INFO:werkzeug:127.0.0.1 - - [10/Feb/2022 14:09:20] "GET /api/v1/dashboard/_info?q=(keys:!(permissions)) HTTP/1.0" 200 -
Feb 10 14:09:20 dashboard-server python[34169]: 2022-02-10 14:09:20,771:INFO:werkzeug:127.0.0.1 - - [10/Feb/2022 14:09:20] "GET /api/v1/dashboard/?q=(order_column:changed_on_delta_humanized,order_direction:desc,page:0,page_size:25) HTTP/1.0" 200 -

Any ideas why this is happening?

The complete /etc/nginx/conf.d/superset.conf is as follows:

server {
    listen 8088;
    server_name 192.168.239.40;

    location / {
        proxy_pass http://127.0.0.1:8087;
    }

    location /superset/explore/ {
        if ($args ~* "(.*?)slice_id%22%3A133(.*)$") {
            rewrite ^/superset/explore/(.*)$ /superset/explore/$1?standalone=1 break;
        }

        proxy_pass http://127.0.0.1:8087;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

   location /dashboard/list/ {
        rewrite ^/dashboard/list/(.*)$ /dashboard/list/$1?standalone=1 break;

        proxy_pass http://127.0.0.1:8087;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }


    # required as superset has hardcoded base path urls
    location /static/ {
        proxy_pass http://127.0.0.1:8087/static/;
    }

    # to expose a specific dashboard using a custom url
    # the below example will make dashboard 2 available in standalone mode
    # on $host/dashboards/my-dashboard
    location /dashboards/my-dashboard {
        proxy_pass http://127.0.0.1:8087/superset/dashboard/2/?standalone=true;
    }
}
Score:1
us flag

Mangling URLs like this is quite dangerous without knowing the details how the upstream application actually handles URLs. This can lead to many difficult to diagnose bugs.

You should revisit your original goal and think if you can reach it via some other method.

What becomes to your current issue: rewrite ... break is an internal rewrite of the URL. This means, nginx only modifies the URL that is sent to the upstream server.

In this case, your upstream server just returns the page specified by the modified URL.

In the client's browser, there is no change in the URL, because the server just returns content for the URL requested.

What becomes to the case where browser URL changes with this configuration: In that case your upstream application seems to be responding with 302 redirect that makes the browser visit another URL.

If you want to tell the client to go to the URL, then you need to send a HTTP redirect:

rewrite ^/dashboard/list/(.*)$ /dashboard/list/$1?standalone=1;

However, this will most likely create a redirect loop by itself, since the same location block captures the request again and again. Creating a non-looping HTTP redirect can become a quite complex exercise.

So, I would look into alternative ways of solving the actual problem at hand.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.