Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
7f1a55958e | |||
02f9d6d8f7 | |||
82beddb09b | |||
6cb3a1c4c4 | |||
|
2ff786cb03 | ||
282065f90e | |||
|
b16e6ebd31 | ||
68f4c164d0 | |||
|
d0fee2ca23 | ||
034298b7e0 | |||
f93c35b611 | |||
b5148e90cb | |||
|
a8d47d0c1c | ||
7d4e32298c | |||
|
14ff546fc1 | ||
|
c37d057669 | ||
b925441ea7 | |||
984d09384f | |||
7c15ee784a | |||
f2607d5439 | |||
|
8e607dcc26 | ||
929aae7456 | |||
5ba7742619 | |||
dece47ae0e | |||
|
db5e66e375 | ||
39d3aabf62 | |||
|
25469792df |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: lint
|
||||
uses: golangci/golangci-lint-action@v3.3.1
|
||||
uses: golangci/golangci-lint-action@v3.4.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
|
2
.github/workflows/dependabot-automerge.yml
vendored
2
.github/workflows/dependabot-automerge.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
- name: metadata
|
||||
id: metadata
|
||||
uses: dependabot/fetch-metadata@v1.3.5
|
||||
uses: dependabot/fetch-metadata@v1.3.6
|
||||
with:
|
||||
github-token: "${{ secrets.TOKEN }}"
|
||||
- name: merge
|
||||
|
2
.github/workflows/pr.yml
vendored
2
.github/workflows/pr.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: lint
|
||||
uses: golangci/golangci-lint-action@v3.3.1
|
||||
uses: golangci/golangci-lint-action@v3.4.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
|
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module go.unistack.org/micro-server-http/v3
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
go.unistack.org/micro/v3 v3.9.18
|
||||
go.unistack.org/micro/v3 v3.10.9
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@@ -74,8 +74,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.unistack.org/micro-proto/v3 v3.3.1 h1:nQ0MtWvP2G3QrpOgawVOPhpZZYkq6umTGDqs8FxJYIo=
|
||||
go.unistack.org/micro-proto/v3 v3.3.1/go.mod h1:cwRyv8uInM2I7EbU7O8Fx2Ls3N90Uw9UCCcq4olOdfE=
|
||||
go.unistack.org/micro/v3 v3.9.18 h1:FNsCCJJKyyP9gScc1K3HxGxFjub+c4ZQpL+QwVvIMro=
|
||||
go.unistack.org/micro/v3 v3.9.18/go.mod h1:gI4RkJKHLPW7KV6h4+ZBOZD997MRvFRXMPQIHpozikI=
|
||||
go.unistack.org/micro/v3 v3.10.9 h1:o8gdlE5JC9b2sm89RmztQPHnP4thN6FkGZyrKrahxX8=
|
||||
go.unistack.org/micro/v3 v3.10.9/go.mod h1:gI4RkJKHLPW7KV6h4+ZBOZD997MRvFRXMPQIHpozikI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
28
handler.go
28
handler.go
@@ -73,21 +73,22 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), rspCodeKey{}, &rspCodeVal{})
|
||||
ctx = context.WithValue(ctx, rspHeaderKey{}, &rspHeaderVal{})
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.New(len(r.Header) + 8)
|
||||
}
|
||||
for k, v := range r.Header {
|
||||
md.Set(k, strings.Join(v, ", "))
|
||||
md[k] = strings.Join(v, ", ")
|
||||
}
|
||||
md.Set("RemoteAddr", r.RemoteAddr)
|
||||
md.Set("Method", r.Method)
|
||||
md.Set("URL", r.URL.String())
|
||||
md.Set("Proto", r.Proto)
|
||||
md.Set("ContentLength", fmt.Sprintf("%d", r.ContentLength))
|
||||
md.Set("TransferEncoding", strings.Join(r.TransferEncoding, ","))
|
||||
md.Set("Host", r.Host)
|
||||
md.Set("RequestURI", r.RequestURI)
|
||||
md["RemoteAddr"] = r.RemoteAddr
|
||||
md["Method"] = r.Method
|
||||
md["URL"] = r.URL.String()
|
||||
md["Proto"] = r.Proto
|
||||
md["ContentLength"] = fmt.Sprintf("%d", r.ContentLength)
|
||||
md["TransferEncoding"] = strings.Join(r.TransferEncoding, ",")
|
||||
md["Host"] = r.Host
|
||||
md["RequestURI"] = r.RequestURI
|
||||
ctx = metadata.NewIncomingContext(ctx, md)
|
||||
|
||||
defer r.Body.Close()
|
||||
@@ -117,6 +118,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
break
|
||||
} else if err == rhttp.ErrMethodNotAllowed && !h.registerRPC {
|
||||
h.errorHandler(ctx, nil, w, r, fmt.Errorf("not matching route found"), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +214,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
service: handler.sopts.Name,
|
||||
contentType: ct,
|
||||
method: fmt.Sprintf("%s.%s", hldr.name, hldr.mtype.method.Name),
|
||||
endpoint: fmt.Sprintf("%s.%s", hldr.name, hldr.mtype.method.Name),
|
||||
payload: argv.Interface(),
|
||||
header: md,
|
||||
}
|
||||
@@ -262,6 +265,13 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set(k, v)
|
||||
}
|
||||
}
|
||||
if md := getRspHeader(ctx); md != nil {
|
||||
for k, v := range md {
|
||||
for _, vv := range v {
|
||||
w.Header().Add(k, vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
if nct := w.Header().Get(metadata.HeaderContentType); nct != ct {
|
||||
if cf, err = h.newCodec(nct); err != nil {
|
||||
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
|
||||
|
6
http.go
6
http.go
@@ -602,11 +602,15 @@ func (h *httpServer) Name() string {
|
||||
|
||||
func NewServer(opts ...server.Option) *httpServer {
|
||||
options := server.NewOptions(opts...)
|
||||
eh := DefaultErrorHandler
|
||||
if v, ok := options.Context.Value(errorHandlerKey{}).(errorHandler); ok && v != nil {
|
||||
eh = v
|
||||
}
|
||||
return &httpServer{
|
||||
opts: options,
|
||||
exit: make(chan chan error),
|
||||
subscribers: make(map[*httpSubscriber][]broker.Subscriber),
|
||||
errorHandler: DefaultErrorHandler,
|
||||
errorHandler: eh,
|
||||
pathHandlers: rhttp.NewTrie(),
|
||||
}
|
||||
}
|
||||
|
26
options.go
26
options.go
@@ -38,6 +38,20 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
rspHeaderKey struct{}
|
||||
rspHeaderVal struct {
|
||||
h http.Header
|
||||
}
|
||||
)
|
||||
|
||||
// SetRspHeader add response headers
|
||||
func SetRspHeader(ctx context.Context, h http.Header) {
|
||||
if rsp, ok := ctx.Value(rspHeaderKey{}).(*rspHeaderVal); ok {
|
||||
rsp.h = h
|
||||
}
|
||||
}
|
||||
|
||||
// SetRspCode saves response code in context, must be used by handler to specify http code
|
||||
func SetRspCode(ctx context.Context, code int) {
|
||||
if rsp, ok := ctx.Value(rspCodeKey{}).(*rspCodeVal); ok {
|
||||
@@ -45,6 +59,14 @@ func SetRspCode(ctx context.Context, code int) {
|
||||
}
|
||||
}
|
||||
|
||||
// getRspHeader get http.Header from context
|
||||
func getRspHeader(ctx context.Context) http.Header {
|
||||
if rsp, ok := ctx.Value(rspHeaderKey{}).(*rspHeaderVal); ok {
|
||||
return rsp.h
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRspCode used internally by generated http server handler
|
||||
func GetRspCode(ctx context.Context) int {
|
||||
var code int
|
||||
@@ -68,10 +90,12 @@ func Server(hs *http.Server) server.Option {
|
||||
return server.SetOption(serverKey{}, hs)
|
||||
}
|
||||
|
||||
type errorHandler func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int)
|
||||
|
||||
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 {
|
||||
func ErrorHandler(fn errorHandler) server.Option {
|
||||
return server.SetOption(errorHandlerKey{}, fn)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user