Files
acme-dns/vendor/github.com/gavv/httpexpect/binder_test.go
2018-01-22 11:19:33 +02:00

371 lines
8.3 KiB
Go

package httpexpect
import (
"bufio"
"crypto/tls"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/valyala/fasthttp"
)
type mockHandler struct {
t *testing.T
https bool
http10 bool
chunked bool
}
func (c *mockHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
body, err := ioutil.ReadAll(req.Body)
assert.True(c.t, err == nil)
if c.http10 {
assert.Equal(c.t, "HTTP/1.0", req.Proto)
assert.Equal(c.t, 1, req.ProtoMajor)
assert.Equal(c.t, 0, req.ProtoMinor)
} else {
assert.Equal(c.t, "HTTP/1.1", req.Proto)
assert.Equal(c.t, 1, req.ProtoMajor)
assert.Equal(c.t, 1, req.ProtoMinor)
}
if c.https {
assert.Equal(c.t, "https://example.com/path", req.URL.String())
} else {
assert.Equal(c.t, "http://example.com/path", req.URL.String())
}
assert.Equal(c.t, "/path", req.URL.RequestURI())
assert.Equal(c.t, "/path", req.RequestURI)
assert.Equal(c.t, "GET", req.Method)
assert.Equal(c.t, "body", string(body))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, err = w.Write([]byte(`{"hello":"world"}`))
if c.chunked {
w.(http.Flusher).Flush()
}
assert.True(c.t, err == nil)
}
func TestBinder(t *testing.T) {
handler := &mockHandler{
t: t,
http10: true,
chunked: false,
}
client := &http.Client{
Transport: NewBinder(handler),
}
req, err := http.NewRequest("GET", "http://example.com/path", strings.NewReader("body"))
if err != nil {
t.Fatal(err)
}
req.ProtoMajor = 1
req.ProtoMinor = 0
req.Proto = ""
resp, err := client.Do(req)
if err != nil {
t.Fatal(err)
}
header := http.Header{
"Content-Type": {"application/json"},
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, header, resp.Header)
assert.Equal(t, `{"hello":"world"}`, string(b))
assert.Equal(t, []string(nil), resp.TransferEncoding)
}
func TestBinderTLS(t *testing.T) {
handler := &mockHandler{t: t}
httpClient := &http.Client{
Transport: &Binder{
Handler: handler,
TLS: nil,
},
}
tlsState := &tls.ConnectionState{}
httpsClient := &http.Client{
Transport: &Binder{
Handler: handler,
TLS: tlsState,
},
}
handler.https = false
req, _ := http.NewRequest("GET", "http://example.com/path", strings.NewReader("body"))
resp, err := httpClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.Nil(t, req.TLS)
handler.https = true
req, _ = http.NewRequest("GET", "https://example.com/path", strings.NewReader("body"))
resp, err = httpClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.Nil(t, req.TLS)
handler.https = false
req, _ = http.NewRequest("GET", "http://example.com/path", strings.NewReader("body"))
resp, err = httpsClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.Nil(t, req.TLS)
handler.https = true
req, _ = http.NewRequest("GET", "https://example.com/path", strings.NewReader("body"))
resp, err = httpsClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.NotNil(t, req.TLS)
assert.Equal(t, tlsState, req.TLS)
}
func TestBinderChunked(t *testing.T) {
handler := &mockHandler{
t: t,
chunked: true,
}
client := &http.Client{
Transport: NewBinder(handler),
}
req, err := http.NewRequest("GET", "http://example.com/path", strings.NewReader("body"))
if err != nil {
t.Fatal(err)
}
req.ContentLength = -1
resp, err := client.Do(req)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, []string{"chunked"}, req.TransferEncoding)
assert.Equal(t, []string{"chunked"}, resp.TransferEncoding)
}
func TestFastBinder(t *testing.T) {
handler := func(ctx *fasthttp.RequestCtx) {
assert.Equal(t, "POST", string(ctx.Request.Header.Method()))
assert.Equal(t, "http://example.com/path", string(ctx.Request.Header.RequestURI()))
assert.Equal(t, "application/x-www-form-urlencoded",
string(ctx.Request.Header.ContentType()))
headers := map[string][]string{}
ctx.Request.Header.VisitAll(func(k, v []byte) {
headers[string(k)] = append(headers[string(k)], string(v))
})
expected := map[string][]string{
"Content-Type": {"application/x-www-form-urlencoded"},
"Content-Length": {"7"},
"Some-Header": {"foo", "bar"},
}
assert.Equal(t, expected, headers)
assert.Equal(t, "bar", string(ctx.FormValue("foo")))
assert.Equal(t, "foo=bar", string(ctx.Request.Body()))
ctx.Response.Header.Set("Content-Type", "application/json")
ctx.Response.SetBody([]byte(`{"hello":"world"}`))
}
client := &http.Client{
Transport: NewFastBinder(handler),
}
req, err := http.NewRequest(
"POST", "http://example.com/path", strings.NewReader("foo=bar"))
if err != nil {
t.Fatal(err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Some-Header", "foo")
req.Header.Add("Some-Header", "bar")
resp, err := client.Do(req)
if err != nil {
t.Fatal(err)
}
header := http.Header{
"Content-Type": {"application/json"},
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, header, resp.Header)
assert.Equal(t, `{"hello":"world"}`, string(b))
assert.Equal(t, []string(nil), resp.TransferEncoding)
}
func TestFastBinderTLS(t *testing.T) {
var isHTTPS, isTLS bool
tlsState := &tls.ConnectionState{}
handler := func(ctx *fasthttp.RequestCtx) {
isHTTPS = strings.HasPrefix(string(ctx.Request.Header.RequestURI()), "https://")
isTLS = ctx.IsTLS()
if isTLS {
assert.Equal(t, *tlsState, *ctx.TLSConnectionState())
}
}
httpClient := &http.Client{
Transport: &FastBinder{
Handler: handler,
TLS: nil,
},
}
httpsClient := &http.Client{
Transport: &FastBinder{
Handler: handler,
TLS: tlsState,
},
}
req, _ := http.NewRequest("GET", "http://example.com/path", strings.NewReader("body"))
resp, err := httpClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.False(t, isHTTPS)
assert.False(t, isTLS)
req, _ = http.NewRequest("GET", "https://example.com/path", strings.NewReader("body"))
resp, err = httpClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.True(t, isHTTPS)
assert.False(t, isTLS)
req, _ = http.NewRequest("GET", "http://example.com/path", strings.NewReader("body"))
resp, err = httpsClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.False(t, isHTTPS)
assert.False(t, isTLS)
req, _ = http.NewRequest("GET", "https://example.com/path", strings.NewReader("body"))
resp, err = httpsClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.True(t, isHTTPS)
assert.True(t, isTLS)
}
func TestFastBinderChunked(t *testing.T) {
handler := func(ctx *fasthttp.RequestCtx) {
assert.Equal(t, "POST", string(ctx.Request.Header.Method()))
assert.Equal(t, "http://example.com/path", string(ctx.Request.Header.RequestURI()))
assert.Equal(t, "application/x-www-form-urlencoded",
string(ctx.Request.Header.ContentType()))
headers := map[string][]string{}
ctx.Request.Header.VisitAll(func(k, v []byte) {
headers[string(k)] = append(headers[string(k)], string(v))
})
expected := map[string][]string{
"Content-Type": {"application/x-www-form-urlencoded"},
"Transfer-Encoding": {"chunked"},
}
assert.Equal(t, expected, headers)
assert.Equal(t, "bar", string(ctx.FormValue("foo")))
assert.Equal(t, "foo=bar", string(ctx.Request.Body()))
ctx.Response.Header.Set("Content-Type", "application/json")
ctx.Response.SetBodyStreamWriter(func(w *bufio.Writer) {
w.WriteString(`[1, `)
w.Flush()
w.WriteString(`2]`)
})
}
client := &http.Client{
Transport: NewFastBinder(handler),
}
req, err := http.NewRequest(
"POST", "http://example.com/path", strings.NewReader("foo=bar"))
if err != nil {
t.Fatal(err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.ContentLength = -1
resp, err := client.Do(req)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, []string{"chunked"}, resp.TransferEncoding)
}
func TestFastBinderEmptyResponse(t *testing.T) {
handler := func(*fasthttp.RequestCtx) {}
client := &http.Client{
Transport: NewFastBinder(handler),
}
req, err := http.NewRequest("POST", "http://example.com/path", nil)
if err != nil {
t.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
t.Fatal(err)
}
assert.False(t, resp.Body == nil)
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, "", string(b))
}