// parseURL parses the URL. The url.Parse function is not used here because // url.Parse mangles the path. func parseURL(s string) (*url.URL, error) { // From the RFC: // // ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ] // wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ] // // We don't use the net/url parser here because the dialer interface does // not provide a way for applications to work around percent deocding in // the net/url parser. var u url.URL switch { case strings.HasPrefix(s, "ws://"): u.Scheme = "ws" s = s[len("ws://"):] case strings.HasPrefix(s, "wss://"): u.Scheme = "wss" s = s[len("wss://"):] default: return nil, errMalformedURL } u.Host = s u.Opaque = "/" if i := strings.Index(s, "/"); i >= 0 { u.Host = s[:i] u.Opaque = s[i:] } return &u, nil }
// parseURL parses the URL. // // This function is a replacement for the standard library url.Parse function. // In Go 1.4 and earlier, url.Parse loses information from the path. func parseURL(s string) (*url.URL, error) { // From the RFC: // // ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ] // wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ] var u url.URL switch { case strings.HasPrefix(s, "ws://"): u.Scheme = "ws" s = s[len("ws://"):] case strings.HasPrefix(s, "wss://"): u.Scheme = "wss" s = s[len("wss://"):] default: return nil, errMalformedURL } u.Host = s u.Opaque = "/" if i := strings.Index(s, "/"); i >= 0 { u.Host = s[:i] u.Opaque = s[i:] } if strings.Contains(u.Host, "@") { // Don't bother parsing user information because user information is // not allowed in websocket URIs. return nil, errMalformedURL } return &u, nil }
func updatePath(url *url.URL, urlPath string) { scheme, query := url.Scheme, url.RawQuery // get formatted URL minus scheme so we can build this into Opaque url.Scheme, url.Path, url.RawQuery = "", "", "" s := url.String() url.Scheme = scheme url.RawQuery = query // build opaque URI url.Opaque = s + urlPath }
func updatePath(url *url.URL, urlPath string) { scheme, query := url.Scheme, url.RawQuery hasSlash := strings.HasSuffix(urlPath, "/") // clean up path urlPath = path.Clean(urlPath) if hasSlash && !strings.HasSuffix(urlPath, "/") { urlPath += "/" } // get formatted URL minus scheme so we can build this into Opaque url.Scheme, url.Path, url.RawQuery = "", "", "" s := url.String() url.Scheme = scheme url.RawQuery = query // build opaque URI url.Opaque = s + urlPath }
func updatePath(url *url.URL, urlPath string) { scheme, query := url.Scheme, url.RawQuery //path.Clean会去掉最后的斜杠,导致无法创建目录。所以添加以下逻辑 add := false if urlPath[len(urlPath)-1] == '/' && len(urlPath) > 1 { add = true } // clean up path urlPath = path.Clean(urlPath) if add { urlPath += "/" } // get formatted URL minus scheme so we can build this into Opaque url.Scheme, url.Path, url.RawQuery = "", "", "" s := url.String() url.Scheme = scheme url.RawQuery = query // build opaque URI url.Opaque = s + urlPath }
// SetOpaque sets u.Opaque from u.Path such that HTTP requests to it // don't alter any hex-escaped characters in u.Path. func SetOpaque(u *url.URL) { u.Opaque = "//" + u.Host + u.Path if !has4860Fix { u.Opaque = u.Scheme + ":" + u.Opaque } }
func (self *Client) addToUrl(u *url.URL, s string) *url.URL { u.Opaque = fmt.Sprintf("%s/%s", u.Opaque, s) return u }
func pushURL(l *lua.State, u *url.URL) { l.NewTable() var urlFunc = map[string]func(*url.URL) lua.Function{ "isAbs": urlIsAbs, "parse": urlParse, "requestURI": urlRequestURI, "string": urlString, } for name, goFn := range urlFunc { l.PushGoFunction(goFn(u)) l.SetField(-2, name) } l.NewTable() getHook := func(l *lua.State) int { key := lua.CheckString(l, 2) switch key { case "scheme": l.PushString(u.Scheme) case "opaque": l.PushString(u.Opaque) case "host": l.PushString(u.Host) case "path": l.PushString(u.Path) case "rawQuery": l.PushString(u.RawQuery) case "fragment": l.PushString(u.Fragment) default: return 0 } return 1 } l.PushGoFunction(getHook) l.SetField(-2, "__index") setHook := func(l *lua.State) int { key := lua.CheckString(l, 2) val := lua.CheckString(l, 3) switch key { case "scheme": u.Scheme = val case "opaque": u.Opaque = val case "host": u.Host = val case "path": u.Path = val case "rawQuery": u.RawQuery = val case "fragment": u.Fragment = val default: l.RawSet(1) } return 0 } l.PushGoFunction(setHook) l.SetField(-2, "__newindex") l.SetMetaTable(-2) }
func addToURL(u *url.URL, s string) *url.URL { u.Opaque = fmt.Sprintf("%s/%s", u.Opaque, s) return u }
func (conn Conn) doRequest(method string, uri *url.URL, canonicalizedResource string, headers map[string]string, data io.Reader) (*Response, error) { httpTimeOut := conn.config.HTTPTimeout method = strings.ToUpper(method) uri.Opaque = uri.Path req := &http.Request{ Method: method, URL: uri, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: make(http.Header), Host: uri.Host, } conn.handleBody(req, data) date := time.Now().UTC().Format(http.TimeFormat) req.Header.Set(HTTPHeaderDate, date) req.Header.Set(HTTPHeaderHost, conn.config.Endpoint) req.Header.Set(HTTPHeaderUserAgent, conn.config.UserAgent) if conn.config.SecurityToken != "" { req.Header.Set(HTTPHeaderOssSecurityToken, conn.config.SecurityToken) } if headers != nil { for k, v := range headers { req.Header.Set(k, v) } } conn.signHeader(req, canonicalizedResource) timeoutClient := &http.Client{Transport: &http.Transport{ Dial: func(netw, addr string) (net.Conn, error) { conn, err := net.DialTimeout(netw, addr, httpTimeOut.ConnectTimeout) if err != nil { return nil, err } return newTimeoutConn(conn, httpTimeOut.ReadWriteTimeout, httpTimeOut.LongTimeout), nil }, ResponseHeaderTimeout: httpTimeOut.HeaderTimeout, MaxIdleConnsPerHost: 2000, }} resp, err := timeoutClient.Do(req) if err != nil { return nil, err } return conn.handleResponse(resp) }