1
0
mirror of https://github.com/go-micro/go-micro.git synced 2024-12-18 08:26:38 +02:00
go-micro/api/handler/http/http.go
2022-09-30 16:27:07 +02:00

85 lines
1.5 KiB
Go

// Package http is a http reverse proxy handler
package http
import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"go-micro.dev/v4/api/handler"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/selector"
)
const (
Handler = "http"
)
type httpHandler struct {
options handler.Options
}
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 *router.Route
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")
}
// create a random selector
next := selector.Random(service.Versions)
// get the next node
s, err := next()
if err != nil {
return "", nil
}
return fmt.Sprintf("http://%s", s.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,
}
}