parseURL parses s as a URL, handling URLs that have been munged by path.Clean or a webserver that collapses multiple slashes. The returned enc bool indicates whether the remote URL was encoded.
(s string, baseURL *url.URL)
| 404 | // path.Clean or a webserver that collapses multiple slashes. |
| 405 | // The returned enc bool indicates whether the remote URL was encoded. |
| 406 | func parseURL(s string, baseURL *url.URL) (_ *url.URL, enc bool, _ error) { |
| 407 | // Try to base64 decode the string. If it is not base64 encoded, |
| 408 | // this will fail quickly on the first invalid character like ":", ".", or "/". |
| 409 | // Accept the decoded string if it looks like an absolute HTTP URL, |
| 410 | // or if we have a baseURL and the decoded string did not contain invalid code points. |
| 411 | // This allows for values like "/path", which do successfully base64 decode, |
| 412 | // but not to valid code points, to be treated as an unencoded string. |
| 413 | if b, err := base64.RawURLEncoding.DecodeString(s); err == nil { |
| 414 | d := string(b) |
| 415 | if strings.HasPrefix(d, "http://") || strings.HasPrefix(d, "https://") { |
| 416 | enc = true |
| 417 | s = d |
| 418 | } else if baseURL != nil && !strings.ContainsRune(d, unicode.ReplacementChar) { |
| 419 | enc = true |
| 420 | s = d |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | // If the string looks like a URL encoded absolute HTTP(S) URL, decode it. |
| 425 | if reIsEncodedURL.MatchString(s) { |
| 426 | if u, err := url.PathUnescape(s); err == nil { |
| 427 | enc = true |
| 428 | s = u |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | s = reCleanedURL.ReplaceAllString(s, "$1://$2") |
| 433 | u, err := url.Parse(s) |
| 434 | return u, enc, err |
| 435 | } |