Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
1c36c1685f | |||
e889545210 | |||
|
526e414d60 | ||
db423dff58 | |||
542d4cec00 | |||
0ecd1da0dc | |||
0a8755ecb7 | |||
9c29d92d7f | |||
b871c1be38 | |||
74bb12e75e | |||
49a95c183b | |||
5e6bd93a6b | |||
9ef26caf40 | |||
b3e58d2cb6 | |||
b89d9fdc5b | |||
|
95dcdd6025 | ||
abe5be3ddc | |||
c3e6cdd973 |
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
bin
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.idea
|
||||||
|
.vscode
|
17
go.mod
17
go.mod
@@ -5,15 +5,18 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
go.unistack.org/micro-codec-yaml/v3 v3.10.0
|
go.unistack.org/micro-codec-yaml/v3 v3.10.0
|
||||||
go.unistack.org/micro-proto/v3 v3.3.1
|
go.unistack.org/micro-proto/v3 v3.3.1
|
||||||
go.unistack.org/micro/v3 v3.10.14
|
go.unistack.org/micro/v3 v3.10.52
|
||||||
golang.org/x/net v0.7.0
|
golang.org/x/net v0.22.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/gnostic v0.6.9 // indirect
|
github.com/google/gnostic v0.7.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||||
|
google.golang.org/grpc v1.62.1 // indirect
|
||||||
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
@@ -115,14 +115,14 @@ func (h *Server) HTTPHandlerFunc(handler interface{}) (http.HandlerFunc, error)
|
|||||||
md["Method"] = r.Method
|
md["Method"] = r.Method
|
||||||
md["URL"] = r.URL.String()
|
md["URL"] = r.URL.String()
|
||||||
md["Proto"] = r.Proto
|
md["Proto"] = r.Proto
|
||||||
md["ContentLength"] = fmt.Sprintf("%d", r.ContentLength)
|
md["Content-Length"] = fmt.Sprintf("%d", r.ContentLength)
|
||||||
md["TransferEncoding"] = strings.Join(r.TransferEncoding, ",")
|
md["Transfer-Encoding"] = strings.Join(r.TransferEncoding, ",")
|
||||||
md["Host"] = r.Host
|
md["Host"] = r.Host
|
||||||
md["RequestURI"] = r.RequestURI
|
md["RequestURI"] = r.RequestURI
|
||||||
if r.TLS != nil {
|
if r.TLS != nil {
|
||||||
md["TLS"] = "true"
|
md["TLS"] = "true"
|
||||||
md["TLS_ALPN"] = r.TLS.NegotiatedProtocol
|
md["TLS-ALPN"] = r.TLS.NegotiatedProtocol
|
||||||
md["TLS_ServerName"] = r.TLS.ServerName
|
md["TLS-ServerName"] = r.TLS.ServerName
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = metadata.NewIncomingContext(ctx, md)
|
ctx = metadata.NewIncomingContext(ctx, md)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package health // import "go.unistack.org/micro-server-http/v3/handler/health"
|
package health_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package micro.server.http.v3.handler.health;
|
package micro.server.http.v3.handler.health;
|
||||||
option go_package = "go.unistack.org/micro-server-http/v3/handler/health;health";
|
option go_package = "go.unistack.org/micro-server-http/v3/handler/health;health_handler";
|
||||||
|
|
||||||
import "api/annotations.proto";
|
import "api/annotations.proto";
|
||||||
import "openapiv3/annotations.proto";
|
import "openapiv3/annotations.proto";
|
||||||
|
@@ -1,45 +1,26 @@
|
|||||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-micro v3.10.2
|
// - protoc-gen-go-micro v3.10.4
|
||||||
// - protoc v3.21.12
|
// - protoc v5.26.1
|
||||||
// source: health.proto
|
// source: health/health.proto
|
||||||
|
|
||||||
package health
|
package health_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
codec "go.unistack.org/micro-proto/v3/codec"
|
codec "go.unistack.org/micro-proto/v3/codec"
|
||||||
v3 "go.unistack.org/micro-server-http/v3"
|
client "go.unistack.org/micro/v3/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
HealthServiceName = "HealthService"
|
HealthServiceName = "HealthService"
|
||||||
)
|
)
|
||||||
var (
|
|
||||||
HealthServiceServerEndpoints = []v3.EndpointMetadata{
|
type HealthServiceClient interface {
|
||||||
{
|
Live(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
|
||||||
Name: "HealthService.Live",
|
Ready(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
|
||||||
Path: "/live",
|
Version(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
|
||||||
Method: "GET",
|
}
|
||||||
Body: "",
|
|
||||||
Stream: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "HealthService.Ready",
|
|
||||||
Path: "/ready",
|
|
||||||
Method: "GET",
|
|
||||||
Body: "",
|
|
||||||
Stream: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "HealthService.Version",
|
|
||||||
Path: "/version",
|
|
||||||
Method: "GET",
|
|
||||||
Body: "",
|
|
||||||
Stream: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type HealthServiceServer interface {
|
type HealthServiceServer interface {
|
||||||
Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
Live(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||||
|
@@ -1,16 +1,108 @@
|
|||||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||||
// protoc-gen-go-micro version: v3.10.2
|
// protoc-gen-go-micro version: v3.10.4
|
||||||
// source: health.proto
|
// source: health/health.proto
|
||||||
|
|
||||||
package health
|
package health_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
v31 "go.unistack.org/micro-client-http/v3"
|
||||||
codec "go.unistack.org/micro-proto/v3/codec"
|
codec "go.unistack.org/micro-proto/v3/codec"
|
||||||
v3 "go.unistack.org/micro-server-http/v3"
|
v3 "go.unistack.org/micro-server-http/v3"
|
||||||
|
client "go.unistack.org/micro/v3/client"
|
||||||
server "go.unistack.org/micro/v3/server"
|
server "go.unistack.org/micro/v3/server"
|
||||||
|
http "net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
HealthServiceServerEndpoints = []v3.EndpointMetadata{
|
||||||
|
{
|
||||||
|
Name: "HealthService.Live",
|
||||||
|
Path: "/live",
|
||||||
|
Method: "GET",
|
||||||
|
Body: "",
|
||||||
|
Stream: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "HealthService.Ready",
|
||||||
|
Path: "/ready",
|
||||||
|
Method: "GET",
|
||||||
|
Body: "",
|
||||||
|
Stream: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "HealthService.Version",
|
||||||
|
Path: "/version",
|
||||||
|
Method: "GET",
|
||||||
|
Body: "",
|
||||||
|
Stream: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type healthServiceClient struct {
|
||||||
|
c client.Client
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHealthServiceClient(name string, c client.Client) HealthServiceClient {
|
||||||
|
return &healthServiceClient{c: c, name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthServiceClient) Live(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error) {
|
||||||
|
errmap := make(map[string]interface{}, 1)
|
||||||
|
errmap["default"] = &codec.Frame{}
|
||||||
|
opts = append(opts,
|
||||||
|
v31.ErrorMap(errmap),
|
||||||
|
)
|
||||||
|
opts = append(opts,
|
||||||
|
v31.Method(http.MethodGet),
|
||||||
|
v31.Path("/live"),
|
||||||
|
)
|
||||||
|
rsp := &codec.Frame{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "HealthService.Live", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthServiceClient) Ready(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error) {
|
||||||
|
errmap := make(map[string]interface{}, 1)
|
||||||
|
errmap["default"] = &codec.Frame{}
|
||||||
|
opts = append(opts,
|
||||||
|
v31.ErrorMap(errmap),
|
||||||
|
)
|
||||||
|
opts = append(opts,
|
||||||
|
v31.Method(http.MethodGet),
|
||||||
|
v31.Path("/ready"),
|
||||||
|
)
|
||||||
|
rsp := &codec.Frame{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "HealthService.Ready", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthServiceClient) Version(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error) {
|
||||||
|
errmap := make(map[string]interface{}, 1)
|
||||||
|
errmap["default"] = &codec.Frame{}
|
||||||
|
opts = append(opts,
|
||||||
|
v31.ErrorMap(errmap),
|
||||||
|
)
|
||||||
|
opts = append(opts,
|
||||||
|
v31.Method(http.MethodGet),
|
||||||
|
v31.Path("/version"),
|
||||||
|
)
|
||||||
|
rsp := &codec.Frame{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "HealthService.Version", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
type healthServiceServer struct {
|
type healthServiceServer struct {
|
||||||
HealthServiceServer
|
HealthServiceServer
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,36 @@
|
|||||||
package meter // import "go.unistack.org/micro-server-http/v3/handler/meter"
|
package meter_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
codecpb "go.unistack.org/micro-proto/v3/codec"
|
codecpb "go.unistack.org/micro-proto/v3/codec"
|
||||||
"go.unistack.org/micro/v3/errors"
|
"go.unistack.org/micro/v3/logger"
|
||||||
|
"go.unistack.org/micro/v3/metadata"
|
||||||
"go.unistack.org/micro/v3/meter"
|
"go.unistack.org/micro/v3/meter"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
contentEncodingHeader = "Content-Encoding"
|
||||||
|
acceptEncodingHeader = "Accept-Encoding"
|
||||||
|
)
|
||||||
|
|
||||||
|
var gzipPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return gzip.NewWriter(nil)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var bufPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return bytes.NewBuffer(nil)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// guard to fail early
|
// guard to fail early
|
||||||
var _ MeterServiceServer = &Handler{}
|
var _ MeterServiceServer = &Handler{}
|
||||||
|
|
||||||
@@ -19,9 +41,10 @@ type Handler struct {
|
|||||||
type Option func(*Options)
|
type Option func(*Options)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Meter meter.Meter
|
Meter meter.Meter
|
||||||
Name string
|
Name string
|
||||||
MeterOptions []meter.Option
|
MeterOptions []meter.Option
|
||||||
|
DisableCompress bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Meter(m meter.Meter) Option {
|
func Meter(m meter.Meter) Option {
|
||||||
@@ -36,6 +59,12 @@ func Name(name string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DisableCompress(g bool) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.DisableCompress = g
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func MeterOptions(opts ...meter.Option) Option {
|
func MeterOptions(opts ...meter.Option) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.MeterOptions = append(o.MeterOptions, opts...)
|
o.MeterOptions = append(o.MeterOptions, opts...)
|
||||||
@@ -43,7 +72,7 @@ func MeterOptions(opts ...meter.Option) Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewOptions(opts ...Option) Options {
|
func NewOptions(opts ...Option) Options {
|
||||||
options := Options{Meter: meter.DefaultMeter}
|
options := Options{Meter: meter.DefaultMeter, DisableCompress: false}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&options)
|
o(&options)
|
||||||
}
|
}
|
||||||
@@ -56,12 +85,48 @@ func NewHandler(opts ...Option) *Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Metrics(ctx context.Context, req *codecpb.Frame, rsp *codecpb.Frame) error {
|
func (h *Handler) Metrics(ctx context.Context, req *codecpb.Frame, rsp *codecpb.Frame) error {
|
||||||
buf := bytes.NewBuffer(nil)
|
log, ok := logger.FromContext(ctx)
|
||||||
if err := h.opts.Meter.Write(buf, h.opts.MeterOptions...); err != nil {
|
if !ok {
|
||||||
return errors.InternalServerError(h.opts.Name, "%v", err)
|
log = logger.DefaultLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bufPool.Get().(*bytes.Buffer)
|
||||||
|
defer bufPool.Put(buf)
|
||||||
|
buf.Reset()
|
||||||
|
|
||||||
|
w := io.Writer(buf)
|
||||||
|
|
||||||
|
if md, ok := metadata.FromOutgoingContext(ctx); gzipAccepted(md) && ok && !h.opts.DisableCompress {
|
||||||
|
omd, _ := metadata.FromOutgoingContext(ctx)
|
||||||
|
omd.Set(contentEncodingHeader, "gzip")
|
||||||
|
gz := gzipPool.Get().(*gzip.Writer)
|
||||||
|
defer gzipPool.Put(gz)
|
||||||
|
|
||||||
|
gz.Reset(w)
|
||||||
|
defer gz.Close()
|
||||||
|
|
||||||
|
w = gz
|
||||||
|
gz.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.opts.Meter.Write(w, h.opts.MeterOptions...); err != nil {
|
||||||
|
log.Error(ctx, "http/meter write failed", err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rsp.Data = buf.Bytes()
|
rsp.Data = buf.Bytes()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gzipAccepted returns whether the client will accept gzip-encoded content.
|
||||||
|
func gzipAccepted(md metadata.Metadata) bool {
|
||||||
|
a, ok := md.Get(acceptEncodingHeader)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if strings.Contains(a, "gzip") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package micro.server.http.v3.handler.meter;
|
package micro.server.http.v3.handler.meter;
|
||||||
option go_package = "go.unistack.org/micro-server-http/v3/handler/meter;meter";
|
option go_package = "go.unistack.org/micro-server-http/v3/handler/meter;meter_handler";
|
||||||
|
|
||||||
import "api/annotations.proto";
|
import "api/annotations.proto";
|
||||||
import "openapiv3/annotations.proto";
|
import "openapiv3/annotations.proto";
|
||||||
|
@@ -1,31 +1,24 @@
|
|||||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-micro v3.10.2
|
// - protoc-gen-go-micro v3.10.4
|
||||||
// - protoc v3.21.12
|
// - protoc v5.26.1
|
||||||
// source: meter.proto
|
// source: meter/meter.proto
|
||||||
|
|
||||||
package meter
|
package meter_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
codec "go.unistack.org/micro-proto/v3/codec"
|
codec "go.unistack.org/micro-proto/v3/codec"
|
||||||
v3 "go.unistack.org/micro-server-http/v3"
|
client "go.unistack.org/micro/v3/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MeterServiceName = "MeterService"
|
MeterServiceName = "MeterService"
|
||||||
)
|
)
|
||||||
var (
|
|
||||||
MeterServiceServerEndpoints = []v3.EndpointMetadata{
|
type MeterServiceClient interface {
|
||||||
{
|
Metrics(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error)
|
||||||
Name: "MeterService.Metrics",
|
}
|
||||||
Path: "/metrics",
|
|
||||||
Method: "GET",
|
|
||||||
Body: "",
|
|
||||||
Stream: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type MeterServiceServer interface {
|
type MeterServiceServer interface {
|
||||||
Metrics(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
Metrics(ctx context.Context, req *codec.Frame, rsp *codec.Frame) error
|
||||||
|
@@ -1,16 +1,58 @@
|
|||||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||||
// protoc-gen-go-micro version: v3.10.2
|
// protoc-gen-go-micro version: v3.10.4
|
||||||
// source: meter.proto
|
// source: meter/meter.proto
|
||||||
|
|
||||||
package meter
|
package meter_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
|
v31 "go.unistack.org/micro-client-http/v3"
|
||||||
codec "go.unistack.org/micro-proto/v3/codec"
|
codec "go.unistack.org/micro-proto/v3/codec"
|
||||||
v3 "go.unistack.org/micro-server-http/v3"
|
v3 "go.unistack.org/micro-server-http/v3"
|
||||||
|
client "go.unistack.org/micro/v3/client"
|
||||||
server "go.unistack.org/micro/v3/server"
|
server "go.unistack.org/micro/v3/server"
|
||||||
|
http "net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
MeterServiceServerEndpoints = []v3.EndpointMetadata{
|
||||||
|
{
|
||||||
|
Name: "MeterService.Metrics",
|
||||||
|
Path: "/metrics",
|
||||||
|
Method: "GET",
|
||||||
|
Body: "",
|
||||||
|
Stream: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type meterServiceClient struct {
|
||||||
|
c client.Client
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMeterServiceClient(name string, c client.Client) MeterServiceClient {
|
||||||
|
return &meterServiceClient{c: c, name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *meterServiceClient) Metrics(ctx context.Context, req *codec.Frame, opts ...client.CallOption) (*codec.Frame, error) {
|
||||||
|
errmap := make(map[string]interface{}, 1)
|
||||||
|
errmap["default"] = &codec.Frame{}
|
||||||
|
opts = append(opts,
|
||||||
|
v31.ErrorMap(errmap),
|
||||||
|
)
|
||||||
|
opts = append(opts,
|
||||||
|
v31.Method(http.MethodGet),
|
||||||
|
v31.Path("/metrics"),
|
||||||
|
)
|
||||||
|
rsp := &codec.Frame{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "MeterService.Metrics", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
type meterServiceServer struct {
|
type meterServiceServer struct {
|
||||||
MeterServiceServer
|
MeterServiceServer
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package pprof
|
package pprof_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"expvar"
|
"expvar"
|
||||||
|
@@ -1,20 +0,0 @@
|
|||||||
window.onload = function() {
|
|
||||||
//<editor-fold desc="Changeable Configuration Block">
|
|
||||||
|
|
||||||
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
|
||||||
window.ui = SwaggerUIBundle({
|
|
||||||
url: "{{ .SWAGGER }}",
|
|
||||||
dom_id: '#swagger-ui',
|
|
||||||
deepLinking: true,
|
|
||||||
presets: [
|
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout"
|
|
||||||
});
|
|
||||||
|
|
||||||
//</editor-fold>
|
|
||||||
};
|
|
@@ -1,4 +1,4 @@
|
|||||||
package swaggerui // import "go.unistack.org/micro-server-http/v3/handler/swagger-ui"
|
package swaggerui_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package swaggerui
|
package swaggerui_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package swagger
|
package swagger_handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
90
http.go
90
http.go
@@ -191,6 +191,11 @@ func (h *Server) NewHandler(handler interface{}, opts ...server.HandlerOption) s
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
registerCORS := false
|
||||||
|
if v, ok := options.Context.Value(registerCORSHandlerKey{}).(bool); ok && v {
|
||||||
|
registerCORS = true
|
||||||
|
}
|
||||||
|
|
||||||
for hn, md := range options.Metadata {
|
for hn, md := range options.Metadata {
|
||||||
var method reflect.Method
|
var method reflect.Method
|
||||||
mname := hn[strings.Index(hn, ".")+1:]
|
mname := hn[strings.Index(hn, ".")+1:]
|
||||||
@@ -223,13 +228,22 @@ func (h *Server) NewHandler(handler interface{}, opts ...server.HandlerOption) s
|
|||||||
pth := &patHandler{mtype: mtype, name: name, rcvr: rcvr}
|
pth := &patHandler{mtype: mtype, name: name, rcvr: rcvr}
|
||||||
hdlr.name = name
|
hdlr.name = name
|
||||||
|
|
||||||
if err := hdlr.handlers.Insert([]string{md["Method"]}, md["Path"], pth); err != nil {
|
methods := []string{md["Method"]}
|
||||||
h.opts.Logger.Errorf(h.opts.Context, "cant add handler for %s %s", md["Method"], md["Path"])
|
if registerCORS {
|
||||||
|
methods = append(methods, http.MethodOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := hdlr.handlers.Insert(methods, md["Path"], pth); err != nil {
|
||||||
|
h.opts.Logger.Errorf(h.opts.Context, "cant add handler for %v %s", methods, md["Path"])
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.registerRPC {
|
if h.registerRPC {
|
||||||
h.opts.Logger.Infof(h.opts.Context, "register rpc handler for http.MethodPost %s /%s", hn, hn)
|
methods := []string{http.MethodPost}
|
||||||
if err := hdlr.handlers.Insert([]string{http.MethodPost}, "/"+hn, pth); err != nil {
|
if registerCORS {
|
||||||
|
methods = append(methods, http.MethodOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := hdlr.handlers.Insert(methods, "/"+hn, pth); err != nil {
|
||||||
h.opts.Logger.Errorf(h.opts.Context, "cant add rpc handler for http.MethodPost %s /%s", hn, hn)
|
h.opts.Logger.Errorf(h.opts.Context, "cant add rpc handler for http.MethodPost %s /%s", hn, hn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,13 +287,23 @@ func (h *Server) NewHandler(handler interface{}, opts ...server.HandlerOption) s
|
|||||||
pth := &patHandler{mtype: mtype, name: name, rcvr: rcvr}
|
pth := &patHandler{mtype: mtype, name: name, rcvr: rcvr}
|
||||||
hdlr.name = name
|
hdlr.name = name
|
||||||
|
|
||||||
if err := hdlr.handlers.Insert([]string{md.Method}, md.Path, pth); err != nil {
|
methods := []string{md.Method}
|
||||||
|
if registerCORS {
|
||||||
|
methods = append(methods, http.MethodOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := hdlr.handlers.Insert(methods, md.Path, pth); err != nil {
|
||||||
h.opts.Logger.Errorf(h.opts.Context, "cant add handler for %s %s", md.Method, md.Path)
|
h.opts.Logger.Errorf(h.opts.Context, "cant add handler for %s %s", md.Method, md.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.registerRPC {
|
if h.registerRPC {
|
||||||
|
methods := []string{http.MethodPost}
|
||||||
|
if registerCORS {
|
||||||
|
methods = append(methods, http.MethodOptions)
|
||||||
|
}
|
||||||
|
|
||||||
h.opts.Logger.Infof(h.opts.Context, "register rpc handler for http.MethodPost %s /%s", hn, hn)
|
h.opts.Logger.Infof(h.opts.Context, "register rpc handler for http.MethodPost %s /%s", hn, hn)
|
||||||
if err := hdlr.handlers.Insert([]string{http.MethodPost}, "/"+hn, pth); err != nil {
|
if err := hdlr.handlers.Insert(methods, "/"+hn, pth); err != nil {
|
||||||
h.opts.Logger.Errorf(h.opts.Context, "cant add rpc handler for http.MethodPost %s /%s", hn, hn)
|
h.opts.Logger.Errorf(h.opts.Context, "cant add rpc handler for http.MethodPost %s /%s", hn, hn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +517,7 @@ func (h *Server) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.Logger.V(logger.InfoLevel) {
|
if config.Logger.V(logger.InfoLevel) {
|
||||||
config.Logger.Infof(config.Context, "Listening on %s", ts.Addr().String())
|
config.Logger.Info(config.Context, "Listening on "+ts.Addr().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Lock()
|
h.Lock()
|
||||||
@@ -501,7 +525,6 @@ func (h *Server) Start() error {
|
|||||||
h.Unlock()
|
h.Unlock()
|
||||||
|
|
||||||
var handler http.Handler
|
var handler http.Handler
|
||||||
var srvFunc func(net.Listener) error
|
|
||||||
|
|
||||||
// nolint: nestif
|
// nolint: nestif
|
||||||
if h.opts.Context != nil {
|
if h.opts.Context != nil {
|
||||||
@@ -538,7 +561,7 @@ func (h *Server) Start() error {
|
|||||||
|
|
||||||
if err := config.RegisterCheck(h.opts.Context); err != nil {
|
if err := config.RegisterCheck(h.opts.Context); err != nil {
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s", config.Name, config.ID, err)
|
config.Logger.Error(config.Context, fmt.Sprintf("Server %s-%s register check error", config.Name, config.ID), err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err = h.Register(); err != nil {
|
if err = h.Register(); err != nil {
|
||||||
@@ -552,6 +575,7 @@ func (h *Server) Start() error {
|
|||||||
|
|
||||||
fn := handler
|
fn := handler
|
||||||
|
|
||||||
|
var hs *http.Server
|
||||||
if h.opts.Context != nil {
|
if h.opts.Context != nil {
|
||||||
if mwf, ok := h.opts.Context.Value(middlewareKey{}).([]func(http.Handler) http.Handler); ok && len(mwf) > 0 {
|
if mwf, ok := h.opts.Context.Value(middlewareKey{}).([]func(http.Handler) http.Handler); ok && len(mwf) > 0 {
|
||||||
// wrap the handler func
|
// wrap the handler func
|
||||||
@@ -559,25 +583,19 @@ func (h *Server) Start() error {
|
|||||||
fn = mwf[i-1](fn)
|
fn = mwf[i-1](fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if hs, ok := h.opts.Context.Value(serverKey{}).(*http.Server); ok && hs != nil {
|
var ok bool
|
||||||
|
if hs, ok = h.opts.Context.Value(serverKey{}).(*http.Server); ok && hs != nil {
|
||||||
hs.Handler = fn
|
hs.Handler = fn
|
||||||
srvFunc = hs.Serve
|
} else {
|
||||||
|
hs = &http.Server{Handler: fn}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if srvFunc != nil {
|
go func() {
|
||||||
go func() {
|
if cerr := hs.Serve(ts); cerr != nil && !errors.Is(cerr, net.ErrClosed) {
|
||||||
if cerr := srvFunc(ts); cerr != nil && !errors.Is(cerr, net.ErrClosed) {
|
h.opts.Logger.Error(h.opts.Context, "serve error", cerr)
|
||||||
h.opts.Logger.Error(h.opts.Context, cerr)
|
}
|
||||||
}
|
}()
|
||||||
}()
|
|
||||||
} else {
|
|
||||||
go func() {
|
|
||||||
if cerr := http.Serve(ts, fn); cerr != nil && !errors.Is(cerr, net.ErrClosed) {
|
|
||||||
h.opts.Logger.Error(h.opts.Context, cerr)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
t := new(time.Ticker)
|
t := new(time.Ticker)
|
||||||
@@ -603,28 +621,28 @@ func (h *Server) Start() error {
|
|||||||
// nolint: nestif
|
// nolint: nestif
|
||||||
if rerr != nil && registered {
|
if rerr != nil && registered {
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s, deregister it", config.Name, config.ID, rerr)
|
config.Logger.Error(config.Context, fmt.Sprintf("Server %s-%s register check error, deregister it", config.Name, config.ID), rerr)
|
||||||
}
|
}
|
||||||
// deregister self in case of error
|
// deregister self in case of error
|
||||||
if err := h.Deregister(); err != nil {
|
if err := h.Deregister(); err != nil {
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
config.Logger.Errorf(config.Context, "Server %s-%s deregister error: %s", config.Name, config.ID, err)
|
config.Logger.Error(config.Context, fmt.Sprintf("Server %s-%s deregister error", config.Name, config.ID), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if rerr != nil && !registered {
|
} else if rerr != nil && !registered {
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s", config.Name, config.ID, rerr)
|
config.Logger.Error(config.Context, fmt.Sprintf("Server %s-%s register check error", config.Name, config.ID), rerr)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := h.Register(); err != nil {
|
if err := h.Register(); err != nil {
|
||||||
if config.Logger.V(logger.ErrorLevel) {
|
if config.Logger.V(logger.ErrorLevel) {
|
||||||
config.Logger.Errorf(config.Context, "Server %s-%s register error: %s", config.Name, config.ID, err)
|
config.Logger.Error(config.Context, fmt.Sprintf("Server %s-%s register error", config.Name, config.ID), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.Register(); err != nil {
|
if err := h.Register(); err != nil {
|
||||||
config.Logger.Errorf(config.Context, "Server register error: %s", err)
|
config.Logger.Error(config.Context, "Server register error", err)
|
||||||
}
|
}
|
||||||
// wait for exit
|
// wait for exit
|
||||||
case ch = <-h.exit:
|
case ch = <-h.exit:
|
||||||
@@ -634,14 +652,22 @@ func (h *Server) Start() error {
|
|||||||
|
|
||||||
// deregister
|
// deregister
|
||||||
if err := h.Deregister(); err != nil {
|
if err := h.Deregister(); err != nil {
|
||||||
config.Logger.Errorf(config.Context, "Server deregister error: %s", err)
|
config.Logger.Error(config.Context, "Server deregister error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := config.Broker.Disconnect(config.Context); err != nil {
|
if err := config.Broker.Disconnect(config.Context); err != nil {
|
||||||
config.Logger.Errorf(config.Context, "Broker disconnect error: %s", err)
|
config.Logger.Error(config.Context, "Broker disconnect error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- ts.Close()
|
ctx, cancel := context.WithTimeout(context.Background(), h.opts.GracefulTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
err := hs.Shutdown(ctx)
|
||||||
|
if err != nil {
|
||||||
|
err = hs.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
ch <- err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@@ -133,6 +133,13 @@ func RegisterRPCHandler(b bool) server.Option {
|
|||||||
return server.SetOption(registerRPCHandlerKey{}, b)
|
return server.SetOption(registerRPCHandlerKey{}, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type registerCORSHandlerKey struct{}
|
||||||
|
|
||||||
|
// RegisterCORSHandler registers cors endpoints with /ServiceName.ServiceEndpoint method POPTIONSOST
|
||||||
|
func RegisterCORSHandler(b bool) server.HandlerOption {
|
||||||
|
return server.SetHandlerOption(registerCORSHandlerKey{}, b)
|
||||||
|
}
|
||||||
|
|
||||||
type handlerEndpointsKey struct{}
|
type handlerEndpointsKey struct{}
|
||||||
|
|
||||||
type EndpointMetadata struct {
|
type EndpointMetadata struct {
|
||||||
|
Reference in New Issue
Block a user