mirror of
https://github.com/go-kratos/kratos.git
synced 2025-03-17 21:07:54 +02:00
transport/http: add http handler (#937)
* add http handler * fix request error
This commit is contained in:
parent
ef6e52d1ba
commit
b9f821c29f
6
.github/workflows/go.yml
vendored
6
.github/workflows/go.yml
vendored
@ -36,12 +36,6 @@ jobs:
|
||||
go build ./...
|
||||
go test ./...
|
||||
|
||||
- name: Errors
|
||||
run: |
|
||||
cd cmd/protoc-gen-go-errors
|
||||
go build ./...
|
||||
go test ./...
|
||||
|
||||
- name: Examples
|
||||
run: |
|
||||
cd examples
|
||||
|
@ -26,64 +26,11 @@ type MetadataHandler interface {
|
||||
}
|
||||
|
||||
func NewMetadataHandler(srv MetadataHandler, opts ...http1.HandleOption) http.Handler {
|
||||
h := http1.DefaultHandleOptions()
|
||||
for _, o := range opts {
|
||||
o(&h)
|
||||
}
|
||||
r := mux.NewRouter()
|
||||
|
||||
r.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in ListServicesRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
r.Handle("/services", http1.NewHandler(srv.ListServices, opts...)).Methods("GET")
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.ListServices(ctx, req.(*ListServicesRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*ListServicesReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("GET")
|
||||
|
||||
r.HandleFunc("/services/{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in GetServiceDescRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.GetServiceDesc(ctx, req.(*GetServiceDescRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*GetServiceDescReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("GET")
|
||||
r.Handle("/services/{name}", http1.NewHandler(srv.GetServiceDesc, opts...)).Methods("GET")
|
||||
|
||||
return r
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
pb "github.com/go-kratos/kratos/v2/api/kratos/api"
|
||||
|
||||
"google.golang.org/protobuf/compiler/protogen"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
errorsPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/errors")
|
||||
)
|
||||
|
||||
// generateFile generates a _http.pb.go file containing kratos errors definitions.
|
||||
func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
|
||||
if len(file.Enums) == 0 {
|
||||
return nil
|
||||
}
|
||||
filename := file.GeneratedFilenamePrefix + "_errors.pb.go"
|
||||
g := gen.NewGeneratedFile(filename, file.GoImportPath)
|
||||
g.P("// Code generated by protoc-gen-go-errors. DO NOT EDIT.")
|
||||
g.P()
|
||||
g.P("package ", file.GoPackageName)
|
||||
g.P()
|
||||
generateFileContent(gen, file, g)
|
||||
return g
|
||||
}
|
||||
|
||||
// generateFileContent generates the kratos errors definitions, excluding the package statement.
|
||||
func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile) {
|
||||
if len(file.Enums) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
g.P("// This is a compile-time assertion to ensure that this generated file")
|
||||
g.P("// is compatible with the kratos package it is being compiled against.")
|
||||
g.P("const _ = ", errorsPackage.Ident("SupportPackageIsVersion1"))
|
||||
g.P()
|
||||
for _, enum := range file.Enums {
|
||||
genErrorsReason(gen, file, g, enum)
|
||||
}
|
||||
}
|
||||
|
||||
func genErrorsReason(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, enum *protogen.Enum) {
|
||||
err := proto.GetExtension(enum.Desc.Options(), pb.E_Errors)
|
||||
if ok := err.(bool); !ok {
|
||||
return
|
||||
}
|
||||
var ew errorWrapper
|
||||
for _, v := range enum.Values {
|
||||
err := &errorInfo{
|
||||
Name: string(enum.Desc.Name()),
|
||||
Value: string(v.Desc.Name()),
|
||||
}
|
||||
ew.Errors = append(ew.Errors, err)
|
||||
}
|
||||
g.P(ew.execute())
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
module github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/go-kratos/kratos/v2 v2.0.0-beta2
|
||||
google.golang.org/protobuf v1.25.0
|
||||
)
|
@ -1,95 +0,0 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-kratos/kratos/v2 v2.0.0-beta2 h1:KfYlxfXsjRiccGS1TVRKvXVuEnPJDwrrTSx5HtaOBlc=
|
||||
github.com/go-kratos/kratos/v2 v2.0.0-beta2/go.mod h1:hwEYWw8GFuJ8IoNt3T/3k+7kUfYt+h2fHDcyFlR1jBA=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
go.opentelemetry.io/otel v0.18.0/go.mod h1:PT5zQj4lTsR1YeARt8YNKcFb88/c2IKoSABK9mX0r78=
|
||||
go.opentelemetry.io/otel/metric v0.18.0/go.mod h1:kEH2QtzAyBy3xDVQfGZKIcok4ZZFvd5xyKPfPcuK6pE=
|
||||
go.opentelemetry.io/otel/oteltest v0.18.0/go.mod h1:NyierCU3/G8DLTva7KRzGii2fdxdR89zXKH1bNWY7Bo=
|
||||
go.opentelemetry.io/otel/trace v0.18.0/go.mod h1:FzdUu3BPwZSZebfQ1vl5/tAa8LyMLXSJN57AXIt/iDk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
@ -1,35 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/compiler/protogen"
|
||||
"google.golang.org/protobuf/types/pluginpb"
|
||||
)
|
||||
|
||||
const version = "v2.0.0-beta4"
|
||||
|
||||
func main() {
|
||||
showVersion := flag.Bool("version", false, "print the version and exit")
|
||||
flag.Parse()
|
||||
if *showVersion {
|
||||
fmt.Printf("protoc-gen-go-errors %v\n", version)
|
||||
return
|
||||
}
|
||||
|
||||
var flags flag.FlagSet
|
||||
|
||||
protogen.Options{
|
||||
ParamFunc: flags.Set,
|
||||
}.Run(func(gen *protogen.Plugin) error {
|
||||
gen.SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
|
||||
for _, f := range gen.Files {
|
||||
if !f.Generate {
|
||||
continue
|
||||
}
|
||||
generateFile(gen, f)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var errorsTemplate = `const (
|
||||
{{ range .Errors }}
|
||||
Errors_{{.Value}} = "{{.Name}}_{{.Value}}"
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{ range .Errors }}
|
||||
|
||||
func Is{{.Value}}(err error) bool {
|
||||
return errors.Reason(err) == Errors_{{.Value}}
|
||||
}
|
||||
{{- end }}
|
||||
`
|
||||
|
||||
type errorInfo struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
type errorWrapper struct {
|
||||
Errors []*errorInfo
|
||||
}
|
||||
|
||||
func (e *errorWrapper) execute() string {
|
||||
buf := new(bytes.Buffer)
|
||||
tmpl, err := template.New("errors").Parse(errorsTemplate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := tmpl.Execute(buf, e); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(buf.Bytes())
|
||||
}
|
@ -14,40 +14,9 @@ type {{.ServiceType}}Handler interface {
|
||||
}
|
||||
|
||||
func New{{.ServiceType}}Handler(srv {{.ServiceType}}Handler, opts ...http1.HandleOption) http.Handler {
|
||||
h := http1.DefaultHandleOptions()
|
||||
for _, o := range opts {
|
||||
o(&h)
|
||||
}
|
||||
r := mux.NewRouter()
|
||||
{{range .Methods}}
|
||||
r.HandleFunc("{{.Path}}", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in {{.Request}}
|
||||
if err := h.Decode(r, &in{{.Body}}); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
{{if ne (len .Vars) 0}}
|
||||
if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
{{end}}
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.{{.Name}}(ctx, req.(*{{.Request}}))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*{{.Reply}})
|
||||
if err := h.Encode(w, r, reply{{.ResponseBody}}); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("{{.Method}}")
|
||||
r.Handle("{{.Path}}", http1.NewHandler(srv.{{.Name}}, opts...)).Methods("{{.Method}}")
|
||||
{{end}}
|
||||
return r
|
||||
}
|
||||
|
@ -32,146 +32,17 @@ type BlogServiceHandler interface {
|
||||
}
|
||||
|
||||
func NewBlogServiceHandler(srv BlogServiceHandler, opts ...http1.HandleOption) http.Handler {
|
||||
h := http1.DefaultHandleOptions()
|
||||
for _, o := range opts {
|
||||
o(&h)
|
||||
}
|
||||
r := mux.NewRouter()
|
||||
|
||||
r.HandleFunc("/v1/article/", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in CreateArticleRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
r.Handle("/v1/article/", http1.NewHandler(srv.CreateArticle, opts...)).Methods("POST")
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.CreateArticle(ctx, req.(*CreateArticleRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*CreateArticleReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("POST")
|
||||
r.Handle("/v1/article/{id}", http1.NewHandler(srv.UpdateArticle, opts...)).Methods("PUT")
|
||||
|
||||
r.HandleFunc("/v1/article/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in UpdateArticleRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
r.Handle("/v1/article/{id}", http1.NewHandler(srv.DeleteArticle, opts...)).Methods("DELETE")
|
||||
|
||||
if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
r.Handle("/v1/article/{id}", http1.NewHandler(srv.GetArticle, opts...)).Methods("GET")
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.UpdateArticle(ctx, req.(*UpdateArticleRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*UpdateArticleReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("PUT")
|
||||
|
||||
r.HandleFunc("/v1/article/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in DeleteArticleRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.DeleteArticle(ctx, req.(*DeleteArticleRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*DeleteArticleReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("DELETE")
|
||||
|
||||
r.HandleFunc("/v1/article/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in GetArticleRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.GetArticle(ctx, req.(*GetArticleRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*GetArticleReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("GET")
|
||||
|
||||
r.HandleFunc("/v1/article/", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in ListArticleRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.ListArticle(ctx, req.(*ListArticleRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
reply := out.(*ListArticleReply)
|
||||
if err := h.Encode(w, r, reply); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("GET")
|
||||
r.Handle("/v1/article/", http1.NewHandler(srv.ListArticle, opts...)).Methods("GET")
|
||||
|
||||
return r
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc v3.13.0
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.14.0
|
||||
// source: helloworld.proto
|
||||
|
||||
package helloworld
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
@ -22,10 +21,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
// The request message containing the user's name.
|
||||
type HelloRequest struct {
|
||||
state protoimpl.MessageState
|
||||
|
@ -24,39 +24,9 @@ type GreeterHandler interface {
|
||||
}
|
||||
|
||||
func NewGreeterHandler(srv GreeterHandler, opts ...http1.HandleOption) http.Handler {
|
||||
h := http1.DefaultHandleOptions()
|
||||
for _, o := range opts {
|
||||
o(&h)
|
||||
}
|
||||
r := mux.NewRouter()
|
||||
|
||||
r.HandleFunc("/helloworld/{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in HelloRequest
|
||||
|
||||
if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.SayHello(ctx, req.(*HelloRequest))
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
if err := h.Encode(w, r, out); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("GET")
|
||||
r.Handle("/helloworld/{name}", http1.NewHandler(srv.SayHello, opts...)).Methods("GET")
|
||||
|
||||
return r
|
||||
}
|
||||
|
52
examples/http/handler/main.go
Normal file
52
examples/http/handler/main.go
Normal file
@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/go-kratos/kratos/v2"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// User is a user model.
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// UserService is a user service.
|
||||
type UserService struct{ users map[string]*User }
|
||||
|
||||
// Get get a user from memory.
|
||||
func (u *UserService) Get(ctx context.Context, user *User) (*User, error) {
|
||||
return u.users[user.ID], nil
|
||||
}
|
||||
|
||||
// Add add a user to memory.
|
||||
func (u *UserService) Add(ctx context.Context, user *User) (*User, error) {
|
||||
u.users[user.ID] = user
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
us := &UserService{
|
||||
users: make(map[string]*User),
|
||||
}
|
||||
router := mux.NewRouter()
|
||||
router.Handle("/users", http.NewHandler(us.Add)).Methods("POST")
|
||||
router.Handle("/users/{id}", http.NewHandler(us.Get)).Methods("GET")
|
||||
|
||||
httpSrv := http.NewServer(http.Address(":8000"))
|
||||
httpSrv.HandlePrefix("/", router)
|
||||
|
||||
app := kratos.New(
|
||||
kratos.Name("handler"),
|
||||
kratos.Server(
|
||||
httpSrv,
|
||||
),
|
||||
)
|
||||
if err := app.Run(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -16,3 +16,15 @@ func BindForm(req *http.Request, target interface{}) error {
|
||||
}
|
||||
return mapForm(target, req.Form)
|
||||
}
|
||||
|
||||
// BindValue bind map parameters to target.
|
||||
func BindValue(vars map[string]string, target interface{}) error {
|
||||
values := make(map[string][]string, len(vars))
|
||||
for k, v := range vars {
|
||||
values[k] = []string{v}
|
||||
}
|
||||
if msg, ok := target.(proto.Message); ok {
|
||||
return mapProto(msg, values)
|
||||
}
|
||||
return mapForm(target, values)
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// MapProto sets a value in a nested Protobuf structure.
|
||||
// Deprecated: use BindValue instead.
|
||||
func MapProto(msg proto.Message, values map[string]string) error {
|
||||
for key, value := range values {
|
||||
if err := populateFieldValues(msg.ProtoReflect(), strings.Split(key, "."), []string{value}); err != nil {
|
||||
|
@ -1,14 +1,20 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/encoding"
|
||||
"github.com/go-kratos/kratos/v2/encoding/json"
|
||||
xhttp "github.com/go-kratos/kratos/v2/internal/http"
|
||||
"github.com/go-kratos/kratos/v2/middleware"
|
||||
"github.com/go-kratos/kratos/v2/middleware/recovery"
|
||||
"github.com/go-kratos/kratos/v2/transport/http/binding"
|
||||
"github.com/gorilla/mux"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
@ -26,64 +32,134 @@ type EncodeResponseFunc func(http.ResponseWriter, *http.Request, interface{}) er
|
||||
type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error)
|
||||
|
||||
// HandleOption is handle option.
|
||||
type HandleOption func(*HandleOptions)
|
||||
|
||||
// HandleOptions is handle options.
|
||||
type HandleOptions struct {
|
||||
Decode DecodeRequestFunc
|
||||
Encode EncodeResponseFunc
|
||||
Error EncodeErrorFunc
|
||||
Middleware middleware.Middleware
|
||||
}
|
||||
|
||||
// DefaultHandleOptions returns a default handle options.
|
||||
func DefaultHandleOptions() HandleOptions {
|
||||
return HandleOptions{
|
||||
Decode: decodeRequest,
|
||||
Encode: encodeResponse,
|
||||
Error: encodeError,
|
||||
}
|
||||
}
|
||||
type HandleOption func(*Handler)
|
||||
|
||||
// RequestDecoder with request decoder.
|
||||
func RequestDecoder(dec DecodeRequestFunc) HandleOption {
|
||||
return func(o *HandleOptions) {
|
||||
o.Decode = dec
|
||||
return func(o *Handler) {
|
||||
o.dec = dec
|
||||
}
|
||||
}
|
||||
|
||||
// ResponseEncoder with response encoder.
|
||||
func ResponseEncoder(en EncodeResponseFunc) HandleOption {
|
||||
return func(o *HandleOptions) {
|
||||
o.Encode = en
|
||||
return func(o *Handler) {
|
||||
o.enc = en
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorEncoder with error encoder.
|
||||
func ErrorEncoder(en EncodeErrorFunc) HandleOption {
|
||||
return func(o *HandleOptions) {
|
||||
o.Error = en
|
||||
return func(o *Handler) {
|
||||
o.err = en
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware with middleware option.
|
||||
func Middleware(m ...middleware.Middleware) HandleOption {
|
||||
return func(o *HandleOptions) {
|
||||
o.Middleware = middleware.Chain(m...)
|
||||
return func(o *Handler) {
|
||||
o.next = middleware.Chain(m...)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler is handle options.
|
||||
type Handler struct {
|
||||
method reflect.Value
|
||||
in reflect.Type
|
||||
out reflect.Type
|
||||
dec DecodeRequestFunc
|
||||
enc EncodeResponseFunc
|
||||
err EncodeErrorFunc
|
||||
next middleware.Middleware
|
||||
}
|
||||
|
||||
// NewHandler new a HTTP handler.
|
||||
func NewHandler(handler interface{}, opts ...HandleOption) http.Handler {
|
||||
if err := validateHandler(handler); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
typ := reflect.TypeOf(handler)
|
||||
h := &Handler{
|
||||
method: reflect.ValueOf(handler),
|
||||
in: typ.In(1).Elem(),
|
||||
out: typ.Out(0).Elem(),
|
||||
dec: decodeRequest,
|
||||
enc: encodeResponse,
|
||||
err: encodeError,
|
||||
next: recovery.Recovery(),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(h)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
in := reflect.New(h.in).Interface()
|
||||
if err := h.dec(req, in); err != nil {
|
||||
h.err(w, req, err)
|
||||
return
|
||||
}
|
||||
invoke := func(ctx context.Context, in interface{}) (interface{}, error) {
|
||||
ret := h.method.Call([]reflect.Value{
|
||||
reflect.ValueOf(ctx),
|
||||
reflect.ValueOf(in),
|
||||
})
|
||||
if ret[1].IsNil() {
|
||||
return ret[0].Interface(), nil
|
||||
}
|
||||
return nil, ret[1].Interface().(error)
|
||||
}
|
||||
if h.next != nil {
|
||||
invoke = h.next(invoke)
|
||||
}
|
||||
out, err := invoke(req.Context(), in)
|
||||
if err != nil {
|
||||
h.err(w, req, err)
|
||||
return
|
||||
}
|
||||
if err := h.enc(w, req, out); err != nil {
|
||||
h.err(w, req, err)
|
||||
}
|
||||
}
|
||||
|
||||
func validateHandler(handler interface{}) error {
|
||||
typ := reflect.TypeOf(handler)
|
||||
if typ.NumIn() != 2 || typ.NumOut() != 2 {
|
||||
return fmt.Errorf("invalid types, in: %d out: %d", typ.NumIn(), typ.NumOut())
|
||||
}
|
||||
if typ.In(1).Kind() != reflect.Ptr || typ.Out(0).Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("invalid types is not a pointer")
|
||||
}
|
||||
if !typ.In(0).Implements(reflect.TypeOf((*context.Context)(nil)).Elem()) {
|
||||
return fmt.Errorf("input does not implement the context")
|
||||
}
|
||||
if !typ.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||||
return fmt.Errorf("input does not implement the error")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeRequest decodes the request body to object.
|
||||
func decodeRequest(req *http.Request, v interface{}) error {
|
||||
subtype := xhttp.ContentSubtype(req.Header.Get(xhttp.HeaderContentType))
|
||||
if codec := encoding.GetCodec(subtype); codec != nil {
|
||||
data, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
if err := codec.Unmarshal(data, v); err != nil {
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err := binding.BindForm(req, v); err != nil {
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
return codec.Unmarshal(data, v)
|
||||
}
|
||||
return binding.BindForm(req, v)
|
||||
if err := binding.BindValue(mux.Vars(req), v); err != nil {
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodeResponse encodes the object to the HTTP response.
|
||||
|
@ -2,10 +2,7 @@ package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type HelloRequest struct {
|
||||
@ -21,37 +18,7 @@ func (s *GreeterService) SayHello(ctx context.Context, req *HelloRequest) (*Hell
|
||||
return &HelloReply{Message: "hello " + req.Name}, nil
|
||||
}
|
||||
|
||||
func newGreeterHandler(srv *GreeterService, opts ...HandleOption) http.Handler {
|
||||
h := DefaultHandleOptions()
|
||||
for _, o := range opts {
|
||||
o(&h)
|
||||
}
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/helloworld", func(w http.ResponseWriter, r *http.Request) {
|
||||
var in HelloRequest
|
||||
if err := h.Decode(r, &in); err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
next := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.SayHello(ctx, &in)
|
||||
}
|
||||
if h.Middleware != nil {
|
||||
next = h.Middleware(next)
|
||||
}
|
||||
out, err := next(r.Context(), &in)
|
||||
if err != nil {
|
||||
h.Error(w, r, err)
|
||||
return
|
||||
}
|
||||
if err := h.Encode(w, r, out); err != nil {
|
||||
h.Error(w, r, err)
|
||||
}
|
||||
}).Methods("POST")
|
||||
return r
|
||||
}
|
||||
|
||||
func TestHandler(t *testing.T) {
|
||||
s := &GreeterService{}
|
||||
_ = newGreeterHandler(s)
|
||||
_ = NewHandler(s.SayHello)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user