33 lines
1.0 KiB
Go
33 lines
1.0 KiB
Go
// Package secureurl holds the one transport rule for URLs that carry
|
|||
|
|
// credentials or session cookies: HTTPS, or plain HTTP to a loopback host for
|
||
|
|
// local development and tests.
|
||
|
|
package secureurl
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"net/url"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// loopbackHosts are the only hosts plain HTTP is allowed for, compared
|
||
|
|
// case-insensitively. url.URL's Hostname strips the brackets from "[::1]".
|
||
|
|
var loopbackHosts = map[string]bool{"localhost": true, "127.0.0.1": true, "::1": true}
|
||
|
|
|
||
|
|
// Check reports an error unless u is an absolute https:// URL, or an http://
|
||
|
|
// URL whose host is localhost, 127.0.0.1 or ::1.
|
||
|
|
func Check(u *url.URL) error {
|
||
|
|
switch {
|
||
|
|
case u.Hostname() == "":
|
||
|
|
return errors.New("URL has no host")
|
||
|
|
case u.Scheme == "https":
|
||
|
|
return nil
|
||
|
|
case u.Scheme == "http" && loopbackHosts[strings.ToLower(u.Hostname())]:
|
||
|
|
return nil
|
||
|
|
case u.Scheme == "http":
|
||
|
|
return errors.New("plain http:// is allowed only for localhost, 127.0.0.1 or [::1]; use https://")
|
||
|
|
default:
|
||
|
|
return fmt.Errorf("unsupported scheme %q (want https://)", u.Scheme)
|
||
|
|
}
|
||
|
|
}
|