normalize_url.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package internal
  2. import (
  3. "net/url"
  4. "regexp"
  5. "strings"
  6. )
  7. const (
  8. defaultHTTPPort = ":80"
  9. defaultHTTPSPort = ":443"
  10. )
  11. // Regular expressions used by the normalizations
  12. var rxPort = regexp.MustCompile(`(:\d+)/?$`)
  13. var rxDupSlashes = regexp.MustCompile(`/{2,}`)
  14. // NormalizeURL will normalize the specified URL
  15. // This was added to replace a previous call to the no longer maintained purell library:
  16. // The call that was used looked like the following:
  17. //
  18. // url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes))
  19. //
  20. // To explain all that was included in the call above, purell.FlagsSafe was really just the following:
  21. // - FlagLowercaseScheme
  22. // - FlagLowercaseHost
  23. // - FlagRemoveDefaultPort
  24. // - FlagRemoveDuplicateSlashes (and this was mixed in with the |)
  25. //
  26. // This also normalizes the URL into its urlencoded form by removing RawPath and RawFragment.
  27. func NormalizeURL(u *url.URL) {
  28. lowercaseScheme(u)
  29. lowercaseHost(u)
  30. removeDefaultPort(u)
  31. removeDuplicateSlashes(u)
  32. u.RawPath = ""
  33. u.RawFragment = ""
  34. }
  35. func lowercaseScheme(u *url.URL) {
  36. if len(u.Scheme) > 0 {
  37. u.Scheme = strings.ToLower(u.Scheme)
  38. }
  39. }
  40. func lowercaseHost(u *url.URL) {
  41. if len(u.Host) > 0 {
  42. u.Host = strings.ToLower(u.Host)
  43. }
  44. }
  45. func removeDefaultPort(u *url.URL) {
  46. if len(u.Host) > 0 {
  47. scheme := strings.ToLower(u.Scheme)
  48. u.Host = rxPort.ReplaceAllStringFunc(u.Host, func(val string) string {
  49. if (scheme == "http" && val == defaultHTTPPort) || (scheme == "https" && val == defaultHTTPSPort) {
  50. return ""
  51. }
  52. return val
  53. })
  54. }
  55. }
  56. func removeDuplicateSlashes(u *url.URL) {
  57. if len(u.Path) > 0 {
  58. u.Path = rxDupSlashes.ReplaceAllString(u.Path, "/")
  59. }
  60. }