Пример #1
0
func TestServeHTTPReadRequestError(t *testing.T) {
	p := NewProxy(mitm)
	// Shorten the timeout to force a ReadRequest error.
	p.Timeout = time.Second

	rc, wc := pipeWithTimeout()
	defer rc.Close()
	defer wc.Close()

	rw := newHijackRecorder(wc)
	req, err := http.NewRequest("CONNECT", "//www.example.com:443", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no error", err)
	}

	go p.ServeHTTP(rw, req)

	res, err := http.ReadResponse(bufio.NewReader(rc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	res.Body.Close()

	tlsConn := tlsClient(rc, p.mitm.Authority, "www.example.com")
	tlsConn.Write([]byte("INVALID /invalid NOTHTTP/1.1\r\n"))

	if _, err = http.ReadResponse(bufio.NewReader(tlsConn), nil); err != io.ErrUnexpectedEOF {
		t.Fatalf("http.ReadResponse(): got %v, want io.ErrUnexpectedEOF", err)
	}
}
Пример #2
0
func TestServeHTTPKeepAlive(t *testing.T) {
	p := NewProxy(mitm)

	rc, wc := pipeWithTimeout()
	defer rc.Close()
	defer wc.Close()

	rw := newHijackRecorder(wc)
	req, err := http.NewRequest("CONNECT", "//www.example.com:443", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no error", err)
	}

	go p.ServeHTTP(rw, req)

	res, err := http.ReadResponse(bufio.NewReader(rc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	res.Body.Close()

	tlsConn := tlsClient(rc, p.mitm.Authority, "www.example.com")

	tt := []struct {
		closing bool
	}{
		{false},
		{false},
		{true},
	}
	for _, tc := range tt {
		req, err = http.NewRequest("GET", "https://www.example.com/", nil)
		if err != nil {
			t.Fatalf("http.NewRequest(): got %v, want no error", err)
		}

		// Close the connection on the last request.
		if tc.closing {
			req.Header.Set("Connection", "close")
		}

		if err := req.Write(tlsConn); err != nil {
			t.Fatalf("req.Write(): got %v, want no error", err)
		}

		res, err = http.ReadResponse(bufio.NewReader(tlsConn), nil)
		if err != nil {
			t.Fatalf("http.ReadResponse(): got %v, want no error", err)
		}
		res.Body.Close()

		if got, want := res.StatusCode, 200; got != want {
			t.Errorf("res.StatusCode: got %d, want %d", got, want)
		}
		if tc.closing && !res.Close {
			t.Error("res.Close: got false, want true")
		}
	}
}
Пример #3
0
func TestServeHTTPConnectRequestWithoutMITM(t *testing.T) {
	p := NewProxy(nil)
	f := func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("secret!"))
	}
	server := httptest.NewTLSServer(http.HandlerFunc(f))
	defer server.Close()

	rc, wc := pipeWithTimeout()
	defer rc.Close()
	defer wc.Close()

	rw := newHijackRecorder(wc)

	req, err := http.NewRequest("CONNECT", server.URL, nil)
	if err != nil {
		t.Fatalf("http.NewRequest(%q, %q, nil): got %v, want no error", "CONNECT", server.URL, err)
	}

	go p.ServeHTTP(rw, req)

	res, err := http.ReadResponse(bufio.NewReader(rc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}

	if got, want := res.StatusCode, 200; got != want {
		t.Errorf("res.StatusCode: got %d, want %d", got, want)
	}

	req, err = http.NewRequest("GET", server.URL, nil)
	if err != nil {
		t.Fatalf("http.NewRequest(%q, %q, nil): got %v, want no error", "GET", server.URL, err)
	}
	req.Header.Set("Connection", "close")

	tlsrc := tls.Client(rc, &tls.Config{
		InsecureSkipVerify: true,
	})

	go req.Write(tlsrc)

	res, err = http.ReadResponse(bufio.NewReader(tlsrc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}

	got, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll(res.Body): got %v, want no error", err)
	}
	res.Body.Close()

	if want := []byte("secret!"); !bytes.Equal(got, want) {
		t.Errorf("res.Body: got %q, want %q", got, want)
	}
}
Пример #4
0
// StaticResponder returns an HTTP response generator that parses res
// for an entire HTTP response, including headers and body.
func StaticResponder(res string) func() *http.Response {
	_, err := http.ReadResponse(bufio.NewReader(strings.NewReader(res)), nil)
	if err != nil {
		panic("Invalid response given to StaticResponder: " + err.Error())
	}
	return func() *http.Response {
		res, _ := http.ReadResponse(bufio.NewReader(strings.NewReader(res)), nil)
		return res
	}
}
Пример #5
0
func TestServeHTTPBuildsValidRequest(t *testing.T) {
	p := NewProxy(mitm)
	p.RoundTripper = RoundTripFunc(func(req *http.Request) (*http.Response, error) {
		if got, want := req.URL.Scheme, "https"; got != want {
			t.Errorf("req.URL.Scheme: got %q, want %q", got, want)
		}
		if got, want := req.URL.Host, "www.example.com"; got != want {
			t.Errorf("req.URL.Host: got %q, want %q", got, want)
		}
		if req.RemoteAddr == "" {
			t.Error("req.RemoteAddr: got empty, want addr")
		}

		return proxyutil.NewResponse(201, nil, req), nil
	})

	rc, wc := pipeWithTimeout()
	defer rc.Close()
	defer wc.Close()

	rw := newHijackRecorder(wc)
	req, err := http.NewRequest("CONNECT", "//www.example.com:443", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no error", err)
	}

	go p.ServeHTTP(rw, req)

	res, err := http.ReadResponse(bufio.NewReader(rc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	res.Body.Close()

	tlsConn := tlsClient(rc, p.mitm.Authority, "www.example.com")
	req, err = http.NewRequest("GET", "https://www.example.com", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no erro", err)
	}
	req.Header.Set("Connection", "close")

	if err := req.Write(tlsConn); err != nil {
		t.Fatalf("req.Write(): got %v, want no error", err)
	}

	res, err = http.ReadResponse(bufio.NewReader(tlsConn), nil)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	defer res.Body.Close()

	if got, want := res.StatusCode, 201; got != want {
		t.Errorf("res.StatusCode: got %d, want %d", got, want)
	}
}
Пример #6
0
// load an external image or fetch it from the cache
// and write it to the ResponseWriter
func (ipw *ImgProxy) ProxyImage(w http.ResponseWriter, req *http.Request, url string) (err error) {
	cacheKey := ipw.cacheKey(url)
	xCacheHeader := "HIT"

	var resp *http.Response

	// attempt to read from cache
	cachedData, ok := ipw.cache.Get(cacheKey)
	if ok {
		b := bytes.NewBuffer(cachedData)
		resp, err = http.ReadResponse(bufio.NewReader(b), req)
		if err != nil {
			log.Printf("Unable to read cached entry for %s: %v (cacheKey: %s)", url, err, cacheKey)

			// remove any invalid data from the cache and
			// fetch it fresh from upstream
			ipw.cache.Delete(cacheKey)
			resp = nil
		}
	}

	// fetch from upstream
	if resp == nil {
		xCacheHeader = "MISS"

		downloadedData := <-ipw.fetchFromUpstream(url)
		if downloadedData.err != nil {
			return downloadedData.err
		}
		resp, err = http.ReadResponse(bufio.NewReader(bytes.NewBuffer(downloadedData.httpResponseData)), req)
		if err != nil {
			return err
		}
	}

	// write to responsewriter
	copyHeader(w, resp, "Last-Modified")
	copyHeader(w, resp, "Expires")
	copyHeader(w, resp, "Etag")
	w.Header()[http.CanonicalHeaderKey("X-Cache")] = []string{xCacheHeader}

	if is304 := check304(req, resp); is304 {
		w.WriteHeader(http.StatusNotModified)
		return
	}

	copyHeader(w, resp, "Content-Length")
	copyHeader(w, resp, "Content-Type")
	w.WriteHeader(resp.StatusCode)
	io.Copy(w, resp.Body)

	return nil
}
Пример #7
0
func TestServeHTTPModifyResponseError(t *testing.T) {
	p := NewProxy(mitm)
	f := func(*Context, *http.Response) error {
		return fmt.Errorf("modifier error")
	}
	p.SetResponseModifier(ResponseModifierFunc(f))

	rc, wc := pipeWithTimeout()
	defer rc.Close()
	defer wc.Close()

	rw := newHijackRecorder(wc)
	req, err := http.NewRequest("CONNECT", "//www.example.com:443", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no error", err)
	}

	go p.ServeHTTP(rw, req)

	res, err := http.ReadResponse(bufio.NewReader(rc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	res.Body.Close()

	tlsConn := tlsClient(rc, p.mitm.Authority, "www.example.com")
	req, err = http.NewRequest("GET", "https://www.example.com/", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no erro", err)
	}
	if err := req.Write(tlsConn); err != nil {
		t.Fatalf("req.Write(): got %v, want no error", err)
	}

	res, err = http.ReadResponse(bufio.NewReader(tlsConn), nil)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	defer res.Body.Close()

	if got, want := res.StatusCode, 400; got != want {
		t.Errorf("res.StatusCode: got %d, want %d", got, want)
	}

	got, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll(): got %v, want no error", err)
	}
	if want := []byte("modifier error"); !bytes.Equal(got, want) {
		t.Errorf("res.Body: got %q, want %q", got, want)
	}
}
Пример #8
0
func TestServeHTTPSkipRoundTrip(t *testing.T) {
	p := NewProxy(mitm)
	f := func(ctx *Context, _ *http.Request) error {
		ctx.SkipRoundTrip = true
		return nil
	}
	p.SetRequestModifier(RequestModifierFunc(f))

	p.RoundTripper = RoundTripFunc(func(*http.Request) (*http.Response, error) {
		t.Fatal("RoundTrip(): got called, want skipped")
		return nil, nil
	})

	rc, wc := pipeWithTimeout()
	defer rc.Close()
	defer wc.Close()

	rw := newHijackRecorder(wc)
	req, err := http.NewRequest("CONNECT", "//www.example.com:443", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no error", err)
	}

	go p.ServeHTTP(rw, req)

	res, err := http.ReadResponse(bufio.NewReader(rc), req)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	res.Body.Close()

	tlsConn := tlsClient(rc, p.mitm.Authority, "www.example.com")
	req, err = http.NewRequest("GET", "https://www.example.com/", nil)
	if err != nil {
		t.Fatalf("http.NewRequest(): got %v, want no error", err)
	}
	req.Header.Set("Connection", "close")

	if err := req.Write(tlsConn); err != nil {
		t.Fatalf("req.Write(): got %v, want no error", err)
	}

	res, err = http.ReadResponse(bufio.NewReader(tlsConn), nil)
	if err != nil {
		t.Fatalf("http.ReadResponse(): got %v, want no error", err)
	}
	defer res.Body.Close()

	if got, want := res.StatusCode, 200; got != want {
		t.Errorf("res.StatusCode: got %d, want %d", got, want)
	}
}
Пример #9
0
func (st *supervisorTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if req.URL == nil {
		return nil, errors.New("unix: nil Request.URL")
	}

	if req.Header == nil {
		return nil, errors.New("unix: nil Request.Header")
	}

	if req.URL.Scheme != "unix" {
		panic("unix: unsupported protocol scheme")
	}

	sock, err := net.Dial("unix", req.URL.Path)
	if err != nil {
		return nil, err
	}
	defer sock.Close()

	//create shallow copy of request object
	newReq := new(http.Request)
	*newReq = *req

	newReq.URL = supervisorURL
	newReq.Write(sock)

	return http.ReadResponse(bufio.NewReader(sock), req)
}
Пример #10
0
func parseSearchResponse(httpResponse io.Reader, responseAddr *net.UDPAddr) (*SearchResponse, error) {
	reader := bufio.NewReader(httpResponse)
	request := &http.Request{} // Needed for ReadResponse but doesn't have to be real
	response, err := http.ReadResponse(reader, request)
	if err != nil {
		return nil, err
	}
	headers := response.Header

	res := &SearchResponse{}

	res.Control = headers.Get("cache-control")
	res.Server = headers.Get("server")
	res.ST = headers.Get("st")
	res.Ext = headers.Get("ext")
	res.USN = headers.Get("usn")
	res.ResponseAddr = responseAddr

	if headers.Get("location") != "" {
		res.Location, err = response.Location()
		if err != nil {
			return nil, err
		}
	}

	date := headers.Get("date")
	if date != "" {
		res.Date, err = http.ParseTime(date)
		if err != nil {
			return nil, err
		}
	}

	return res, nil
}
Пример #11
0
func (c *Client) do(method, path string, doOptions doOptions) ([]byte, int, error) {
	var params io.Reader
	if doOptions.data != nil || doOptions.forceJSON {
		buf, err := json.Marshal(doOptions.data)
		if err != nil {
			return nil, -1, err
		}
		params = bytes.NewBuffer(buf)
	}
	if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
		err := c.checkAPIVersion()
		if err != nil {
			return nil, -1, err
		}
	}
	req, err := http.NewRequest(method, c.getURL(path), params)
	if err != nil {
		return nil, -1, err
	}
	req.Header.Set("User-Agent", userAgent)
	if doOptions.data != nil {
		req.Header.Set("Content-Type", "application/json")
	} else if method == "POST" {
		req.Header.Set("Content-Type", "plain/text")
	}
	var resp *http.Response
	protocol := c.endpointURL.Scheme
	address := c.endpointURL.Path
	if protocol == "unix" {
		var dial net.Conn
		dial, err = net.Dial(protocol, address)
		if err != nil {
			return nil, -1, err
		}
		defer dial.Close()
		breader := bufio.NewReader(dial)
		err = req.Write(dial)
		if err != nil {
			return nil, -1, err
		}
		resp, err = http.ReadResponse(breader, req)
	} else {
		resp, err = c.HTTPClient.Do(req)
	}
	if err != nil {
		if strings.Contains(err.Error(), "connection refused") {
			return nil, -1, ErrConnectionRefused
		}
		return nil, -1, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, -1, err
	}
	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		return nil, resp.StatusCode, newError(resp.StatusCode, body)
	}
	return body, resp.StatusCode, nil
}
Пример #12
0
// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
// request (both keep-alive), when a Handler never writes any
// response, the net/http package adds a "Content-Length: 0" response
// header.
func TestContentLengthZero(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}))
	defer ts.Close()

	for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
		if err != nil {
			t.Fatalf("error dialing: %v", err)
		}
		_, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
		if err != nil {
			t.Fatalf("error writing: %v", err)
		}
		req, _ := http.NewRequest("GET", "/", nil)
		res, err := http.ReadResponse(bufio.NewReader(conn), req)
		if err != nil {
			t.Fatalf("error reading response: %v", err)
		}
		if te := res.TransferEncoding; len(te) > 0 {
			t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
		}
		if cl := res.ContentLength; cl != 0 {
			t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
		}
		conn.Close()
	}
}
Пример #13
0
// 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) {
	check(t)
	if runtime.GOOS == "windows" {
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	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 {
		return isProcessRunning(t, pid)
	}

	if !childRunning() {
		t.Fatalf("pre-conn.Close, expected child to be running")
	}
	conn.Close()

	tries := 0
	for tries < 25 && childRunning() {
		time.Sleep(50 * time.Millisecond * time.Duration(tries))
		tries++
	}
	if childRunning() {
		t.Fatalf("post-conn.Close, expected child to be gone")
	}
}
Пример #14
0
func parseResponse(msg, hostPort string) *ResponseMessage {
	resp, err := http.ReadResponse(bufio.NewReader(strings.NewReader(msg)), nil)
	if err != nil {
		return nil
	}
	defer resp.Body.Close()

	maxAge := -1
	if cc := resp.Header.Get("CACHE-CONTROL"); cc != "" {
		subMatch := cacheControlAge.FindStringSubmatch(cc)
		if len(subMatch) == 2 {
			maxAgeInt64, err := strconv.ParseInt(subMatch[1], 10, 0)
			if err == nil {
				maxAge = int(maxAgeInt64)
			}
		}
	}
	usn := resp.Header.Get("USN")
	deviceId, urn := extractUrnDeviceIdFromUsn(usn)

	respMessage := ResponseMessage{
		MaxAge:      maxAge,
		SearchType:  resp.Header.Get("ST"),
		Usn:         usn,
		Urn:         urn,
		DeviceId:    deviceId,
		Location:    resp.Header.Get("LOCATION"),
		Server:      resp.Header.Get("SERVER"),
		RawResponse: resp,
	}
	return &respMessage
}
Пример #15
0
func (this Tunnel) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	conn, err := this.session.Open()
	if err != nil {
		log.Println(err.Error())
		response.Write([]byte("<html><body>" + err.Error() + "</body></html>"))
		return
	}
	defer conn.Close()

	if err := request.Write(conn); err != nil {
		log.Println(err.Error())
		return
	}

	tunnelResponse, err := http.ReadResponse(bufio.NewReader(conn), request)
	if err != nil {
		response.Write([]byte("<html><body>" + err.Error() + "</body></html>"))
		return
	}

	for header, values := range tunnelResponse.Header {
		for _, value := range values {
			response.Header().Add(header, value)
		}
	}

	response.WriteHeader(tunnelResponse.StatusCode)
	if tunnelResponse.Body != nil {
		io.Copy(response, tunnelResponse.Body)
	}
}
Пример #16
0
func (teller *GoTeller) sendRequest(fileIndex uint32, filename string, to ipaddr.IPAddr, onResponse func(error, uint32, string, *http.Response)) {
	endpoint := to.String()
	path := fmt.Sprintf("/get/%d/%s", fileIndex, filename)
	req, err := http.NewRequest("GET", "http://"+endpoint+path, nil)
	if err != nil {
		onResponse(err, fileIndex, filename, nil)
		return
	}
	conn, err := net.Dial("tcp", endpoint)
	if err != nil {
		onResponse(err, fileIndex, filename, nil)
		return
	}
	err = req.Write(conn)
	if err != nil {
		onResponse(err, fileIndex, filename, nil)
		return
	}

	connReader := bufio.NewReader(conn)
	res, err := http.ReadResponse(connReader, req)
	if err != nil {
		onResponse(err, fileIndex, filename, nil)
		return
	}

	onResponse(nil, fileIndex, filename, res)
}
Пример #17
0
// handleConnection is spawned once per connection from a client, and exits when the client is
// done sending requests.
func handleConnection(conn net.Conn) {
	defer conn.Close()
	reader := bufio.NewReader(conn)

	for {
		req, err := http.ReadRequest(reader)
		if err != nil {
			if err != io.EOF {
				log.Printf("Failed to read request: %s", err)
			}
			return
		}

		// Connect to a backend and send the request along.
		if be, err := net.Dial("tcp", "127.0.0.1:8081"); err == nil {
			be_reader := bufio.NewReader(be)
			if err := req.Write(be); err == nil {
				if resp, err := http.ReadResponse(be_reader, req); err == nil {
					FixHttp10Response(resp, req)
					if err := resp.Write(conn); err == nil {
						log.Printf("proxied %s: got %d", req.URL.Path, resp.StatusCode)
					}
					if resp.Close {
						return
					}
				}
			}
		}
	}
}
Пример #18
0
// issue #177
func (s *S) TestRequestURIEscaping(c *C) {
	l := s.newHTTPListener(c)
	defer l.Close()
	var prefix string
	uri := "/O08YqxVCf6KRJM6I8p594tzJizQ=/200x300/filters:no_upscale()/http://i.imgur.com/Wru0cNM.jpg?foo=bar"
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		c.Assert(req.RequestURI, Equals, prefix+uri)
	}))
	defer srv.Close()

	addHTTPRoute(c, l)

	discoverdRegisterHTTP(c, l, srv.Listener.Addr().String())

	for _, prefix = range []string{"", "http://example.com"} {
		conn, err := net.Dial("tcp", l.Addr)
		c.Assert(err, IsNil)
		defer conn.Close()

		fmt.Fprintf(conn, "GET %s HTTP/1.1\r\nHost: example.com\r\n\r\n", prefix+uri)
		res, err := http.ReadResponse(bufio.NewReader(conn), nil)
		c.Assert(err, IsNil)
		c.Assert(res.StatusCode, Equals, 200)
	}
}
Пример #19
0
func (p *Proxy) connect(req *http.Request) (*http.Response, net.Conn, error) {
	if p.proxyURL != nil {
		log.Debugf("martian: CONNECT with downstream proxy: %s", p.proxyURL.Host)

		conn, err := net.Dial("tcp", p.proxyURL.Host)
		if err != nil {
			return nil, nil, err
		}
		pbw := bufio.NewWriter(conn)
		pbr := bufio.NewReader(conn)

		req.Write(pbw)
		pbw.Flush()

		res, err := http.ReadResponse(pbr, req)
		if err != nil {
			return nil, nil, err
		}

		return res, conn, nil
	}

	log.Debugf("martian: CONNECT to host directly: %s", req.URL.Host)

	conn, err := net.Dial("tcp", req.URL.Host)
	if err != nil {
		return nil, nil, err
	}

	return proxyutil.NewResponse(200, nil, req), conn, nil
}
Пример #20
0
func (f *FetchServer) decodeResponse(resp *http.Response) (resp1 *http.Response, err error) {
	if resp.StatusCode != 200 {
		return resp, nil
	}

	var hdrLen uint16
	if err = binary.Read(resp.Body, binary.BigEndian, &hdrLen); err != nil {
		return
	}

	hdrBuf := make([]byte, hdrLen)
	if _, err = io.ReadFull(resp.Body, hdrBuf); err != nil {
		return
	}

	resp1, err = http.ReadResponse(bufio.NewReader(flate.NewReader(bytes.NewReader(hdrBuf))), resp.Request)
	if err != nil {
		return
	}

	data, _ := ioutil.ReadAll(resp.Body)

	resp1.Body = httpproxy.NewMultiReadCloser(bytes.NewReader(data), resp.Body)

	return
}
Пример #21
0
func dialHTTP(network, address, codecName string, cFactory ClientCodecFactory, auth bool, connectTimeout time.Duration, config *tls.Config) (*rpc.Client, error) {
	var err error
	var conn net.Conn
	if connectTimeout != 0 {
		conn, err = net.DialTimeout(network, address, connectTimeout)
	} else {
		conn, err = net.Dial(network, address)
	}
	if err != nil {
		return nil, err
	}

	if config != nil {
		conn = tls.Client(conn, config)
	}

	_, err = io.WriteString(conn, "CONNECT "+GetRpcPath(codecName, auth)+" HTTP/1.0\n\n")
	if err != nil {
		return nil, err
	}

	// Require successful HTTP response
	// before switching to RPC protocol.
	buffered := NewBufferedConnection(conn)
	resp, err := http.ReadResponse(buffered.Reader, &http.Request{Method: "CONNECT"})
	if err == nil && resp.Status == connected {
		return rpc.NewClientWithCodec(cFactory(buffered)), nil
	}
	if err == nil {
		err = errors.New("unexpected HTTP response: " + resp.Status)
	}
	conn.Close()
	return nil, &net.OpError{Op: "dial-http", Net: network + " " + address, Addr: nil, Err: err}
}
Пример #22
0
func (t *transport) UpgradeHTTP(req *http.Request, l log15.Logger) (*http.Response, net.Conn, error) {
	stickyBackend := t.getStickyBackend(req)
	backends := t.getOrderedBackends(stickyBackend, req)
	upconn, addr, err := dialTCP(context.Background(), l, backends)
	if err != nil {
		status := http.StatusServiceUnavailable
		if err == errTimeout {
			status = http.StatusGatewayTimeout
		}
		l.Error("dial failed", "status", status, "num_backends", len(backends))
		return nil, nil, err
	}
	conn := &streamConn{bufio.NewReader(upconn), upconn}
	req.URL.Host = addr

	if err := req.Write(conn); err != nil {
		conn.Close()
		l.Error("error writing request", "err", err, "backend", addr)
		return nil, nil, err
	}
	res, err := http.ReadResponse(conn.Reader, req)
	if err != nil {
		conn.Close()
		l.Error("error reading response", "err", err, "backend", addr)
		return nil, nil, err
	}
	t.setStickyBackend(res, stickyBackend)
	return res, conn, nil
}
Пример #23
0
// DialHTTPPath connects to an HTTP RPC server
// at the specified network address and path.
func DialHTTPPath(network, address, path string) (*Client, error) {
	var err 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 = errors.New("unexpected HTTP response: " + resp.Status)
	}
	conn.Close()
	return nil, &net.OpError{
		Op:   "dial-http",
		Net:  network + " " + address,
		Addr: nil,
		Err:  err,
	}
}
Пример #24
0
func (f *FetchServer) decodeResponse(resp *http.Response) (resp1 *http.Response, err error) {
	if resp.StatusCode != 200 {
		return resp, nil
	}

	var hdrLen uint16
	if err = binary.Read(resp.Body, binary.BigEndian, &hdrLen); err != nil {
		return
	}

	hdrBuf := make([]byte, hdrLen)
	if _, err = io.ReadFull(resp.Body, hdrBuf); err != nil {
		return
	}

	resp1, err = http.ReadResponse(bufio.NewReader(flate.NewReader(bytes.NewReader(hdrBuf))), resp.Request)
	if err != nil {
		return
	}

	const cookieKey string = "Set-Cookie"
	if cookie := resp1.Header.Get(cookieKey); cookie != "" {
		parts := strings.Split(cookie, ", ")

		parts1 := make([]string, 0)
		for i := 0; i < len(parts); i++ {
			c := parts[i]
			if i == 0 || strings.Contains(strings.Split(c, ";")[0], "=") {
				parts1 = append(parts1, c)
			} else {
				parts1[len(parts1)-1] = parts1[len(parts1)-1] + ", " + c
			}
		}

		resp1.Header.Del(cookieKey)
		for i := 0; i < len(parts1); i++ {
			resp1.Header.Add(cookieKey, parts1[i])
		}
	}

	if resp1.StatusCode >= 400 {
		switch {
		case resp.Body == nil:
			break
		case resp1.Body == nil:
			resp1.Body = resp.Body
		default:
			b, _ := ioutil.ReadAll(resp1.Body)
			if b != nil && len(b) > 0 {
				resp1.Body = httpproxy.NewMultiReadCloser(bytes.NewReader(b), resp.Body)
			} else {
				resp1.Body = resp.Body
			}
		}
	} else {
		resp1.Body = resp.Body
	}

	return
}
Пример #25
0
func doHTTP(s *shim, conf *tls.Config) error {
	// TODO: support http proxies
	c := tls.Client(s, conf)
	s.Start()
	err := c.Handshake()
	s.Stop()
	if err != nil {
		return fmt.Errorf("http handshake failed: %s", err)
	}
	req, _ := http.NewRequest("GET", "/", nil)
	req.Host = conf.ServerName
	req.Header = httpHeaders
	if err := req.Write(c); err != nil {
		return fmt.Errorf("http request write failed: %s", err)
	}
	b := bufio.NewReader(c)
	resp, err := http.ReadResponse(b, req)
	if err != nil {
		return fmt.Errorf("http response read failed: %s", err)
	}
	resp.Body.Close()
	if err := c.Close(); err != nil {
		return fmt.Errorf("http close failed: %s", err)
	}
	return nil
}
Пример #26
0
// fetch html from a WARC file
// returns: html, url, err
func fromWARC(filename string) ([]byte, string, error) {
	in, err := os.Open(filename)
	if err != nil {
		return nil, "", err
	}
	defer in.Close()

	warcReader := warc.NewReader(in)
	for {
		//	fmt.Printf("WARC\n")
		rec, err := warcReader.ReadRecord()
		if err != nil {
			return nil, "", fmt.Errorf("Error reading %s: %s", filename, err)
		}
		if rec.Header.Get("Warc-Type") != "response" {
			continue
		}
		reqURL := rec.Header.Get("Warc-Target-Uri")
		// parse response, grab raw html
		rdr := bufio.NewReader(bytes.NewReader(rec.Block))
		response, err := http.ReadResponse(rdr, nil)
		if err != nil {
			return nil, "", fmt.Errorf("Error parsing response: %s", err)
		}
		defer response.Body.Close()
		if response.StatusCode != 200 {
			return nil, "", fmt.Errorf("HTTP error: %d", response.StatusCode)
		}
		rawHTML, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, "", err
		}
		return rawHTML, reqURL, err
	}
}
Пример #27
0
func TestResponseError(t *testing.T) {
	message := "Something went seriously wrong."
	raw := "HTTP/1.1 500 Internal Server Error\r\n" +
		"\r\n" +
		`{"status":500,"error":"` + message + `"}` + "\r\n"
	r := bufio.NewReader(strings.NewReader(raw))

	resp, err := http.ReadResponse(r, nil)
	if err != nil {
		t.Fatal(err)
	}
	err = checkResponse(resp)
	if err == nil {
		t.Fatalf("expected error; got: %v", err)
	}

	// Check for correct error message
	expected := fmt.Sprintf("elastic: Error %d (%s): %s", resp.StatusCode, http.StatusText(resp.StatusCode), message)
	got := err.Error()
	if got != expected {
		t.Fatalf("expected %q; got: %q", expected, got)
	}

	// Check that error is of type *elastic.Error, which contains additional information
	e, ok := err.(*Error)
	if !ok {
		t.Fatal("expected error to be of type *elastic.Error")
	}
	if e.Status != resp.StatusCode {
		t.Fatalf("expected status code %d; got: %d", resp.StatusCode, e.Status)
	}
	if e.Message != message {
		t.Fatalf("expected error message %q; got: %q", message, e.Message)
	}
}
Пример #28
0
func (t testTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	var raw string

	switch req.URL.Path {
	case "/ok":
		raw = "HTTP/1.1 200 OK\n\n"
	case "/error":
		return nil, errors.New("http protocol error")
	case "/nocontent":
		raw = "HTTP/1.1 204 No Content\n\n"
	case "/etag":
		raw = "HTTP/1.1 200 OK\nEtag: \"tag\"\n\n"
	case "/png":
		m := image.NewNRGBA(image.Rect(0, 0, 1, 1))
		img := new(bytes.Buffer)
		png.Encode(img, m)

		raw = fmt.Sprintf("HTTP/1.1 200 OK\nContent-Length: %d\n\n%s", len(img.Bytes()), img.Bytes())
	default:
		raw = "HTTP/1.1 404 Not Found\n\n"
	}

	buf := bufio.NewReader(bytes.NewBufferString(raw))
	return http.ReadResponse(buf, req)
}
Пример #29
0
// RoundTrip executes the Request and upgrades it. After a successful upgrade,
// clients may call SpdyRoundTripper.Connection() to retrieve the upgraded
// connection.
func (s *SpdyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	// TODO what's the best way to clone the request?
	r := *req
	req = &r
	req.Header.Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
	req.Header.Add(httpstream.HeaderUpgrade, HeaderSpdy31)

	conn, err := s.dial(req)
	if err != nil {
		return nil, err
	}

	err = req.Write(conn)
	if err != nil {
		return nil, err
	}

	resp, err := http.ReadResponse(bufio.NewReader(conn), req)
	if err != nil {
		return nil, err
	}

	s.conn = conn

	return resp, nil
}
Пример #30
0
// handleConnection is spawned once per connection from a client,
// and exits when the client is done sending requests
func handleConnection(conn net.Conn) {
	// always close the conn no matter how this function exits:
	defer conn.Close()
	reader := bufio.NewReader(conn)
	// loop to handle multiple requests from user conn,
	// since we are now running concurrently:
	for {
		req, err := http.ReadRequest(reader)
		if err != nil {
			if err != io.EOF {
				log.Printf("Failed to read request: %s", err)
			}
			return
		}
		// connect to a backend and send the request along
		if be, err := net.Dial("tcp", "127.0.0.1:8081"); err == nil {
			be_reader := bufio.NewReader(be)
			if err := req.Write(be); err == nil {
				if resp, err := http.ReadResponse(be_reader, req); err == nil {
					FixHttp10Response(resp, req)
					if err := resp.Write(conn); err == nil {
						log.Printf("proxied %s: got %d", req.URL.Path, resp.StatusCode)
					}
					if resp.Close {
						return
					}
				}
			}
		}
	}
}