add path handler option

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2021-04-13 11:32:56 +03:00
parent 0eb3c0b452
commit 622a79bd06
3 changed files with 47 additions and 7 deletions

View File

@ -66,6 +66,14 @@ func (h *httpHandler) Options() server.HandlerOptions {
} }
func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for exp, ph := range h.pathHandlers {
if exp.MatchString(r.URL.String()) {
ph(w, r)
return
}
}
ctx := metadata.NewContext(r.Context(), nil) ctx := metadata.NewContext(r.Context(), nil)
defer r.Body.Close() defer r.Body.Close()
@ -76,9 +84,9 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
ct := strings.Split(DefaultContentType, ";")[0] ct := DefaultContentType
if htype := r.Header.Get("Content-Type"); htype != "" { if htype := r.Header.Get("Content-Type"); htype != "" {
ct = strings.Split(htype, ";")[0] ct = htype
} }
var cf codec.Codec var cf codec.Codec
@ -87,7 +95,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
case "application/x-www-form-urlencoded": case "application/x-www-form-urlencoded":
cf, err = h.newCodec(strings.Split(DefaultContentType, ";")[0]) cf, err = h.newCodec(strings.Split(DefaultContentType, ";")[0])
default: default:
cf, err = h.newCodec(ct) cf, err = h.newCodec(strings.Split(ct, ";")[0])
} }
if err != nil { if err != nil {

19
http.go
View File

@ -8,6 +8,7 @@ import (
"net" "net"
"net/http" "net/http"
"reflect" "reflect"
"regexp"
"sort" "sort"
"strings" "strings"
"sync" "sync"
@ -35,6 +36,7 @@ type httpServer struct {
rsvc *register.Service rsvc *register.Service
init bool init bool
errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int) errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int)
pathHandlers map[*regexp.Regexp]http.HandlerFunc
} }
func (h *httpServer) newCodec(ct string) (codec.Codec, error) { func (h *httpServer) newCodec(ct string) (codec.Codec, error) {
@ -57,6 +59,8 @@ func (h *httpServer) Init(opts ...server.Option) error {
} }
h.Lock() h.Lock()
defer h.Unlock()
for _, o := range opts { for _, o := range opts {
o(&h.opts) o(&h.opts)
} }
@ -66,8 +70,18 @@ func (h *httpServer) Init(opts ...server.Option) error {
if h.handlers == nil { if h.handlers == nil {
h.handlers = make(map[string]server.Handler) h.handlers = make(map[string]server.Handler)
} }
h.Unlock() if h.pathHandlers == nil {
h.pathHandlers = make(map[*regexp.Regexp]http.HandlerFunc)
}
if phs, ok := h.opts.Context.Value(pathHandlerKey{}).(*pathHandlerVal); ok && phs.h != nil {
for pp, ph := range phs.h {
exp, err := regexp.Compile(pp)
if err != nil {
return err
}
h.pathHandlers[exp] = ph
}
}
if err := h.opts.Register.Init(); err != nil { if err := h.opts.Register.Init(); err != nil {
return err return err
} }
@ -554,5 +568,6 @@ func NewServer(opts ...server.Option) server.Server {
exit: make(chan chan error), exit: make(chan chan error),
subscribers: make(map[*httpSubscriber][]broker.Subscriber), subscribers: make(map[*httpSubscriber][]broker.Subscriber),
errorHandler: DefaultErrorHandler, errorHandler: DefaultErrorHandler,
pathHandlers: make(map[*regexp.Regexp]http.HandlerFunc),
} }
} }

View File

@ -65,5 +65,22 @@ func ErrorHandler(fn func(ctx context.Context, s server.Handler, w http.Response
return server.SetOption(errorHandlerKey{}, fn) return server.SetOption(errorHandlerKey{}, fn)
} }
// type pathHandlerKey struct{} type pathHandlerKey struct{}
// PathHandler specifies http handler for path type pathHandlerVal struct {
h map[string]http.HandlerFunc
}
// PathHandler specifies http handler for path regexp
func PathHandler(path string, h http.HandlerFunc) server.Option {
return func(o *server.Options) {
if o.Context == nil {
o.Context = context.Background()
}
v, ok := o.Context.Value(pathHandlerKey{}).(*pathHandlerVal)
if !ok {
v = &pathHandlerVal{h: make(map[string]http.HandlerFunc)}
}
v.h[path] = h
o.Context = context.WithValue(o.Context, pathHandlerKey{}, v)
}
}