Score:1

Change upstream response from 302 to 301 in nginx

cn flag

I have a Django app as an upstream using Gunicorn in nginx, and that app sometimes sent me back a 302 with a Location. And that it's perfectly fine.

We can't touch Django's code but colleagues need the 302 to be 301.

So I would like to modify that 302 to 301, but I haven't found a way to do it without using LUA. I have tried combinations of "error_page" statement, eg. error_page 302 =301 @redirect; with the "proxy_intercept_errors on;", named location, etc. but haven't had any luck.

Is there any quick way to achieve it? Thanks.

Edit1: Here below my pretty simple upstream:

upstream test {
  server unix:/webapps/test/gunicorn.sock fail_timeout=0;
}
YonzLeon avatar
de flag
Please add your upstream conf sample txt
cn flag
@YonzLeon added, thanks, it is pretty straightforward.
Score:1
jp flag

You can change the 3xx status code by using proxy_intercept_errors and error_page as you suggest.

You will need to use the value from $upstream_http_location to reconstruct the Location header in the replacement response.

In its simplest form, you could use:

proxy_intercept_errors on;
error_page 302 = @redirect;
location @redirect {
    return 301 $upstream_http_location;
}

In this case, $upstream_http_location is the original value for the Location header in the response from the upstream server before being transformed by proxy_redirect - equivalent to using proxy_redirect off;.

This may be sufficient for your needs.


However, if you need to rewrite the Location response header - for example, if you are using proxy_redirect default; - you may need to modify the response using a map.

For example:

map $upstream_http_location $location {
        ~^https?://[^/]+(.*)$    $1;
        default                  /oops;
}

server {
    ...
    proxy_intercept_errors on;
    error_page 302 = @redirect;
    location @redirect {
        return 301 $location;
    }
}
cn flag
Richard, your simplest form works, but the login stopped working. I noticed that it didn't sent the headers, so I resolved doing location @redirect { add_header Set-Cookie "sessionid=${upstream_cookie_sessionid}; HttpOnly; Path=/; SameSite=Lax"; add_header Set-Cookie "csrftoken=${upstream_cookie_csrftoken}; Path=/; SameSite=Lax"; return 301 $upstream_http_location; } is there any better way of passing headers? Right now I'm missing the "expires" part.
I sit in a Tesla and translated this thread with Ai:

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.