Initial cloud-services repo - gateway service + pkg modules

This commit is contained in:
Chris Rai
2026-01-30 23:14:52 -05:00
commit fbb820d7b3
1037 changed files with 171318 additions and 0 deletions

65
pkg/httpclient/client.go Normal file
View 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)
}

View 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)
}
}

View 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)
}

View 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
}