1package httprp 2 3import ( 4 "context" 5 "net/http" 6 "net/http/httputil" 7 "net/url" 8) 9 10// RequestFunc may take information from an HTTP request and put it into a 11// request context. BeforeFuncs are executed prior to invoking the 12// endpoint. 13type RequestFunc func(context.Context, *http.Request) context.Context 14 15// Server is a proxying request handler. 16type Server struct { 17 proxy http.Handler 18 before []RequestFunc 19 errorEncoder func(w http.ResponseWriter, err error) 20} 21 22// NewServer constructs a new server that implements http.Server and will proxy 23// requests to the given base URL using its scheme, host, and base path. 24// If the target's path is "/base" and the incoming request was for "/dir", 25// the target request will be for /base/dir. 26func NewServer( 27 baseURL *url.URL, 28 options ...ServerOption, 29) *Server { 30 s := &Server{ 31 proxy: httputil.NewSingleHostReverseProxy(baseURL), 32 } 33 for _, option := range options { 34 option(s) 35 } 36 return s 37} 38 39// ServerOption sets an optional parameter for servers. 40type ServerOption func(*Server) 41 42// ServerBefore functions are executed on the HTTP request object before the 43// request is decoded. 44func ServerBefore(before ...RequestFunc) ServerOption { 45 return func(s *Server) { s.before = append(s.before, before...) } 46} 47 48// ServeHTTP implements http.Handler. 49func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 50 ctx := r.Context() 51 52 for _, f := range s.before { 53 ctx = f(ctx, r) 54 } 55 56 s.proxy.ServeHTTP(w, r) 57} 58