Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Httpmon 3 #4

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: release

on:
create:
push:
tags:
- v*

Expand Down
12 changes: 5 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: test

on: [push]
on:
push:
paths-ignore:
- 'cmd/**/*'

jobs:
run-tests:
Expand All @@ -19,10 +22,5 @@ jobs:
go-version: 1.13
- name: Checkout
uses: actions/checkout@v2
# - name: Lint
# run: |
# GO111MODULE=off GOBIN=$(pwd)/bin go get golang.org/x/lint/golint
# bin/golint -set_exit_status ./...
# if: "matrix.os == 'ubuntu-latest' || matrix.os == 'macOS-latest'"
- name: Run Tests
run: make check
run: make test
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ test-cli:
test:
go test ./...

.PHONY: tidy-root
tidy-root:
go mod tidy

.PHONY: tidy-cli
tidy-cli:
cd cmd/httpmon && go mod tidy

.PHONY: tidy
tidy: tidy-root tidy-cli

.PHONY: clean
clean:
go clean
Expand Down
14 changes: 7 additions & 7 deletions case.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package httpmon

import "fmt"

// RunTestCase runs http access test against given url, inspecting its response.
func RunTestCase(method, URL, timout string, status int) ([]TestResult, error) {
// RunGetRequestCase runs http access test against given url, inspecting its response.
func RunGetRequestCase(method, URL, timout string, status int) ([]TestResult, error) {
caseRunner, err := NewCaseRunner(method, URL, timout)
if err != nil {
return nil, err
Expand All @@ -24,11 +24,11 @@ type CaseRunner interface {

type defaultCaseRunner struct {
HttpMon
HttpTestRequest
HttpRequestDetails
}

func (c *defaultCaseRunner) Run() (HttpTest, error) {
httpTest, err := c.HttpMon.Run(c.HttpTestRequest)
httpTest, err := c.HttpMon.Run(c.HttpRequestDetails)
if err != nil {
return nil, &HttpCommunicationError{
CaseError{
Expand Down Expand Up @@ -80,7 +80,7 @@ func NewCaseRunner(method, URL, timout string) (CaseRunner, error) {
},
}
}
request, err := NewRequest(*httpMethod, URL)
requestDetails, err := NewGetRequestDetails(*httpMethod, URL)
if err != nil {
return nil, &UserInputError{
CaseError{
Expand All @@ -90,7 +90,7 @@ func NewCaseRunner(method, URL, timout string) (CaseRunner, error) {
}
}
return &defaultCaseRunner{
HttpMon: *httpMon,
HttpTestRequest: request,
HttpMon: *httpMon,
HttpRequestDetails: requestDetails,
}, nil
}
6 changes: 3 additions & 3 deletions case_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import (
)

func TestRunTestCase_InvalidInput(t *testing.T) {
results, err := RunTestCase("HEAD", "https://examaple.com", "5s", 404)
results, err := RunGetRequestCase("HEAD", "https://examaple.com", "5s", 404)
assert.NotNil(t, err)
assert.IsType(t, new(UserInputError), err)
assert.Nil(t, results)
}

func TestRunTestCase_HttpCommunicationError(t *testing.T) {
results, err := RunTestCase("GET", "http://localhost:4000/test", "2s", 200)
results, err := RunGetRequestCase("GET", "http://localhost:4000/test", "2s", 200)
assert.NotNil(t, err)
assert.IsType(t, new(HttpCommunicationError), err)
assert.Nil(t, results)
Expand All @@ -29,7 +29,7 @@ func TestRunTestCase(t *testing.T) {
}))
defer func() { _ = server.Close }()

results, err := RunTestCase("GET", server.URL, "2s", 200)
results, err := RunGetRequestCase("GET", server.URL, "2s", 200)
assert.Nil(t, err)
assert.Equal(t, 1, len(results))
assert.True(t, results[0].IsSuccess())
Expand Down
7 changes: 3 additions & 4 deletions client.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package httpmon

import (
"bytes"
"io"
"net/http"
)

type HttpClient interface {
Run(method HttpMethod, url string) (HttpResponse, error)
Run(builder HttpRequestDetails) (HttpResponse, error)
}

type HttpClientFactory func(out TimeOut) HttpClient
Expand All @@ -30,8 +29,8 @@ type defaultHttpClient struct {
delegate http.Client
}

func (dhc *defaultHttpClient) Run(method HttpMethod, url string) (HttpResponse, error) {
request, err := http.NewRequest(string(method), url, bytes.NewReader(make([]byte, 0)))
func (dhc *defaultHttpClient) Run(details HttpRequestDetails) (HttpResponse, error) {
request, err := BuildRequest(details)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/httpmon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func testCaseAction(method, timeout *string, status *int) cli.ActionFunc {
}
}
url := ctx.Args().First()
results, err := httpmon.RunTestCase(*method, url, *timeout, *status)
results, err := httpmon.RunGetRequestCase(*method, url, *timeout, *status)
if err != nil {
return err
}
Expand Down
38 changes: 33 additions & 5 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package httpmon

import (
"fmt"
"io"
"net/http"
"strings"
)

Expand Down Expand Up @@ -39,21 +41,47 @@ func ToHttpMethod(input string) (*HttpMethod, error) {
case GET:
return &method, nil
case POST:
return &method, nil
case PUT:
case DELETE:
return nil, fmt.Errorf("%s is not supported", method)
}
return nil, fmt.Errorf("unknown method: %s", method)
}

type URL string

type HttpRequestDetails interface {
Method() HttpMethod
URL() URL
Body() io.Reader
Headers() HttpHeaders
}

func BuildRequest(details HttpRequestDetails) (*http.Request, error) {
req, err := http.NewRequest(string(details.Method()), string(details.URL()), details.Body())
if err != nil {
return nil, err
}
headers := details.Headers()
for name, values := range headers {
for _, v := range values {
req.Header.Add(name, v)
}
}
return req, nil
}

type HttpHeader struct {
Name string
Value string
}

type HttpHeaders map[string][]string

type Queries map[string][]string

type HttpTestRequest interface {
Method() HttpMethod
URL() string
}
type HttpTestRequest HttpRequestDetails

type TestResult interface {
IsSuccess() bool
Expand All @@ -78,7 +106,7 @@ func (hm *HttpMon) httpClient() HttpClient {

func (hm *HttpMon) Run(request HttpTestRequest) (HttpTest, error) {
client := hm.httpClient()
response, err := client.Run(request.Method(), request.URL())
response, err := client.Run(request)
if err != nil {
return nil, err
}
Expand Down
19 changes: 14 additions & 5 deletions http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package httpmon
import (
"fmt"
"github.com/stretchr/testify/assert"
"io"
"testing"
)

Expand Down Expand Up @@ -30,28 +31,36 @@ var timeout TimeOut = TimeOut{
type errorHttpClient struct {
}

func (ehc *errorHttpClient) Run(method HttpMethod, url string) (HttpResponse, error) {
return nil, fmt.Errorf("method: %s, url: %s", method, url)
func (ech *errorHttpClient) Run(details HttpRequestDetails) (HttpResponse, error) {
return nil, fmt.Errorf("method: %s, url: %s", details.Method(), details.URL())
}

type testHttpTestRequest struct {
method string
url string
}

func (r *testHttpTestRequest) Body() io.Reader {
panic("implement me")
}

func (r *testHttpTestRequest) Headers() HttpHeaders {
panic("implement me")
}

func (r *testHttpTestRequest) Method() HttpMethod {
return HttpMethod(r.method)
}

func (r *testHttpTestRequest) URL() string {
return r.url
func (r *testHttpTestRequest) URL() URL {
return URL(r.url)
}

type successHttpClient struct {
closeCalled bool
}

func (s *successHttpClient) Run(method HttpMethod, url string) (HttpResponse, error) {
func (s *successHttpClient) Run(details HttpRequestDetails) (HttpResponse, error) {
return &successResponse{callback: func() {
s.closeCalled = true
}}, nil
Expand Down
38 changes: 30 additions & 8 deletions request.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,49 @@
package httpmon

import "net/url"
import (
"bytes"
"io"
"net/url"
)

type request struct {
type getRequest struct {
method HttpMethod
targetURL url.URL
headers []HttpHeader
}

func (r *request) Method() HttpMethod {
return r.method
func (r *getRequest) URL() URL {
return URL(r.targetURL.String())
}

func (r *getRequest) Body() io.Reader {
empty := make([]byte, 0)
return bytes.NewReader(empty)
}

func (r *request) URL() string {
return r.targetURL.String()
func (r *getRequest) Headers() HttpHeaders {
hs := make(HttpHeaders, 0)
for _, h := range r.headers {
if _, ok := hs[h.Name]; !ok {
hs[h.Name] = make([]string, 0)
}
hs[h.Name] = append(hs[h.Name], h.Value)
}
return hs
}

func (r *getRequest) Method() HttpMethod {
return r.method
}

func NewRequest(method HttpMethod, URL string) (HttpTestRequest, error) {
func NewGetRequestDetails(method HttpMethod, URL string, headers ...HttpHeader) (HttpRequestDetails, error) {
u, err := url.Parse(URL)
if err != nil {
return nil, err
}
return &request{
return &getRequest{
method: method,
targetURL: *u,
headers: headers,
}, nil
}