| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 | 
							- package routing
 
- import (
 
- 	"context"
 
- 	"encoding/json"
 
- 	"net/http"
 
- 	"net/url"
 
- 	"time"
 
- 	"github.com/go-kit/kit/circuitbreaker"
 
- 	"github.com/go-kit/kit/endpoint"
 
- 	kithttp "github.com/go-kit/kit/transport/http"
 
- 	shipping "github.com/longjoy/micro-go-course/section19/cargo/model"
 
- )
 
- type proxyService struct {
 
- 	context.Context
 
- 	FetchRoutesEndpoint endpoint.Endpoint
 
- 	shipping.RoutingService
 
- }
 
- func (s proxyService) FetchRoutesForSpecification(rs shipping.RouteSpecification) []shipping.Itinerary {
 
- 	response, err := s.FetchRoutesEndpoint(s.Context, fetchRoutesRequest{
 
- 		From: string(rs.Origin),
 
- 		To:   string(rs.Destination),
 
- 	})
 
- 	if err != nil {
 
- 		return []shipping.Itinerary{}
 
- 	}
 
- 	resp := response.(fetchRoutesResponse)
 
- 	var itineraries []shipping.Itinerary
 
- 	for _, r := range resp.Paths {
 
- 		var legs []shipping.Leg
 
- 		for _, e := range r.Edges {
 
- 			legs = append(legs, shipping.Leg{
 
- 				VoyageNumber:   shipping.VoyageNumber(e.Voyage),
 
- 				LoadLocation:   shipping.UNLocode(e.Origin),
 
- 				UnloadLocation: shipping.UNLocode(e.Destination),
 
- 				LoadTime:       e.Departure,
 
- 				UnloadTime:     e.Arrival,
 
- 			})
 
- 		}
 
- 		itineraries = append(itineraries, shipping.Itinerary{Legs: legs})
 
- 	}
 
- 	return itineraries
 
- }
 
- // ServiceMiddleware defines a middleware for a routing service.
 
- type ServiceMiddleware func(shipping.RoutingService) shipping.RoutingService
 
- // NewProxyingMiddleware returns a new instance of a proxying middleware.
 
- func NewProxyingMiddleware(ctx context.Context, proxyURL string) ServiceMiddleware {
 
- 	return func(next shipping.RoutingService) shipping.RoutingService {
 
- 		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
 
- }
 
 
  |