Merge remote-tracking branch 'main/v3' into issue_179_v3

# Conflicts:
#	http.go
This commit is contained in:
Денис Евстигнеев 2024-03-12 16:48:51 +03:00
commit 49a95c183b
2 changed files with 64 additions and 8 deletions

View File

@ -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)

View File

@ -2,13 +2,35 @@ package meter // import "go.unistack.org/micro-server-http/v3/handler/meter"
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{}
@ -56,12 +78,46 @@ 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.FromIncomingContext(ctx); gzipAccepted(md) && ok {
md.Set(contentEncodingHeader, "gzip")
gz := gzipPool.Get().(*gzip.Writer)
defer gzipPool.Put(gz)
gz.Reset(w)
defer gz.Close()
w = gz
}
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
}