mirror of
https://github.com/acme-dns/acme-dns.git
synced 2026-02-25 04:45:34 -07:00
371 lines
8.3 KiB
Go
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))
|
|
}
|