1
0
Fork 0
mirror of https://github.com/imjasonh/staticmaps synced 2026-07-09 11:16:42 +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
func (c Client) Directions(orig, dest Location, opts *DirectionsOpts) (*DirectionsResponse, error) {
var d DirectionsResponse
func (c Client) Directions(orig, dest Location, opts *DirectionsOpts) ([]Route, error) {
var d directionsResponse
if err := c.doDecode(baseURL+directions(orig, dest, opts), &d); err != nil {
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 {
@ -89,29 +92,31 @@ func (do *DirectionsOpts) update(p url.Values) {
}
}
type DirectionsResponse struct {
Status string `json:"status"`
ErrorMessage string `json:"error_message"`
Routes []struct {
Summary string `json:"summary"`
Legs []struct {
Duration *Duration `json:"duration"`
DurationInTraffic *Duration `json:"duration_in_traffic"`
Distance *Distance `json:"distance"`
ArrivalTime Time `json:"arrival_time"`
DepartureTime Time `json:"departure_time"`
StartLocation *LatLng `json:"start_location"`
EndLocation *LatLng `json:"end_location"`
StartAddress string `json:"start_address"`
EndAddress string `json:"end_address"`
Steps []Step `json:"steps"`
} `json:"legs"`
Bounds Bounds `json:"bounds"`
Copyrights string `json:"copyrights"`
OverviewPolyline Polyline `json:"overview_polyline"`
Warnings []string `json:"warnings"`
WaypointOrder []int `json:"waypoint_order"`
} `json:"routes"`
type directionsResponse struct {
Status string `json:"status"`
ErrorMessage string `json:"error_message"`
Routes []Route `json:"routes"`
}
type Route struct {
Summary string `json:"summary"`
Legs []struct {
Duration *Duration `json:"duration"`
DurationInTraffic *Duration `json:"duration_in_traffic"`
Distance *Distance `json:"distance"`
ArrivalTime Time `json:"arrival_time"`
DepartureTime Time `json:"departure_time"`
StartLocation *LatLng `json:"start_location"`
EndLocation *LatLng `json:"end_location"`
StartAddress string `json:"start_address"`
EndAddress string `json:"end_address"`
Steps []Step `json:"steps"`
} `json:"legs"`
Bounds Bounds `json:"bounds"`
Copyrights string `json:"copyrights"`
OverviewPolyline Polyline `json:"overview_polyline"`
Warnings []string `json:"warnings"`
WaypointOrder []int `json:"waypoint_order"`
}
type Time struct {

View file

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

View file

@ -5,36 +5,48 @@ import (
"net/url"
)
func (c Client) Elevation(ll []LatLng) (*ElevationResponse, error) {
var r ElevationResponse
func (c Client) Elevation(ll []LatLng) ([]ElevationResult, error) {
var r elevationResponse
if err := c.doDecode(baseURL+elevation(ll), &r); err != nil {
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) {
var r ElevationResponse
func (c Client) ElevationPolyline(p string) ([]ElevationResult, error) {
var r elevationResponse
if err := c.doDecode(baseURL+elevationpoly(p), &r); err != nil {
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) {
var r ElevationResponse
func (c Client) ElevationPath(ll []LatLng, samples int) ([]ElevationResult, error) {
var r elevationResponse
if err := c.doDecode(baseURL+elevationpath(ll, samples), &r); err != nil {
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) {
var r ElevationResponse
func (c Client) ElevationPathPoly(p string, samples int) ([]ElevationResult, error) {
var r elevationResponse
if err := c.doDecode(baseURL+elevationpathpoly(p, samples), &r); err != nil {
return nil, err
}
return &r, nil
if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
}
func elevation(ll []LatLng) string {
@ -63,11 +75,12 @@ func elevationpathpoly(poly string, s int) string {
return "elevation/json?" + p.Encode()
}
type ElevationResponse struct {
Results []struct {
Elevation float64 `json:"elevation"`
Location LatLng `json:"location"`
Resolution float64 `json:"resolution"`
} `json:"results"`
Status string `json:"status"`
type elevationResponse struct {
Results []ElevationResult `json:"results"`
Status string `json:"status"`
}
type ElevationResult struct {
Elevation float64 `json:"elevation"`
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
)
func (c Client) Geocode(opts *GeocodeOpts) (*GeocodeResponse, error) {
var r GeocodeResponse
func (c Client) Geocode(opts *GeocodeOpts) ([]GeocodeResult, error) {
var r geocodeResponse
if err := c.doDecode(baseURL+geocode(opts), &r); err != nil {
return nil, err
}
return &r, nil
if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
}
func geocode(opts *GeocodeOpts) string {
@ -79,33 +82,37 @@ func (g *GeocodeOpts) update(p url.Values) {
}
}
type GeocodeResponse struct {
Results []struct {
AddressComponents []struct {
LongName string `json:"long_name"`
ShortName string `json:"short_name"`
Types []string `json:"types"`
} `json:"address_components"`
PostcodeLocalities []string `json:"postcode_localities"`
FormattedAddress string `json:"formatted_address"`
Geometry struct {
Location LatLng `json:"location"`
LocationType string `json:"location_type"`
Viewport Bounds `json:"viewport"`
Bounds Bounds `json:"bounds"`
} `json:"geometry"`
Types []string `json:"types"`
PartialMatch string `json:"partial_match"`
} `json:"results"`
Status string `json:"status"`
type geocodeResponse struct {
Results []GeocodeResult `json:"results"`
Status string `json:"status"`
}
type GeocodeResult struct {
AddressComponents []struct {
LongName string `json:"long_name"`
ShortName string `json:"short_name"`
Types []string `json:"types"`
} `json:"address_components"`
PostcodeLocalities []string `json:"postcode_localities"`
FormattedAddress string `json:"formatted_address"`
Geometry struct {
Location LatLng `json:"location"`
LocationType string `json:"location_type"`
Viewport Bounds `json:"viewport"`
Bounds Bounds `json:"bounds"`
} `json:"geometry"`
Types []string `json:"types"`
PartialMatch string `json:"partial_match"`
}
func (c Client) ReverseGeocode(ll LatLng, opts *ReverseGeocodeOpts) (*GeocodeResponse, error) {
var r GeocodeResponse
func (c Client) ReverseGeocode(ll LatLng, opts *ReverseGeocodeOpts) ([]GeocodeResult, error) {
var r geocodeResponse
if err := c.doDecode(baseURL+reversegeocode(ll, opts), &r); err != nil {
return nil, err
}
return &r, nil
if r.Status != StatusOK {
return nil, APIError{r.Status, ""}
}
return r.Results, nil
}
type ReverseGeocodeOpts struct {

14
maps.go
View file

@ -57,6 +57,7 @@ func (c Client) doDecode(url string, r interface{}) error {
return nil
}
// HTTPError indicates an error communicating with the API, and includes the HTTP response returned from the server.
type HTTPError struct {
Response *http.Response
}
@ -65,6 +66,19 @@ func (e HTTPError) Error() string {
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 {
Location() string
}

View file

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