forked from marcusolsson/goddd
/
proxying.go
118 lines (99 loc) · 2.83 KB
/
proxying.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package routing
import (
"encoding/json"
"net/http"
"net/url"
"time"
"golang.org/x/net/context"
"github.com/go-kit/kit/circuitbreaker"
"github.com/go-kit/kit/endpoint"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/marcusolsson/goddd/cargo"
"github.com/marcusolsson/goddd/location"
"github.com/marcusolsson/goddd/voyage"
)
type proxyService struct {
context.Context
FetchRoutesEndpoint endpoint.Endpoint
Service
}
func (s proxyService) FetchRoutesForSpecification(rs cargo.RouteSpecification) []cargo.Itinerary {
response, err := s.FetchRoutesEndpoint(s.Context, fetchRoutesRequest{
From: string(rs.Origin),
To: string(rs.Destination),
})
if err != nil {
return []cargo.Itinerary{}
}
resp := response.(fetchRoutesResponse)
var itineraries []cargo.Itinerary
for _, r := range resp.Paths {
var legs []cargo.Leg
for _, e := range r.Edges {
legs = append(legs, cargo.Leg{
VoyageNumber: voyage.Number(e.Voyage),
LoadLocation: location.UNLocode(e.Origin),
UnloadLocation: location.UNLocode(e.Destination),
LoadTime: e.Departure,
UnloadTime: e.Arrival,
})
}
itineraries = append(itineraries, cargo.Itinerary{Legs: legs})
}
return itineraries
}
// ServiceMiddleware defines a middleware for a routing service.
type ServiceMiddleware func(Service) Service
// NewProxyingMiddleware returns a new instance of a proxying middleware.
func NewProxyingMiddleware(ctx context.Context, proxyURL string) ServiceMiddleware {
return func(next Service) Service {
var e endpoint.Endpoint
e = makeFetchRoutesEndpoint(ctx, proxyURL)
e = circuitbreaker.Hystrix("fetch-routes")(e)
return proxyService{ctx, e, next}
}
}
type fetchRoutesRequest struct {
From string
To string
}
type fetchRoutesResponse struct {
Paths []struct {
Edges []struct {
Origin string `json:"origin"`
Destination string `json:"destination"`
Voyage string `json:"voyage"`
Departure time.Time `json:"departure"`
Arrival time.Time `json:"arrival"`
} `json:"edges"`
} `json:"paths"`
}
func makeFetchRoutesEndpoint(ctx context.Context, instance string) endpoint.Endpoint {
u, err := url.Parse(instance)
if err != nil {
panic(err)
}
if u.Path == "" {
u.Path = "/paths"
}
return kithttp.NewClient(
"GET", u,
encodeFetchRoutesRequest,
decodeFetchRoutesResponse,
).Endpoint()
}
func decodeFetchRoutesResponse(_ context.Context, resp *http.Response) (interface{}, error) {
var response fetchRoutesResponse
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, err
}
return response, nil
}
func encodeFetchRoutesRequest(_ context.Context, r *http.Request, request interface{}) error {
req := request.(fetchRoutesRequest)
vals := r.URL.Query()
vals.Add("from", req.From)
vals.Add("to", req.To)
r.URL.RawQuery = vals.Encode()
return nil
}