snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
126
internal/proxy/grpc.go
Normal file
126
internal/proxy/grpc.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/centrifugal/centrifugo/v6/internal/clientcontext"
|
||||
"github.com/centrifugal/centrifugo/v6/internal/middleware"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/encoding/gzip"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
type rpcCredentials struct {
|
||||
key string
|
||||
value string
|
||||
}
|
||||
|
||||
func (t rpcCredentials) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) {
|
||||
return map[string]string{
|
||||
t.key: t.value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t rpcCredentials) RequireTransportSecurity() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getGrpcHost(endpoint string) (string, error) {
|
||||
var host string
|
||||
if strings.HasPrefix(endpoint, "grpc://") {
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
host = u.Host
|
||||
} else {
|
||||
host = endpoint
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func getDialOpts(name string, p Config) ([]grpc.DialOption, error) {
|
||||
var dialOpts []grpc.DialOption
|
||||
if p.GRPC.CredentialsKey != "" {
|
||||
dialOpts = append(dialOpts, grpc.WithPerRPCCredentials(&rpcCredentials{
|
||||
key: p.GRPC.CredentialsKey,
|
||||
value: p.GRPC.CredentialsValue,
|
||||
}))
|
||||
}
|
||||
if p.GRPC.TLS.Enabled {
|
||||
tlsConfig, err := p.GRPC.TLS.ToGoTLSConfig("proxy_grpc:" + name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create TLS config %v", err)
|
||||
}
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
|
||||
} else {
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
}
|
||||
if p.GRPC.Compression {
|
||||
dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.UseCompressor(gzip.Name)))
|
||||
}
|
||||
|
||||
if p.TestGrpcDialer != nil {
|
||||
dialOpts = append(dialOpts, grpc.WithContextDialer(p.TestGrpcDialer))
|
||||
}
|
||||
|
||||
return dialOpts, nil
|
||||
}
|
||||
|
||||
func grpcRequestContext(ctx context.Context, proxy Config) context.Context {
|
||||
md := requestMetadata(ctx, proxy.HttpHeaders, proxy.GrpcMetadata, emulatedHeaderAllowList(proxy), proxy.GRPC.StaticMetadata)
|
||||
return metadata.NewOutgoingContext(ctx, md)
|
||||
}
|
||||
|
||||
func requestMetadata(ctx context.Context, allowedHeaders, allowedMetaKeys, allowedEmulatedHeaders []string, staticMetadata map[string]string) metadata.MD {
|
||||
requestMD := metadata.MD{}
|
||||
|
||||
// Set static metadata first, so that dynamic metadata can override it.
|
||||
for k, v := range staticMetadata {
|
||||
requestMD.Set(k, v)
|
||||
}
|
||||
|
||||
// Emulated headers come from the client connect frame and are client-controlled,
|
||||
// so they are forwarded only when listed in emulated_headers - never via
|
||||
// the transport-level http_headers allow list.
|
||||
emulatedHeaders, _ := clientcontext.GetEmulatedHeadersFromContext(ctx)
|
||||
var droppedEmulated bool
|
||||
for k, v := range emulatedHeaders {
|
||||
lk := strings.ToLower(k)
|
||||
if slices.Contains(allowedEmulatedHeaders, lk) {
|
||||
requestMD.Set(k, v)
|
||||
} else if slices.Contains(allowedHeaders, lk) {
|
||||
// Listed in http_headers but not emulated_headers: this would
|
||||
// have been forwarded before v6.9.0. Flag for a throttled migration hint.
|
||||
droppedEmulated = true
|
||||
}
|
||||
}
|
||||
if droppedEmulated {
|
||||
logDroppedEmulatedHeadersHint(emulatedHeaders, allowedHeaders, allowedEmulatedHeaders)
|
||||
}
|
||||
|
||||
httpHeaders, hasHTTPHeaders := middleware.GetHeadersFromContext(ctx)
|
||||
for k, vv := range httpHeaders {
|
||||
if slices.Contains(allowedHeaders, strings.ToLower(k)) {
|
||||
requestMD.Set(k, vv...)
|
||||
}
|
||||
}
|
||||
|
||||
if !hasHTTPHeaders {
|
||||
md, _ := metadata.FromIncomingContext(ctx)
|
||||
for k, vv := range md {
|
||||
if slices.Contains(allowedMetaKeys, k) {
|
||||
requestMD[k] = vv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requestMD
|
||||
}
|
||||
Reference in New Issue
Block a user