Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
65
pkg/httpclient/client.go
Normal file
65
pkg/httpclient/client.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HTTPClient interface
|
||||
type HTTPClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// Global
|
||||
var (
|
||||
Client HTTPClient
|
||||
)
|
||||
|
||||
func init() {
|
||||
Client = &http.Client{Timeout: 10 * time.Second}
|
||||
}
|
||||
|
||||
// Get sends a get request to the URL
|
||||
func Get(url string, headers http.Header) (*http.Response, error) {
|
||||
request, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header = headers
|
||||
return Client.Do(request)
|
||||
}
|
||||
|
||||
// Post sends a post request to the URL with the body
|
||||
func Post(url string, body interface{}, headers http.Header) (*http.Response, error) {
|
||||
jsonBytes, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(jsonBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header = headers
|
||||
return Client.Do(request)
|
||||
}
|
||||
|
||||
// Delete sends a delete request to the URL with the body
|
||||
func Delete(url string, body interface{}, headers http.Header) (*http.Response, error) {
|
||||
jsonBytes, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request, err := http.NewRequest(http.MethodDelete, url, bytes.NewReader(jsonBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header = headers
|
||||
return Client.Do(request)
|
||||
}
|
||||
|
||||
// Do sends the request
|
||||
func Do(request *http.Request) (*http.Response, error) {
|
||||
return Client.Do(request)
|
||||
}
|
||||
96
pkg/httpclient/client_test.go
Normal file
96
pkg/httpclient/client_test.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"fiskerinc.com/modules/httpclient/mock"
|
||||
)
|
||||
|
||||
const (
|
||||
jsonBody = `{"name":"test data"}`
|
||||
TestErrorTemplate = "%s test. Expected '%v'. Got '%v'"
|
||||
testURL = "https://fiskerinc.com"
|
||||
)
|
||||
|
||||
var (
|
||||
httpHeader = http.Header{"content-type": []string{"application/json"}}
|
||||
errServer = errors.New("Error from web server")
|
||||
)
|
||||
|
||||
func TestGetRequest(t *testing.T) {
|
||||
c := mock.Client{
|
||||
DoFunc: func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: 200}, nil
|
||||
},
|
||||
}
|
||||
|
||||
Client = &c
|
||||
|
||||
_, err := Get(testURL, httpHeader)
|
||||
if err != nil {
|
||||
t.Fatalf(TestErrorTemplate, "TestGetRequest", errors.New("Error from web server"), err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRequestError(t *testing.T) {
|
||||
c := mock.Client{
|
||||
DoFunc: func(*http.Request) (*http.Response, error) {
|
||||
return nil, errServer
|
||||
},
|
||||
}
|
||||
|
||||
Client = &c
|
||||
|
||||
_, err := Get(testURL, httpHeader)
|
||||
if err == nil {
|
||||
t.Fatalf(TestErrorTemplate, "TestGetRequestError", errServer, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostRequest(t *testing.T) {
|
||||
c := mock.Client{
|
||||
DoFunc: func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: 200}, nil
|
||||
},
|
||||
}
|
||||
|
||||
Client = &c
|
||||
|
||||
_, err := Post(testURL, jsonBody, httpHeader)
|
||||
if err != nil {
|
||||
t.Fatalf(TestErrorTemplate, "TestPostRequest", nil, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostRequestError(t *testing.T) {
|
||||
c := mock.Client{
|
||||
DoFunc: func(*http.Request) (*http.Response, error) {
|
||||
return nil, errServer
|
||||
},
|
||||
}
|
||||
|
||||
Client = &c
|
||||
|
||||
_, err := Post(testURL, jsonBody, httpHeader)
|
||||
if err == nil {
|
||||
t.Fatalf(TestErrorTemplate, "TestPostRequestError", errServer, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoRequest(t *testing.T) {
|
||||
Client = &mock.Client{
|
||||
DoFunc: func(*http.Request) (*http.Response, error) {
|
||||
return &http.Response{StatusCode: 200}, nil
|
||||
},
|
||||
}
|
||||
request, _ := http.NewRequest(http.MethodPost, "http://test.com", nil)
|
||||
response, err := Do(request)
|
||||
if err != nil {
|
||||
t.Errorf(TestErrorTemplate, "Response error", "nil", err)
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
t.Errorf(TestErrorTemplate, "Response status", 200, response.StatusCode)
|
||||
}
|
||||
}
|
||||
13
pkg/httpclient/mock/client.go
Normal file
13
pkg/httpclient/mock/client.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package mock
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Client is the mock client
|
||||
type Client struct {
|
||||
DoFunc func(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// Do is the mock client's version
|
||||
func (m *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
return m.DoFunc(req)
|
||||
}
|
||||
86
pkg/httpclient/tester/http_test_case.go
Normal file
86
pkg/httpclient/tester/http_test_case.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package tester
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/jeremywohl/flatten"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
th "fiskerinc.com/modules/testhelper"
|
||||
"fiskerinc.com/modules/validator"
|
||||
)
|
||||
|
||||
type HttpTestCase struct {
|
||||
Request *http.Request
|
||||
ExpectedStatus int
|
||||
ExpectedResponse string
|
||||
ExpectedRegexResponse string
|
||||
ExpectedRegexMap map[string]string
|
||||
ValidateResponse bool `default:"false"`
|
||||
Setup func()
|
||||
}
|
||||
|
||||
func (tc *HttpTestCase) Test(handler http.HandlerFunc) *httptest.ResponseRecorder {
|
||||
return th.ExecHTTPHandler(handler, tc.Request)
|
||||
}
|
||||
|
||||
func (tc *HttpTestCase) TestWithParamPath(handler http.HandlerFunc, routePath string) *httptest.ResponseRecorder {
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
router := httprouter.New()
|
||||
router.HandlerFunc(tc.Request.Method, routePath, handler)
|
||||
router.ServeHTTP(recorder, tc.Request)
|
||||
|
||||
return recorder
|
||||
}
|
||||
|
||||
func (tc *HttpTestCase) ValidateHttp(t *testing.T, name string, w *httptest.ResponseRecorder) {
|
||||
if w.Result().StatusCode != tc.ExpectedStatus {
|
||||
t.Errorf(th.TestErrorTemplate, name, tc.ExpectedStatus, w.Result().StatusCode)
|
||||
}
|
||||
|
||||
if w.Body.String() != tc.ExpectedResponse && tc.ExpectedResponse != "" {
|
||||
t.Errorf(th.TestErrorTemplate, name, tc.ExpectedResponse, w.Body.String())
|
||||
}
|
||||
|
||||
if tc.ValidateResponse {
|
||||
err := validator.ValidateStruct(w.Body)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
if tc.ExpectedRegexResponse != "" {
|
||||
body := w.Body.String()
|
||||
match, _ := regexp.MatchString(tc.ExpectedRegexResponse, body)
|
||||
if !match {
|
||||
t.Errorf(th.TestErrorTemplate, name, tc.ExpectedRegexResponse, body)
|
||||
}
|
||||
}
|
||||
|
||||
if tc.ExpectedRegexMap != nil {
|
||||
match, key, returned, _ := matchRegexMap(tc.ExpectedRegexMap, w)
|
||||
if !match {
|
||||
t.Errorf(th.TestErrorTemplate2, name, key, tc.ExpectedRegexMap[key], returned)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func matchRegexMap(regexMap map[string]string, w *httptest.ResponseRecorder) (bool, string, string, error) {
|
||||
m := make(map[string]interface{})
|
||||
err := json.Unmarshal(w.Body.Bytes(), &m)
|
||||
flatmap, _ := flatten.Flatten(m, "", flatten.RailsStyle)
|
||||
for key, element := range regexMap {
|
||||
if val, ok := flatmap[key]; ok {
|
||||
match, _ := regexp.MatchString(element, val.(string))
|
||||
if !match {
|
||||
return false, key, val.(string), err
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, "", "", err
|
||||
}
|
||||
Reference in New Issue
Block a user