Files
geo-service/main.go
T
2019-02-26 14:54:16 +01:00

138 lines
3.2 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"github.com/caarlos0/env"
"googlemaps.github.io/maps"
"log"
"net/http"
"strings"
)
type config struct {
MapsApiKey string `env:"MAPS_API_KEY"`
Port int `env:"PORT" envDefault:"80"`
}
type location struct {
Lat float64 `json:"latitude"`
Long float64 `json:"longitude"`
}
type distance struct {
Text string `json:"text"`
Value int `json:"value"`
}
type duration struct {
Text string `json:"text"`
Value float64 `json:"value"`
}
type destination struct {
Destination string `json:"destination"`
Distance distance `json:"distance"`
Duration duration `json:"duration"`
}
type origin struct {
Origin string `json:"origin"`
Destinations []destination `json:"destinations"`
}
type distanceResponse struct {
Origins []origin `json:"origins"`
}
func main() {
cfg := config{}
err := env.Parse(&cfg)
if err != nil {
fmt.Printf("%+v\n", err)
}
fmt.Printf("%+v\n", cfg)
client, err := maps.NewClient(maps.WithAPIKey(cfg.MapsApiKey))
if err != nil {
log.Fatalf("fatal error: %s", err)
}
http.HandleFunc("/latlong/", makeHandler(handleLatLongRequest, client))
http.HandleFunc("/distance/", makeHandler(handleDistanceMatrixRequest, client))
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Port), nil))
}
func makeHandler(fn func(http.ResponseWriter, *http.Request, *maps.Client), client *maps.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fn(w, r, client)
}
}
func handleDistanceMatrixRequest(w http.ResponseWriter, r *http.Request, client *maps.Client) {
origins := strings.Split(r.URL.Query().Get("origins"), "|")
destinations := strings.Split(r.URL.Query().Get("destinations"), "|")
req := &maps.DistanceMatrixRequest{
Origins: origins,
Destinations: destinations,
Language: "sv",
Units: maps.UnitsMetric,
}
if result, err := client.DistanceMatrix(context.Background(), req); err != nil {
log.Fatalf("fatal error: %s", err)
w.WriteHeader(400)
} else {
res := distanceResponse{}
for i, r := range result.Rows {
var dests []destination
for j, e := range r.Elements {
dests = append(dests, destination{
destinations[j],
distance{
Text: e.Distance.HumanReadable,
Value: e.Distance.Meters,
},
duration{
e.Duration.String(),
e.Duration.Minutes(),
},
})
}
res.Origins = append(res.Origins, origin{origins[i], dests})
}
if response, err := json.Marshal(res); err != nil {
log.Fatalf("fatal error: %s", err)
w.WriteHeader(404)
} else {
_, _ = w.Write(response)
}
}
}
func handleLatLongRequest(w http.ResponseWriter, r *http.Request, client *maps.Client) {
req := &maps.GeocodingRequest{
Address: r.URL.Path[len("/latlong/"):],
}
if result, err := client.Geocode(context.Background(), req); err != nil {
log.Fatalf("fatal error: %s", err)
w.WriteHeader(400)
} else {
if len(result) > 0 {
l := location{
Lat: result[0].Geometry.Location.Lat,
Long: result[0].Geometry.Location.Lng,
}
if response, err := json.Marshal(l); err != nil {
log.Fatalf("fatal error: %s", err)
w.WriteHeader(404)
} else {
_, _ = w.Write(response)
}
}
}
}