Skip to content

net/http: Server sends duplicate Transfer-Encoding: chunked when set explicitly #15960

Closed
@seoester

Description

@seoester

When setting the Transfer-Encoding header to chunked explicitly within a handler for a net/http Server (to trigger chunked encoding), the header field is sent to the client twice.

While this does not break most clients (e.g. Chrome, wget) it is confusing and in discord with RFC 2616:

The "chunked" transfer-coding MUST NOT be applied more than once to a message-body.

The transfer-coding is of course only applied once, just the header is sent twice.

server.go:1148 sets the chunked flag when a Transfer-Encoding is manually set and != "identity".
But Transfer-Encoding is not removed from the header map.
As I understand, this is the generally sought after behaviour, (developers should be able to use custom transfer-codings without interference), with the exception of when Transfer-Encoding is set to chunked.

Later on the Transfer-Encoding header is sent when writing the header map and then again by server.go:1176.

If Transfer-Encoding is simply not meant to be set to chunked to signal the server to chunk the response this should perhaps be pointed out in the documentation.
It does however provide a nice way to enable sending chunked content without use of the Flusher interface (and is very readable), even though so far it is essentially a side effect. Just dropping the explicit header in this case should be fine as HTTP does not allow multiple chunked codings.

  1. What version of Go are you using (go version)?
    go version go1.6.2 linux/amd64
  2. What operating system and processor architecture are you using (go env)?
    GOARCH="amd64"
    GOBIN=""
    GOEXE=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOOS="linux"
    GOPATH=""
    GORACE=""
    GOROOT="/usr/local/go"
    GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
    GO15VENDOREXPERIMENT="1"
    CC="gcc"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
    CXX="g++"
    CGO_ENABLED="1"
  3. What did you do?
package main

import (
    "net/http"
)

func myHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Transfer-Encoding", "chunked")
    w.Write([]byte("Some content..."))
}

func main() {
    http.ListenAndServe(":8080", http.HandlerFunc(myHandler))
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions