Source File
url.go
Belonging Package
net/url
package url
import (
)
type Error struct {
Op string
URL string
Err error
}
func ( *Error) () error { return .Err }
func ( *Error) () string { return fmt.Sprintf("%s %q: %s", .Op, .URL, .Err) }
func ( *Error) () bool {
, := .Err.(interface {
() bool
})
return && .()
}
func ( *Error) () bool {
, := .Err.(interface {
() bool
})
return && .()
}
const upperhex = "0123456789ABCDEF"
func ( byte) bool {
switch {
case '0' <= && <= '9':
return true
case 'a' <= && <= 'f':
return true
case 'A' <= && <= 'F':
return true
}
return false
}
func ( byte) byte {
switch {
case '0' <= && <= '9':
return - '0'
case 'a' <= && <= 'f':
return - 'a' + 10
case 'A' <= && <= 'F':
return - 'A' + 10
}
return 0
}
type encoding int
const (
encodePath encoding = 1 + iota
encodePathSegment
encodeHost
encodeZone
encodeUserPassword
encodeQueryComponent
encodeFragment
)
type EscapeError string
func ( EscapeError) () string {
return "invalid URL escape " + strconv.Quote(string())
}
type InvalidHostError string
func ( InvalidHostError) () string {
return "invalid character " + strconv.Quote(string()) + " in host name"
}
if 'a' <= && <= 'z' || 'A' <= && <= 'Z' || '0' <= && <= '9' {
return false
}
switch {
return == '?'
return == '/' || == ';' || == ',' || == '?'
return == '@' || == '/' || == '?' || == ':'
return true
return false
}
}
switch {
case '!', '(', ')', '*':
return false
}
}
return true
}
func ( string) (string, error) {
return unescape(, encodeQueryComponent)
}
func ( string) (string, error) {
return unescape(, encodePathSegment)
}
if == encodeHost && unhex([+1]) < 8 && [:+3] != "%25" {
return "", EscapeError([ : +3])
}
:= unhex([+1])<<4 | unhex([+2])
if [:+3] != "%25" && != ' ' && shouldEscape(, encodeHost) {
return "", EscapeError([ : +3])
}
}
+= 3
case '+':
= == encodeQueryComponent
++
default:
if ( == encodeHost || == encodeZone) && [] < 0x80 && shouldEscape([], ) {
return "", InvalidHostError([ : +1])
}
++
}
}
if == 0 && ! {
return , nil
}
var strings.Builder
.Grow(len() - 2*)
for := 0; < len(); ++ {
switch [] {
case '%':
.WriteByte(unhex([+1])<<4 | unhex([+2]))
+= 2
case '+':
if == encodeQueryComponent {
.WriteByte(' ')
} else {
.WriteByte('+')
}
default:
.WriteByte([])
}
}
return .String(), nil
}
func ( string) string {
return escape(, encodeQueryComponent)
}
func ( string) string {
return escape(, encodePathSegment)
}
func ( string, encoding) string {
, := 0, 0
for := 0; < len(); ++ {
:= []
if shouldEscape(, ) {
if == ' ' && == encodeQueryComponent {
++
} else {
++
}
}
}
if == 0 && == 0 {
return
}
var [64]byte
var []byte
:= len() + 2*
if <= len() {
= [:]
} else {
= make([]byte, )
}
if == 0 {
copy(, )
for := 0; < len(); ++ {
if [] == ' ' {
[] = '+'
}
}
return string()
}
:= 0
for := 0; < len(); ++ {
switch := []; {
case == ' ' && == encodeQueryComponent:
[] = '+'
++
case shouldEscape(, ):
[] = '%'
[+1] = upperhex[>>4]
[+2] = upperhex[&15]
+= 3
default:
[] = []
++
}
}
return string()
}
type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path string // path (relative paths may omit leading slash)
RawPath string // encoded path hint (see EscapedPath method)
ForceQuery bool // append a query ('?') even if RawQuery is empty
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
RawFragment string // encoded fragment hint (see EscapedFragment method)
}
func ( *Userinfo) () string {
if == nil {
return ""
}
:= escape(.username, encodeUserPassword)
if .passwordSet {
+= ":" + escape(.password, encodeUserPassword)
}
return
}
if := .setPath(); != nil {
return nil,
}
return , nil
}
func ( string) ( *Userinfo, string, error) {
:= strings.LastIndex(, "@")
if < 0 {
, = parseHost()
} else {
, = parseHost([+1:])
}
if != nil {
return nil, "",
}
if < 0 {
return nil, , nil
}
:= [:]
if !validUserinfo() {
return nil, "", errors.New("net/url: invalid userinfo")
}
if !strings.Contains(, ":") {
if , = unescape(, encodeUserPassword); != nil {
return nil, "",
}
= User()
} else {
, := split(, ':', true)
if , = unescape(, encodeUserPassword); != nil {
return nil, "",
}
if , = unescape(, encodeUserPassword); != nil {
return nil, "",
}
= UserPassword(, )
}
return , , nil
}
:= strings.Index([:], "%25")
if >= 0 {
, := unescape([:], encodeHost)
if != nil {
return "",
}
, := unescape([:], encodeZone)
if != nil {
return "",
}
, := unescape([:], encodeHost)
if != nil {
return "",
}
return + + , nil
}
} else if := strings.LastIndex(, ":"); != -1 {
:= [:]
if !validOptionalPort() {
return "", fmt.Errorf("invalid port %q after host", )
}
}
var error
if , = unescape(, encodeHost); != nil {
return "",
}
return , nil
}
func ( *URL) () string {
if .RawPath != "" && validEncoded(.RawPath, encodePath) {
, := unescape(.RawPath, encodePath)
if == nil && == .Path {
return .RawPath
}
}
if .Path == "*" {
return "*" // don't escape (Issue 11202)
}
return escape(.Path, encodePath)
}
switch [] {
default:
if shouldEscape([], ) {
return false
}
}
}
return true
}
.RawFragment = ""
} else {
.RawFragment =
}
return nil
}
func ( *URL) () string {
if .RawFragment != "" && validEncoded(.RawFragment, encodeFragment) {
, := unescape(.RawFragment, encodeFragment)
if == nil && == .Fragment {
return .RawFragment
}
}
return escape(.Fragment, encodeFragment)
}
func ( *URL) () string {
var strings.Builder
if .Scheme != "" {
.WriteString(.Scheme)
.WriteByte(':')
}
if .Opaque != "" {
.WriteString(.Opaque)
} else {
if .Scheme != "" || .Host != "" || .User != nil {
if .Host != "" || .Path != "" || .User != nil {
.WriteString("//")
}
if := .User; != nil {
.WriteString(.String())
.WriteByte('@')
}
if := .Host; != "" {
.WriteString(escape(, encodeHost))
}
}
:= .EscapedPath()
if != "" && [0] != '/' && .Host != "" {
.WriteByte('/')
}
if := strings.IndexByte(, ':'); > -1 && strings.IndexByte([:], '/') == -1 {
.WriteString("./")
}
}
.WriteString()
}
if .ForceQuery || .RawQuery != "" {
.WriteByte('?')
.WriteString(.RawQuery)
}
if .Fragment != "" {
.WriteByte('#')
.WriteString(.EscapedFragment())
}
return .String()
}
func ( string) (Values, error) {
:= make(Values)
:= parseQuery(, )
return ,
}
func ( Values, string) ( error) {
for != "" {
:=
if := strings.IndexAny(, "&;"); >= 0 {
, = [:], [+1:]
} else {
= ""
}
if == "" {
continue
}
:= ""
if := strings.Index(, "="); >= 0 {
, = [:], [+1:]
}
, := QueryUnescape()
if != nil {
if == nil {
=
}
continue
}
, = QueryUnescape()
if != nil {
if == nil {
=
}
continue
}
[] = append([], )
}
return
}
func ( Values) () string {
if == nil {
return ""
}
var strings.Builder
:= make([]string, 0, len())
for := range {
= append(, )
}
sort.Strings()
for , := range {
:= []
:= QueryEscape()
for , := range {
if .Len() > 0 {
.WriteByte('&')
}
.WriteString()
.WriteByte('=')
.WriteString(QueryEscape())
}
}
return .String()
}
continue
}
if == ".." {
:= .String()
:= strings.LastIndexByte(, '/')
.Reset()
if == -1 {
= true
} else {
.WriteString([:])
}
} else {
if ! {
.WriteByte('/')
}
.WriteString()
= false
}
}
if == "." || == ".." {
.WriteByte('/')
}
return "/" + strings.TrimPrefix(.String(), "/")
}
.setPath(resolvePath(.EscapedPath(), ""))
return &
}
if .Opaque != "" {
.User = nil
.Host = ""
.Path = ""
return &
}
if .Path == "" && .RawQuery == "" {
.RawQuery = .RawQuery
if .Fragment == "" {
.Fragment = .Fragment
.RawFragment = .RawFragment
}
.Host = .Host
.User = .User
.setPath(resolvePath(.EscapedPath(), .EscapedPath()))
return &
}
func ( *URL) () Values {
, := ParseQuery(.RawQuery)
return
}
func ( *URL) () string {
:= .Opaque
if == "" {
= .EscapedPath()
if == "" {
= "/"
}
} else {
if strings.HasPrefix(, "//") {
= .Scheme + ":" +
}
}
if .ForceQuery || .RawQuery != "" {
+= "?" + .RawQuery
}
return
}
func ( *URL) () string {
, := splitHostPort(.Host)
return
}
func ( *URL) () string {
, := splitHostPort(.Host)
return
}
func ( string) (, string) {
=
:= strings.LastIndexByte(, ':')
if != -1 && validOptionalPort([:]) {
, = [:], [+1:]
}
if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") {
= [1 : len()-1]
}
return
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |