added tests and did some refactoring
This commit is contained in:
parent
8dd13008d9
commit
6feef3f97d
|
@ -56,20 +56,40 @@ func (h *HTTPResponse) SampleConfig() string {
|
||||||
// ErrRedirectAttempted indicates that a redirect occurred
|
// ErrRedirectAttempted indicates that a redirect occurred
|
||||||
var ErrRedirectAttempted = errors.New("redirect")
|
var ErrRedirectAttempted = errors.New("redirect")
|
||||||
|
|
||||||
|
// CreateHttpClient creates an http client which will timeout at the specified
|
||||||
|
// timeout period and can follow redirects if specified
|
||||||
|
func CreateHttpClient(followRedirects bool, ResponseTimeout time.Duration) *http.Client {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * ResponseTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
if followRedirects == false {
|
||||||
|
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||||
|
return ErrRedirectAttempted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseHeaders takes a string of newline seperated http headers and returns a
|
||||||
|
// http.Header object. An error is returned if the headers cannot be parsed.
|
||||||
|
func ParseHeaders(headers string) (http.Header, error) {
|
||||||
|
headers = strings.TrimSpace(headers) + "\n\n"
|
||||||
|
reader := bufio.NewReader(strings.NewReader(headers))
|
||||||
|
tp := textproto.NewReader(reader)
|
||||||
|
mimeHeader, err := tp.ReadMIMEHeader()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return http.Header(mimeHeader), nil
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPGather gathers all fields and returns any errors it encounters
|
// HTTPGather gathers all fields and returns any errors it encounters
|
||||||
func (h *HTTPResponse) HTTPGather() (map[string]interface{}, error) {
|
func (h *HTTPResponse) HTTPGather() (map[string]interface{}, error) {
|
||||||
// Prepare fields
|
// Prepare fields
|
||||||
fields := make(map[string]interface{})
|
fields := make(map[string]interface{})
|
||||||
|
|
||||||
client := &http.Client{
|
client := CreateHttpClient(h.FollowRedirects, time.Duration(h.ResponseTimeout))
|
||||||
Timeout: time.Second * time.Duration(h.ResponseTimeout),
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.FollowRedirects == false {
|
|
||||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
||||||
return ErrRedirectAttempted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body io.Reader
|
var body io.Reader
|
||||||
if h.Body != "" {
|
if h.Body != "" {
|
||||||
|
@ -79,14 +99,10 @@ func (h *HTTPResponse) HTTPGather() (map[string]interface{}, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
h.Headers = strings.TrimSpace(h.Headers) + "\n\n"
|
request.Header, err = ParseHeaders(h.Headers)
|
||||||
reader := bufio.NewReader(strings.NewReader(h.Headers))
|
|
||||||
tp := textproto.NewReader(reader)
|
|
||||||
mimeHeader, err := tp.ReadMIMEHeader()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
request.Header = http.Header(mimeHeader)
|
|
||||||
// Start Timer
|
// Start Timer
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := client.Do(request)
|
resp, err := client.Do(request)
|
||||||
|
|
|
@ -0,0 +1,245 @@
|
||||||
|
package http_response
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseHeaders(t *testing.T) {
|
||||||
|
fakeHeaders := `
|
||||||
|
Accept: text/plain
|
||||||
|
Content-Type: application/json
|
||||||
|
Cache-Control: no-cache
|
||||||
|
`
|
||||||
|
headers, err := ParseHeaders(fakeHeaders)
|
||||||
|
require.NoError(t, err)
|
||||||
|
testHeaders := make(http.Header)
|
||||||
|
testHeaders.Add("Accept", "text/plain")
|
||||||
|
testHeaders.Add("Content-Type", "application/json")
|
||||||
|
testHeaders.Add("Cache-Control", "no-cache")
|
||||||
|
assert.Equal(t, testHeaders, headers)
|
||||||
|
|
||||||
|
headers, err = ParseHeaders("Accept text/plain")
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUpTestMux() http.Handler {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/redirect", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
http.Redirect(w, req, "/good", http.StatusMovedPermanently)
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/good", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
fmt.Fprintf(w, "hit the good page!")
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/badredirect", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
http.Redirect(w, req, "/badredirect", http.StatusMovedPermanently)
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/mustbepostmethod", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
if req.Method != "POST" {
|
||||||
|
http.Error(w, "method wasn't post", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "used post correctly!")
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/musthaveabody", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
body, err := ioutil.ReadAll(req.Body)
|
||||||
|
req.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "couldn't read request body", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if string(body) == "" {
|
||||||
|
http.Error(w, "body was empty", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "sent a body!")
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/twosecondnap", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
return mux
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFields(t *testing.T) {
|
||||||
|
mux := setUpTestMux()
|
||||||
|
ts := httptest.NewServer(mux)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
h := &HTTPResponse{
|
||||||
|
Address: ts.URL + "/good",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err := h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusOK, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
assert.NotNil(t, fields["response_time"])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedirects(t *testing.T) {
|
||||||
|
mux := setUpTestMux()
|
||||||
|
ts := httptest.NewServer(mux)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
h := &HTTPResponse{
|
||||||
|
Address: ts.URL + "/redirect",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err := h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusOK, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
|
||||||
|
h = &HTTPResponse{
|
||||||
|
Address: ts.URL + "/badredirect",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err = h.HTTPGather()
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMethod(t *testing.T) {
|
||||||
|
mux := setUpTestMux()
|
||||||
|
ts := httptest.NewServer(mux)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
h := &HTTPResponse{
|
||||||
|
Address: ts.URL + "/mustbepostmethod",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "POST",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err := h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusOK, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
|
||||||
|
h = &HTTPResponse{
|
||||||
|
Address: ts.URL + "/mustbepostmethod",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err = h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusMethodNotAllowed, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
|
||||||
|
//check that lowercase methods work correctly
|
||||||
|
h = &HTTPResponse{
|
||||||
|
Address: ts.URL + "/mustbepostmethod",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "head",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err = h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusMethodNotAllowed, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBody(t *testing.T) {
|
||||||
|
mux := setUpTestMux()
|
||||||
|
ts := httptest.NewServer(mux)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
h := &HTTPResponse{
|
||||||
|
Address: ts.URL + "/musthaveabody",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err := h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusOK, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
|
||||||
|
h = &HTTPResponse{
|
||||||
|
Address: ts.URL + "/musthaveabody",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 20,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
fields, err = h.HTTPGather()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, fields)
|
||||||
|
if assert.NotNil(t, fields["http_response_code"]) {
|
||||||
|
assert.Equal(t, http.StatusBadRequest, fields["http_response_code"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeout(t *testing.T) {
|
||||||
|
mux := setUpTestMux()
|
||||||
|
ts := httptest.NewServer(mux)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
h := &HTTPResponse{
|
||||||
|
Address: ts.URL + "/twosecondnap",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: 1,
|
||||||
|
Headers: `
|
||||||
|
Content-Type: application/json
|
||||||
|
`,
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
_, err := h.HTTPGather()
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
Loading…
Reference in New Issue