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  }