aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2017-07-10 15:04:02 +0200
committerMartin Polden <mpolden@mpolden.no>2017-07-10 15:04:02 +0200
commit14bd023670aa6f783473f5858db58b1229050d95 (patch)
tree5901c303239764fe03ca37f103a0418db412a342
parent32ea45b06eb829e38bee60a9b0b76341bed9c38c (diff)
Cleanup
-rw-r--r--api/api.go84
-rw-r--r--api/api_test.go14
-rw-r--r--atb/atb.go21
-rw-r--r--atb/atb_test.go4
-rw-r--r--atb/rpc.go6
5 files changed, 52 insertions, 77 deletions
diff --git a/api/api.go b/api/api.go
index 3c76565..37cda69 100644
--- a/api/api.go
+++ b/api/api.go
@@ -14,15 +14,15 @@ import (
cache "github.com/pmylund/go-cache"
)
-// An API defines parameters for running an API server.
+// API defines parameters for running an API server.
type API struct {
Client atb.Client
CORS bool
cache *cache.Cache
- expiration
+ ttl
}
-type expiration struct {
+type ttl struct {
departures time.Duration
stops time.Duration
}
@@ -48,14 +48,9 @@ func (a *API) getBusStops(urlPrefix string) (BusStops, bool, error) {
const cacheKey = "stops"
cached, hit := a.cache.Get(cacheKey)
if hit {
- cachedBusStops, ok := cached.(BusStops)
- if !ok {
- return BusStops{}, false, fmt.Errorf(
- "type assertion of cached value failed")
- }
- return cachedBusStops, hit, nil
+ return cached.(BusStops), hit, nil
}
- atbBusStops, err := a.Client.GetBusStops()
+ atbBusStops, err := a.Client.BusStops()
if err != nil {
return BusStops{}, hit, err
}
@@ -72,7 +67,7 @@ func (a *API) getBusStops(urlPrefix string) (BusStops, bool, error) {
// Store a pointer to the BusStop struct
busStops.nodeIDs[s.NodeID] = &busStops.Stops[i]
}
- a.cache.Set(cacheKey, busStops, a.expiration.stops)
+ a.cache.Set(cacheKey, busStops, a.ttl.stops)
return busStops, hit, nil
}
@@ -80,14 +75,9 @@ func (a *API) getDepartures(urlPrefix string, nodeID int) (Departures, bool, err
cacheKey := strconv.Itoa(nodeID)
cached, hit := a.cache.Get(cacheKey)
if hit {
- cachedDepartures, ok := cached.(Departures)
- if !ok {
- return Departures{}, false, fmt.Errorf(
- "type assertion of cached value failed")
- }
- return cachedDepartures, hit, nil
+ return cached.(Departures), hit, nil
}
- forecasts, err := a.Client.GetRealTimeForecast(nodeID)
+ forecasts, err := a.Client.Forecasts(nodeID)
if err != nil {
return Departures{}, hit, err
}
@@ -115,7 +105,7 @@ func (a *API) BusStopsHandler(w http.ResponseWriter, r *http.Request) (interface
return nil, &Error{
err: err,
Status: http.StatusInternalServerError,
- Message: "failed to get bus stops from atb",
+ Message: "Failed to get bus stops from AtB",
}
}
a.setCacheHeader(w, hit)
@@ -133,7 +123,7 @@ func (a *API) BusStopHandler(w http.ResponseWriter, r *http.Request) (interface{
return nil, &Error{
err: err,
Status: http.StatusBadRequest,
- Message: "missing or invalid nodeID",
+ Message: "Invalid nodeID",
}
}
busStops, hit, err := a.getBusStops(urlPrefix(r))
@@ -141,16 +131,14 @@ func (a *API) BusStopHandler(w http.ResponseWriter, r *http.Request) (interface{
return nil, &Error{
err: err,
Status: http.StatusInternalServerError,
- Message: "failed to get bus stops from atb",
+ Message: "Failed to get bus stops from AtB",
}
}
busStop, ok := busStops.nodeIDs[nodeID]
if !ok {
- msg := fmt.Sprintf("bus stop with nodeID=%d not found", nodeID)
return nil, &Error{
- err: err,
Status: http.StatusNotFound,
- Message: msg,
+ Message: "Unknown bus stop",
}
}
a.setCacheHeader(w, hit)
@@ -168,7 +156,7 @@ func (a *API) DepartureHandler(w http.ResponseWriter, r *http.Request) (interfac
return nil, &Error{
err: err,
Status: http.StatusBadRequest,
- Message: "missing or invalid nodeID",
+ Message: "Invalid nodeID",
}
}
busStops, hit, err := a.getBusStops(urlPrefix(r))
@@ -176,16 +164,14 @@ func (a *API) DepartureHandler(w http.ResponseWriter, r *http.Request) (interfac
return nil, &Error{
err: err,
Status: http.StatusInternalServerError,
- Message: "could not get bus stops from atb",
+ Message: "Failed to get bus stops from AtB",
}
}
- _, knownBusStop := busStops.nodeIDs[nodeID]
- if !knownBusStop {
- msg := fmt.Sprintf("bus stop with nodeID=%d not found", nodeID)
+ _, ok := busStops.nodeIDs[nodeID]
+ if !ok {
return nil, &Error{
- err: err,
Status: http.StatusNotFound,
- Message: msg,
+ Message: "Unknown bus stop",
}
}
departures, hit, err := a.getDepartures(urlPrefix(r), nodeID)
@@ -193,7 +179,7 @@ func (a *API) DepartureHandler(w http.ResponseWriter, r *http.Request) (interfac
return nil, &Error{
err: err,
Status: http.StatusInternalServerError,
- Message: "could not get departures from atb",
+ Message: "Failed to get departures from AtB",
}
}
a.setCacheHeader(w, hit)
@@ -207,7 +193,7 @@ func (a *API) DeparturesHandler(w http.ResponseWriter, r *http.Request) (interfa
return nil, &Error{
err: err,
Status: http.StatusInternalServerError,
- Message: "failed to get bus stops from atb",
+ Message: "Failed to get bus stops from AtB",
}
}
a.setCacheHeader(w, hit)
@@ -221,10 +207,10 @@ func (a *API) DeparturesHandler(w http.ResponseWriter, r *http.Request) (interfa
return urls, nil
}
-// RootHandler lists known URLs.
-func (a *API) RootHandler(w http.ResponseWriter, r *http.Request) (interface{}, *Error) {
+// DefaultHandler lists known URLs.
+func (a *API) DefaultHandler(w http.ResponseWriter, r *http.Request) (interface{}, *Error) {
if r.URL.Path != "/" {
- return a.NotFoundHandler(w, r)
+ return nil, &Error{Status: http.StatusNotFound, Message: "Resource not found"}
}
prefix := urlPrefix(r)
busStopsURL := fmt.Sprintf("%s/api/v1/busstops", prefix)
@@ -236,27 +222,17 @@ func (a *API) RootHandler(w http.ResponseWriter, r *http.Request) (interface{},
}, nil
}
-// NotFoundHandler handles requests to invalid routes.
-func (a *API) NotFoundHandler(w http.ResponseWriter, r *http.Request) (interface{}, *Error) {
- return nil, &Error{
- err: nil,
- Status: http.StatusNotFound,
- Message: "route not found",
- }
-}
-
-// New returns an new API using client to communicate with AtB. stopsExpiration
-// and depExpiration control the cache expiration times for bus stops and
-// departures.
-func New(client atb.Client, stopsExpiration, depExpiration time.Duration, cors bool) API {
- cache := cache.New(depExpiration, 30*time.Second)
+// New returns an new API using client to communicate with AtB. stopTTL and departureTTL control the cache TTL bus stops
+// and departures.
+func New(client atb.Client, stopTTL, departureTTL time.Duration, cors bool) API {
+ cache := cache.New(departureTTL, 30*time.Second)
return API{
Client: client,
CORS: cors,
cache: cache,
- expiration: expiration{
- stops: stopsExpiration,
- departures: depExpiration,
+ ttl: ttl{
+ stops: stopTTL,
+ departures: departureTTL,
},
}
}
@@ -303,6 +279,6 @@ func (a *API) Handler() http.Handler {
mux.Handle("/api/v1/busstops/", appHandler(a.BusStopHandler))
mux.Handle("/api/v1/departures", appHandler(a.DeparturesHandler))
mux.Handle("/api/v1/departures/", appHandler(a.DepartureHandler))
- mux.Handle("/", appHandler(a.RootHandler))
+ mux.Handle("/", appHandler(a.DefaultHandler))
return requestFilter(mux, a.CORS)
}
diff --git a/api/api_test.go b/api/api_test.go
index 5824878..9bc1c4b 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -67,7 +67,7 @@ func TestAPI(t *testing.T) {
status int
}{
// Unknown resources
- {"/not-found", `{"status":404,"message":"route not found"}`, 404},
+ {"/not-found", `{"status":404,"message":"Resource not found"}`, 404},
// List know URLs
{"/", fmt.Sprintf(`{"urls":["%s/api/v1/busstops","%s/api/v1/departures"]}`, server.URL, server.URL), 200},
// List all bus stops
@@ -75,14 +75,14 @@ func TestAPI(t *testing.T) {
// List all departures
{"/api/v1/departures", fmt.Sprintf(`{"urls":["%s/api/v1/departures/16011376"]}`, server.URL), 200},
// Show specific bus stop
- {"/api/v1/busstops/", `{"status":400,"message":"missing or invalid nodeID"}`, 400},
- {"/api/v1/busstops/foo", `{"status":400,"message":"missing or invalid nodeID"}`, 400},
- {"/api/v1/busstops/42", `{"status":404,"message":"bus stop with nodeID=42 not found"}`, 404},
+ {"/api/v1/busstops/", `{"status":400,"message":"Invalid nodeID"}`, 400},
+ {"/api/v1/busstops/foo", `{"status":400,"message":"Invalid nodeID"}`, 400},
+ {"/api/v1/busstops/42", `{"status":404,"message":"Unknown bus stop"}`, 404},
{"/api/v1/busstops/16011376", fmt.Sprintf(`{"url":"%s/api/v1/busstops/16011376","stopId":100633,"nodeId":16011376,"description":"Prof. Brochs gt","longitude":10.398126,"latitude":63.415535,"mobileCode":"16011376 (Prof.)","mobileName":"Prof. (16011376)"}`, server.URL), 200},
// Show specific departure
- {"/api/v1/departures/", `{"status":400,"message":"missing or invalid nodeID"}`, 400},
- {"/api/v1/departures/foo", `{"status":400,"message":"missing or invalid nodeID"}`, 400},
- {"/api/v1/departures/42", `{"status":404,"message":"bus stop with nodeID=42 not found"}`, 404},
+ {"/api/v1/departures/", `{"status":400,"message":"Invalid nodeID"}`, 400},
+ {"/api/v1/departures/foo", `{"status":400,"message":"Invalid nodeID"}`, 400},
+ {"/api/v1/departures/42", `{"status":404,"message":"Unknown bus stop"}`, 404},
{"/api/v1/departures/16011376", fmt.Sprintf(`{"url":"%s/api/v1/departures/16011376","isGoingTowardsCentrum":true,"departures":[{"line":"6","registeredDepartureTime":"2015-02-26T18:38:00.000","scheduledDepartureTime":"2015-02-26T18:01:00.000","destination":"Munkegata M5","isRealtimeData":true}]}`, server.URL), 200},
}
for _, tt := range tests {
diff --git a/atb/atb.go b/atb/atb.go
index 1772dcf..fc3d928 100644
--- a/atb/atb.go
+++ b/atb/atb.go
@@ -93,48 +93,47 @@ func (c *Client) post(m method, data interface{}) ([]byte, error) {
if err != nil {
return nil, err
}
- jsonBlob, err := m.ParseResponse(body)
+ out, err := m.Unmarshal(body)
if err != nil {
return nil, err
}
- return jsonBlob, nil
+ return out, nil
}
-// GetBusStops retrieves bus stops from AtBs API.
-func (c *Client) GetBusStops() (BusStops, error) {
+// BusStops retrieves bus stops from AtBs API.
+func (c *Client) BusStops() (BusStops, error) {
values := struct {
Username string
Password string
}{c.Username, c.Password}
- jsonBlob, err := c.post(busStopsList, values)
+ res, err := c.post(busStopsList, values)
if err != nil {
return BusStops{}, err
}
var stops BusStops
- if err := json.Unmarshal(jsonBlob, &stops); err != nil {
+ if err := json.Unmarshal(res, &stops); err != nil {
return BusStops{}, err
}
return stops, nil
}
-// GetRealTimeForecast retrieves a forecast from AtBs API, using nodeID to
-// identify the bus stop.
-func (c *Client) GetRealTimeForecast(nodeID int) (Forecasts, error) {
+// Forecasts retrieves forecasts from AtBs API, using nodeID to identify the bus stop.
+func (c *Client) Forecasts(nodeID int) (Forecasts, error) {
values := struct {
Username string
Password string
NodeID int
}{c.Username, c.Password, nodeID}
- jsonBlob, err := c.post(realTimeForecast, values)
+ res, err := c.post(realTimeForecast, values)
if err != nil {
return Forecasts{}, err
}
var forecasts Forecasts
- if err := json.Unmarshal(jsonBlob, &forecasts); err != nil {
+ if err := json.Unmarshal(res, &forecasts); err != nil {
return Forecasts{}, err
}
return forecasts, nil
diff --git a/atb/atb_test.go b/atb/atb_test.go
index f73fa94..0aaf0cb 100644
--- a/atb/atb_test.go
+++ b/atb/atb_test.go
@@ -35,7 +35,7 @@ func TestGetBusStops(t *testing.T) {
},
},
}
- stops, err := atb.GetBusStops()
+ stops, err := atb.BusStops()
if err != nil {
t.Fatal(err)
}
@@ -48,7 +48,7 @@ func TestGetRealTimeForecast(t *testing.T) {
server := newTestServer("/", forecastResponse)
defer server.Close()
atb := Client{URL: server.URL}
- forecasts, err := atb.GetRealTimeForecast(16011376)
+ forecasts, err := atb.Forecasts(16011376)
expected := Forecasts{
Total: 1,
Nodes: []NodeInfo{
diff --git a/atb/rpc.go b/atb/rpc.go
index 18d470e..5a50942 100644
--- a/atb/rpc.go
+++ b/atb/rpc.go
@@ -8,7 +8,7 @@ import (
type method interface {
NewRequest(data interface{}) (string, error)
- ParseResponse(body []byte) ([]byte, error)
+ Unmarshal(b []byte) ([]byte, error)
}
func compileTemplate(t *template.Template, data interface{}) (string, error) {
@@ -35,7 +35,7 @@ func (m *busStopsListMethod) NewRequest(data interface{}) (string, error) {
return compileTemplate(m.template, data)
}
-func (m *busStopsListMethod) ParseResponse(body []byte) ([]byte, error) {
+func (m *busStopsListMethod) Unmarshal(body []byte) ([]byte, error) {
var stops busStopsListMethod
if err := xml.Unmarshal(body, &stops); err != nil {
return nil, err
@@ -47,7 +47,7 @@ func (m *realTimeForecastMethod) NewRequest(data interface{}) (string, error) {
return compileTemplate(m.template, data)
}
-func (m *realTimeForecastMethod) ParseResponse(body []byte) ([]byte, error) {
+func (m *realTimeForecastMethod) Unmarshal(body []byte) ([]byte, error) {
var forecast realTimeForecastMethod
if err := xml.Unmarshal(body, &forecast); err != nil {
return nil, err