* client/{grpc,rpc}: depricate selector (wip)
* {client,cmd}: remove client/selector
* deprecate client/selector
* router/static: fix lookup
* config/cmd: add support for legacy static selector flag
* config/cmd: add support for legacy dns selector flag
		
	
		
			
				
	
	
		
			105 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package http is a http reverse proxy handler
 | |
| package http
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"math/rand"
 | |
| 	"net/http"
 | |
| 	"net/http/httputil"
 | |
| 	"net/url"
 | |
| 
 | |
| 	"github.com/micro/go-micro/v2/api"
 | |
| 	"github.com/micro/go-micro/v2/api/handler"
 | |
| 	"github.com/micro/go-micro/v2/registry"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	Handler = "http"
 | |
| )
 | |
| 
 | |
| type httpHandler struct {
 | |
| 	options handler.Options
 | |
| 
 | |
| 	// set with different initialiser
 | |
| 	s *api.Service
 | |
| }
 | |
| 
 | |
| func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | |
| 	service, err := h.getService(r)
 | |
| 	if err != nil {
 | |
| 		w.WriteHeader(500)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if len(service) == 0 {
 | |
| 		w.WriteHeader(404)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	rp, err := url.Parse(service)
 | |
| 	if err != nil {
 | |
| 		w.WriteHeader(500)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	httputil.NewSingleHostReverseProxy(rp).ServeHTTP(w, r)
 | |
| }
 | |
| 
 | |
| // getService returns the service for this request from the selector
 | |
| func (h *httpHandler) getService(r *http.Request) (string, error) {
 | |
| 	var service *api.Service
 | |
| 
 | |
| 	if h.s != nil {
 | |
| 		// we were given the service
 | |
| 		service = h.s
 | |
| 	} else if h.options.Router != nil {
 | |
| 		// try get service from router
 | |
| 		s, err := h.options.Router.Route(r)
 | |
| 		if err != nil {
 | |
| 			return "", err
 | |
| 		}
 | |
| 		service = s
 | |
| 	} else {
 | |
| 		// we have no way of routing the request
 | |
| 		return "", errors.New("no route found")
 | |
| 	}
 | |
| 
 | |
| 	// get the nodes for this service
 | |
| 	var nodes []*registry.Node
 | |
| 	for _, srv := range service.Services {
 | |
| 		nodes = append(nodes, srv.Nodes...)
 | |
| 	}
 | |
| 
 | |
| 	// select a random node
 | |
| 	if len(nodes) == 0 {
 | |
| 		return "", errors.New("no route found")
 | |
| 	}
 | |
| 	node := nodes[rand.Int()%len(nodes)]
 | |
| 
 | |
| 	return fmt.Sprintf("http://%s", node.Address), nil
 | |
| }
 | |
| 
 | |
| func (h *httpHandler) String() string {
 | |
| 	return "http"
 | |
| }
 | |
| 
 | |
| // NewHandler returns a http proxy handler
 | |
| func NewHandler(opts ...handler.Option) handler.Handler {
 | |
| 	options := handler.NewOptions(opts...)
 | |
| 
 | |
| 	return &httpHandler{
 | |
| 		options: options,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // WithService creates a handler with a service
 | |
| func WithService(s *api.Service, opts ...handler.Option) handler.Handler {
 | |
| 	options := handler.NewOptions(opts...)
 | |
| 
 | |
| 	return &httpHandler{
 | |
| 		options: options,
 | |
| 		s:       s,
 | |
| 	}
 | |
| }
 |