Search code examples
gohttphttp-redirect

golang issue with redirection of request (superfluous error)


I got a really weird behavior from golang.
I want to do stuff with a post request and then redirect the request. Depending on random factors ... it works, or not.
When it is not working I get that error:
"http: superfluous response.WriteHeader call from ..."
the deeper in the function the less likely the redirection will work.

  • As far as I can tell I am redirecting only one time (or zero ...)
  • I am not writing into the header before redirecting.
  • the only thing I do with the writer before redirect, is putting it into a map.

I do not want to copy all the code here so I will sum it up.
A handler handle POST requests, pass request data in a map called demand.
Then the request is parsed to get the form values, that are saved it into demand which is sent into a channel.
from the channel the demand map is passed to the below function :

func answer_login(demand map[string]any) map[string]any {
    writer := demand["writer"].(http.ResponseWriter)
    request := demand["request"].(*http.Request)
    http.Redirect(writer, request, "/", 302) // <- if it is here it works (at95 %)
    // some mundane code (printing stuff, really)
    .
    .
    .
    // http.Redirect(writer, request, "/", 302) // <- if it is here it works (only at 20 %)
    ...
    

If I smash F5 it eventually redirects correctly. I tried with simply writing something into the writer.Write([]byte("same issue")), same problem.
I am on linux and I tried with different browsers.

Question : is it a (known) bug ?
is there any workaround ?
(force writing to the client)
thx


Solution

  • I finally got an understanding of the issue and a solution.
    The issue:

    Then the request is parsed to get the form values, that are saved it into demand which is sent into a channel. from the channel the demand map is passed to the below function ...

    So, the writer-request where treated and redirected in a function that was in a different scope from the actual handler function. and when the actual handler function end. some context things make the writer-request expired : you cannot redirect or respond to that request anymore. This is written in the doc:

    A ResponseWriter interface is used by an HTTP handler to construct an HTTP response. A ResponseWriter may not be used after the Handler.ServeHTTP method has returned.

    https://pkg.go.dev/net/http

    A possible explanation about why it sometimes works is ... maybe the " the channel transfer, processing and redirection" happened fast enough (sometimes) and the actual handler function wasn't closed yet.

    Blocking the handler function until the data was processed killed the purpose of having parallel asynchronous processing. So i ended up nesting all in the handler function.
    Smarter people are welcome to correct me or share better explanations about context and ResponseWriters.