summaryrefslogtreecommitdiff
path: root/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go')
-rw-r--r--vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go417
1 files changed, 0 insertions, 417 deletions
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
deleted file mode 100644
index 2f2b34243..000000000
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go
+++ /dev/null
@@ -1,417 +0,0 @@
-package runtime
-
-import (
- "context"
- "encoding/base64"
- "fmt"
- "net"
- "net/http"
- "net/textproto"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/grpclog"
- "google.golang.org/grpc/metadata"
- "google.golang.org/grpc/status"
-)
-
-// MetadataHeaderPrefix is the http prefix that represents custom metadata
-// parameters to or from a gRPC call.
-const MetadataHeaderPrefix = "Grpc-Metadata-"
-
-// MetadataPrefix is prepended to permanent HTTP header keys (as specified
-// by the IANA) when added to the gRPC context.
-const MetadataPrefix = "grpcgateway-"
-
-// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to
-// HTTP headers in a response handled by grpc-gateway
-const MetadataTrailerPrefix = "Grpc-Trailer-"
-
-const metadataGrpcTimeout = "Grpc-Timeout"
-const metadataHeaderBinarySuffix = "-Bin"
-
-const xForwardedFor = "X-Forwarded-For"
-const xForwardedHost = "X-Forwarded-Host"
-
-// DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound
-// header isn't present. If the value is 0 the sent `context` will not have a timeout.
-var DefaultContextTimeout = 0 * time.Second
-
-// malformedHTTPHeaders lists the headers that the gRPC server may reject outright as malformed.
-// See https://github.com/grpc/grpc-go/pull/4803#issuecomment-986093310 for more context.
-var malformedHTTPHeaders = map[string]struct{}{
- "connection": {},
-}
-
-type (
- rpcMethodKey struct{}
- httpPathPatternKey struct{}
- httpPatternKey struct{}
-
- AnnotateContextOption func(ctx context.Context) context.Context
-)
-
-func WithHTTPPathPattern(pattern string) AnnotateContextOption {
- return func(ctx context.Context) context.Context {
- return withHTTPPathPattern(ctx, pattern)
- }
-}
-
-func decodeBinHeader(v string) ([]byte, error) {
- if len(v)%4 == 0 {
- // Input was padded, or padding was not necessary.
- return base64.StdEncoding.DecodeString(v)
- }
- return base64.RawStdEncoding.DecodeString(v)
-}
-
-/*
-AnnotateContext adds context information such as metadata from the request.
-
-At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For",
-except that the forwarded destination is not another HTTP service but rather
-a gRPC service.
-*/
-func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, error) {
- ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName, options...)
- if err != nil {
- return nil, err
- }
- if md == nil {
- return ctx, nil
- }
-
- return metadata.NewOutgoingContext(ctx, md), nil
-}
-
-// AnnotateIncomingContext adds context information such as metadata from the request.
-// Attach metadata as incoming context.
-func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, error) {
- ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName, options...)
- if err != nil {
- return nil, err
- }
- if md == nil {
- return ctx, nil
- }
-
- return metadata.NewIncomingContext(ctx, md), nil
-}
-
-func isValidGRPCMetadataKey(key string) bool {
- // Must be a valid gRPC "Header-Name" as defined here:
- // https://github.com/grpc/grpc/blob/4b05dc88b724214d0c725c8e7442cbc7a61b1374/doc/PROTOCOL-HTTP2.md
- // This means 0-9 a-z _ - .
- // Only lowercase letters are valid in the wire protocol, but the client library will normalize
- // uppercase ASCII to lowercase, so uppercase ASCII is also acceptable.
- bytes := []byte(key) // gRPC validates strings on the byte level, not Unicode.
- for _, ch := range bytes {
- validLowercaseLetter := ch >= 'a' && ch <= 'z'
- validUppercaseLetter := ch >= 'A' && ch <= 'Z'
- validDigit := ch >= '0' && ch <= '9'
- validOther := ch == '.' || ch == '-' || ch == '_'
- if !validLowercaseLetter && !validUppercaseLetter && !validDigit && !validOther {
- return false
- }
- }
- return true
-}
-
-func isValidGRPCMetadataTextValue(textValue string) bool {
- // Must be a valid gRPC "ASCII-Value" as defined here:
- // https://github.com/grpc/grpc/blob/4b05dc88b724214d0c725c8e7442cbc7a61b1374/doc/PROTOCOL-HTTP2.md
- // This means printable ASCII (including/plus spaces); 0x20 to 0x7E inclusive.
- bytes := []byte(textValue) // gRPC validates strings on the byte level, not Unicode.
- for _, ch := range bytes {
- if ch < 0x20 || ch > 0x7E {
- return false
- }
- }
- return true
-}
-
-func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, metadata.MD, error) {
- ctx = withRPCMethod(ctx, rpcMethodName)
- for _, o := range options {
- ctx = o(ctx)
- }
- timeout := DefaultContextTimeout
- if tm := req.Header.Get(metadataGrpcTimeout); tm != "" {
- var err error
- timeout, err = timeoutDecode(tm)
- if err != nil {
- return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
- }
- }
- var pairs []string
- for key, vals := range req.Header {
- key = textproto.CanonicalMIMEHeaderKey(key)
- switch key {
- case xForwardedFor, xForwardedHost:
- // Handled separately below
- continue
- }
-
- for _, val := range vals {
- // For backwards-compatibility, pass through 'authorization' header with no prefix.
- if key == "Authorization" {
- pairs = append(pairs, "authorization", val)
- }
- if h, ok := mux.incomingHeaderMatcher(key); ok {
- if !isValidGRPCMetadataKey(h) {
- grpclog.Errorf("HTTP header name %q is not valid as gRPC metadata key; skipping", h)
- continue
- }
- // Handles "-bin" metadata in grpc, since grpc will do another base64
- // encode before sending to server, we need to decode it first.
- if strings.HasSuffix(key, metadataHeaderBinarySuffix) {
- b, err := decodeBinHeader(val)
- if err != nil {
- return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err)
- }
-
- val = string(b)
- } else if !isValidGRPCMetadataTextValue(val) {
- grpclog.Errorf("Value of HTTP header %q contains non-ASCII value (not valid as gRPC metadata): skipping", h)
- continue
- }
- pairs = append(pairs, h, val)
- }
- }
- }
- if host := req.Header.Get(xForwardedHost); host != "" {
- pairs = append(pairs, strings.ToLower(xForwardedHost), host)
- } else if req.Host != "" {
- pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host)
- }
-
- xff := req.Header.Values(xForwardedFor)
- if addr := req.RemoteAddr; addr != "" {
- if remoteIP, _, err := net.SplitHostPort(addr); err == nil {
- xff = append(xff, remoteIP)
- }
- }
- if len(xff) > 0 {
- pairs = append(pairs, strings.ToLower(xForwardedFor), strings.Join(xff, ", "))
- }
-
- if timeout != 0 {
- ctx, _ = context.WithTimeout(ctx, timeout)
- }
- if len(pairs) == 0 {
- return ctx, nil, nil
- }
- md := metadata.Pairs(pairs...)
- for _, mda := range mux.metadataAnnotators {
- md = metadata.Join(md, mda(ctx, req))
- }
- return ctx, md, nil
-}
-
-// ServerMetadata consists of metadata sent from gRPC server.
-type ServerMetadata struct {
- HeaderMD metadata.MD
- TrailerMD metadata.MD
-}
-
-type serverMetadataKey struct{}
-
-// NewServerMetadataContext creates a new context with ServerMetadata
-func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context {
- if ctx == nil {
- ctx = context.Background()
- }
- return context.WithValue(ctx, serverMetadataKey{}, md)
-}
-
-// ServerMetadataFromContext returns the ServerMetadata in ctx
-func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) {
- if ctx == nil {
- return md, false
- }
- md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata)
- return
-}
-
-// ServerTransportStream implements grpc.ServerTransportStream.
-// It should only be used by the generated files to support grpc.SendHeader
-// outside of gRPC server use.
-type ServerTransportStream struct {
- mu sync.Mutex
- header metadata.MD
- trailer metadata.MD
-}
-
-// Method returns the method for the stream.
-func (s *ServerTransportStream) Method() string {
- return ""
-}
-
-// Header returns the header metadata of the stream.
-func (s *ServerTransportStream) Header() metadata.MD {
- s.mu.Lock()
- defer s.mu.Unlock()
- return s.header.Copy()
-}
-
-// SetHeader sets the header metadata.
-func (s *ServerTransportStream) SetHeader(md metadata.MD) error {
- if md.Len() == 0 {
- return nil
- }
-
- s.mu.Lock()
- s.header = metadata.Join(s.header, md)
- s.mu.Unlock()
- return nil
-}
-
-// SendHeader sets the header metadata.
-func (s *ServerTransportStream) SendHeader(md metadata.MD) error {
- return s.SetHeader(md)
-}
-
-// Trailer returns the cached trailer metadata.
-func (s *ServerTransportStream) Trailer() metadata.MD {
- s.mu.Lock()
- defer s.mu.Unlock()
- return s.trailer.Copy()
-}
-
-// SetTrailer sets the trailer metadata.
-func (s *ServerTransportStream) SetTrailer(md metadata.MD) error {
- if md.Len() == 0 {
- return nil
- }
-
- s.mu.Lock()
- s.trailer = metadata.Join(s.trailer, md)
- s.mu.Unlock()
- return nil
-}
-
-func timeoutDecode(s string) (time.Duration, error) {
- size := len(s)
- if size < 2 {
- return 0, fmt.Errorf("timeout string is too short: %q", s)
- }
- d, ok := timeoutUnitToDuration(s[size-1])
- if !ok {
- return 0, fmt.Errorf("timeout unit is not recognized: %q", s)
- }
- t, err := strconv.ParseInt(s[:size-1], 10, 64)
- if err != nil {
- return 0, err
- }
- return d * time.Duration(t), nil
-}
-
-func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) {
- switch u {
- case 'H':
- return time.Hour, true
- case 'M':
- return time.Minute, true
- case 'S':
- return time.Second, true
- case 'm':
- return time.Millisecond, true
- case 'u':
- return time.Microsecond, true
- case 'n':
- return time.Nanosecond, true
- default:
- return
- }
-}
-
-// isPermanentHTTPHeader checks whether hdr belongs to the list of
-// permanent request headers maintained by IANA.
-// http://www.iana.org/assignments/message-headers/message-headers.xml
-func isPermanentHTTPHeader(hdr string) bool {
- switch hdr {
- case
- "Accept",
- "Accept-Charset",
- "Accept-Language",
- "Accept-Ranges",
- "Authorization",
- "Cache-Control",
- "Content-Type",
- "Cookie",
- "Date",
- "Expect",
- "From",
- "Host",
- "If-Match",
- "If-Modified-Since",
- "If-None-Match",
- "If-Schedule-Tag-Match",
- "If-Unmodified-Since",
- "Max-Forwards",
- "Origin",
- "Pragma",
- "Referer",
- "User-Agent",
- "Via",
- "Warning":
- return true
- }
- return false
-}
-
-// isMalformedHTTPHeader checks whether header belongs to the list of
-// "malformed headers" and would be rejected by the gRPC server.
-func isMalformedHTTPHeader(header string) bool {
- _, isMalformed := malformedHTTPHeaders[strings.ToLower(header)]
- return isMalformed
-}
-
-// RPCMethod returns the method string for the server context. The returned
-// string is in the format of "/package.service/method".
-func RPCMethod(ctx context.Context) (string, bool) {
- m := ctx.Value(rpcMethodKey{})
- if m == nil {
- return "", false
- }
- ms, ok := m.(string)
- if !ok {
- return "", false
- }
- return ms, true
-}
-
-func withRPCMethod(ctx context.Context, rpcMethodName string) context.Context {
- return context.WithValue(ctx, rpcMethodKey{}, rpcMethodName)
-}
-
-// HTTPPathPattern returns the HTTP path pattern string relating to the HTTP handler, if one exists.
-// The format of the returned string is defined by the google.api.http path template type.
-func HTTPPathPattern(ctx context.Context) (string, bool) {
- m := ctx.Value(httpPathPatternKey{})
- if m == nil {
- return "", false
- }
- ms, ok := m.(string)
- if !ok {
- return "", false
- }
- return ms, true
-}
-
-func withHTTPPathPattern(ctx context.Context, httpPathPattern string) context.Context {
- return context.WithValue(ctx, httpPathPatternKey{}, httpPathPattern)
-}
-
-// HTTPPattern returns the HTTP path pattern struct relating to the HTTP handler, if one exists.
-func HTTPPattern(ctx context.Context) (Pattern, bool) {
- v, ok := ctx.Value(httpPatternKey{}).(Pattern)
- return v, ok
-}
-
-func withHTTPPattern(ctx context.Context, httpPattern Pattern) context.Context {
- return context.WithValue(ctx, httpPatternKey{}, httpPattern)
-}