1
0
Fork 0
mirror of https://github.com/imjasonh/staticmaps synced 2026-07-19 07:15:38 +00:00

return responses that don't include Status and ErrorMessage, instead return an APIError if the API response is not 'OK'

This commit is contained in:
Jason Hall 2014-10-09 16:08:02 -04:00
parent 41f9b8b763
commit aa3b05a35f
6 changed files with 134 additions and 81 deletions

View file

@ -32,12 +32,15 @@ const (
// TODO: via_waypoint not documented // TODO: via_waypoint not documented
func (c Client) Directions(orig, dest Location, opts *DirectionsOpts) (*DirectionsResponse, error) { func (c Client) Directions(orig, dest Location, opts *DirectionsOpts) ([]Route, error) {
var d DirectionsResponse var d directionsResponse
if err := c.doDecode(baseURL+directions(orig, dest, opts), &d); err != nil { if err := c.doDecode(baseURL+directions(orig, dest, opts), &d); err != nil {
return nil, err return nil, err
} }
return &d, nil if d.Status != StatusOK {
return nil, APIError{d.Status, d.ErrorMessage}
}
return d.Routes, nil
} }
func directions(orig, dest Location, opts *DirectionsOpts) string { func directions(orig, dest Location, opts *DirectionsOpts) string {
@ -89,29 +92,31 @@ func (do *DirectionsOpts) update(p url.Values) {
} }
} }
type DirectionsResponse struct { type directionsResponse struct {
Status string `json:"status"` Status string `json:"status"`
ErrorMessage string `json:"error_message"` ErrorMessage string `json:"error_message"`
Routes []struct { Routes []Route `json:"routes"`
Summary string `json:"summary"` }
Legs []struct {
Duration *Duration `json:"duration"` type Route struct {
DurationInTraffic *Duration `json:"duration_in_traffic"` Summary string `json:"summary"`
Distance *Distance `json:"distance"` Legs []struct {
ArrivalTime Time `json:"arrival_time"` Duration *Duration `json:"duration"`
DepartureTime Time `json:"departure_time"` DurationInTraffic *Duration `json:"duration_in_traffic"`
StartLocation *LatLng `json:"start_location"` Distance *Distance `json:"distance"`
EndLocation *LatLng `json:"end_location"` ArrivalTime Time `json:"arrival_time"`
StartAddress string `json:"start_address"` DepartureTime Time `json:"departure_time"`
EndAddress string `json:"end_address"` StartLocation *LatLng `json:"start_location"`
Steps []Step `json:"steps"` EndLocation *LatLng `json:"end_location"`
} `json:"legs"` StartAddress string `json:"start_address"`
Bounds Bounds `json:"bounds"` EndAddress string `json:"end_address"`
Copyrights string `json:"copyrights"` Steps []Step `json:"steps"`
OverviewPolyline Polyline `json:"overview_polyline"` } `json:"legs"`
Warnings []string `json:"warnings"` Bounds Bounds `json:"bounds"`
WaypointOrder []int `json:"waypoint_order"` Copyrights string `json:"copyrights"`
} `json:"routes"` OverviewPolyline Polyline `json:"overview_polyline"`
Warnings []string `json:"warnings"`
WaypointOrder []int `json:"waypoint_order"`
} }
type Time struct { type Time struct {

View file

@ -6,12 +6,15 @@ import (
"time" "time"
) )
func (c Client) DistanceMatrix(orig, dest []Location, opts *DistanceMatrixOpts) (*DistanceMatrixResponse, error) { func (c Client) DistanceMatrix(orig, dest []Location, opts *DistanceMatrixOpts) (*DistanceMatrixResult, error) {
var d DistanceMatrixResponse var d distanceResponse
if err := c.doDecode(baseURL+distancematrix(orig, dest, opts), &d); err != nil { if err := c.doDecode(baseURL+distancematrix(orig, dest, opts), &d); err != nil {
return nil, err return nil, err
} }
return &d, nil if d.Status != StatusOK {
return nil, APIError{d.Status, ""}
}
return &d.DistanceMatrixResult, nil
} }
func distancematrix(orig, dest []Location, opts *DistanceMatrixOpts) string { func distancematrix(orig, dest []Location, opts *DistanceMatrixOpts) string {
@ -49,8 +52,12 @@ func (o *DistanceMatrixOpts) update(p url.Values) {
} }
} }
type DistanceMatrixResponse struct { type distanceResponse struct {
Status string `json:"status"` Status string `json:"status"`
DistanceMatrixResult
}
type DistanceMatrixResult struct {
OriginAddresses []string `json:"origin_addresses"` OriginAddresses []string `json:"origin_addresses"`
DestinationAddresses []string `json:"destination_addresses"` DestinationAddresses []string `json:"destination_addresses"`
Rows []struct { Rows []struct {

View file

@ -5,36 +5,48 @@ import (
"net/url" "net/url"
) )
func (c Client) Elevation(ll []LatLng) (*ElevationResponse, error) { func (c Client) Elevation(ll []LatLng) ([]ElevationResult, error) {
var r ElevationResponse var r elevationResponse
if err := c.doDecode(baseURL+elevation(ll), &r); err != nil { if err := c.doDecode(baseURL+elevation(ll), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
} }
func (c Client) ElevationPolyline(p string) (*ElevationResponse, error) { func (c Client) ElevationPolyline(p string) ([]ElevationResult, error) {
var r ElevationResponse var r elevationResponse
if err := c.doDecode(baseURL+elevationpoly(p), &r); err != nil { if err := c.doDecode(baseURL+elevationpoly(p), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
} }
func (c Client) ElevationPath(ll []LatLng, samples int) (*ElevationResponse, error) { func (c Client) ElevationPath(ll []LatLng, samples int) ([]ElevationResult, error) {
var r ElevationResponse var r elevationResponse
if err := c.doDecode(baseURL+elevationpath(ll, samples), &r); err != nil { if err := c.doDecode(baseURL+elevationpath(ll, samples), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
} }
func (c Client) ElevationPathPoly(p string, samples int) (*ElevationResponse, error) { func (c Client) ElevationPathPoly(p string, samples int) ([]ElevationResult, error) {
var r ElevationResponse var r elevationResponse
if err := c.doDecode(baseURL+elevationpathpoly(p, samples), &r); err != nil { if err := c.doDecode(baseURL+elevationpathpoly(p, samples), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
} }
func elevation(ll []LatLng) string { func elevation(ll []LatLng) string {
@ -63,11 +75,12 @@ func elevationpathpoly(poly string, s int) string {
return "elevation/json?" + p.Encode() return "elevation/json?" + p.Encode()
} }
type ElevationResponse struct { type elevationResponse struct {
Results []struct { Results []ElevationResult `json:"results"`
Elevation float64 `json:"elevation"` Status string `json:"status"`
Location LatLng `json:"location"` }
Resolution float64 `json:"resolution"` type ElevationResult struct {
} `json:"results"` Elevation float64 `json:"elevation"`
Status string `json:"status"` Location LatLng `json:"location"`
Resolution float64 `json:"resolution"`
} }

View file

@ -21,12 +21,15 @@ const (
// TODO: enums for https://developers.google.com/maps/documentation/geocoding/#Types // TODO: enums for https://developers.google.com/maps/documentation/geocoding/#Types
) )
func (c Client) Geocode(opts *GeocodeOpts) (*GeocodeResponse, error) { func (c Client) Geocode(opts *GeocodeOpts) ([]GeocodeResult, error) {
var r GeocodeResponse var r geocodeResponse
if err := c.doDecode(baseURL+geocode(opts), &r); err != nil { if err := c.doDecode(baseURL+geocode(opts), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
} }
func geocode(opts *GeocodeOpts) string { func geocode(opts *GeocodeOpts) string {
@ -79,33 +82,37 @@ func (g *GeocodeOpts) update(p url.Values) {
} }
} }
type GeocodeResponse struct { type geocodeResponse struct {
Results []struct { Results []GeocodeResult `json:"results"`
AddressComponents []struct { Status string `json:"status"`
LongName string `json:"long_name"` }
ShortName string `json:"short_name"` type GeocodeResult struct {
Types []string `json:"types"` AddressComponents []struct {
} `json:"address_components"` LongName string `json:"long_name"`
PostcodeLocalities []string `json:"postcode_localities"` ShortName string `json:"short_name"`
FormattedAddress string `json:"formatted_address"` Types []string `json:"types"`
Geometry struct { } `json:"address_components"`
Location LatLng `json:"location"` PostcodeLocalities []string `json:"postcode_localities"`
LocationType string `json:"location_type"` FormattedAddress string `json:"formatted_address"`
Viewport Bounds `json:"viewport"` Geometry struct {
Bounds Bounds `json:"bounds"` Location LatLng `json:"location"`
} `json:"geometry"` LocationType string `json:"location_type"`
Types []string `json:"types"` Viewport Bounds `json:"viewport"`
PartialMatch string `json:"partial_match"` Bounds Bounds `json:"bounds"`
} `json:"results"` } `json:"geometry"`
Status string `json:"status"` Types []string `json:"types"`
PartialMatch string `json:"partial_match"`
} }
func (c Client) ReverseGeocode(ll LatLng, opts *ReverseGeocodeOpts) (*GeocodeResponse, error) { func (c Client) ReverseGeocode(ll LatLng, opts *ReverseGeocodeOpts) ([]GeocodeResult, error) {
var r GeocodeResponse var r geocodeResponse
if err := c.doDecode(baseURL+reversegeocode(ll, opts), &r); err != nil { if err := c.doDecode(baseURL+reversegeocode(ll, opts), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
} }
type ReverseGeocodeOpts struct { type ReverseGeocodeOpts struct {

14
maps.go
View file

@ -57,6 +57,7 @@ func (c Client) doDecode(url string, r interface{}) error {
return nil return nil
} }
// HTTPError indicates an error communicating with the API, and includes the HTTP response returned from the server.
type HTTPError struct { type HTTPError struct {
Response *http.Response Response *http.Response
} }
@ -65,6 +66,19 @@ func (e HTTPError) Error() string {
return fmt.Sprintf("http error %d", e.Response.StatusCode) return fmt.Sprintf("http error %d", e.Response.StatusCode)
} }
// APIError indicates a failure response from the API server, even though a successful HTTP response was returned.
// Its Status and Message fields can be consulted for more information about the specific error conditions.
type APIError struct {
Status, Message string
}
func (e APIError) Error() string {
if e.Message != "" {
return fmt.Sprintf("API error %q: %s", e.Status, e.Message)
}
return fmt.Sprintf("API Error %q", e.Status)
}
type Location interface { type Location interface {
Location() string Location() string
} }

View file

@ -6,12 +6,15 @@ import (
"time" "time"
) )
func (c Client) TimeZone(ll LatLng, t time.Time, opts *TimeZoneOpts) (*TimeZoneResponse, error) { func (c Client) TimeZone(ll LatLng, t time.Time, opts *TimeZoneOpts) (*TimeZoneResult, error) {
var r TimeZoneResponse var r timeZoneResponse
if err := c.doDecode(baseURL+timezone(ll, t, opts), &r); err != nil { if err := c.doDecode(baseURL+timezone(ll, t, opts), &r); err != nil {
return nil, err return nil, err
} }
return &r, nil if r.Status != StatusOK {
return nil, APIError{r.Status, r.ErrorMessage}
}
return &r.TimeZoneResult, nil
} }
func timezone(ll LatLng, t time.Time, opts *TimeZoneOpts) string { func timezone(ll LatLng, t time.Time, opts *TimeZoneOpts) string {
@ -35,19 +38,23 @@ func (t *TimeZoneOpts) update(p url.Values) {
} }
} }
type TimeZoneResponse struct { type timeZoneResponse struct {
Status string `json:"status"` Status string `json:"status"`
ErrorMessage string `json:"error_message"` ErrorMessage string `json:"error_message"`
TimeZoneResult
}
type TimeZoneResult struct {
DSTOffset int64 `json:"dstOffset"` // secs offset for DST DSTOffset int64 `json:"dstOffset"` // secs offset for DST
RawOffset int64 `json:"rawOffset"` RawOffset int64 `json:"rawOffset"`
TimeZoneID string `json:"timeZoneId"` TimeZoneID string `json:"timeZoneId"`
TimeZoneName string `json:"timeZoneName"` TimeZoneName string `json:"timeZoneName"`
} }
func (r TimeZoneResponse) DSTOffsetDuration() time.Duration { func (r TimeZoneResult) DSTOffsetDuration() time.Duration {
return time.Duration(r.DSTOffset) * time.Second return time.Duration(r.DSTOffset) * time.Second
} }
func (r TimeZoneResponse) RawOffsetDuration() time.Duration { func (r TimeZoneResult) RawOffsetDuration() time.Duration {
return time.Duration(r.RawOffset) * time.Second return time.Duration(r.RawOffset) * time.Second
} }