func send(req *http.Request) (resp *http.Response, err os.Error) { addr := req.URL.Host if !hasPort(addr) { addr += ":http" } conn, err := net.Dial("tcp", addr) if err != nil { return nil, err } err = req.Write(conn) if err != nil { conn.Close() return nil, err } reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, req.Method) if err != nil { conn.Close() return nil, err } r := io.Reader(reader) if n := resp.ContentLength; n != -1 { r = io.LimitReader(r, n) } resp.Body = readClose{r, conn} return }
func ReadFrom(conn net.Conn, method string) (resp *http.Response, e os.Error) { // Read from and proccess the connection req := new(http.Request) req.Method = method reader := bufio.NewReader(conn) resp, e = http.ReadResponse(reader, req) if e != nil { fmt.Println("Error reading response:", e) } return }
// execute a request; date it, sign it, send it func (bucket *Bucket) Execute(req *http.Request) (resp *http.Response, err os.Error) { // time stamp it date := time.LocalTime().Format(time.RFC1123) req.Header["Date"] = date // sign the request bucket.Sign(req) // open a connection conn, err := net.Dial("tcp", "", req.URL.Host+":"+req.URL.Scheme) if err != nil { return nil, err } // send the request req.Write(conn) // now read the response reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, req.Method) if err != nil { return nil, err } return }
func send(req *http.Request) (resp *http.Response, err os.Error) { addr := req.URL.Host if !hasPort(addr) { addr += ":http" } conn, err := net.Dial("tcp", "", addr) if err != nil { return nil, err } err = req.Write(conn) if err != nil { conn.Close() return nil, err } reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, "GET") if err != nil { conn.Close() return nil, err } r := io.Reader(reader) if v := resp.GetHeader("Content-Length"); v != "" { n, err := strconv.Atoi64(v) if err != nil { // return nil, &badStringError{"invalid Content-Length", v} } r = io.LimitReader(r, n) } resp.Body = readClose{r, conn} return }
/* Handhake described in (soon obsolete) draft-hixie-thewebsocket-protocol-75. */ func draft75handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) { bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n") bw.WriteString("Upgrade: WebSocket\r\n") bw.WriteString("Connection: Upgrade\r\n") bw.WriteString("Host: " + host + "\r\n") bw.WriteString("Origin: " + origin + "\r\n") if protocol != "" { bw.WriteString("WebSocket-Protocol: " + protocol + "\r\n") } bw.WriteString("\r\n") bw.Flush() resp, err := http.ReadResponse(br, "GET") if err != nil { return } if resp.Status != "101 Web Socket Protocol Handshake" { return ErrBadStatus } if resp.Header["Upgrade"] != "WebSocket" || resp.Header["Connection"] != "Upgrade" { return ErrBadUpgrade } if resp.Header["Websocket-Origin"] != origin { return ErrBadWebSocketOrigin } if resp.Header["Websocket-Location"] != location { return ErrBadWebSocketLocation } if protocol != "" && resp.Header["Websocket-Protocol"] != protocol { return ErrBadWebSocketProtocol } return }
func pipeRequestResponse(server, client net.Conn) os.Error { // Read request from wire req, err := http.ReadRequest(bufio.NewReader(client)) if err != nil { return err } rawReq, err := http.DumpRequest(req, true) if err != nil { return err } // forward it on server.Write(rawReq) // Read response from wire resp, err := http.ReadResponse(bufio.NewReader(server), req) if err != nil { return err } rawResp, err := http.DumpResponse(resp, true) if err != nil { return err } log.Printf("%s %s [%s]", req.Method, req.RawURL, resp.Status) // forward it on client.Write(rawResp) return nil }
func (bucket *Bucket) GetFile(file *os.FileInfo) (err os.Error) { url, e := http.ParseURL(bucket.Url + "/" + file.Name) if e != nil { return err } req := &http.Request{Method: "GET", RawURL: bucket.Url + "/" + file.Name, URL: url, Header: make(map[string]string)} date := time.LocalTime().Format(time.RFC1123) req.Header["Date"] = date bucket.sign(req) //req.Write(os.Stdout) conn, err := net.Dial("tcp", "", req.URL.Host+":"+req.URL.Scheme) if err != nil { return err } req.Write(conn) reader := bufio.NewReader(conn) resp, _ := http.ReadResponse(reader, req.Method) //resp.Write(os.Stdout) filename := strings.TrimLeft(url.Path, "/") path := strings.SplitAfter(filename, "/", -1) //pid := os.GetPid() var b []byte b, err = ioutil.ReadAll(resp.Body) if err != nil { return err } mode := (file.Mode & 0777) fmt.Printf("0%o\n", mode) //var dirmode uint32 //dirmode = (syscall.S_IFDIR^0666)&0777 resp.Body.Close() //create file or dir for i := 0; i < len(path); i++ { f := i + 1 if f == len(path) { openfile, err := os.Open(filename, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL, mode) if err != nil { return err } else { openfile.Chown(file.Uid, file.Gid) openfile.Write(b) openfile.Close() os.Chtimes(filename, file.Mtime_ns, file.Mtime_ns) } } else { err := os.Mkdir(path[i], 0755) if err != nil { return err } } } return nil }
func (proxy *Proxy) ServeHTTP(conn *http.Conn, req *http.Request) { // Open a connection to the Hub. hubconn, err := net.Dial("tcp", "", remoteAddr) if err != nil { if debugMode { fmt.Printf("Couldn't connect to remote %s: %v\n", remoteHost, err) } return } hub := tls.Client(hubconn, tlsconf.Config) defer hub.Close() // Modify the request Host: header. req.Host = remoteHost // Send the request to the Hub. err = req.Write(hub) if err != nil { if debugMode { fmt.Printf("Error writing to the hub: %v\n", err) } return } // Parse the response from the Hub. resp, err := http.ReadResponse(bufio.NewReader(hub), req.Method) if err != nil { if debugMode { fmt.Printf("Error parsing response from the hub: %v\n", err) } return } // Set the received headers back to the initial connection. for k, v := range resp.Header { conn.SetHeader(k, v) } // Read the full response body. body, err := ioutil.ReadAll(resp.Body) if err != nil { if debugMode { fmt.Printf("Error reading response from the hub: %v\n", err) } resp.Body.Close() return } // Write the response body back to the initial connection. resp.Body.Close() conn.WriteHeader(resp.StatusCode) conn.Write(body) }
func get(p string, accept string) (r *http.Response, err os.Error) { var conn net.Conn if conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%v", port())); err == nil { req, _ := http.NewRequest("GET", fmt.Sprintf("http://%v", path.Join(fmt.Sprintf("localhost:%v/", port()), p)), nil) req.Header.Set("Accept-Encoding", accept) req.Write(conn) buf := bufio.NewReader(conn) r, err = http.ReadResponse(buf, req) } return }
func send(req *http.Request) (resp *http.Response, err os.Error) { if req.URL.Scheme != "http" && req.URL.Scheme != "https" { return nil, nil } addr := req.URL.Host if !hasPort(addr) { addr += ":" + req.URL.Scheme } /*info := req.URL.Userinfo if len(info) > 0 { enc := base64.URLEncoding encoded := make([]byte, enc.EncodedLen(len(info))) enc.Encode(encoded, []byte(info)) if req.Header == nil { req.Header = make(map[string]string) } req.Header["Authorization"] = "Basic " + string(encoded) } */ var conn io.ReadWriteCloser if req.URL.Scheme == "http" { conn, err = net.Dial("tcp", addr) } else { // https conn, err = tls.Dial("tcp", addr, nil) } if err != nil { return nil, err } err = req.Write(conn) if err != nil { conn.Close() return nil, err } reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, req) if err != nil { conn.Close() return nil, err } resp.Body = readClose{resp.Body, conn} return }
// ReadResponse waits for a signal that the reqid request is complete. // It uses http.ReadResponse to read and return an http.Response object from reqid's // response buffer. // After the response is read, the reqid is freed, and might immediately be used // again for a new request. func (ws *wsConn) ReadResponse(reqid uint16, method string) (ret *http.Response, err os.Error) { <-ws.signals[reqid] // wait for this reqid to be finished defer ws.freeReqId(reqid) buf := ws.buffers[reqid] content := buf.Bytes() findBytes := []byte("\r\n\r\n") i := bytes.Index(content, findBytes) if i >= 0 { length := "\r\nContent-Length: " + strconv.Itoa(len(content[i+4:])) newContent := make([]byte, 0, len(content)+len(length)) buf = bytes.NewBuffer(newContent) buf.Write(content[:i]) buf.Write([]byte(length)) buf.Write(content[i:]) } return http.ReadResponse(bufio.NewReader(buf), method) }
func send(req *http.Request) (resp *http.Response, err os.Error) { //dump, _ := http.DumpRequest(req, true) //fmt.Fprintf(os.Stderr, "%s", dump) //fmt.Fprintf(os.Stderr, "\n--- body:\n%s\n---", bodyString(req.Body)) if req.URL.Scheme != "http" && req.URL.Scheme != "https" { return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme} } addr := req.URL.Host var conn net.Conn switch req.URL.Scheme { case "http": if !hasPort(addr) { addr += ":http" } conn, err = net.Dial("tcp", addr) case "https": if !hasPort(addr) { addr += ":https" } conn, err = tls.Dial("tcp", addr, nil) } if err != nil { return nil, err } err = req.Write(conn) if err != nil { conn.Close() return nil, err } reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, req) if err != nil { conn.Close() return nil, err } resp.Body = readClose{resp.Body, conn} return }
// DialHTTP connects to an HTTP RPC server at the specified network address. func DialHTTP(network, address string) (*Client, os.Error) { conn, err := net.Dial(network, "", address); if err != nil { return nil, err; } io.WriteString(conn, "CONNECT " + rpcPath + " HTTP/1.0\n\n"); // Require successful HTTP response // before switching to RPC protocol. resp, err := http.ReadResponse(bufio.NewReader(conn)); if err == nil && resp.Status == connected { return NewClient(conn), nil; } if err == nil { err = os.ErrorString("unexpected HTTP response: " + resp.Status); } conn.Close(); return nil, &net.OpError{"dial-http", network+" "+address, nil, err}; }
func sendPost(postRequest *http.Request) (body string, err os.Error) { // Create and use TCP connection (lifted mostly wholesale from http.send) conn, err := net.Dial("tcp", "api.flickr.com:80") defer conn.Close() if err != nil { return "", err } postRequest.Write(conn) reader := bufio.NewReader(conn) resp, err := http.ReadResponse(reader, postRequest.Method) if err != nil { return "", err } rawBody, _ := ioutil.ReadAll(resp.Body) return string(rawBody), nil }
func main() { url := "http://twitter.com/statuses/public_timeline.json" var req http.Request req.URL, _ = http.ParseURL(url) addr := req.URL.Host addr += ":http" conn, _ := net.Dial("tcp", "", addr) _ = req.Write(conn) reader := bufio.NewReader(conn) resp, _ := http.ReadResponse(reader) r := io.Reader(reader) if v := resp.GetHeader("Content-Length"); v != "" { n, _ := strconv.Atoi64(v) r = io.LimitReader(r, n) } resp.Body = readClose{r, conn} b, _ := io.ReadAll(resp.Body) resp.Body.Close() fmt.Println(string(b)) }
// DialHTTPPath connects to an HTTP RPC server // at the specified network address and path. func DialHTTPPath(network, address, path string) (*Client, os.Error) { var err os.Error conn, err := net.Dial(network, address) if err != nil { return nil, err } io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n") // Require successful HTTP response // before switching to RPC protocol. resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"}) if err == nil && resp.Status == connected { return NewClient(conn), nil } if err == nil { err = os.NewError("unexpected HTTP response: " + resp.Status) } conn.Close() return nil, &net.OpError{"dial-http", network + " " + address, nil, err} }
func send(req *http.Request) (resp *http.Response, err os.Error) { if req.URL.Scheme != "http" { return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme} } addr := req.URL.Host if !hasPort(addr) { addr += ":http" } info := req.URL.Userinfo if len(info) > 0 { enc := base64.URLEncoding encoded := make([]byte, enc.EncodedLen(len(info))) enc.Encode(encoded, strings.Bytes(info)) if req.Header == nil { req.Header = make(map[string]string) } req.Header["Authorization"] = "Basic " + string(encoded) } conn, err := net.Dial("tcp", "", addr) if err != nil { return nil, err } err = req.Write(conn) if err != nil { conn.Close() return nil, err } reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, req.Method) if err != nil { conn.Close() return nil, err } resp.Body = readClose{resp.Body, conn} return }
// Client Handshake described in (soon obsolete) // draft-hixie-thewebsocket-protocol-75. func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) { if config.Version != ProtocolVersionHixie75 { panic("wrong protocol version.") } bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n") bw.WriteString("Upgrade: WebSocket\r\n") bw.WriteString("Connection: Upgrade\r\n") bw.WriteString("Host: " + config.Location.Host + "\r\n") bw.WriteString("Origin: " + config.Origin.String() + "\r\n") if len(config.Protocol) > 0 { if len(config.Protocol) != 1 { return ErrBadWebSocketProtocol } bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n") } bw.WriteString("\r\n") bw.Flush() resp, err := http.ReadResponse(br, &http.Request{Method: "GET"}) if err != nil { return } if resp.Status != "101 Web Socket Protocol Handshake" { return ErrBadStatus } if resp.Header.Get("Upgrade") != "WebSocket" || resp.Header.Get("Connection") != "Upgrade" { return ErrBadUpgrade } if resp.Header.Get("Websocket-Origin") != config.Origin.String() { return ErrBadWebSocketOrigin } if resp.Header.Get("Websocket-Location") != config.Location.String() { return ErrBadWebSocketLocation } if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] { return ErrBadWebSocketProtocol } return }
// execute a request; date it, sign it, send it // note: specialcase is temporary hack to set Content-Length: 0 when needed func (p *Propolis) SignAndExecute(req *http.Request, specialcase bool) (resp *http.Response, err os.Error) { // time stamp it date := time.LocalTime().Format(time.RFC1123) req.Header.Set("Date", date) // sign the request p.SignRequest(req) // open a connection conn, err := net.Dial("tcp", req.URL.Host+":"+req.URL.Scheme) if err != nil { return nil, err } // send the request if specialcase { var buf bytes.Buffer req.Write(&buf) fixed := bytes.Replace(buf.Bytes(), []byte("User-Agent: Go http package\r\n"), []byte("User-Agent: Go http package\r\nContent-Length: 0\r\n"), 1) _, err = conn.Write(fixed) } else { err = req.Write(conn) } if err != nil { return } // now read the response reader := bufio.NewReader(conn) resp, err = http.ReadResponse(reader, req) if err != nil { return nil, err } return }
func (frontend *Frontend) ServeHTTP(conn http.ResponseWriter, req *http.Request) { originalHost := req.Host // Redirect all requests to the "official" public host if the Host header // doesn't match. if !frontend.isValidHost(originalHost) { conn.Header().Set("Location", frontend.RedirectURL) conn.WriteHeader(http.StatusMovedPermanently) conn.Write(frontend.RedirectHTML) frontend.Log(HTTPS_REDIRECT, http.StatusMovedPermanently, originalHost, req) return } // Return the HTTP 503 error page if we're in maintenance mode. if frontend.MaintenanceMode { headers := conn.Header() headers.Set("Content-Type", "text/html; charset=utf-8") headers.Set("Content-Length", frontend.Error503Length) conn.WriteHeader(http.StatusServiceUnavailable) conn.Write(frontend.Error503) frontend.Log(HTTPS_MAINTENANCE, http.StatusServiceUnavailable, originalHost, req) return } reqPath := req.URL.Path // Handle requests for any files exposed within the static directory. if staticFile, ok := frontend.StaticFiles[reqPath]; ok { expires := time.SecondsToUTC(time.Seconds() + frontend.StaticMaxAge) headers := conn.Header() headers.Set("Expires", expires.Format(http.TimeFormat)) headers.Set("Cache-Control", frontend.StaticCache) headers.Set("Etag", staticFile.ETag) if req.Header.Get("If-None-Match") == staticFile.ETag { conn.WriteHeader(http.StatusNotModified) frontend.Log(HTTPS_STATIC, http.StatusNotModified, originalHost, req) return } // Special case /.well-known/oauth.json?callback= requests. if reqPath == "/.well-known/oauth.json" && req.URL.RawQuery != "" { query, err := http.ParseQuery(req.URL.RawQuery) if err != nil { logging.Error("Error parsing oauth.json query string %q: %s", req.URL.RawQuery, err) frontend.ServeError400(conn, originalHost, req) return } if callbackList, found := query["callback"]; found { callback := callbackList[0] if callback != "" { respLen := len(callback) + len(staticFile.Content) + 2 headers.Set("Content-Type", "text/javascript") headers.Set("Content-Length", fmt.Sprintf("%d", respLen)) conn.WriteHeader(http.StatusOK) conn.Write([]byte(callback)) conn.Write([]byte{'('}) conn.Write(staticFile.Content) conn.Write([]byte{')'}) frontend.Log(HTTPS_STATIC, http.StatusOK, originalHost, req) return } } } headers.Set("Content-Type", staticFile.Mimetype) headers.Set("Content-Length", staticFile.Size) conn.WriteHeader(http.StatusOK) conn.Write(staticFile.Content) frontend.Log(HTTPS_STATIC, http.StatusOK, originalHost, req) return } if frontend.LiveMode { // Handle WebSocket requests. if strings.HasPrefix(reqPath, frontend.WebsocketPrefix) { websocket.Handler(frontend.getWebSocketHandler()).ServeHTTP(conn, req) return } // Handle long-polling Comet requests. if strings.HasPrefix(reqPath, frontend.CometPrefix) { query, err := http.ParseQuery(req.URL.RawQuery) if err != nil { logging.Error("Error parsing Comet query string %q: %s", req.URL.RawQuery, err) frontend.ServeError400(conn, originalHost, req) return } queryReq, found := query["q"] if !found { frontend.ServeError400(conn, originalHost, req) return } response, status := getLiveItems(queryReq[0]) headers := conn.Header() headers.Set("Content-Type", "application/json") headers.Set("Content-Length", fmt.Sprintf("%d", len(response))) conn.WriteHeader(status) conn.Write(response) frontend.Log(HTTPS_COMET, status, originalHost, req) return } } // Open a connection to the upstream server. upstreamConn, err := net.Dial("tcp", frontend.upstreamAddr) if err != nil { logging.Error("Couldn't connect to upstream: %s", err) frontend.ServeError502(conn, originalHost, req) return } var clientIP string var upstream net.Conn splitPoint := strings.LastIndex(req.RemoteAddr, ":") if splitPoint == -1 { clientIP = req.RemoteAddr } else { clientIP = req.RemoteAddr[0:splitPoint] } if frontend.upstreamTLS { upstream = tls.Client(upstreamConn, tlsconf.Config) defer upstream.Close() } else { upstream = upstreamConn } // Modify the request Host: and User-Agent: headers. req.Host = frontend.upstreamHost req.Header.Set( "User-Agent", fmt.Sprintf("%s, %s, %s", req.UserAgent(), clientIP, originalHost)) // Send the request to the upstream server. err = req.Write(upstream) if err != nil { logging.Error("Error writing to the upstream server: %s", err) frontend.ServeError502(conn, originalHost, req) return } // Parse the response from upstream. resp, err := http.ReadResponse(bufio.NewReader(upstream), req) if err != nil { logging.Error("Error parsing response from upstream: %s", err) frontend.ServeError502(conn, originalHost, req) return } defer resp.Body.Close() // Get the original request header. headers := conn.Header() // Set a variable to hold the X-Live header value if present. var liveLength int if frontend.LiveMode { xLive := resp.Header.Get("X-Live") if xLive != "" { // If the X-Live header was set, parse it into an int. liveLength, err = strconv.Atoi(xLive) if err != nil { logging.Error("Error converting X-Live header value %q: %s", xLive, err) frontend.ServeError500(conn, originalHost, req) return } resp.Header.Del("X-Live") } } var body []byte if liveLength > 0 { var gzipSet bool var respBody io.ReadCloser // Check Content-Encoding to see if upstream sent gzipped content. if resp.Header.Get("Content-Encoding") == "gzip" { gzipSet = true respBody, err = gzip.NewReader(resp.Body) if err != nil { logging.Error("Error reading gzipped response from upstream: %s", err) frontend.ServeError500(conn, originalHost, req) return } defer respBody.Close() } else { respBody = resp.Body } // Read the X-Live content from the response body. liveMessage := make([]byte, liveLength) n, err := respBody.Read(liveMessage) if n != liveLength || err != nil { logging.Error("Error reading X-Live response from upstream: %s", err) frontend.ServeError500(conn, originalHost, req) return } // Read the response to send back to the original request. body, err = ioutil.ReadAll(respBody) if err != nil { logging.Error("Error reading non X-Live response from upstream: %s", err) frontend.ServeError500(conn, originalHost, req) return } // Re-encode the response if it had been gzipped by upstream. if gzipSet { buffer := &bytes.Buffer{} encoder, err := gzip.NewWriter(buffer) if err != nil { logging.Error("Error creating a new gzip Writer: %s", err) frontend.ServeError500(conn, originalHost, req) return } n, err = encoder.Write(body) if n != len(body) || err != nil { logging.Error("Error writing to the gzip Writer: %s", err) frontend.ServeError500(conn, originalHost, req) return } err = encoder.Close() if err != nil { logging.Error("Error finalising the write to the gzip Writer: %s", err) frontend.ServeError500(conn, originalHost, req) return } body = buffer.Bytes() } resp.Header.Set("Content-Length", fmt.Sprintf("%d", len(body))) liveChannel <- liveMessage } else { // Read the full response body. body, err = ioutil.ReadAll(resp.Body) if err != nil { logging.Error("Error reading response from upstream: %s", err) frontend.ServeError502(conn, originalHost, req) return } } // Set the received headers back to the initial connection. for k, values := range resp.Header { for _, v := range values { headers.Add(k, v) } } // Write the response body back to the initial connection. conn.WriteHeader(resp.StatusCode) conn.Write(body) frontend.Log(HTTPS_UPSTREAM, resp.StatusCode, originalHost, req) }
/* Web Socket protocol handshake based on http://www.whatwg.org/specs/web-socket-protocol/ (draft of http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol) */ func handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) { // 4.1. Opening handshake. // Step 5. send a request line. bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n") // Step 6-14. push request headers in fields. var fields vector.StringVector fields.Push("Upgrade: WebSocket\r\n") fields.Push("Connection: Upgrade\r\n") fields.Push("Host: " + host + "\r\n") fields.Push("Origin: " + origin + "\r\n") if protocol != "" { fields.Push("Sec-WebSocket-Protocol: " + protocol + "\r\n") } // TODO(ukai): Step 15. send cookie if any. // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields. key1, number1 := generateKeyNumber() key2, number2 := generateKeyNumber() fields.Push("Sec-WebSocket-Key1: " + key1 + "\r\n") fields.Push("Sec-WebSocket-Key2: " + key2 + "\r\n") // Step 24. shuffle fields and send them out. for i := 1; i < len(fields); i++ { j := rand.Intn(i) fields[i], fields[j] = fields[j], fields[i] } for i := 0; i < len(fields); i++ { bw.WriteString(fields[i]) } // Step 25. send CRLF. bw.WriteString("\r\n") // Step 26. genearte 8 bytes random key. key3 := generateKey3() // Step 27. send it out. bw.Write(key3) if err = bw.Flush(); err != nil { return } // Step 28-29, 32-40. read response from server. resp, err := http.ReadResponse(br, "GET") if err != nil { return err } // Step 30. check response code is 101. if resp.StatusCode != 101 { return ErrBadStatus } // Step 41. check websocket headers. if resp.Header["Upgrade"] != "WebSocket" || strings.ToLower(resp.Header["Connection"]) != "upgrade" { return ErrBadUpgrade } if resp.Header["Sec-Websocket-Origin"] != origin { return ErrBadWebSocketOrigin } if resp.Header["Sec-Websocket-Location"] != location { return ErrBadWebSocketLocation } if protocol != "" && resp.Header["Sec-Websocket-Protocol"] != protocol { return ErrBadWebSocketProtocol } // Step 42-43. get expected data from challange data. expected, err := getChallengeResponse(number1, number2, key3) if err != nil { return err } // Step 44. read 16 bytes from server. reply := make([]byte, 16) if _, err = io.ReadFull(br, reply); err != nil { return err } // Step 45. check the reply equals to expected data. if !bytes.Equal(expected, reply) { return ErrChallengeResponse } // WebSocket connection is established. return }
// TestCopyError tests that we kill the process if there's an error copying // its output. (for example, from the client having gone away) func TestCopyError(t *testing.T) { if skipTest(t) || runtime.GOOS == "windows" { return } h := &Handler{ Path: "testdata/test.cgi", Root: "/test.cgi", } ts := httptest.NewServer(h) defer ts.Close() conn, err := net.Dial("tcp", ts.Listener.Addr().String()) if err != nil { t.Fatal(err) } req, _ := http.NewRequest("GET", "http://example.com/test.cgi?bigresponse=1", nil) err = req.Write(conn) if err != nil { t.Fatalf("Write: %v", err) } res, err := http.ReadResponse(bufio.NewReader(conn), req) if err != nil { t.Fatalf("ReadResponse: %v", err) } pidstr := res.Header.Get("X-CGI-Pid") if pidstr == "" { t.Fatalf("expected an X-CGI-Pid header in response") } pid, err := strconv.Atoi(pidstr) if err != nil { t.Fatalf("invalid X-CGI-Pid value") } var buf [5000]byte n, err := io.ReadFull(res.Body, buf[:]) if err != nil { t.Fatalf("ReadFull: %d bytes, %v", n, err) } childRunning := func() bool { p, err := os.FindProcess(pid) if err != nil { return false } return p.Signal(os.UnixSignal(0)) == nil } if !childRunning() { t.Fatalf("pre-conn.Close, expected child to be running") } conn.Close() if tries := 0; childRunning() { for tries < 15 && childRunning() { time.Sleep(50e6 * int64(tries)) tries++ } if childRunning() { t.Fatalf("post-conn.Close, expected child to be gone") } } }
func (frontend *Frontend) ServeHTTP(conn *http.Conn, req *http.Request) { if frontend.enforceHost && req.Host != frontend.officialHost { conn.SetHeader("Location", frontend.officialRedirectURL) conn.WriteHeader(http.StatusMovedPermanently) conn.Write(frontend.officialRedirectHTML) logRequest(http.StatusMovedPermanently, req.Host, conn) return } originalHost := req.Host // Open a connection to the App Engine server. gaeConn, err := net.Dial("tcp", "", frontend.gaeAddr) if err != nil { if debugMode { fmt.Printf("Couldn't connect to remote %s: %v\n", frontend.gaeHost, err) } serveError502(conn, originalHost) return } var gae net.Conn if frontend.gaeTLS { gae = tls.Client(gaeConn, tlsconf.Config) defer gae.Close() } else { gae = gaeConn } // Modify the request Host: header. req.Host = frontend.gaeHost // Send the request to the App Engine server. err = req.Write(gae) if err != nil { if debugMode { fmt.Printf("Error writing to App Engine: %v\n", err) } serveError502(conn, originalHost) return } // Parse the response from App Engine. resp, err := http.ReadResponse(bufio.NewReader(gae), req.Method) if err != nil { if debugMode { fmt.Printf("Error parsing response from App Engine: %v\n", err) } serveError502(conn, originalHost) return } // Read the full response body. body, err := ioutil.ReadAll(resp.Body) if err != nil { if debugMode { fmt.Printf("Error reading response from App Engine: %v\n", err) } serveError502(conn, originalHost) resp.Body.Close() return } // Set the received headers back to the initial connection. for k, v := range resp.Header { conn.SetHeader(k, v) } // Write the response body back to the initial connection. resp.Body.Close() conn.WriteHeader(resp.StatusCode) conn.Write(body) logRequest(resp.StatusCode, originalHost, conn) }
// Client handhake described in draft-ietf-hybi-thewebsocket-protocol-17 func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) { if !isHybiVersion(config.Version) { panic("wrong protocol version.") } bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n") bw.WriteString("Host: " + config.Location.Host + "\r\n") bw.WriteString("Upgrade: websocket\r\n") bw.WriteString("Connection: Upgrade\r\n") nonce := generateNonce() if config.handshakeData != nil { nonce = []byte(config.handshakeData["key"]) } bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n") if config.Version == ProtocolVersionHybi13 { bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") } else if config.Version == ProtocolVersionHybi08 { bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") } bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n") if len(config.Protocol) > 0 { bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n") } // TODO(ukai): send extensions. // TODO(ukai): send cookie if any. bw.WriteString("\r\n") if err = bw.Flush(); err != nil { return err } resp, err := http.ReadResponse(br, &http.Request{Method: "GET"}) if err != nil { return err } if resp.StatusCode != 101 { return ErrBadStatus } if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" || strings.ToLower(resp.Header.Get("Connection")) != "upgrade" { return ErrBadUpgrade } expectedAccept, err := getNonceAccept(nonce) if err != nil { return err } if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) { return ErrChallengeResponse } if resp.Header.Get("Sec-WebSocket-Extensions") != "" { return ErrUnsupportedExtensions } offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol") if offeredProtocol != "" { protocolMatched := false for i := 0; i < len(config.Protocol); i++ { if config.Protocol[i] == offeredProtocol { protocolMatched = true break } } if !protocolMatched { return ErrBadWebSocketProtocol } config.Protocol = []string{offeredProtocol} } return nil }
// NewClient creates a new connection to a host given as "hostname" or "hostname:port". // If host is not specified, the DNS SRV should be used to find the host from the domainpart of the JID. // Default the port to 5222. func NewClient(host, user, passwd string) (*Client, os.Error) { addr := host if strings.TrimSpace(host) == "" { a := strings.Split(user, "@", 2) if len(a) == 2 { host = a[1] } } a := strings.Split(host, ":", 2) if len(a) == 1 { host += ":5222" } proxy := os.Getenv("HTTP_PROXY") if proxy == "" { proxy = os.Getenv("http_proxy") } if proxy != "" { url, err := http.ParseRequestURL(proxy) if err == nil { addr = url.Host } } c, err := net.Dial("tcp", addr) if err != nil { return nil, err } if proxy != "" { fmt.Fprintf(c, "CONNECT %s HTTP/1.1\r\n", host) fmt.Fprintf(c, "Host: %s\r\n", host) fmt.Fprintf(c, "\r\n") br := bufio.NewReader(c) req, _ := http.NewRequest("CONNECT", host, nil) resp, err := http.ReadResponse(br, req) if err != nil { return nil, err } if resp.StatusCode != 200 { f := strings.Split(resp.Status, " ", 2) return nil, os.ErrorString(f[1]) } } tlsconn := tls.Client(c, &DefaultConfig) if err = tlsconn.Handshake(); err != nil { return nil, err } if strings.LastIndex(host, ":") > 0 { host = host[:strings.LastIndex(host, ":")] } if err = tlsconn.VerifyHostname(host); err != nil { return nil, err } client := new(Client) client.tls = tlsconn if err := client.init(user, passwd); err != nil { client.Close() return nil, err } return client, nil }
// Cilent handhake described in (soon obsolete) // draft-ietf-hybi-thewebsocket-protocol-00 // (draft-hixie-thewebsocket-protocol-76) func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) { switch config.Version { case ProtocolVersionHixie76, ProtocolVersionHybi00: default: panic("wrong protocol version.") } // 4.1. Opening handshake. // Step 5. send a request line. bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n") // Step 6-14. push request headers in fields. var fields vector.StringVector fields.Push("Upgrade: WebSocket\r\n") fields.Push("Connection: Upgrade\r\n") fields.Push("Host: " + config.Location.Host + "\r\n") fields.Push("Origin: " + config.Origin.String() + "\r\n") if len(config.Protocol) > 0 { if len(config.Protocol) != 1 { return ErrBadWebSocketProtocol } fields.Push("Sec-WebSocket-Protocol: " + config.Protocol[0] + "\r\n") } // TODO(ukai): Step 15. send cookie if any. // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields. key1, number1 := generateKeyNumber() key2, number2 := generateKeyNumber() if config.handshakeData != nil { key1 = config.handshakeData["key1"] n, err := strconv.Atoui(config.handshakeData["number1"]) if err != nil { panic(err) } number1 = uint32(n) key2 = config.handshakeData["key2"] n, err = strconv.Atoui(config.handshakeData["number2"]) if err != nil { panic(err) } number2 = uint32(n) } fields.Push("Sec-WebSocket-Key1: " + key1 + "\r\n") fields.Push("Sec-WebSocket-Key2: " + key2 + "\r\n") // Step 24. shuffle fields and send them out. for i := 1; i < len(fields); i++ { j := rand.Intn(i) fields[i], fields[j] = fields[j], fields[i] } for i := 0; i < len(fields); i++ { bw.WriteString(fields[i]) } // Step 25. send CRLF. bw.WriteString("\r\n") // Step 26. generate 8 bytes random key. key3 := generateKey3() if config.handshakeData != nil { key3 = []byte(config.handshakeData["key3"]) } // Step 27. send it out. bw.Write(key3) if err = bw.Flush(); err != nil { return } // Step 28-29, 32-40. read response from server. resp, err := http.ReadResponse(br, &http.Request{Method: "GET"}) if err != nil { return err } // Step 30. check response code is 101. if resp.StatusCode != 101 { return ErrBadStatus } // Step 41. check websocket headers. if resp.Header.Get("Upgrade") != "WebSocket" || strings.ToLower(resp.Header.Get("Connection")) != "upgrade" { return ErrBadUpgrade } if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() { return ErrBadWebSocketOrigin } if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() { return ErrBadWebSocketLocation } if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] { return ErrBadWebSocketProtocol } // Step 42-43. get expected data from challenge data. expected, err := getChallengeResponse(number1, number2, key3) if err != nil { return err } // Step 44. read 16 bytes from server. reply := make([]byte, 16) if _, err = io.ReadFull(br, reply); err != nil { return err } // Step 45. check the reply equals to expected data. if !bytes.Equal(expected, reply) { return ErrChallengeResponse } // WebSocket connection is established. return }
func (bucket *Bucket) GetFileInfo(filename string) (file *os.FileInfo, err os.Error) { url, e := http.ParseURL(bucket.Url + "/" + filename) if e != nil { fmt.Println("Error parsing URL", e) } req := &http.Request{Method: "HEAD", RawURL: bucket.Url + "/" + filename, URL: url, Header: make(map[string]string)} date := time.LocalTime().Format(time.RFC1123) req.Header["Date"] = date bucket.sign(req) //req.Write(os.Stdout) conn, err := net.Dial("tcp", "", req.URL.Host+":"+req.URL.Scheme) req.Write(conn) reader := bufio.NewReader(conn) resp, _ := http.ReadResponse(reader, req.Method) //resp.Write(os.Stdout) name := filename var mtime int64 var mode uint if resp.Header["x-amz-meta-mtime"] == "" { mtime, _ = strconv.Atoi64(resp.GetHeader("Last-Modified")) } else { mtime, _ = strconv.Atoi64(resp.GetHeader("x-amz-meta-mtime")) } if resp.Header["X-Amz-Meta-Mode"] == "" { if temp := resp.GetHeader("Content-Type"); temp == "application/x-directory" { mode = syscall.S_IFDIR } else { mode = syscall.S_IFREG } } else { fmt.Println(resp.GetHeader("X-Amz-Meta-Mode")) mode, _ = strconv.Atoui(resp.GetHeader("X-Amz-Meta-Mode")) /*if((mode & syscall.S_IFMT) == syscall.S_IFDIR){ mode = syscall.S_IFDIR } else { mode = syscall.S_IFREG }*/ } mode2 := uint32(mode) //fmt.Print(mode2) size, _ := strconv.Atoi64(resp.GetHeader("content-Length")) uid, _ := strconv.Atoi(resp.GetHeader("x-amz-meta-uid")) gid, _ := strconv.Atoi(resp.GetHeader("x-amz-meta-gid")) file = &os.FileInfo{ Name: name, Mtime_ns: mtime, Mode: mode2, Size: size, Uid: uid, Gid: gid, } return file, err }