mirror of
https://github.com/hanzoai/oxy.git
synced 2026-09-30 23:42:31 +00:00
395 lines
11 KiB
Go
395 lines
11 KiB
Go
package buffer
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/vulcand/oxy/forward"
|
|
"github.com/vulcand/oxy/testutils"
|
|
"github.com/vulcand/oxy/utils"
|
|
)
|
|
|
|
func TestSimple(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr)
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, body, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
assert.Equal(t, "hello", string(body))
|
|
}
|
|
|
|
func TestChunkedEncodingSuccess(t *testing.T) {
|
|
var reqBody string
|
|
var contentLength int64
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
body, err := ioutil.ReadAll(req.Body)
|
|
require.NoError(t, err)
|
|
reqBody = string(body)
|
|
contentLength = req.ContentLength
|
|
w.Write([]byte("hello"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr)
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
conn, err := net.Dial("tcp", testutils.ParseURI(proxy.URL).Host)
|
|
require.NoError(t, err)
|
|
|
|
fmt.Fprintf(conn, "POST / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nTransfer-Encoding: chunked\r\n\r\n4\r\ntest\r\n5\r\ntest1\r\n5\r\ntest2\r\n0\r\n\r\n")
|
|
status, err := bufio.NewReader(conn).ReadString('\n')
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "testtest1test2", reqBody)
|
|
assert.Equal(t, "HTTP/1.1 200 OK\r\n", status)
|
|
assert.EqualValues(t, len(reqBody), contentLength)
|
|
}
|
|
|
|
func TestChunkedEncodingLimitReached(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr, MemRequestBodyBytes(4), MaxRequestBodyBytes(8))
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
conn, err := net.Dial("tcp", testutils.ParseURI(proxy.URL).Host)
|
|
require.NoError(t, err)
|
|
fmt.Fprint(conn, "POST / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nTransfer-Encoding: chunked\r\n\r\n4\r\ntest\r\n5\r\ntest1\r\n5\r\ntest2\r\n0\r\n\r\n")
|
|
status, err := bufio.NewReader(conn).ReadString('\n')
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "HTTP/1.1 413 Request Entity Too Large\r\n", status)
|
|
}
|
|
|
|
func TestChunkedResponse(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
h := w.(http.Hijacker)
|
|
conn, _, _ := h.Hijack()
|
|
fmt.Fprintf(conn, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n4\r\ntest\r\n5\r\ntest1\r\n5\r\ntest2\r\n0\r\n\r\n")
|
|
conn.Close()
|
|
})
|
|
defer srv.Close()
|
|
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
st, err := New(rdr)
|
|
require.NoError(t, err)
|
|
proxy := httptest.NewServer(st)
|
|
|
|
defer proxy.Close()
|
|
|
|
re, body, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "testtest1test2", string(body))
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
assert.Equal(t, strconv.Itoa(len("testtest1test2")), re.Header.Get("Content-Length"))
|
|
}
|
|
|
|
func TestRequestLimitReached(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr, MaxRequestBodyBytes(4))
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, _, err := testutils.Get(proxy.URL, testutils.Body("this request is too long"))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusRequestEntityTooLarge, re.StatusCode)
|
|
}
|
|
|
|
func TestResponseLimitReached(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello, this response is too large"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr, MaxResponseBodyBytes(4))
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, _, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusInternalServerError, re.StatusCode)
|
|
}
|
|
|
|
func TestFileStreamingResponse(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello, this response is too large to fit in memory"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr, MemResponseBodyBytes(4))
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, body, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
assert.Equal(t, "hello, this response is too large to fit in memory", string(body))
|
|
}
|
|
|
|
func TestCustomErrorHandler(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello, this response is too large"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
errHandler := utils.ErrorHandlerFunc(func(w http.ResponseWriter, req *http.Request, err error) {
|
|
w.WriteHeader(http.StatusTeapot)
|
|
w.Write([]byte(http.StatusText(http.StatusTeapot)))
|
|
})
|
|
st, err := New(rdr, MaxResponseBodyBytes(4), ErrorHandler(errHandler))
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, _, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusTeapot, re.StatusCode)
|
|
}
|
|
|
|
func TestNotModified(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.WriteHeader(http.StatusNotModified)
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr)
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, _, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusNotModified, re.StatusCode)
|
|
}
|
|
|
|
func TestNoBody(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr)
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, _, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
}
|
|
|
|
// Make sure that stream handler preserves TLS settings
|
|
func TestPreservesTLS(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("ok"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
var cs *tls.ConnectionState
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
cs = req.TLS
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr)
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewUnstartedServer(st)
|
|
proxy.StartTLS()
|
|
defer proxy.Close()
|
|
|
|
re, _, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
assert.NotNil(t, cs)
|
|
}
|
|
|
|
func TestNotNilBody(t *testing.T) {
|
|
srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Write([]byte("hello"))
|
|
})
|
|
defer srv.Close()
|
|
|
|
// forwarder will proxy the request to whatever destination
|
|
fwd, err := forward.New()
|
|
require.NoError(t, err)
|
|
|
|
// this is our redirect to server
|
|
rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
req.URL = testutils.ParseURI(srv.URL)
|
|
// During a request check if the request body is no nil before sending to the next middleware
|
|
// Because we can send a POST request without body
|
|
assert.NotNil(t, req.Body)
|
|
fwd.ServeHTTP(w, req)
|
|
})
|
|
|
|
// stream handler will forward requests to redirect
|
|
st, err := New(rdr, MaxRequestBodyBytes(10))
|
|
require.NoError(t, err)
|
|
|
|
proxy := httptest.NewServer(st)
|
|
defer proxy.Close()
|
|
|
|
re, body, err := testutils.Get(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
assert.Equal(t, "hello", string(body))
|
|
|
|
re, body, err = testutils.Post(proxy.URL)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, http.StatusOK, re.StatusCode)
|
|
assert.Equal(t, "hello", string(body))
|
|
}
|