github.com/grailbio/base@v0.0.11/web/webutil/host.go (about) 1 // Copyright 2018 GRAIL, Inc. All rights reserved. 2 // Use of this source code is governed by the Apache-2.0 3 // license that can be found in the LICENSE file. 4 5 package webutil 6 7 import ( 8 "net" 9 "strings" 10 ) 11 12 // CanonicalizeHost accepts a server host name as typically encountered by web 13 // server and generally obtained from the http request Host header field and 14 // canonicalizes it into: 15 // fqhp - fully qualified host+domain with a port - ie: host.domain:port 16 // fqh - fully qualified host+domain without a port - ie: host.domain 17 // host - the hostname, i.e. the first component of a . separated name 18 // domain - the second and subsequent components of a . separated name 19 // port - the port. 20 // 21 // It is generally used for constructing redirects, determine/scoping 22 // cookie names etc. 23 // 24 // The server name can be in any of the forms accepted by a web browser: 25 // 1. [<protocol>://]<ip-addr>[:port] 26 // 2. [<protocol>://]<name>[:<port>] 27 // 3. [<protocol>://]<name>[.<subdomain>]+[:<port>] 28 // The defaultDomain and defaultPort, if not "", will be used if there is 29 // no domain or port in hostName. 30 func CanonicalizeHost(hostName, defaultDomain, defaultPort string) (protocol, fqhp, fqh, host, domain, port string, hosterr error) { 31 32 if idx := strings.Index(hostName, "//"); idx >= 0 { 33 protocol = hostName[:idx] 34 hostName = hostName[idx+len("//"):] 35 } 36 37 h, p, err := net.SplitHostPort(hostName) 38 if err == nil { 39 // There is a port. 40 port = p 41 host = h 42 } else { 43 // There is no port, or there is some kind of other error, so 44 // we append a port and split again to see if it's an error. 45 _, _, err := net.SplitHostPort(net.JoinHostPort(hostName, "80")) 46 if err != nil { 47 hosterr = err 48 host = "" 49 return 50 } 51 host = hostName 52 } 53 if len(port) == 0 { 54 port = defaultPort 55 } 56 // host without port and port are now determined. 57 58 jhp := func(h, p string) string { 59 if len(p) > 0 { 60 return net.JoinHostPort(h, p) 61 } 62 return h 63 } 64 65 if net.ParseIP(host) != nil { 66 // an IP address 67 fqhp = jhp(host, port) 68 fqh = host 69 host = host 70 return 71 } 72 73 if dot := strings.Index(host, "."); dot >= 0 { 74 // we have a domain... 75 fqhp = jhp(host, port) 76 fqh = host 77 host, domain = host[:dot], host[dot+1:] 78 return 79 } 80 // use default domain 81 domain = strings.TrimPrefix(defaultDomain, ".") 82 if len(domain) > 0 { 83 fqh = host + "." + domain 84 fqhp = jhp(fqh, port) 85 return 86 } 87 fqhp = jhp(host, port) 88 fqh = host 89 return 90 }