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

Added context + https support #1

Open
wants to merge 3 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
61 changes: 41 additions & 20 deletions statusio.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package statusio

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand All @@ -15,15 +16,34 @@ import (
type Client struct {
baseAddr string
client *http.Client
scheme string
}

// extractScheme detects if the url is http instead of https
func extractScheme(rawurl string) (scheme, baseAddr string, err error) {
u, err := url.Parse(rawurl)
if err != nil {
return "", "", err
}
if u.Scheme == "" || u.Host == "" {
return "https", rawurl, nil
}
return u.Scheme, u.Host, nil
}

// NewClient creates a new statusio client for the *public api*.
// baseAddr is i.e. status.example.copm/api/v2/
func NewClient(baseAddr string) *Client {
return &Client{
func NewClient(baseAddr string) (c Client, err error) {
scheme, baseAddr, err := extractScheme(baseAddr)
if err != nil {
return c, err
}
c = Client{
baseAddr: baseAddr,
client: &http.Client{},
scheme: scheme,
}
return c, err
}

type SummaryResponse struct {
Expand All @@ -38,9 +58,9 @@ type SummaryResponse struct {
}

// GetSummary returns a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances.
func (c *Client) GetSummary() (SummaryResponse, error) {
func (c *Client) GetSummary(ctx context.Context) (SummaryResponse, error) {
s := SummaryResponse{}
err := c.request("api/v2/summary.json", &s)
err := c.request(ctx, "api/v2/summary.json", &s)
return s, err
}

Expand All @@ -54,9 +74,9 @@ type StatusResponse struct {

// GetStatus returns rollup for the whole page. This endpoint includes an indicator - one of none, minor, major, or critical, as well as a human description of the blended component status.
// Examples of the blended status include "All Systems Operational", "Partial System Outage", and "Major Service Outage".
func (c *Client) GetStatus() (StatusResponse, error) {
func (c *Client) GetStatus(ctx context.Context) (StatusResponse, error) {
s := StatusResponse{}
err := c.request("api/v2/status.json", &s)
err := c.request(ctx, "api/v2/status.json", &s)
return s, err
}

Expand All @@ -66,9 +86,9 @@ type ComponentsResponse struct {
}

// GetComponents gets the components for the page. Each component is listed along with its status - one of operational, degraded_performance, partial_outage, or major_outage.
func (c *Client) GetComponents() (ComponentsResponse, error) {
func (c *Client) GetComponents(ctx context.Context) (ComponentsResponse, error) {
comp := ComponentsResponse{}
err := c.request("api/v2/components.json", &comp)
err := c.request(ctx, "api/v2/components.json", &comp)
return comp, err
}

Expand All @@ -79,17 +99,17 @@ type IncidentsResponse struct {

// GetUnresolvedIncidents gets a list of any unresolved incidents.
// This endpoint will only return incidents in the Investigating, Identified, or Monitoring state.
func (c *Client) GetUnresolvedIncidents() (IncidentsResponse, error) {
func (c *Client) GetUnresolvedIncidents(ctx context.Context) (IncidentsResponse, error) {
i := IncidentsResponse{}
err := c.request("api/v2/incidents/unresolved.json", &i)
err := c.request(ctx, "api/v2/incidents/unresolved.json", &i)
return i, err
}

// GetIncidents returns a list of the 50 most recent incidents.
// This includes all unresolved incidents returned in GetUnresolvedIncidents, as well as those in the Resolved and Postmortem state.
func (c *Client) GetIncidents() (IncidentsResponse, error) {
func (c *Client) GetIncidents(ctx context.Context) (IncidentsResponse, error) {
i := IncidentsResponse{}
err := c.request("api/v2/incidents.json", &i)
err := c.request(ctx, "api/v2/incidents.json", &i)
return i, err
}

Expand All @@ -100,24 +120,24 @@ type ScheduledMaintenancesResponse struct {

// GetUpcomingScheduledMaintenances gets a list of any upcoming maintenances.
// This endpoint will only return scheduled maintenances still in the Scheduled state.
func (c *Client) GetUpcomingScheduledMaintenances() (ScheduledMaintenancesResponse, error) {
func (c *Client) GetUpcomingScheduledMaintenances(ctx context.Context) (ScheduledMaintenancesResponse, error) {
s := ScheduledMaintenancesResponse{}
err := c.request("api/v2/scheduled-maintenances/upcoming.json", &s)
err := c.request(ctx, "api/v2/scheduled-maintenances/upcoming.json", &s)
return s, err
}

// GetActiveScheduledMaintenances gets a list of any upcoming maintenances. // This endpoint will only return scheduled maintenances in the In Progress or Verifying state.
func (c *Client) GetActiveScheduledMaintenances() (ScheduledMaintenancesResponse, error) {
func (c *Client) GetActiveScheduledMaintenances(ctx context.Context) (ScheduledMaintenancesResponse, error) {
s := ScheduledMaintenancesResponse{}
err := c.request("api/v2/scheduled-maintenances/active.json", &s)
err := c.request(ctx, "api/v2/scheduled-maintenances/active.json", &s)
return s, err
}

// GetAllScheduledMaintenances gets a list of the 50 most recent scheduled maintenances.
// This includes scheduled maintenances as described in the above two endpoints, as well as those in the Completed state.
func (c *Client) GetAllScheduledMaintenances() (ScheduledMaintenancesResponse, error) {
func (c *Client) GetAllScheduledMaintenances(ctx context.Context) (ScheduledMaintenancesResponse, error) {
s := ScheduledMaintenancesResponse{}
err := c.request("api/v2/scheduled-maintenances.json", &s)
err := c.request(ctx, "api/v2/scheduled-maintenances.json", &s)
return s, err
}

Expand All @@ -138,9 +158,9 @@ func (c *Client) RemoveSubscription() NotImplemented {
return true
}

func (c *Client) request(path string, s interface{}) error {
func (c *Client) request(ctx context.Context, path string, s interface{}) error {
u := &url.URL{
Scheme: "https",
Scheme: c.scheme,
Host: c.baseAddr,
Path: path,
}
Expand All @@ -149,6 +169,7 @@ func (c *Client) request(path string, s interface{}) error {
slog.Error(err)
return err
}
req = req.WithContext(ctx)
req.Header.Set("Accept", "application/json")
resp, err := c.client.Do(req)
if err != nil {
Expand Down
29 changes: 29 additions & 0 deletions statusio_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package statusio

import "testing"

func TestExtractScheme(t *testing.T) {
samples := []struct {
url string
scheme string
baseAddr string
}{
// url => scheme, base address
{"foo.com", "https", "foo.com"},
{"http://foo.com", "http", "foo.com"},
{"https://foo.com", "https", "foo.com"},
{"http://https://foo.com", "http", "https:"},
{"", "https", ""},
}
for _, s := range samples {
scheme, baseAddr := extractScheme(s.url)
if scheme != s.scheme {
t.Errorf("scheme: got %s, wants: %s (%s)",
scheme, s.scheme, s.url)
}
if baseAddr != s.baseAddr {
t.Errorf("baseAddr: got %s, wants: %s (%s)",
baseAddr, s.baseAddr, s.url)
}
}
}