Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
676634850e | |||
0d442683ee | |||
|
c8587ec93a | ||
7e35316cf2 | |||
|
475452a781 | ||
|
dd0bb7c5d4 | ||
|
b74f3762dd | ||
|
e30590c707 | ||
|
132e95dec6 | ||
48620e6297 | |||
|
e31185b6dc | ||
|
151e45ca30 | ||
|
93c4f219e9 | ||
|
396654b066 | ||
|
a769031246 | ||
|
99915c1633 | ||
|
c7759d29b8 | ||
|
0f97e432a4 | ||
|
713b4f96be | ||
360b15a3b6 | |||
|
4959b0040b | ||
e93c6dc1de | |||
|
9ad01954dc | ||
|
8483b85c94 | ||
|
d1a8f76d77 | ||
|
9d7f4bfa66 | ||
|
656dfd4d05 | ||
|
70e14e6592 | ||
39e6d9f586 | |||
a46c9d395a | |||
|
d3c5a503c6 | ||
|
be224692a4 | ||
|
0da73b62ae | ||
|
a30c2972fd | ||
f28de46379 | |||
af91220a09 | |||
|
14bf4a9f30 |
6
go.mod
6
go.mod
@@ -1,10 +1,10 @@
|
||||
module github.com/unistack-org/micro-server-http/v3
|
||||
|
||||
go 1.13
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/unistack-org/micro/v3 v3.2.14
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
github.com/unistack-org/micro/v3 v3.3.13
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
|
||||
)
|
||||
|
||||
//replace github.com/unistack-org/micro/v3 => ../../micro
|
||||
|
68
go.sum
68
go.sum
@@ -1,32 +1,62 @@
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg=
|
||||
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/heimdalr/dag v1.0.1/go.mod h1:t+ZkR+sjKL4xhlE1B9rwpvwfo+x+2R0363efS+Oghns=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
|
||||
github.com/unistack-org/micro/v3 v3.2.14 h1:BD7JR2W0WlJvJgHN3uPWrE/vNAGyxhIQrIODeDCfoSk=
|
||||
github.com/unistack-org/micro/v3 v3.2.14/go.mod h1:3j13mSd/rILNjyP0tEVtDxyDkJBtnHUXShNCuPHkC5A=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM=
|
||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226101413-39120d07d75e h1:jIQURUJ9mlLvYwTBtRHm9h58rYhSonLvRvgAnP8Nr7I=
|
||||
golang.org/x/net v0.0.0-20210226101413-39120d07d75e/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
github.com/unistack-org/micro/v3 v3.3.0 h1:pEj/8QVFzMlNMEL//q/Te8qgG+XI6LTYIQrb6hMymgk=
|
||||
github.com/unistack-org/micro/v3 v3.3.0/go.mod h1:iJwCWq2PECMxigfqe6TPC5GLWvj6P94Kk+PTVZGL3w8=
|
||||
github.com/unistack-org/micro/v3 v3.3.1 h1:2KUgb5THy5GUjYgMcOf3TXYIJ0h2RbJHb2j6eeWdRx0=
|
||||
github.com/unistack-org/micro/v3 v3.3.1/go.mod h1:iJwCWq2PECMxigfqe6TPC5GLWvj6P94Kk+PTVZGL3w8=
|
||||
github.com/unistack-org/micro/v3 v3.3.2 h1:1r7fmaobJVZBKDhIewSBy8R4H/6YazQFetsDgULV6Mw=
|
||||
github.com/unistack-org/micro/v3 v3.3.2/go.mod h1:tX95c0Qx4w6oqU7qKThs9lya9P507BdZ29MsTVDmU6w=
|
||||
github.com/unistack-org/micro/v3 v3.3.4 h1:wSYjL1sfrqtMmgFfYKylrKpAepMHrPcOpe10hvQAKuo=
|
||||
github.com/unistack-org/micro/v3 v3.3.4/go.mod h1:tX95c0Qx4w6oqU7qKThs9lya9P507BdZ29MsTVDmU6w=
|
||||
github.com/unistack-org/micro/v3 v3.3.7 h1:AKQEevrlT2aqHYRFGd6BEFNnurHLvJyqvWvLCFP7iX4=
|
||||
github.com/unistack-org/micro/v3 v3.3.7/go.mod h1:M3RGgKZX1OlTn0QB+3R1tlSoGwmEg6rb/Isr0lLYmjQ=
|
||||
github.com/unistack-org/micro/v3 v3.3.8 h1:4e4gWuZI/cRUGZ6ZZpdrIDOF2MLO6cjHxeFfZzy610Y=
|
||||
github.com/unistack-org/micro/v3 v3.3.8/go.mod h1:M3RGgKZX1OlTn0QB+3R1tlSoGwmEg6rb/Isr0lLYmjQ=
|
||||
github.com/unistack-org/micro/v3 v3.3.9 h1:NFF4wymDDxgYeZU++04BxvETrrAnd0iNzVyfm/ssQI4=
|
||||
github.com/unistack-org/micro/v3 v3.3.9/go.mod h1:M3RGgKZX1OlTn0QB+3R1tlSoGwmEg6rb/Isr0lLYmjQ=
|
||||
github.com/unistack-org/micro/v3 v3.3.10 h1:yMSiyplupFQ7xy/kNXL/zqSnqGSjrlNa2GTCwea5BVg=
|
||||
github.com/unistack-org/micro/v3 v3.3.10/go.mod h1:5ragE2E8ER5d4FZQJG9pB6qdfOoLXLfKW89l77Dy3jQ=
|
||||
github.com/unistack-org/micro/v3 v3.3.11 h1:Jr0gAw5lLqgddiHKQeWUOUeP6ZqgRhz52EA9zJ5MJ3U=
|
||||
github.com/unistack-org/micro/v3 v3.3.11/go.mod h1:PPCt675o3HPcODFbJ4iRWPmQFAk1WQ+asQSOb/syq6U=
|
||||
github.com/unistack-org/micro/v3 v3.3.13 h1:y4bDDkbwnjgOckrhFkC6D/o42tr75X33UbrB+Ko0M68=
|
||||
github.com/unistack-org/micro/v3 v3.3.13/go.mod h1:98hNcMXp/WyWJwLwCuwrhN1Jm7aCWaRNsMfRjK8Fq+Y=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf h1:sewfyKLWuY3ko6EI4hbFziQ8bHkfammpzCDfLT92I1c=
|
||||
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210324051636-2c4c8ecb7826 h1:lNRDRnwZWawoPHDS50ebYHTOHjctRMLSrUSQFcAHiW4=
|
||||
golang.org/x/net v0.0.0-20210324051636-2c4c8ecb7826/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210324205630-d1beb07c2056 h1:sANdAef76Ioam9aQUUdcAqricwY/WUaMc4+7LY4eGg8=
|
||||
golang.org/x/net v0.0.0-20210324205630-d1beb07c2056/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210326220855-61e056675ecf h1:WUcCxqQqDT0aXO4VnQbfMvp4zh7m1Gb2clVuHUAGGRE=
|
||||
golang.org/x/net v0.0.0-20210326220855-61e056675ecf/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210329181859-df645c7b52b1 h1:GDp1VG8WvY8lq4ic4L7GzKC3fNRlOa3UqUEpib8aBQE=
|
||||
golang.org/x/net v0.0.0-20210329181859-df645c7b52b1/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210330075724-22f4162a9025 h1:WkEv4x2mvGbnkuK9cWl/Ru2pzfVxAgpSDLT/holPSug=
|
||||
golang.org/x/net v0.0.0-20210330075724-22f4162a9025/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210330142815-c8897c278d10 h1:j6SlnKgJhONcqBZAH/cLNz6hg79L7Q18RY4BiN0r0LI=
|
||||
golang.org/x/net v0.0.0-20210330142815-c8897c278d10/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210330230544-e57232859fb2 h1:nGCZOty+lVDsc4H2qPFksI5Se296+V+GhMiL/TzmYNk=
|
||||
golang.org/x/net v0.0.0-20210330230544-e57232859fb2/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5 h1:zuP3axpB9rV3xH0EA7n3/gCrNPZm2SRl0l4mVH2BRj4=
|
||||
golang.org/x/net v0.0.0-20210331060903-cb1fcc7394e5/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c h1:KHUzaHIpjWVlVVNh65G3hhuj3KB1HnjY6Cq5cTvRQT8=
|
||||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
114
handler.go
114
handler.go
@@ -34,13 +34,12 @@ type patHandler struct {
|
||||
}
|
||||
|
||||
type httpHandler struct {
|
||||
name string
|
||||
opts server.HandlerOptions
|
||||
sopts server.Options
|
||||
eps []*register.Endpoint
|
||||
hd interface{}
|
||||
handlers map[string][]patHandler
|
||||
errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int)
|
||||
name string
|
||||
opts server.HandlerOptions
|
||||
sopts server.Options
|
||||
eps []*register.Endpoint
|
||||
hd interface{}
|
||||
handlers map[string][]patHandler
|
||||
}
|
||||
|
||||
func (h *httpHandler) newCodec(ct string) (codec.Codec, error) {
|
||||
@@ -66,24 +65,34 @@ func (h *httpHandler) Options() server.HandlerOptions {
|
||||
return h.opts
|
||||
}
|
||||
|
||||
func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := metadata.NewContext(r.Context(), nil)
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
path := r.URL.Path
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
h.errorHandler(ctx, h, w, r, fmt.Errorf("path must contains /"), http.StatusBadRequest)
|
||||
h.errorHandler(ctx, nil, w, r, fmt.Errorf("path must contains /"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ct := DefaultContentType
|
||||
ct := strings.Split(DefaultContentType, ";")[0]
|
||||
if htype := r.Header.Get("Content-Type"); htype != "" {
|
||||
ct = htype
|
||||
ct = strings.Split(htype, ";")[0]
|
||||
}
|
||||
|
||||
var cf codec.Codec
|
||||
var err error
|
||||
switch ct {
|
||||
case "application/x-www-form-urlencoded":
|
||||
cf, err = h.newCodec(strings.Split(DefaultContentType, ";")[0])
|
||||
default:
|
||||
cf, err = h.newCodec(ct)
|
||||
}
|
||||
|
||||
cf, err := h.newCodec(ct)
|
||||
if err != nil {
|
||||
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
|
||||
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
components := strings.Split(path[1:], "/")
|
||||
@@ -91,7 +100,7 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
var verb string
|
||||
idx := strings.LastIndex(components[l-1], ":")
|
||||
if idx == 0 {
|
||||
h.errorHandler(ctx, h, w, r, fmt.Errorf("not found"), http.StatusNotFound)
|
||||
h.errorHandler(ctx, nil, w, r, fmt.Errorf("not found"), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if idx > 0 {
|
||||
@@ -100,21 +109,28 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
matches := make(map[string]interface{})
|
||||
|
||||
var match bool
|
||||
var hldr patHandler
|
||||
for _, hldr = range h.handlers[r.Method] {
|
||||
mp, err := hldr.pat.Match(components, verb)
|
||||
if err == nil {
|
||||
match = true
|
||||
for k, v := range mp {
|
||||
matches[k] = v
|
||||
var handler *httpHandler
|
||||
for _, hpat := range h.handlers {
|
||||
handlertmp := hpat.(*httpHandler)
|
||||
for _, hldrtmp := range handlertmp.handlers[r.Method] {
|
||||
mp, err := hldrtmp.pat.Match(components, verb)
|
||||
if err == nil {
|
||||
match = true
|
||||
for k, v := range mp {
|
||||
matches[k] = v
|
||||
}
|
||||
hldr = hldrtmp
|
||||
handler = handlertmp
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
h.errorHandler(ctx, h, w, r, fmt.Errorf("not matching route found"), http.StatusNotFound)
|
||||
h.errorHandler(ctx, nil, w, r, fmt.Errorf("not matching route found"), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -131,7 +147,24 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if len(r.URL.RawQuery) > 0 {
|
||||
umd, err := rflutil.URLMap(r.URL.RawQuery)
|
||||
if err != nil {
|
||||
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
|
||||
h.errorHandler(ctx, handler, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
for k, v := range umd {
|
||||
matches[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
if ct == "application/x-www-form-urlencoded" {
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
umd, err := rflutil.URLMap(string(buf))
|
||||
if err != nil {
|
||||
h.errorHandler(ctx, handler, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
for k, v := range umd {
|
||||
matches[k] = v
|
||||
@@ -160,25 +193,31 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
//function := hldr.rcvr
|
||||
var returnValues []reflect.Value
|
||||
|
||||
if err = cf.ReadBody(r.Body, argv.Interface()); err != nil && err != io.EOF {
|
||||
h.errorHandler(ctx, h, w, r, err, http.StatusInternalServerError)
|
||||
if ct != "application/x-www-form-urlencoded" {
|
||||
if err = cf.ReadBody(r.Body, argv.Interface()); err != nil && err != io.EOF {
|
||||
h.errorHandler(ctx, handler, w, r, err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
matches = rflutil.FlattenMap(matches)
|
||||
if err = rflutil.MergeMap(argv.Interface(), matches); err != nil {
|
||||
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
|
||||
if err = rflutil.Merge(argv.Interface(), matches, rflutil.SliceAppend(true), rflutil.Tags([]string{"protobuf", "json"})); err != nil {
|
||||
h.errorHandler(ctx, handler, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
b, err := cf.Marshal(argv.Interface())
|
||||
if err != nil {
|
||||
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
var b []byte
|
||||
if ct != "application/x-www-form-urlencoded" {
|
||||
b, err = cf.Marshal(argv.Interface())
|
||||
if err != nil {
|
||||
h.errorHandler(ctx, handler, w, r, err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
hr := &rpcRequest{
|
||||
codec: cf,
|
||||
service: h.sopts.Name,
|
||||
service: handler.sopts.Name,
|
||||
contentType: ct,
|
||||
method: fmt.Sprintf("%s.%s", hldr.name, hldr.mtype.method.Name),
|
||||
body: b,
|
||||
@@ -206,8 +245,8 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// wrap the handler func
|
||||
for i := len(h.sopts.HdlrWrappers); i > 0; i-- {
|
||||
fn = h.sopts.HdlrWrappers[i-1](fn)
|
||||
for i := len(handler.sopts.HdlrWrappers); i > 0; i-- {
|
||||
fn = handler.sopts.HdlrWrappers[i-1](fn)
|
||||
}
|
||||
|
||||
if appErr := fn(ctx, hr, replyv.Interface()); appErr != nil {
|
||||
@@ -223,8 +262,8 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
b, err = cf.Marshal(replyv.Interface())
|
||||
}
|
||||
if err != nil && h.sopts.Logger.V(logger.ErrorLevel) {
|
||||
h.sopts.Logger.Errorf(h.sopts.Context, "handler err: %v", err)
|
||||
if err != nil && handler.sopts.Logger.V(logger.ErrorLevel) {
|
||||
handler.sopts.Logger.Errorf(handler.sopts.Context, "handler err: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -238,7 +277,8 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if scode != 0 {
|
||||
w.WriteHeader(scode)
|
||||
} else {
|
||||
h.sopts.Logger.Warn(h.sopts.Context, "response code not set in handler via SetRspCode(ctx, http.StatusXXX)")
|
||||
//handler.sopts.Logger.Warn(handler.sopts.Context, "response code not set in handler via SetRspCode(ctx, http.StatusXXX)")
|
||||
w.WriteHeader(200)
|
||||
}
|
||||
w.Write(b)
|
||||
}
|
||||
|
98
http.go
98
http.go
@@ -2,8 +2,8 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -25,13 +25,16 @@ import (
|
||||
type httpServer struct {
|
||||
sync.RWMutex
|
||||
opts server.Options
|
||||
handlers map[string]server.Handler
|
||||
hd server.Handler
|
||||
exit chan chan error
|
||||
subscribers map[*httpSubscriber][]broker.Subscriber
|
||||
// used for first registration
|
||||
registered bool
|
||||
// register service instance
|
||||
rsvc *register.Service
|
||||
rsvc *register.Service
|
||||
init bool
|
||||
errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int)
|
||||
}
|
||||
|
||||
func (h *httpServer) newCodec(ct string) (codec.Codec, error) {
|
||||
@@ -49,17 +52,63 @@ func (h *httpServer) Options() server.Options {
|
||||
}
|
||||
|
||||
func (h *httpServer) Init(opts ...server.Option) error {
|
||||
if len(opts) == 0 && h.init {
|
||||
return nil
|
||||
}
|
||||
|
||||
h.Lock()
|
||||
for _, o := range opts {
|
||||
o(&h.opts)
|
||||
}
|
||||
if fn, ok := h.opts.Context.Value(errorHandlerKey{}).(func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int)); ok && fn != nil {
|
||||
h.errorHandler = fn
|
||||
}
|
||||
if h.handlers == nil {
|
||||
h.handlers = make(map[string]server.Handler)
|
||||
}
|
||||
h.Unlock()
|
||||
|
||||
if err := h.opts.Register.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.opts.Broker.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.opts.Tracer.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.opts.Auth.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.opts.Logger.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.opts.Meter.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.opts.Transport.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.init = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *httpServer) Handle(handler server.Handler) error {
|
||||
h.Lock()
|
||||
h.hd = handler
|
||||
if hdlr, ok := handler.(*httpHandler); ok {
|
||||
if _, ok := hdlr.hd.(http.Handler); ok {
|
||||
h.hd = handler
|
||||
} else {
|
||||
if h.handlers == nil {
|
||||
h.handlers = make(map[string]server.Handler)
|
||||
}
|
||||
h.handlers[handler.Name()] = handler
|
||||
}
|
||||
} else {
|
||||
h.hd = handler
|
||||
}
|
||||
h.Unlock()
|
||||
return nil
|
||||
}
|
||||
@@ -179,8 +228,11 @@ func (h *httpServer) Subscribe(sb server.Subscriber) error {
|
||||
}
|
||||
|
||||
func (h *httpServer) Register() error {
|
||||
var eps []*register.Endpoint
|
||||
h.RLock()
|
||||
eps := h.hd.Endpoints()
|
||||
for _, hdlr := range h.handlers {
|
||||
eps = append(eps, hdlr.Endpoints()...)
|
||||
}
|
||||
rsvc := h.rsvc
|
||||
config := h.opts
|
||||
h.RUnlock()
|
||||
@@ -317,7 +369,6 @@ func (h *httpServer) Deregister() error {
|
||||
func (h *httpServer) Start() error {
|
||||
h.RLock()
|
||||
config := h.opts
|
||||
hd := h.hd
|
||||
h.RUnlock()
|
||||
|
||||
// micro: config.Transport.Listen(config.Address)
|
||||
@@ -352,13 +403,32 @@ func (h *httpServer) Start() error {
|
||||
h.opts.Address = ts.Addr().String()
|
||||
h.Unlock()
|
||||
|
||||
handler, ok := hd.Handler().(http.Handler)
|
||||
if !ok {
|
||||
handler, ok = hd.(http.Handler)
|
||||
var handler http.Handler
|
||||
var srvFunc func(net.Listener) error
|
||||
|
||||
if h.opts.Context != nil {
|
||||
if hs, ok := h.opts.Context.Value(serverKey{}).(*http.Server); ok && hs != nil {
|
||||
if hs.Handler == nil && h.hd != nil {
|
||||
if hdlr, ok := h.hd.Handler().(http.Handler); ok {
|
||||
hs.Handler = hdlr
|
||||
handler = hs.Handler
|
||||
}
|
||||
} else {
|
||||
handler = hs.Handler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return errors.New("Server required http.Handler")
|
||||
if handler == nil && h.hd == nil {
|
||||
handler = h
|
||||
} else if handler == nil && h.hd != nil {
|
||||
if hdlr, ok := h.hd.Handler().(http.Handler); ok {
|
||||
handler = hdlr
|
||||
}
|
||||
}
|
||||
|
||||
if handler == nil {
|
||||
return fmt.Errorf("cant process with nil handler")
|
||||
}
|
||||
|
||||
if err := config.Broker.Connect(h.opts.Context); err != nil {
|
||||
@@ -376,7 +446,6 @@ func (h *httpServer) Start() error {
|
||||
}
|
||||
|
||||
fn := handler
|
||||
var srvFunc func(net.Listener) error
|
||||
|
||||
if h.opts.Context != nil {
|
||||
if mwf, ok := h.opts.Context.Value(middlewareKey{}).([]func(http.Handler) http.Handler); ok && len(mwf) > 0 {
|
||||
@@ -481,8 +550,9 @@ func (h *httpServer) Name() string {
|
||||
func NewServer(opts ...server.Option) server.Server {
|
||||
options := server.NewOptions(opts...)
|
||||
return &httpServer{
|
||||
opts: options,
|
||||
exit: make(chan chan error),
|
||||
subscribers: make(map[*httpSubscriber][]broker.Subscriber),
|
||||
opts: options,
|
||||
exit: make(chan chan error),
|
||||
subscribers: make(map[*httpSubscriber][]broker.Subscriber),
|
||||
errorHandler: DefaultErrorHandler,
|
||||
}
|
||||
}
|
||||
|
15
options.go
15
options.go
@@ -13,14 +13,17 @@ type rspCodeVal struct {
|
||||
code int
|
||||
}
|
||||
|
||||
// SetError pass error to caller
|
||||
func SetError(err interface{}) error {
|
||||
return &Error{err: err}
|
||||
}
|
||||
|
||||
// Error struct holds error
|
||||
type Error struct {
|
||||
err interface{}
|
||||
}
|
||||
|
||||
// Error func for error interface
|
||||
func (err *Error) Error() string {
|
||||
return fmt.Sprintf("%v", err.err)
|
||||
}
|
||||
@@ -43,12 +46,24 @@ func GetRspCode(ctx context.Context) int {
|
||||
|
||||
type middlewareKey struct{}
|
||||
|
||||
// Middleware passes http middlewares
|
||||
func Middleware(mw ...func(http.Handler) http.Handler) server.Option {
|
||||
return server.SetOption(middlewareKey{}, mw)
|
||||
}
|
||||
|
||||
type serverKey struct{}
|
||||
|
||||
// Server provide ability to pass *http.Server
|
||||
func Server(hs *http.Server) server.Option {
|
||||
return server.SetOption(serverKey{}, hs)
|
||||
}
|
||||
|
||||
type errorHandlerKey struct{}
|
||||
|
||||
// ErrorHandler specifies handler for errors
|
||||
func ErrorHandler(fn func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int)) server.Option {
|
||||
return server.SetOption(errorHandlerKey{}, fn)
|
||||
}
|
||||
|
||||
// type pathHandlerKey struct{}
|
||||
// PathHandler specifies http handler for path
|
||||
|
Reference in New Issue
Block a user