Skip to content

Commit bc5d55a

Browse files
authored
Merge pull request #21 from Azure/toma/mdConversion
Adding grpc gateway mux mw and responseheader grpc interceptor
2 parents e950f5a + dfbb4b9 commit bc5d55a

26 files changed

+1133
-423
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
all: generate init tidy build test
22

33
generate:
4-
cd test/proto; npx buf mod update; cd ..; npx buf generate; cd ..
4+
cd test/api/v1/proto; npx buf mod update; cd ..; npx buf generate; cd ..
55

66
init:
77
go mod init github.com/Azure/aks-middleware

common/const.go

+13
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,16 @@ const (
1717
// metadata.
1818
RequestIDMetadataHeader = "x-request-id"
1919
)
20+
21+
var (
22+
MetadataToHeader = map[string]string{
23+
OperationIDKey: RequestAcsOperationIDHeader,
24+
ARMClientRequestIDKey: RequestARMClientRequestIDHeader,
25+
}
26+
27+
HeaderToMetadata = map[string]string{
28+
RequestCorrelationIDHeader: CorrelationIDKey,
29+
RequestAcsOperationIDHeader: OperationIDKey,
30+
RequestARMClientRequestIDHeader: ARMClientRequestIDKey,
31+
}
32+
)

ctxlogger/ctxlogger_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package ctxlogger_test
22

33
import (
44
"github.com/Azure/aks-middleware/ctxlogger"
5-
pb "github.com/Azure/aks-middleware/test"
5+
pb "github.com/Azure/aks-middleware/test/api/v1"
66
. "github.com/onsi/ginkgo/v2"
77
. "github.com/onsi/gomega"
88
)

go.mod

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module github.com/Azure/aks-middleware
22

3-
go 1.21.3
3+
go 1.22.7
4+
5+
toolchain go1.23.0
46

57
require (
68
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.32.0-20231115204500-e097f827e652.1
@@ -9,28 +11,30 @@ require (
911
github.com/bufbuild/protovalidate-go v0.4.3
1012
github.com/gorilla/mux v1.8.1
1113
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1
14+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0
1215
github.com/onsi/ginkgo/v2 v2.13.2
1316
github.com/onsi/gomega v1.30.0
14-
google.golang.org/grpc v1.60.1
15-
google.golang.org/protobuf v1.32.0
17+
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697
18+
google.golang.org/grpc v1.68.0
19+
google.golang.org/protobuf v1.35.2
1620
)
1721

1822
require (
1923
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
2024
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
2125
github.com/go-logr/logr v1.3.0 // indirect
2226
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
23-
github.com/golang/protobuf v1.5.3 // indirect
27+
github.com/golang/protobuf v1.5.4 // indirect
2428
github.com/google/cel-go v0.18.2 // indirect
2529
github.com/google/go-cmp v0.6.0 // indirect
2630
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
31+
github.com/rogpeppe/go-internal v1.13.1 // indirect
2732
github.com/stoewer/go-strcase v1.3.0 // indirect
2833
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
29-
golang.org/x/net v0.19.0 // indirect
30-
golang.org/x/sys v0.15.0 // indirect
31-
golang.org/x/text v0.14.0 // indirect
32-
golang.org/x/tools v0.14.0 // indirect
33-
google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect
34-
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
34+
golang.org/x/net v0.29.0 // indirect
35+
golang.org/x/sys v0.25.0 // indirect
36+
golang.org/x/text v0.20.0 // indirect
37+
golang.org/x/tools v0.22.0 // indirect
38+
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
3539
gopkg.in/yaml.v3 v3.0.1 // indirect
3640
)

go.sum

+28-26
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
1616
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1717
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1818
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
19-
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
20-
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
19+
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
20+
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
2121
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
2222
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
2323
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
2424
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
2525
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
26-
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
27-
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
26+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
27+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
2828
github.com/google/cel-go v0.18.2 h1:L0B6sNBSVmt0OyECi8v6VOS74KOc9W/tLiWKfZABvf4=
2929
github.com/google/cel-go v0.18.2/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
3030
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -36,9 +36,11 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
3636
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
3737
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY=
3838
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4=
39+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
40+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
3941
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
40-
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
41-
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
42+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
43+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
4244
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
4345
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
4446
github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
@@ -47,6 +49,8 @@ github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
4749
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
4850
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4951
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
52+
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
53+
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
5054
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
5155
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
5256
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -60,31 +64,29 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
6064
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
6165
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
6266
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
63-
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
64-
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
65-
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
66-
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
67+
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
68+
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
6769
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
68-
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
69-
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
70-
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
71-
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
72-
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
73-
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
70+
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
71+
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
72+
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
73+
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
74+
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
75+
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
7476
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
75-
google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU=
76-
google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0=
77-
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
78-
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
79-
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
80-
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
77+
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ=
78+
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88=
79+
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA=
80+
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
81+
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
82+
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
8183
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
82-
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
83-
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
8484
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
85+
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
86+
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
8587
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
86-
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
87-
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
88+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
89+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
8890
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
8991
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
9092
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

httpmw/metadata/metadata.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package metadata
2+
3+
import (
4+
"context"
5+
"net/http"
6+
7+
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
8+
"google.golang.org/grpc/metadata"
9+
)
10+
11+
// Helper function to extract HTTP headers and put them into metadata.
12+
func extractMetadata(headerToMetadata map[string]string, req *http.Request) metadata.MD {
13+
md := metadata.Pairs()
14+
for headerName, metadataKey := range headerToMetadata {
15+
if value := req.Header.Get(headerName); value != "" {
16+
md.Append(metadataKey, value)
17+
}
18+
}
19+
return md
20+
}
21+
22+
// Helper function to select the metadata key and returns its corresponding HTTP header key.
23+
func matchOutgoingHeader(metadataToHeader map[string]string, s string) (string, bool) {
24+
if header, ok := metadataToHeader[s]; ok {
25+
return header, true
26+
}
27+
return "", false
28+
}
29+
30+
// NewMetadataMiddleware returns an array of ServeMuxOptions that can be used to convert incoming HTTP headers to gRPC metadata and vice versa.
31+
func NewMetadataMiddleware(headerToMetadata, metadataToHeader map[string]string) []runtime.ServeMuxOption {
32+
return []runtime.ServeMuxOption{
33+
runtime.WithMetadata(func(ctx context.Context, req *http.Request) metadata.MD {
34+
return extractMetadata(headerToMetadata, req)
35+
}),
36+
runtime.WithOutgoingHeaderMatcher(func(s string) (string, bool) {
37+
return matchOutgoingHeader(metadataToHeader, s)
38+
}),
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package metadata
2+
3+
import (
4+
"context"
5+
"net"
6+
"net/http"
7+
"net/http/httptest"
8+
9+
"github.com/Azure/aks-middleware/responseheader"
10+
pb "github.com/Azure/aks-middleware/test/api/v1"
11+
testServer "github.com/Azure/aks-middleware/test/server"
12+
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
13+
. "github.com/onsi/ginkgo/v2"
14+
. "github.com/onsi/gomega"
15+
"google.golang.org/grpc"
16+
"google.golang.org/grpc/credentials/insecure"
17+
)
18+
19+
var _ = Describe("Metadata Integration", func() {
20+
var (
21+
mux *runtime.ServeMux
22+
testHTTPSrv *httptest.Server
23+
grpcServer *grpc.Server
24+
testSrv *testServer.TestServer
25+
lis net.Listener
26+
)
27+
28+
BeforeEach(func() {
29+
metadataToHeader := map[string]string{
30+
"custom-header": "X-Custom-Header",
31+
"another-header": "X-Another-Header",
32+
"multi-value-header": "X-Multi-Value-Header",
33+
"empty-metadata-key": "",
34+
}
35+
headerToMetadata := map[string]string{
36+
"X-Custom-Header": "custom-header",
37+
"X-Another-Header": "another-header",
38+
"X-Multi-Value-Header": "multi-value-header",
39+
"X-Empty-Metadata": "",
40+
}
41+
42+
responseInterceptor := responseheader.UnaryServerInterceptor(metadataToHeader)
43+
grpcServer = grpc.NewServer(grpc.UnaryInterceptor(responseInterceptor))
44+
testSrv = &testServer.TestServer{}
45+
pb.RegisterMyGreeterServer(grpcServer, testSrv)
46+
47+
var err error
48+
lis, err = net.Listen("tcp", "localhost:0")
49+
Expect(err).NotTo(HaveOccurred())
50+
51+
go func() {
52+
err := grpcServer.Serve(lis)
53+
Expect(err).NotTo(HaveOccurred())
54+
}()
55+
56+
mux = runtime.NewServeMux(NewMetadataMiddleware(headerToMetadata, metadataToHeader)...)
57+
58+
// Register the gRPC-Gateway handler to forward HTTP to gRPC
59+
err = pb.RegisterMyGreeterHandlerFromEndpoint(context.Background(), mux, lis.Addr().String(), []grpc.DialOption{
60+
grpc.WithTransportCredentials(insecure.NewCredentials()),
61+
})
62+
Expect(err).NotTo(HaveOccurred())
63+
64+
// Create a test HTTP server
65+
testHTTPSrv = httptest.NewServer(mux)
66+
})
67+
68+
AfterEach(func() {
69+
testHTTPSrv.Close()
70+
grpcServer.Stop()
71+
lis.Close()
72+
})
73+
74+
Describe("extractMetadata", func() {
75+
It("should handle multiple headers and extract only mapped ones", func() {
76+
req, err := http.NewRequest("POST", testHTTPSrv.URL+"/v1/hello", nil)
77+
Expect(err).NotTo(HaveOccurred())
78+
req.Header.Set("X-Custom-Header", "value1")
79+
req.Header.Set("X-Another-Header", "value2")
80+
req.Header.Set("X-Irrelevant-Header", "value3")
81+
82+
resp, err := http.DefaultClient.Do(req)
83+
Expect(err).NotTo(HaveOccurred())
84+
defer resp.Body.Close()
85+
86+
Expect(resp.StatusCode).To(Equal(http.StatusOK))
87+
Expect(testSrv.ReceivedMetadata["custom-header"]).To(ContainElement("value1"))
88+
Expect(testSrv.ReceivedMetadata["another-header"]).To(ContainElement("value2"))
89+
Expect(testSrv.ReceivedMetadata).NotTo(HaveKey("irrelevant-header"))
90+
})
91+
92+
})
93+
94+
Describe("matchOutgoingHeader", func() {
95+
It("should match allowed headers and set outgoing HTTP headers", func() {
96+
req, err := http.NewRequest("POST", testHTTPSrv.URL+"/v1/hello", nil)
97+
Expect(err).NotTo(HaveOccurred())
98+
req.Header.Set("X-Custom-Header", "value")
99+
req.Header.Set("X-Disallowed-Header", "value")
100+
101+
resp, err := http.DefaultClient.Do(req)
102+
Expect(err).NotTo(HaveOccurred())
103+
defer resp.Body.Close()
104+
105+
Expect(resp.StatusCode).To(Equal(http.StatusOK))
106+
// Verify the outgoing header
107+
Expect(resp.Header.Get("X-Custom-Header")).To(Equal("value"))
108+
// Disallowed headers should not be present in the response
109+
Expect(resp.Header.Get("X-Disallowed-Header")).To(Equal(""))
110+
})
111+
})
112+
})
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package metadata
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestMetadata(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Metadata Suite")
13+
}

0 commit comments

Comments
 (0)