func TestRequestBadHost(t *testing.T) {
got := []string{}
- req, err := NewRequest("GET", "http://foo.com with spaces/after", nil)
+ req, err := NewRequest("GET", "http://foo/after", nil)
if err != nil {
t.Fatal(err)
}
+ req.Host = "foo.com with spaces"
+ req.URL.Host = "foo.com with spaces"
req.Write(logWrites{t, &got})
want := []string{
"GET /after HTTP/1.1\r\n",
return "invalid URL escape " + strconv.Quote(string(e))
}
+type InvalidHostError string
+
+func (e InvalidHostError) Error() string {
+ return "invalid character " + strconv.Quote(string(e)) + " in host name"
+}
+
// Return true if the specified character should be escaped when
// appearing in a URL string, according to RFC 3986.
//
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
// as part of reg-name.
// We add : because we include :port as part of host.
- // We add [ ] because we include [ipv6]:port as part of host
+ // We add [ ] because we include [ipv6]:port as part of host.
+ // We add < > because they're the only characters left that
+ // we could possibly allow, and Parse will reject them if we
+ // escape them (because hosts can't use %-encoding for
+ // ASCII bytes).
switch c {
- case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', ':', '[', ']':
+ case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', ':', '[', ']', '<', '>', '"':
return false
}
}
hasPlus = mode == encodeQueryComponent
i++
default:
+ if (mode == encodeHost || mode == encodeZone) && s[i] < 0x80 && shouldEscape(s[i], mode) {
+ return "", InvalidHostError(s[i : i+1])
+ }
i++
}
}
},
"",
},
+ // test that we can reparse the host names we accept.
+ {
+ "myscheme://authority<\"hi\">/foo",
+ &URL{
+ Scheme: "myscheme",
+ Host: "authority<\"hi\">",
+ Path: "/foo",
+ },
+ "",
+ },
}
// more useful string for debugging than fmt's struct printer
{"mysql://x@y(1.2.3.4:123)/foo", false},
{"mysql://x@y([2001:db8::1]:123)/foo", false},
{"http://[]%20%48%54%54%50%2f%31%2e%31%0a%4d%79%48%65%61%64%65%72%3a%20%31%32%33%0a%0a/", true}, // golang.org/issue/11208
+ {"http://a b.com/", true}, // no space in host name please
}
for _, tt := range tests {
u, err := Parse(tt.in)