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/httputil: reverse proxy canonicalizes header names #21868

Closed
hryamzik opened this issue Sep 13, 2017 · 5 comments
Closed

net/http/httputil: reverse proxy canonicalizes header names #21868

hryamzik opened this issue Sep 13, 2017 · 5 comments
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.

Comments

@hryamzik
Copy link

hryamzik commented Sep 13, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go1.8.3

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

any

What did you do?

Served ReverseProxy

What did you expect to see?

Response headers unmodified, for example X-Jenkins-JNLP-Port

What did you see instead?

Broken case for headers: X-Jenkins-Jnlp-Port

I'm not 100% sure but looks like that causes Jenkins agent connection failures:

java.io.IOException: https://myjenkins.net/ is not Jenkins

According to RFC 7230 and RFC 7540 HTTP headers are case-insensitive so I'm not sure if that could be treated as a bug but it appears to be painful.

@mvdan
Copy link
Member

mvdan commented Sep 13, 2017

This is technically not a bug - as you say, headers are case insensitive - so it should be up to the server to accept the same header with different casing. Have you filed a bug with Jenkins?

In practice, I wonder if it would be worthwhile to make the reverse proxy keep the original cases. Does net/http have a history of accomodating to broken software?

@mvdan mvdan added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Sep 13, 2017
@mvdan mvdan changed the title net/http reverse proxy headers net/http/httputil: reverse proxy canonicalizes header names Sep 13, 2017
@hryamzik
Copy link
Author

hryamzik commented Sep 13, 2017

@mvdan I didn't fire a bug in Jenkins yet cause I have to prove the issue first. Figuring out if I could modify header with a middleware and set case-sensitive headers at all.

P.S.: it's not that simple:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("RaNdOmCaSe", "oK")
		fmt.Fprintf(w, "Check out headers! %s\n", r.URL.Path)
	})
	http.Handle("/", h)
	http.ListenAndServe(":8080", nil)
}

Results in Randomcase: oK

P.P.S.: That works: w.Header()["RaNdOmCaSe"] = []string{"oK"}
P.P.P.S.: Developed middleware to rewrite headers and proved it fixed Jenkins. Here's that check.
Jenkins issue.

@tombergan
Copy link
Contributor

Great, sounds like this is an issue in Jenkins, not Go. I'm going to close this.

@hryamzik
Copy link
Author

@tombergan I still don't think modifying header names is a good behaviour. I'm sure Jenkins is not the only software to get headers by simple string comparison and debugging this is tricky.

@tombergan
Copy link
Contributor

Canonicalized header names have been in net/http from the beginning. Any server that relies on case-sensitive names is going to have a very bad time when they switch to http/2. Case-sensitive names are not going to be supported, sorry.

@golang golang locked and limited conversation to collaborators Sep 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

4 participants