url.ForceQuery = true
rest = rest[:len(rest)-1]
} else {
- var q string
- rest, q = split(rest, "?", true)
- if validQuery(q) {
- url.RawQuery = q
- } else {
- url.RawQuery = QueryEscape(q)
- }
+ rest, url.RawQuery = split(rest, "?", true)
}
if !strings.HasPrefix(rest, "/") {
}
return true
}
-
-// validQuery reports whether s is a valid query string per RFC 3986
-// Section 3.4:
-// query = *( pchar / "/" / "?" )
-// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
-// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
-// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
-// / "*" / "+" / "," / ";" / "="
-func validQuery(s string) bool {
- pctEnc := 0
-
- for _, r := range s {
- if pctEnc > 0 {
- if uint32(r) > 255 || !ishex(byte(r)) {
- return false
- }
- pctEnc--
- continue
- } else if r == '%' {
- pctEnc = 2
- continue
- }
-
- if 'A' <= r && r <= 'Z' {
- continue
- }
- if 'a' <= r && r <= 'z' {
- continue
- }
- if '0' <= r && r <= '9' {
- continue
- }
- switch r {
- case '-', '.', '_', '~', '!', '$', '&', '\'', '(', ')',
- '*', '+', ',', ';', '=', ':', '@', '/', '?':
- continue
- default:
- return false
- }
- }
-
- return true
-}
},
"mailto:?subject=hi",
},
- {
- "https://example.com/search?q=Фотки собак&source=lnms",
- &URL{
- Scheme: "https",
- Host: "example.com",
- Path: "/search",
- RawQuery: "q%3D%D0%A4%D0%BE%D1%82%D0%BA%D0%B8+%D1%81%D0%BE%D0%B1%D0%B0%D0%BA%26source%3Dlnms",
- },
- "https://example.com/search?q%3D%D0%A4%D0%BE%D1%82%D0%BA%D0%B8+%D1%81%D0%BE%D0%B1%D0%B0%D0%BA%26source%3Dlnms",
- },
}
// more useful string for debugging than fmt's struct printer
{"cache_object:foo", true},
{"cache_object:foo/bar", true},
{"cache_object/:foo/bar", false},
- {"https://example.com/search?q=Фотки собак&source=lnms", false},
}
for _, tt := range tests {
u, err := Parse(tt.in)