thinkski
thinkski

Reputation: 1302

Handling request with chunked transfer-encoding

Does golang's net/http package support requests with chunked transfer-encoding? Thus far I have been able to use the Hijacker interface (https://golang.org/src/net/http/server.go?s=6173:6875#L156) to at least not close the connection and receive the full chunked request, but not yet parsing the chunks and suspect I may be going down the wrong path with this.

From https://golang.org/src/net/http/httputil/httputil.go?s=688:732#L10, I see there is a chunked reader, but appears to be for internal use.

Essentially, I'm trying to accept an HTTP PUT with 'chunked' transfer-encoding and send it off to a backend server 'on-the-fly' (i.e. without buffering the full request in golang). I have no control over the upstream request. Is there a recommended way to handle such a request, or is Hijacker the way to do it?

Upvotes: 1

Views: 5168

Answers (1)

Thundercat
Thundercat

Reputation: 120951

The net/http client and server transparently read and write chunked bodies.

To accept a chunked request and send it to another HTTP server, pass the server request body as the client request body. Here's now to forward the body to another server as a PUT:

 func handler(w http.ResponseWriter, r *http.Request) {
    creq, err := http.NewRequest("PUT", url, r.Body)
    if err != nil {
       // handle error
    }
    if ct := r.Header.Get("Content-Type"); ct != "" {
        creq.Header.Set("Content-Type", ct)
    }
    cresp, err := http.DefaultClient.Do(creq)
    if err != nil {
        // handle error
    }
    ... do something with cresp.
 }

If you want to copy to a file, then io.Copy the request body to the file.

 func handler(w http.ResponseWriter, r *http.Request) {
     f, err := os.Create("fname")
     if err != nil {
         // handle error
     }
     _, err := io.Copy(f, r.Body)
     if err != nil {
          // handle error
     }
     ...
  }

These snippets copy the body 'on the fly'.

Upvotes: 5

Related Questions