github.com/aavshr/aws-sdk-go@v1.41.3/private/protocol/host.go (about) 1 package protocol 2 3 import ( 4 "github.com/aavshr/aws-sdk-go/aws/request" 5 "net" 6 "strconv" 7 "strings" 8 ) 9 10 // ValidateEndpointHostHandler is a request handler that will validate the 11 // request endpoint's hosts is a valid RFC 3986 host. 12 var ValidateEndpointHostHandler = request.NamedHandler{ 13 Name: "awssdk.protocol.ValidateEndpointHostHandler", 14 Fn: func(r *request.Request) { 15 err := ValidateEndpointHost(r.Operation.Name, r.HTTPRequest.URL.Host) 16 if err != nil { 17 r.Error = err 18 } 19 }, 20 } 21 22 // ValidateEndpointHost validates that the host string passed in is a valid RFC 23 // 3986 host. Returns error if the host is not valid. 24 func ValidateEndpointHost(opName, host string) error { 25 paramErrs := request.ErrInvalidParams{Context: opName} 26 27 var hostname string 28 var port string 29 var err error 30 31 if strings.Contains(host, ":") { 32 hostname, port, err = net.SplitHostPort(host) 33 34 if err != nil { 35 paramErrs.Add(request.NewErrParamFormat("endpoint", err.Error(), host)) 36 } 37 38 if !ValidPortNumber(port) { 39 paramErrs.Add(request.NewErrParamFormat("endpoint port number", "[0-65535]", port)) 40 } 41 } else { 42 hostname = host 43 } 44 45 labels := strings.Split(hostname, ".") 46 for i, label := range labels { 47 if i == len(labels)-1 && len(label) == 0 { 48 // Allow trailing dot for FQDN hosts. 49 continue 50 } 51 52 if !ValidHostLabel(label) { 53 paramErrs.Add(request.NewErrParamFormat( 54 "endpoint host label", "[a-zA-Z0-9-]{1,63}", label)) 55 } 56 } 57 58 if len(hostname) == 0 { 59 paramErrs.Add(request.NewErrParamMinLen("endpoint host", 1)) 60 } 61 62 if len(hostname) > 255 { 63 paramErrs.Add(request.NewErrParamMaxLen( 64 "endpoint host", 255, host, 65 )) 66 } 67 68 if paramErrs.Len() > 0 { 69 return paramErrs 70 } 71 return nil 72 } 73 74 // ValidHostLabel returns if the label is a valid RFC 3986 host label. 75 func ValidHostLabel(label string) bool { 76 if l := len(label); l == 0 || l > 63 { 77 return false 78 } 79 for _, r := range label { 80 switch { 81 case r >= '0' && r <= '9': 82 case r >= 'A' && r <= 'Z': 83 case r >= 'a' && r <= 'z': 84 case r == '-': 85 default: 86 return false 87 } 88 } 89 90 return true 91 } 92 93 // ValidPortNumber return if the port is valid RFC 3986 port 94 func ValidPortNumber(port string) bool { 95 i, err := strconv.Atoi(port) 96 if err != nil { 97 return false 98 } 99 100 if i < 0 || i > 65535 { 101 return false 102 } 103 return true 104 }