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:
parent
41f9b8b763
commit
aa3b05a35f
6 changed files with 134 additions and 81 deletions
|
|
@ -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 {
|
||||||
|
|
|
||||||
17
distance.go
17
distance.go
|
|
@ -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 {
|
||||||
|
|
|
||||||
51
elevation.go
51
elevation.go
|
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
57
geocode.go
57
geocode.go
|
|
@ -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
14
maps.go
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
timezone.go
19
timezone.go
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue