github.com/btccom/go-micro/v2@v2.9.3/api/handler/http/http.go (about) 1 // Package http is a http reverse proxy handler 2 package http 3 4 import ( 5 "errors" 6 "fmt" 7 "net/http" 8 "net/http/httputil" 9 "net/url" 10 11 "github.com/btccom/go-micro/v2/api" 12 "github.com/btccom/go-micro/v2/api/handler" 13 "github.com/btccom/go-micro/v2/client/selector" 14 ) 15 16 const ( 17 Handler = "http" 18 ) 19 20 type httpHandler struct { 21 options handler.Options 22 23 // set with different initialiser 24 s *api.Service 25 } 26 27 func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 28 service, err := h.getService(r) 29 if err != nil { 30 w.WriteHeader(500) 31 return 32 } 33 34 if len(service) == 0 { 35 w.WriteHeader(404) 36 return 37 } 38 39 rp, err := url.Parse(service) 40 if err != nil { 41 w.WriteHeader(500) 42 return 43 } 44 45 httputil.NewSingleHostReverseProxy(rp).ServeHTTP(w, r) 46 } 47 48 // getService returns the service for this request from the selector 49 func (h *httpHandler) getService(r *http.Request) (string, error) { 50 var service *api.Service 51 52 if h.s != nil { 53 // we were given the service 54 service = h.s 55 } else if h.options.Router != nil { 56 // try get service from router 57 s, err := h.options.Router.Route(r) 58 if err != nil { 59 return "", err 60 } 61 service = s 62 } else { 63 // we have no way of routing the request 64 return "", errors.New("no route found") 65 } 66 67 // create a random selector 68 next := selector.Random(service.Services) 69 70 // get the next node 71 s, err := next() 72 if err != nil { 73 return "", nil 74 } 75 76 return fmt.Sprintf("http://%s", s.Address), nil 77 } 78 79 func (h *httpHandler) String() string { 80 return "http" 81 } 82 83 // NewHandler returns a http proxy handler 84 func NewHandler(opts ...handler.Option) handler.Handler { 85 options := handler.NewOptions(opts...) 86 87 return &httpHandler{ 88 options: options, 89 } 90 } 91 92 // WithService creates a handler with a service 93 func WithService(s *api.Service, opts ...handler.Option) handler.Handler { 94 options := handler.NewOptions(opts...) 95 96 return &httpHandler{ 97 options: options, 98 s: s, 99 } 100 }