func req(s string) *http.Request { req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(s))) if err != nil { panic(fmt.Sprintf("bad request in test: %q (error: %v)", req, err)) } return req }
func TestHybiServerHandshakeHybiBadVersion(t *testing.T) { config := new(Config) handshaker := &hybiServerHandshaker{Config: config} br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 9 `)) req, err := http.ReadRequest(br) if err != nil { t.Fatal("request", err) } code, err := handshaker.ReadHandshake(br, req) if err != ErrBadWebSocketVersion { t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err) } if code != http.StatusBadRequest { t.Errorf("status expected %q but got %q", http.StatusBadRequest, code) } }
// Attempt to extract an HTTP request from the packet and serialise with the // provided encoder. func SerialisePacket(pkt *pcap.Packet, enc *json.Encoder) { // TODO: serialise packet details for non-HTTP packets // TODO: naively assumes requests are contained in a single packet and // HTTP verbs are not otherwise contained in a request // rfc 2616 httpMethods := [...]string{"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"} // TODO: IPv6 if hdr, ok := pkt.Headers[0].(*pcap.Iphdr); ok { if tcpHdr, ok := pkt.Headers[1].(*pcap.Tcphdr); ok { // TODO: Consider peeking at other ports if tcpHdr.DestPort == 80 { pktString := PacketAsString(pkt) for _, verb := range httpMethods { if strings.Contains(pktString, verb) { unparsedReqs := strings.Split(pktString, verb) for _, unparsed := range unparsedReqs { req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(verb + unparsed))) // TODO: serialise details of packets we fail to parse if err == nil { rp := RequestPacket{hdr.SrcAddr(), hdr.DestAddr(), tcpHdr.SrcPort, tcpHdr.DestPort, pkt.TimeString(), tcpHdr.FlagsString(), req} enc.Encode(rp) } } } } } out.Flush() } } }
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 TestURL(t *testing.T) { for _, ex := range examples { req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(ex.request))) if err != nil { t.Error(err) } if len(req.Header) > 1 { // Only works on requests without any headers // Host header has been removed continue } date := req.Header.Get("Date") url, err := http.ParseURL("http://" + req.Host + req.URL.RawPath) if err != nil { t.Error(err) } signed, err := URL(url, AWSAccessKeyId, AWSSecretAccessKey, req.Method, date) if err != nil { t.Error(err) } // Fudge a bit on this test. The date should be in Unix timestamp // but we can only compare against known signatures for now so use // the existing date. if auth := addAuth(url.Raw, ex.auth, date); auth != signed.Raw { t.Error("Fail URL:", ex.name, "got:", signed.Raw, "want:", auth, "headers:", len(req.Header)) } } }
func newRequest(httpreq string) *http.Request { buf := bufio.NewReader(strings.NewReader(httpreq)) req, err := http.ReadRequest(buf) if err != nil { panic("cgi: bogus http request in test: " + httpreq) } req.RemoteAddr = "1.2.3.4" return req }
func (srv *Server) handler(c net.Conn) { startTime := time.Nanoseconds() defer srv.connectionFinished(c) buf, err := bufio.NewReaderSize(c, 8192) if err != nil { Error("%s Read buffer fail: %v", srv.serverLogPrefix(), err) return } var req *http.Request // no keepalive (for now) reqCount := 0 keepAlive := true for err == nil && keepAlive { if req, err = http.ReadRequest(buf); err == nil { if req.Header.Get("Connection") != "Keep-Alive" { keepAlive = false } request := newRequest(req, c, startTime) reqCount++ var res *http.Response pssInit := new(PipelineStageStat) pssInit.Name = "server.Init" pssInit.StartTime = startTime pssInit.EndTime = time.Nanoseconds() request.appendPipelineStage(pssInit) // execute the pipeline if res = srv.Pipeline.execute(request); res == nil { res = SimpleResponse(req, 404, nil, "Not Found") } // cleanup request.startPipelineStage("server.ResponseWrite") req.Body.Close() wbuf := bufio.NewWriter(c) res.Write(wbuf) wbuf.Flush() if res.Body != nil { res.Body.Close() } request.finishPipelineStage() request.finishRequest() srv.requestFinished(request) } else { // EOF is socket closed if err != io.ErrUnexpectedEOF { Error("%s %v ERROR reading request: %v", srv.serverLogPrefix(), c.RemoteAddr(), err) } } } //Debug("%s Processed %v requests on connection %v", srv.serverLogPrefix(), reqCount, c.RemoteAddr()) }
func TestAuthorize(t *testing.T) { for _, ex := range examples { req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(ex.request))) if err != nil { t.Error(err) } Authorize(req, AWSAccessKeyId, AWSSecretAccessKey) if auth := req.Header.Get("Authorization"); auth != ex.auth { toSign := StringToSign(req.Method, req.URL, req.Header, "") t.Error("Fail Authorize:", ex.name, "got:", auth, "want:", ex.auth, "url:", req.URL.Host, "host:", req.Host, "string:", toSign) } } }
// Test the hybiServerHandshaker supports firefox implementation and // checks Connection request header include (but it's not necessary // equal to) "upgrade" func TestHybiServerFirefoxHandshake(t *testing.T) { config := new(Config) handshaker := &hybiServerHandshaker{Config: config} br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: keep-alive, upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 `)) req, err := http.ReadRequest(br) if err != nil { t.Fatal("request", err) } code, err := handshaker.ReadHandshake(br, req) if err != nil { t.Errorf("handshake failed: %v", err) } if code != http.StatusSwitchingProtocols { t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code) } b := bytes.NewBuffer([]byte{}) bw := bufio.NewWriter(b) config.Protocol = []string{"chat"} err = handshaker.AcceptHandshake(bw) if err != nil { t.Errorf("handshake response failed: %v", err) } expectedResponse := strings.Join([]string{ "HTTP/1.1 101 Switching Protocols", "Upgrade: websocket", "Connection: Upgrade", "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", "Sec-WebSocket-Protocol: chat", "", ""}, "\r\n") if b.String() != expectedResponse { t.Errorf("handshake expected %q but got %q", expectedResponse, b.String()) } }
func TestHixie76ServerHandshake(t *testing.T) { config := new(Config) handshaker := &hixie76ServerHandshaker{Config: config} br := bufio.NewReader(strings.NewReader(`GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U`)) req, err := http.ReadRequest(br) if err != nil { t.Fatal("request", err) } code, err := handshaker.ReadHandshake(br, req) if err != nil { t.Errorf("handshake failed: %v", err) } if code != http.StatusSwitchingProtocols { t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code) } b := bytes.NewBuffer([]byte{}) bw := bufio.NewWriter(b) err = handshaker.AcceptHandshake(bw) if err != nil { t.Errorf("handshake response failed: %v", err) } expectedResponse := strings.Join([]string{ "HTTP/1.1 101 WebSocket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade", "Sec-WebSocket-Origin: http://example.com", "Sec-WebSocket-Location: ws://example.com/demo", "Sec-WebSocket-Protocol: sample", "", ""}, "\r\n") + "8jKS'y:G*Co,Wxa-" if b.String() != expectedResponse { t.Errorf("handshake expected %q but got %q", expectedResponse, b.String()) } }
func TestHybiClientHandshakeHybi08(t *testing.T) { b := bytes.NewBuffer([]byte{}) bw := bufio.NewWriter(b) br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat `)) var err os.Error config := new(Config) config.Location, err = url.ParseRequest("ws://server.example.com/chat") if err != nil { t.Fatal("location url", err) } config.Origin, err = url.ParseRequest("http://example.com") if err != nil { t.Fatal("origin url", err) } config.Protocol = append(config.Protocol, "chat") config.Protocol = append(config.Protocol, "superchat") config.Version = ProtocolVersionHybi08 config.handshakeData = map[string]string{ "key": "dGhlIHNhbXBsZSBub25jZQ==", } err = hybiClientHandshake(config, br, bw) if err != nil { t.Errorf("handshake failed: %v", err) } req, err := http.ReadRequest(bufio.NewReader(b)) if err != nil { t.Fatalf("read request: %v", err) } if req.Method != "GET" { t.Errorf("request method expected GET, but got %q", req.Method) } if req.URL.Path != "/chat" { t.Errorf("request path expected /demo, but got %q", req.URL.Path) } if req.Proto != "HTTP/1.1" { t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto) } if req.Host != "server.example.com" { t.Errorf("request Host expected example.com, but got %v", req.Host) } var expectedHeader = map[string]string{ "Connection": "Upgrade", "Upgrade": "websocket", "Sec-Websocket-Key": config.handshakeData["key"], "Sec-Websocket-Origin": config.Origin.String(), "Sec-Websocket-Protocol": "chat, superchat", "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi08), } for k, v := range expectedHeader { if req.Header.Get(k) != v { t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k))) } } }
func TestCall(t *testing.T) { s := NewServer() s.Register(new(TestService)) for i, test := range tests { str := "POST /json HTTP/1.1\nContent-Length: " + strconv.Itoa(len(test.req)) + "\n\n" + test.req r := bufio.NewReader(strings.NewReader(str)) req, _ := http.ReadRequest(r) b := bytes.NewBuffer([]byte{}) w := &TestResponseWriter{buffer: b, header: make(http.Header)} s.ServeHTTP(w, req) resp := new(jsonResponse) json.Unmarshal(b.Bytes(), resp) if test.error != nil { if resp.Error == nil { t.Error("Test", i, "Error not present") t.Fail() return } else { if test.error.(string) != resp.Error.(string) { t.Error("Test", i, resp.Error.(string)) t.Fail() return } } } else { if resp.Error != nil { t.Error("Test", i, resp.Error.(string)) t.Fail() return } } if test.resp == nil && resp.Result == nil { continue } switch test.resp.(type) { case float64: if fValue, ok := resp.Result.(float64); !ok || fValue != test.resp.(float64) { t.Error("Test", i, "Did not match float") t.Fail() return } case int: if iValue, ok := resp.Result.(int); !ok || iValue != test.resp.(int) { t.Error("Test", i, "Did not match int") t.Fail() return } case bool: if bValue, ok := resp.Result.(bool); !ok || bValue != test.resp.(bool) { t.Error("Test", i, "Did not match bool") t.Fail() return } case string: if sValue, ok := resp.Result.(string); !ok || sValue != test.resp.(string) { t.Error("Test", i, "Did not match string") t.Fail() return } case map[string]interface{}: mapValue, ok := resp.Result.(map[string]interface{}) if !ok { t.Error("Test", i, "Result was not a map[string]interface{}") t.Fail() return } mapResult := test.resp.(map[string]interface{}) if mapValue["x"].(string) != mapResult["x"].(string) || int(mapValue["y"].(float64)) != mapResult["y"].(int) { t.Error("Test", i, "Did not match object") t.Fail() return } default: t.Error("Test", i, "Unknown result") t.Fail() return } } }
func TestHixie76ClientHandshake(t *testing.T) { b := bytes.NewBuffer([]byte{}) bw := bufio.NewWriter(b) br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-`)) var err os.Error config := new(Config) config.Location, err = url.ParseRequest("ws://example.com/demo") if err != nil { t.Fatal("location url", err) } config.Origin, err = url.ParseRequest("http://example.com") if err != nil { t.Fatal("origin url", err) } config.Protocol = append(config.Protocol, "sample") config.Version = ProtocolVersionHixie76 config.handshakeData = map[string]string{ "key1": "4 @1 46546xW%0l 1 5", "number1": "829309203", "key2": "12998 5 Y3 1 .P00", "number2": "259970620", "key3": "^n:ds[4U", } err = hixie76ClientHandshake(config, br, bw) if err != nil { t.Errorf("handshake failed: %v", err) } req, err := http.ReadRequest(bufio.NewReader(b)) if err != nil { t.Fatalf("read request: %v", err) } if req.Method != "GET" { t.Errorf("request method expected GET, but got %q", req.Method) } if req.URL.Path != "/demo" { t.Errorf("request path expected /demo, but got %q", req.URL.Path) } if req.Proto != "HTTP/1.1" { t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto) } if req.Host != "example.com" { t.Errorf("request Host expected example.com, but got %v", req.Host) } var expectedHeader = map[string]string{ "Connection": "Upgrade", "Upgrade": "WebSocket", "Origin": "http://example.com", "Sec-Websocket-Key1": config.handshakeData["key1"], "Sec-Websocket-Key2": config.handshakeData["key2"], "Sec-WebSocket-Protocol": config.Protocol[0], } for k, v := range expectedHeader { if req.Header.Get(k) != v { t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k))) } } }