Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
davidnewhall committed Jan 12, 2021
1 parent 02b8e36 commit 277925a
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 25 deletions.
5 changes: 4 additions & 1 deletion events.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,10 @@ func (e *Events) eventStreamScanner() {

// eventStreamConnect establishes a connection to the event stream and passes off the http Reader.
func (e *Events) eventStreamConnect() error {
resp, err := e.server.Get("++eventStream", url.Values{"version": []string{"3"}})
client := e.server.HTTPClient()
client.Timeout = 0

resp, err := e.server.GetClient("++eventStream", url.Values{"version": []string{"3"}}, client)
if err != nil {
return fmt.Errorf("connecting event stream: %w", err)
}
Expand Down
44 changes: 44 additions & 0 deletions mocks/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions server/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import (
type API interface {
Get(apiPath string, params url.Values) (resp *http.Response, err error)
GetContext(ctx context.Context, apiPath string, params url.Values) (resp *http.Response, err error)
GetContextClient(context.Context, string, url.Values, *http.Client) (resp *http.Response, err error)
GetClient(string, url.Values, *http.Client) (resp *http.Response, err error)
Post(apiPath string, params url.Values, post io.ReadCloser) (body []byte, err error)
GetXML(apiPath string, params url.Values, v interface{}) (err error)
SimpleReq(apiURI string, params url.Values, cameraNum int) error
TimeoutDur() time.Duration
BaseURL() string
Auth() string
HTTPClient() *http.Client
}

var _ = API(&Config{})
83 changes: 60 additions & 23 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,45 @@ type Config struct {
URL string
Password string
Username string
Client *http.Client // Provide an HTTP client, or:
Timeout time.Duration // Only used if you do not provide an HTTP client.
VerifySSL bool // Also only used if you do not provide an HTTP client.
Client *http.Client // Provide an HTTP client, or:
Timeout Duration // Only used if you do not provide an HTTP client.
VerifySSL bool // Also only used if you do not provide an HTTP client.
}

func (s *Config) getClient() {
if s.Client != nil {
return
func (s *Config) HTTPClient() *http.Client {
if s.Timeout.Duration == 0 {
s.Timeout.Duration = DefaultTimeout
}

if s.Timeout == 0 {
s.Timeout = DefaultTimeout
}

s.Client = &http.Client{
Timeout: s.Timeout,
return &http.Client{
Timeout: s.Timeout.Duration,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: !s.VerifySSL}, //nolint:gosec
DisableKeepAlives: true, // SecuritySpy has a Keep-Alive Bug.
TLSClientConfig: &tls.Config{
InsecureSkipVerify: !s.VerifySSL, //nolint:gosec
},
},
}
}

// Duration allows you to pass the server Config struct in from a json file.
type Duration struct {
time.Duration
}

// UnmarshalText parses a duration type from a config file. This method works
// with the Duration type to allow unmarshaling of durations from files and
// env variables in the same struct. You won't generally call this directly.
func (d *Duration) UnmarshalText(b []byte) (err error) {
d.Duration, err = time.ParseDuration(string(b))

if err != nil {
return fmt.Errorf("parsing Go duration '%s': %w", b, err)
}

return nil
}

// BaseURL returns the URL.
func (s *Config) BaseURL() string {
return s.URL
Expand All @@ -61,12 +78,12 @@ func (s *Config) Auth() string {

// TimeoutDur returns the configured timeout.
func (s *Config) TimeoutDur() time.Duration {
return s.Timeout
return s.Timeout.Duration
}

func (s *Config) GetContext(ctx context.Context, apiPath string, params url.Values) (*http.Response, error) {
s.getClient()

// GetContextClient is the same as Get except you can pass in your own context and http Client.
func (s *Config) GetContextClient(ctx context.Context, api string, params url.Values,
client *http.Client) (*http.Response, error) {
if params == nil {
params = make(url.Values)
}
Expand All @@ -75,12 +92,12 @@ func (s *Config) GetContext(ctx context.Context, apiPath string, params url.Valu
params.Set("auth", s.Password)
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, s.URL+apiPath, nil)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, s.URL+api, nil)
if err != nil {
return nil, fmt.Errorf("http.NewRequest(): %w", err)
}

if a := apiPath; !strings.HasPrefix(a, "++getfile") && !strings.HasPrefix(a, "++event") &&
if a := api; !strings.HasPrefix(a, "++getfile") && !strings.HasPrefix(a, "++event") &&
!strings.HasPrefix(a, "++image") && !strings.HasPrefix(a, "++audio") &&
!strings.HasPrefix(a, "++stream") && !strings.HasPrefix(a, "++video") {
params.Set("format", "xml")
Expand All @@ -89,17 +106,37 @@ func (s *Config) GetContext(ctx context.Context, apiPath string, params url.Valu

req.URL.RawQuery = params.Encode()

return s.Client.Do(req)
return client.Do(req)
}

// GetContext is the same as Get except you can pass in your own context.
func (s *Config) GetContext(ctx context.Context, apiPath string, params url.Values) (*http.Response, error) {
if s.Client == nil {
s.Client = s.HTTPClient()
}

return s.GetContextClient(ctx, apiPath, params, s.Client)
}

// GetClient is the same as Get except you can pass in your own http Client.
func (s *Config) GetClient(apiPath string, params url.Values, client *http.Client) (*http.Response, error) {
return s.GetContextClient(context.TODO(), apiPath, params, client)
}

// Get is a helper function that formats the http request to SecuritySpy.
func (s *Config) Get(apiPath string, params url.Values) (*http.Response, error) {
return s.GetContext(context.TODO(), apiPath, params)
if s.Client == nil {
s.Client = s.HTTPClient()
}

return s.GetContextClient(context.TODO(), apiPath, params, s.Client)
}

// Post is a helper function that formats the http request to SecuritySpy.
func (s *Config) Post(apiPath string, params url.Values, body io.ReadCloser) ([]byte, error) {
s.getClient()
if s.Client == nil {
s.Client = s.HTTPClient()
}

if params == nil {
params = make(url.Values)
Expand All @@ -109,7 +146,7 @@ func (s *Config) Post(apiPath string, params url.Values, body io.ReadCloser) ([]
params.Set("auth", s.Password)
}

ctx, cancel := context.WithTimeout(context.Background(), s.Timeout)
ctx, cancel := context.WithTimeout(context.Background(), s.Timeout.Duration)
defer cancel()

req, err := http.NewRequestWithContext(ctx, http.MethodPost, s.URL+apiPath, body)
Expand Down
2 changes: 1 addition & 1 deletion server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestGet(t *testing.T) {
Password: "pass",
URL: "http://some.host:5678/",
VerifySSL: false,
Timeout: time.Second,
Timeout: server.Duration{time.Second},
}
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal("xml", r.FormValue("format"), "format parameter was not added")
Expand Down

0 comments on commit 277925a

Please sign in to comment.