-2

There's probably something obvious that I'm missing but I'm trying to extract the data already written after the return of a chained handler.

func Logger(next http.Handler, name string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    start := time.Now()
    next.ServeHTTP(w, r)
    
    log.Debug(
        fmt.Sprintf("%s %s %s %s",
            r.Method,
            r.RequestURI,
            name,
            time.Since(start)),
    )
})

}

After the next.ServeHTTP function returns I already have the data and I want just to check some values at the response before logging the entire request. I cannot find a way to extra the data from http.ResponseWriter.

Do I miss something ?

  • 5
    You can't extract the data because there's nothing to extract, it's effectively already been sent to the client. – JimB Mar 26 '21 at 17:00
  • But I have not returned from Handler.ServeHTTP. The Logger is just another Handler. It is a chained handler logic. The Logger is calling you can see another handler which itself is also an http handler. I have chain a couple of handlers actually. – Makis Papapanagiotou Mar 26 '21 at 17:08
  • 3
    It doesn't matter, a normal `ResponseWriter` writes sends data to the client, it does not buffer everything indefinitely. If the previous handler were streaming huge files, would you expect them to now all be stored in memory? – JimB Mar 26 '21 at 17:30
  • 3
    ResponseWriter is an interface and all you can do is call one of its methods. What you _can_ do is implement your own ResponseWriter which allows to do more. – Volker Mar 26 '21 at 17:50
  • @JimB : What do you think it happens ? I am chaining 3 handlers before sending back the actual response to the client. Each of the handlers is doing something to the data. Then the final response is sent. Of course they are stored in memory. How else the data will traverse all the handlers or middlewares in order to create the final response ? – Makis Papapanagiotou Mar 26 '21 at 19:15
  • You should have those handlers all working on the *data*, and only one working on the *response*. – Adrian Mar 26 '21 at 19:22
  • @Adrian: That is what I am doing. But in any case the question is whether I can have access to the data "carried" within the ResponseWritter. Not only adding to it, but also extrarcting them in case of a certain handling . – Makis Papapanagiotou Mar 26 '21 at 19:29
  • 1
    @MakisPapapanagiotou: if you have 3 handlers with access to the data, then you have not written it to the `ResponseWriter` between each, which sounds like you already have a pattern to do what you want. There is no data "carried" by the default response writer, that is up to you to maintain that context. Think of it as a `net.Conn`, you cannot go and inspect what you have already written. – JimB Mar 26 '21 at 19:34
  • @MakisPapapanagiotou that's been answered for you several times already. *The data is not carried by the reponse writer*. It is sent to the client by the response writer. If you want to do anything else with it, the response writer *is not* the solution. – Adrian Mar 26 '21 at 19:54
  • If you check the internal implementation of the http.ResponseWriter is implemented by http.response which holds a member to interface io.ReadCloser (the response actually). I was expecting in some way to have a way to access somehow these internal data. But so far it seems not possble. – Makis Papapanagiotou Mar 26 '21 at 20:47
  • 2
    @MakisPapapanagiotou: the only `io.ReadCloser` within the default response data structure is the request body, which has nothing to do with the response data. Writing data goes through a `buffo.Writer`, but nothing that stores the full response. – JimB Mar 26 '21 at 21:09
  • You are right...my mistake... i read reqBody as resBody !!! – Makis Papapanagiotou Mar 26 '21 at 21:28

1 Answers1

0

A ResponseWriter may not be used after the Handler.ServeHTTP method has returned. check the doc here. ResponseWriter is a sort of output chanel so you can't read nothing from it. Here is suggested to use a io.MultiWriter so you can duplicate the output and log what you need.

Ad Fortia
  • 333
  • 1
  • 3
  • 12
  • But I have not returned from Handler.ServeHTTP. The Logger is just another Handler. It is a chained handler logic. You may have missed the point that it is next.ServeHTTP it is not the final one – Makis Papapanagiotou Mar 26 '21 at 17:06
  • I had already seen this post and I was also doing the same but it seems that it is only duplicating the Writer. The bytes.Buffer always remain empty. So I still have a writer but not the actual data. I am starting thinking that what Volker suggested above might be the only solution – Makis Papapanagiotou Mar 26 '21 at 17:54