Browse Source

Added middleware for processing request_id grpc and http requests (#6805)

pull/6808/head
Aleksey Kosov 2 weeks ago
committed by GitHub
parent
commit
5182d46e22
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 26
      weed/pb/grpc_client_server.go
  2. 21
      weed/server/common.go
  3. 8
      weed/server/filer_server.go
  4. 24
      weed/server/master_server.go
  5. 10
      weed/server/volume_server.go
  6. 20
      weed/util/request_id.go

26
weed/pb/grpc_client_server.go

@ -3,6 +3,7 @@ package pb
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/google/uuid"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"math/rand/v2" "math/rand/v2"
"net/http" "net/http"
@ -58,6 +59,7 @@ func NewGrpcServer(opts ...grpc.ServerOption) *grpc.Server {
}), }),
grpc.MaxRecvMsgSize(Max_Message_Size), grpc.MaxRecvMsgSize(Max_Message_Size),
grpc.MaxSendMsgSize(Max_Message_Size), grpc.MaxSendMsgSize(Max_Message_Size),
grpc.UnaryInterceptor(requestIDUnaryInterceptor()),
) )
for _, opt := range opts { for _, opt := range opts {
if opt != nil { if opt != nil {
@ -118,6 +120,30 @@ func getOrCreateConnection(address string, waitForReady bool, opts ...grpc.DialO
return vgc, nil return vgc, nil
} }
func requestIDUnaryInterceptor() grpc.UnaryServerInterceptor {
return func(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
md, _ := metadata.FromIncomingContext(ctx)
idList := md.Get(util.RequestIDKey)
var reqID string
if len(idList) > 0 {
reqID = idList[0]
}
if reqID == "" {
reqID = uuid.New().String()
}
ctx = util.WithRequestID(ctx, reqID)
grpc.SetTrailer(ctx, metadata.Pairs(util.RequestIDKey, reqID))
return handler(ctx, req)
}
}
// WithGrpcClient In streamingMode, always use a fresh connection. Otherwise, try to reuse an existing connection. // WithGrpcClient In streamingMode, always use a fresh connection. Otherwise, try to reuse an existing connection.
func WithGrpcClient(streamingMode bool, signature int32, fn func(*grpc.ClientConn) error, address string, waitForReady bool, opts ...grpc.DialOption) error { func WithGrpcClient(streamingMode bool, signature int32, fn func(*grpc.ClientConn) error, address string, waitForReady bool, opts ...grpc.DialOption) error {

21
weed/server/common.go

@ -3,9 +3,12 @@ package weed_server
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/google/uuid"
"google.golang.org/grpc/metadata"
"io" "io"
"io/fs" "io/fs"
"mime/multipart" "mime/multipart"
@ -421,3 +424,21 @@ func ProcessRangeRequest(r *http.Request, w http.ResponseWriter, totalSize int64
} }
return nil return nil
} }
func requestIDMiddleware(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
reqID := r.Header.Get(util.RequestIdHttpHeader)
if reqID == "" {
reqID = uuid.New().String()
}
ctx := context.WithValue(r.Context(), util.RequestIDKey, reqID)
ctx = metadata.NewOutgoingContext(ctx,
metadata.New(map[string]string{
util.RequestIDKey: reqID,
}))
w.Header().Set(util.RequestIdHttpHeader, reqID)
h(w, r.WithContext(ctx))
}
}

8
weed/server/filer_server.go

@ -189,13 +189,13 @@ func NewFilerServer(defaultMux, readonlyMux *http.ServeMux, option *FilerOption)
handleStaticResources(defaultMux) handleStaticResources(defaultMux)
if !option.DisableHttp { if !option.DisableHttp {
defaultMux.HandleFunc("/healthz", fs.filerHealthzHandler)
defaultMux.HandleFunc("/", fs.filerGuard.WhiteList(fs.filerHandler))
defaultMux.HandleFunc("/healthz", requestIDMiddleware(fs.filerHealthzHandler))
defaultMux.HandleFunc("/", fs.filerGuard.WhiteList(requestIDMiddleware(fs.filerHandler)))
} }
if defaultMux != readonlyMux { if defaultMux != readonlyMux {
handleStaticResources(readonlyMux) handleStaticResources(readonlyMux)
readonlyMux.HandleFunc("/healthz", fs.filerHealthzHandler)
readonlyMux.HandleFunc("/", fs.filerGuard.WhiteList(fs.readonlyFilerHandler))
readonlyMux.HandleFunc("/healthz", requestIDMiddleware(fs.filerHealthzHandler))
readonlyMux.HandleFunc("/", fs.filerGuard.WhiteList(requestIDMiddleware(fs.readonlyFilerHandler)))
} }
existingNodes := fs.filer.ListExistingPeerUpdates(context.Background()) existingNodes := fs.filer.ListExistingPeerUpdates(context.Background())

24
weed/server/master_server.go

@ -134,24 +134,24 @@ func NewMasterServer(r *mux.Router, option *MasterOption, peers map[string]pb.Se
ms.guard = security.NewGuard(append(ms.option.WhiteList, whiteList...), signingKey, expiresAfterSec, readSigningKey, readExpiresAfterSec) ms.guard = security.NewGuard(append(ms.option.WhiteList, whiteList...), signingKey, expiresAfterSec, readSigningKey, readExpiresAfterSec)
handleStaticResources2(r) handleStaticResources2(r)
r.HandleFunc("/", ms.proxyToLeader(ms.uiStatusHandler))
r.HandleFunc("/ui/index.html", ms.uiStatusHandler)
r.HandleFunc("/", ms.proxyToLeader(requestIDMiddleware(ms.uiStatusHandler)))
r.HandleFunc("/ui/index.html", requestIDMiddleware(ms.uiStatusHandler))
if !ms.option.DisableHttp { if !ms.option.DisableHttp {
r.HandleFunc("/dir/assign", ms.proxyToLeader(ms.guard.WhiteList(ms.dirAssignHandler)))
r.HandleFunc("/dir/lookup", ms.guard.WhiteList(ms.dirLookupHandler))
r.HandleFunc("/dir/status", ms.proxyToLeader(ms.guard.WhiteList(ms.dirStatusHandler)))
r.HandleFunc("/col/delete", ms.proxyToLeader(ms.guard.WhiteList(ms.collectionDeleteHandler)))
r.HandleFunc("/vol/grow", ms.proxyToLeader(ms.guard.WhiteList(ms.volumeGrowHandler)))
r.HandleFunc("/vol/status", ms.proxyToLeader(ms.guard.WhiteList(ms.volumeStatusHandler)))
r.HandleFunc("/vol/vacuum", ms.proxyToLeader(ms.guard.WhiteList(ms.volumeVacuumHandler)))
r.HandleFunc("/submit", ms.guard.WhiteList(ms.submitFromMasterServerHandler))
r.HandleFunc("/collection/info", ms.guard.WhiteList(ms.collectionInfoHandler))
r.HandleFunc("/dir/assign", ms.proxyToLeader(ms.guard.WhiteList(requestIDMiddleware(ms.dirAssignHandler))))
r.HandleFunc("/dir/lookup", ms.guard.WhiteList(requestIDMiddleware(ms.dirLookupHandler)))
r.HandleFunc("/dir/status", ms.proxyToLeader(ms.guard.WhiteList(requestIDMiddleware(ms.dirStatusHandler))))
r.HandleFunc("/col/delete", ms.proxyToLeader(ms.guard.WhiteList(requestIDMiddleware(ms.collectionDeleteHandler))))
r.HandleFunc("/vol/grow", ms.proxyToLeader(ms.guard.WhiteList(requestIDMiddleware(ms.volumeGrowHandler))))
r.HandleFunc("/vol/status", ms.proxyToLeader(ms.guard.WhiteList(requestIDMiddleware(ms.volumeStatusHandler))))
r.HandleFunc("/vol/vacuum", ms.proxyToLeader(ms.guard.WhiteList(requestIDMiddleware(ms.volumeVacuumHandler))))
r.HandleFunc("/submit", ms.guard.WhiteList(requestIDMiddleware(ms.submitFromMasterServerHandler)))
r.HandleFunc("/collection/info", ms.guard.WhiteList(requestIDMiddleware(ms.collectionInfoHandler)))
/* /*
r.HandleFunc("/stats/health", ms.guard.WhiteList(statsHealthHandler)) r.HandleFunc("/stats/health", ms.guard.WhiteList(statsHealthHandler))
r.HandleFunc("/stats/counter", ms.guard.WhiteList(statsCounterHandler)) r.HandleFunc("/stats/counter", ms.guard.WhiteList(statsCounterHandler))
r.HandleFunc("/stats/memory", ms.guard.WhiteList(statsMemoryHandler)) r.HandleFunc("/stats/memory", ms.guard.WhiteList(statsMemoryHandler))
*/ */
r.HandleFunc("/{fileId}", ms.redirectHandler)
r.HandleFunc("/{fileId}", requestIDMiddleware(ms.redirectHandler))
} }
ms.Topo.StartRefreshWritableVolumes( ms.Topo.StartRefreshWritableVolumes(

10
weed/server/volume_server.go

@ -115,22 +115,22 @@ func NewVolumeServer(adminMux, publicMux *http.ServeMux, ip string,
vs.guard = security.NewGuard(whiteList, signingKey, expiresAfterSec, readSigningKey, readExpiresAfterSec) vs.guard = security.NewGuard(whiteList, signingKey, expiresAfterSec, readSigningKey, readExpiresAfterSec)
handleStaticResources(adminMux) handleStaticResources(adminMux)
adminMux.HandleFunc("/status", vs.statusHandler)
adminMux.HandleFunc("/healthz", vs.healthzHandler)
adminMux.HandleFunc("/status", requestIDMiddleware(vs.statusHandler))
adminMux.HandleFunc("/healthz", requestIDMiddleware(vs.healthzHandler))
if signingKey == "" || enableUiAccess { if signingKey == "" || enableUiAccess {
// only expose the volume server details for safe environments // only expose the volume server details for safe environments
adminMux.HandleFunc("/ui/index.html", vs.uiStatusHandler)
adminMux.HandleFunc("/ui/index.html", requestIDMiddleware(vs.uiStatusHandler))
/* /*
adminMux.HandleFunc("/stats/counter", vs.guard.WhiteList(statsCounterHandler)) adminMux.HandleFunc("/stats/counter", vs.guard.WhiteList(statsCounterHandler))
adminMux.HandleFunc("/stats/memory", vs.guard.WhiteList(statsMemoryHandler)) adminMux.HandleFunc("/stats/memory", vs.guard.WhiteList(statsMemoryHandler))
adminMux.HandleFunc("/stats/disk", vs.guard.WhiteList(vs.statsDiskHandler)) adminMux.HandleFunc("/stats/disk", vs.guard.WhiteList(vs.statsDiskHandler))
*/ */
} }
adminMux.HandleFunc("/", vs.privateStoreHandler)
adminMux.HandleFunc("/", requestIDMiddleware(vs.privateStoreHandler))
if publicMux != adminMux { if publicMux != adminMux {
// separated admin and public port // separated admin and public port
handleStaticResources(publicMux) handleStaticResources(publicMux)
publicMux.HandleFunc("/", vs.publicReadOnlyHandler)
publicMux.HandleFunc("/", requestIDMiddleware(vs.publicReadOnlyHandler))
} }
go vs.heartbeat() go vs.heartbeat()

20
weed/util/request_id.go

@ -0,0 +1,20 @@
package util
import "context"
const (
RequestIdHttpHeader = "X-Request-ID"
RequestIDKey = "x-request-id"
)
func GetRequestID(ctx context.Context) string {
if ctx == nil {
return ""
}
id, _ := ctx.Value(RequestIDKey).(string)
return id
}
func WithRequestID(ctx context.Context, id string) context.Context {
return context.WithValue(ctx, RequestIDKey, id)
}
Loading…
Cancel
Save