parsers.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package netutil
  2. import (
  3. "net/url"
  4. "strconv"
  5. "strings"
  6. )
  7. const (
  8. httpScheme = "http"
  9. httpsScheme = "https"
  10. tcpScheme = "tcp"
  11. )
  12. // AddressesFromNodes takes a list of node hosts and attempts to return a list of hosts in host:port
  13. // format along with any error encountered.
  14. //
  15. // The function accepts node hosts in URL, ip, ip:port, resolvable-name and resolvable-name:port
  16. // formats and will append the default port value if needed. For hosts where the scheme has been omitted,
  17. // the scheme for the first host will be used. If the first host has no scheme, it will default to http.
  18. func AddressesFromNodes(nodes []string) ([]string, error) {
  19. var addresses []string
  20. var scheme string
  21. for _, node := range nodes {
  22. address := node
  23. // If no scheme present, set the first scheme
  24. if !strings.Contains(address, "://") {
  25. if scheme == "" {
  26. scheme = httpScheme
  27. }
  28. address = strings.Join([]string{scheme, address}, "://")
  29. }
  30. url, err := url.Parse(address)
  31. if err != nil {
  32. return nil, newInvalidNodeError(err)
  33. }
  34. switch url.Scheme {
  35. case tcpScheme:
  36. url.Scheme = httpScheme
  37. fallthrough
  38. case httpScheme, httpsScheme:
  39. if scheme == "" {
  40. scheme = url.Scheme
  41. }
  42. default:
  43. return nil, newInvalidNodeError(errUnsupportedScheme)
  44. }
  45. host := url.Hostname()
  46. if host == "" {
  47. return nil, newInvalidNodeError(errInvalidHostName)
  48. }
  49. port := url.Port()
  50. if port == "" {
  51. port = DefaultDialPort
  52. }
  53. if !validPort(port) {
  54. return nil, newInvalidNodeError(errInvalidPortNumber)
  55. }
  56. addresses = append(addresses, strings.TrimRight(url.String(), "/"))
  57. }
  58. return addresses, nil
  59. }
  60. func validPort(port string) bool {
  61. intPort, err := strconv.Atoi(port)
  62. return (err == nil) &&
  63. (intPort > 0) &&
  64. (intPort <= 65535)
  65. }