NGINX 301 and 302 serving small nginx document body. Any way to remove this behaviour?

Think very carefully about what you're asking for, and strongly consider not doing it.

RFC 2616 specifies that the entity bodies you want to remove should be present.

10.3.2 301 Moved Permanently

The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).

and...

10.3.3 302 Found

The temporary URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).

SHOULD, in this context, is defined in RFC 2119:

This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.

Now you can do this without violating the RFC, but you should be aware of the full implications:

  • You are doing a lot of work for virtually no benefit. The only logical reason I can think of to disable the entity body is to save on bandwidth costs, and indeed this is the reason you mentioned, but the difference is so minimal that it's unlikely you'll even see a difference on your bandwidth graphs.
  • A very tiny fraction of web clients don't automatically follow 3xx redirects. This fraction was much larger when the RFC was written, which is why this is there in the first place, but there are still ancient monstrosities lurking in the shadows of dark bedrooms and data center closets, and sometimes they come out to play. The one you are most likely to see is curl, which is still in common use.

This recommendation has been relaxed somewhat with RFC 7231, which merely says (for both 301 and 302):

The server's response payload usually contains a short hypertext note with a hyperlink to the new URI(s).

The server's response payload usually contains a short hypertext note with a hyperlink to the different URI(s).


Yes, you can ABSOLUTELY do it with NGINX!

  • Simply install an exception handler, a.k.a. error_page, to post-process required responses. Make sure to set it in such a way as to prevent the error page from modifying the HTTP Status Code, e.g., don't use the = parameter (or use it to hardcode whichever code you desire).

  • Make sure to return a response with a return status code that allows you to optionally set the [text], not the URL.

  • Specify default_type of "", which appears to remove the Content-Type header

Here's the full code, also at my GitHub in StackOverflow.cnst.nginx.conf repository:

# cat sf.421976.301-302-redirect-w-no-http-body-text.nginx.conf | sed 's#^#\t#g'
server {
    listen 1976;
    error_page 301 302 @30x; # keep original HTTP status code w/o `=`
    location @30x {
        default_type ""; # will remove Content-Type completely
        # `300` is a filler: client will get the original HTTP status code
        return 300;
    }
    return 301 http://example.su/test;
}

Here's the confirmation of it working properly:

% curl -i localhost:1976 | sed 's#^#\t#g'
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.1
Date: Mon, 28 Aug 2017 22:02:41 GMT
Content-Length: 0
Connection: keep-alive
Location: http://example.su/test

%

I've tried it in the browsers, and it worked fine there, too.

P.S. Another option would be to modify the source code, and edit the ngx_http_error_301_page et al variables, but why go the hard route?! ^_^