Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/http: http.ListenAndServeTLS lowercasing request header keys #15472

Closed
deankarn opened this issue Apr 27, 2016 · 3 comments
Closed

net/http: http.ListenAndServeTLS lowercasing request header keys #15472

deankarn opened this issue Apr 27, 2016 · 3 comments

Comments

@deankarn
Copy link

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)?
go version go1.6.2 darwin/amd64
  1. What operating system and processor architecture are you using (go env)?
GOARCH="amd64"
GOBIN="/Users/dean/.go/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/dean/.go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.6.2/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.6.2/libexec/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT="1"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"
  1. What did you do?

unfortunately I could not make a runnable example, a valid SSL Certificate seems to be needed to recreate this issue, using:

tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}

client := &http.Client{Transport: tr}

or

tlsConfig := &tls.Config{
    Certificates: make([]tls.Certificate, 1),
}

tlsConfig.Certificates[0], err = tls.X509KeyPair([]byte(httpPem), []byte(httpKey))
if err != nil {
    log.Fatal(err)
}
server = &http.Server{Addr: port, Handler: handler, TLSConfig: tlsConfig}
server.ListenAndServeTLS("","")

the issue does not occur, only using the http.ListenAndServerTLS that I could find so far. below is what causes the issue (need to use your own Cretificates + URL.

package main

import (
    "errors"
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
    go server()

    time.Sleep(3000)

    req, err := http.NewRequest("GET", "https://localhost:8080", nil)
    if err != nil {
        log.Fatal(errors.New("Error Creating Request:" + err.Error()))
    }

    req.Header.Set("UPDATE_API_KEY", "Efewfjnewjkfewjkfew")

    // tr := &http.Transport{
    //  TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    // }

    // client := &http.Client{Transport: tr}

    // This issue is very specific, using the code above actually works as expected
    client := &http.Client{}

    _, err = client.Do(req)
    if err != nil {
        log.Fatal(fmt.Sprint("ERROR Fetching Updates:", err))
    }
}

func server() {

    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Println(r.Header)
    })

    http.ListenAndServeTLS(":8080", "path to certFile", "path to keyFile", handler)
}

Go 1.6 does not have this issue, either patch 1.6.1 or 1.6.2 caused this.

  1. What did you expect to see?
map[User-Agent:[Go-http-client/1.1] UPDATE_API_KEY:[Efewfjnewjkfewjkfew] Accept-Encoding:[gzip]]

map key of "UPDATE_API_KEY" is correct
  1. What did you see instead?
map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/2.0] update_api_key:[Efewfjnewjkfewjkfew]]

map key of "update_api_key" is not correct
@bradfitz
Copy link
Contributor

The difference is HTTP/2. With HTTP/2, all header fields must be sent lowercase, mandated by the spec. In HTTP/1 any case is allowed, and they should be compared case-insensitively.

Go tries to map things into their Go-canonical form via https://golang.org/pkg/net/http/#CanonicalHeaderKey but because it has an underscore in it, Go does nothing (but fixed in Go 1.7).

I'd recommend using a hyphen instead of an underscore if possible. Otherwise you'll have to enumerate over the map keys looking for the "UpDaTE_api_KEY" yourself, normalizing the case of the keys as you look.

@bradfitz
Copy link
Contributor

Btw, b24c6fb (issue #13767) was the commit which fixed this. It will be included in Go 1.7.

@deankarn
Copy link
Author

Thanks 👍

@golang golang locked and limited conversation to collaborators Apr 27, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants