Merge branch 'main' into fix-redis-sentinel-docs
This commit is contained in:
		
						commit
						fc5c863174
					
				| 
						 | 
				
			
			@ -12,7 +12,7 @@ require (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763 // indirect
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5 // indirect
 | 
			
		||||
	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
 | 
			
		||||
	github.com/gogo/protobuf v1.3.2 // indirect
 | 
			
		||||
	github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763 h1:9H0+baON+6+x4A/nQ2Lj+1JNk8MSlNv6sik6zfxdvsE=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5 h1:Q26gmPxs6WnnBYoudOlznPHsmrbTawcYEpHg4VoB7v8=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										13
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -65,7 +65,7 @@ require (
 | 
			
		|||
	github.com/cloudwego/kitex-examples v0.1.1
 | 
			
		||||
	github.com/cyphar/filepath-securejoin v0.2.4
 | 
			
		||||
	github.com/dancannon/gorethink v4.0.0+incompatible
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5
 | 
			
		||||
	github.com/didip/tollbooth/v7 v7.0.1
 | 
			
		||||
	github.com/eclipse/paho.mqtt.golang v1.4.3
 | 
			
		||||
	github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5
 | 
			
		||||
| 
						 | 
				
			
			@ -284,7 +284,7 @@ require (
 | 
			
		|||
	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 | 
			
		||||
	github.com/golang/protobuf v1.5.4 // indirect
 | 
			
		||||
	github.com/golang/snappy v1.0.0 // indirect
 | 
			
		||||
	github.com/google/btree v1.1.2 // indirect
 | 
			
		||||
	github.com/google/btree v1.1.3 // indirect
 | 
			
		||||
	github.com/google/flatbuffers v25.2.10+incompatible // indirect
 | 
			
		||||
	github.com/google/generative-ai-go v0.15.1 // indirect
 | 
			
		||||
	github.com/google/gnostic-models v0.6.9 // indirect
 | 
			
		||||
| 
						 | 
				
			
			@ -292,6 +292,7 @@ require (
 | 
			
		|||
	github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
 | 
			
		||||
	github.com/google/s2a-go v0.1.9 // indirect
 | 
			
		||||
	github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
 | 
			
		||||
	github.com/gorilla/css v1.0.1 // indirect
 | 
			
		||||
	github.com/gorilla/websocket v1.5.3 // indirect
 | 
			
		||||
	github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
 | 
			
		||||
	github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
 | 
			
		||||
| 
						 | 
				
			
			@ -362,7 +363,7 @@ require (
 | 
			
		|||
	github.com/panjf2000/ants/v2 v2.8.1 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml v1.9.5 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml/v2 v2.2.4 // indirect
 | 
			
		||||
	github.com/pierrec/lz4 v2.6.0+incompatible // indirect
 | 
			
		||||
	github.com/pierrec/lz4 v2.6.1+incompatible // indirect
 | 
			
		||||
	github.com/pierrec/lz4/v4 v4.1.22 // indirect
 | 
			
		||||
	github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
 | 
			
		||||
	github.com/pkg/errors v0.9.1 // indirect
 | 
			
		||||
| 
						 | 
				
			
			@ -430,15 +431,15 @@ require (
 | 
			
		|||
	go.uber.org/atomic v1.10.0 // indirect
 | 
			
		||||
	go.uber.org/zap v1.27.0 // indirect
 | 
			
		||||
	golang.org/x/arch v0.10.0 // indirect
 | 
			
		||||
	golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
 | 
			
		||||
	golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
 | 
			
		||||
	golang.org/x/sync v0.15.0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.33.0 // indirect
 | 
			
		||||
	golang.org/x/term v0.32.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.26.0 // indirect
 | 
			
		||||
	golang.org/x/time v0.11.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.33.0 // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
 | 
			
		||||
	google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20250512202823-5a2f75b736a9 // indirect
 | 
			
		||||
	google.golang.org/genproto/googleapis/api v0.0.0-20250512202823-5a2f75b736a9 // indirect
 | 
			
		||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
 | 
			
		||||
	google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20 // indirect
 | 
			
		||||
	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										35
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -40,8 +40,8 @@ cloud.google.com/go/datastore v1.20.0/go.mod h1:uFo3e+aEpRfHgtp5pp0+6M0o147KoPaY
 | 
			
		|||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
 | 
			
		||||
cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
 | 
			
		||||
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
 | 
			
		||||
cloud.google.com/go/kms v1.21.1 h1:r1Auo+jlfJSf8B7mUnVw5K0fI7jWyoUy65bV53VjKyk=
 | 
			
		||||
cloud.google.com/go/kms v1.21.1/go.mod h1:s0wCyByc9LjTdCjG88toVs70U9W+cc6RKFc8zAqX7nE=
 | 
			
		||||
cloud.google.com/go/kms v1.21.2 h1:c/PRUSMNQ8zXrc1sdAUnsenWWaNXN+PzTXfXOcSFdoE=
 | 
			
		||||
cloud.google.com/go/kms v1.21.2/go.mod h1:8wkMtHV/9Z8mLXEXr1GK7xPSBdi6knuLXIhqjuWcI6w=
 | 
			
		||||
cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
 | 
			
		||||
cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
 | 
			
		||||
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
 | 
			
		||||
| 
						 | 
				
			
			@ -63,8 +63,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
 | 
			
		|||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
 | 
			
		||||
cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs=
 | 
			
		||||
cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY=
 | 
			
		||||
cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE=
 | 
			
		||||
cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8=
 | 
			
		||||
cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4=
 | 
			
		||||
cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI=
 | 
			
		||||
cloud.google.com/go/vertexai v0.12.0 h1:zTadEo/CtsoyRXNx3uGCncoWAP1H2HakGqwznt+iMo8=
 | 
			
		||||
cloud.google.com/go/vertexai v0.12.0/go.mod h1:8u+d0TsvBfAAd2x5R6GMgbYhsLgo3J7lmP4bR8g2ig8=
 | 
			
		||||
contrib.go.opencensus.io/exporter/prometheus v0.4.1/go.mod h1:t9wvfitlUjGXG2IXAZsuFq26mDGid/JwCEXp+gTG/9U=
 | 
			
		||||
| 
						 | 
				
			
			@ -530,8 +530,8 @@ github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjm
 | 
			
		|||
github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz3WnybhRZtgF1K929FD8z1avU=
 | 
			
		||||
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
 | 
			
		||||
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763 h1:9H0+baON+6+x4A/nQ2Lj+1JNk8MSlNv6sik6zfxdvsE=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5 h1:Q26gmPxs6WnnBYoudOlznPHsmrbTawcYEpHg4VoB7v8=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
 | 
			
		||||
github.com/dave/jennifer v1.4.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
| 
						 | 
				
			
			@ -848,8 +848,8 @@ github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP
 | 
			
		|||
github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs=
 | 
			
		||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
 | 
			
		||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
 | 
			
		||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
 | 
			
		||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
 | 
			
		||||
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
 | 
			
		||||
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
 | 
			
		||||
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
 | 
			
		||||
| 
						 | 
				
			
			@ -917,8 +917,8 @@ github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3
 | 
			
		|||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
 | 
			
		||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 | 
			
		||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
 | 
			
		||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
 | 
			
		||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
 | 
			
		||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
 | 
			
		||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 | 
			
		||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 | 
			
		||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 | 
			
		||||
| 
						 | 
				
			
			@ -1439,8 +1439,9 @@ github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk
 | 
			
		|||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 | 
			
		||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 | 
			
		||||
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 | 
			
		||||
github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A=
 | 
			
		||||
github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 | 
			
		||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
 | 
			
		||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 | 
			
		||||
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
 | 
			
		||||
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
 | 
			
		||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
 | 
			
		||||
| 
						 | 
				
			
			@ -1946,8 +1947,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
 | 
			
		|||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 | 
			
		||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 | 
			
		||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
 | 
			
		||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
 | 
			
		||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
 | 
			
		||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 | 
			
		||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 | 
			
		||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 | 
			
		||||
| 
						 | 
				
			
			@ -2412,10 +2413,10 @@ google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQ
 | 
			
		|||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
 | 
			
		||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0=
 | 
			
		||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20250512202823-5a2f75b736a9 h1:0DnDgelxbooHLt0nyiPeCP0zrH/RL+UG558i1oNU1xE=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:IuQRZAKkz+Mhos3ZZ0+hcGaTmLuuTuGw344uzwztGl8=
 | 
			
		||||
google.golang.org/genproto/googleapis/api v0.0.0-20250512202823-5a2f75b736a9 h1:WvBuA5rjZx9SNIzgcU53OohgZy6lKSus++uY4xLaWKc=
 | 
			
		||||
google.golang.org/genproto/googleapis/api v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:W3S/3np0/dPWsWLi1h/UymYctGXaGBM2StwzD0y140U=
 | 
			
		||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
 | 
			
		||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
 | 
			
		||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/fasthttp-contrib/sessions"
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +43,9 @@ type oAuth2MiddlewareMetadata struct {
 | 
			
		|||
	AuthHeaderName string `json:"authHeaderName" mapstructure:"authHeaderName"`
 | 
			
		||||
	RedirectURL    string `json:"redirectURL" mapstructure:"redirectURL"`
 | 
			
		||||
	ForceHTTPS     string `json:"forceHTTPS" mapstructure:"forceHTTPS"`
 | 
			
		||||
	PathFilter     string `json:"pathFilter" mapstructure:"pathFilter"`
 | 
			
		||||
 | 
			
		||||
	pathFilterRegex *regexp.Regexp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewOAuth2Middleware returns a new oAuth2 middleware.
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +88,15 @@ func (m *Middleware) GetHandler(ctx context.Context, metadata middleware.Metadat
 | 
			
		|||
 | 
			
		||||
	return func(next http.Handler) http.Handler {
 | 
			
		||||
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
			if meta.pathFilterRegex != nil {
 | 
			
		||||
				matched := meta.pathFilterRegex.MatchString(r.URL.Path)
 | 
			
		||||
				if !matched {
 | 
			
		||||
					m.logger.Debugf("PathFilter %s didn't match %s! Skipping!", meta.PathFilter, r.URL.Path)
 | 
			
		||||
					next.ServeHTTP(w, r)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			session := sessions.Start(w, r)
 | 
			
		||||
 | 
			
		||||
			if session.GetString(meta.AuthHeaderName) != "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -153,6 +166,15 @@ func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2Mid
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if middlewareMetadata.PathFilter != "" {
 | 
			
		||||
		rx, err := regexp.Compile(middlewareMetadata.PathFilter)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		middlewareMetadata.pathFilterRegex = rx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &middlewareMetadata, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,3 +61,52 @@ func TestOAuth2CreatesAuthorizationHeaderWhenInSessionState(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	assert.Equal(t, "Bearer abcd", r.Header.Get("someHeader"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOAuth2CreatesAuthorizationHeaderGetNativeMetadata(t *testing.T) {
 | 
			
		||||
	var metadata middleware.Metadata
 | 
			
		||||
	metadata.Properties = map[string]string{
 | 
			
		||||
		"clientID":       "testId",
 | 
			
		||||
		"clientSecret":   "testSecret",
 | 
			
		||||
		"scopes":         "ascope",
 | 
			
		||||
		"authURL":        "https://idp:9999",
 | 
			
		||||
		"tokenURL":       "https://idp:9999",
 | 
			
		||||
		"redirectUrl":    "https://localhost:9999",
 | 
			
		||||
		"authHeaderName": "someHeader",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log := logger.NewLogger("oauth2.test")
 | 
			
		||||
	oauth2Middleware, ok := NewOAuth2Middleware(log).(*Middleware)
 | 
			
		||||
	require.True(t, ok)
 | 
			
		||||
 | 
			
		||||
	tc := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		pathFilter string
 | 
			
		||||
		wantErr    bool
 | 
			
		||||
	}{
 | 
			
		||||
		{name: "empty pathFilter", pathFilter: "", wantErr: false},
 | 
			
		||||
		{name: "wildcard pathFilter", pathFilter: ".*", wantErr: false},
 | 
			
		||||
		{name: "api path pathFilter", pathFilter: "/api/v1/users", wantErr: false},
 | 
			
		||||
		{name: "debug endpoint pathFilter", pathFilter: "^/debug/?$", wantErr: false},
 | 
			
		||||
		{name: "user id pathFilter", pathFilter: "^/user/[0-9]+$", wantErr: false},
 | 
			
		||||
		{name: "invalid wildcard pathFilter", pathFilter: "*invalid", wantErr: true},
 | 
			
		||||
		{name: "unclosed parenthesis pathFilter", pathFilter: "invalid(", wantErr: true},
 | 
			
		||||
		{name: "unopened parenthesis pathFilter", pathFilter: "invalid)", wantErr: true},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tc {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			metadata.Properties["pathFilter"] = tt.pathFilter
 | 
			
		||||
			nativeMetadata, err := oauth2Middleware.getNativeMetadata(metadata)
 | 
			
		||||
			if tt.wantErr {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				if tt.pathFilter != "" {
 | 
			
		||||
					require.NotNil(t, nativeMetadata.pathFilterRegex)
 | 
			
		||||
				} else {
 | 
			
		||||
					require.Nil(t, nativeMetadata.pathFilterRegex)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +44,9 @@ type oAuth2ClientCredentialsMiddlewareMetadata struct {
 | 
			
		|||
	HeaderName          string `json:"headerName" mapstructure:"headerName"`
 | 
			
		||||
	EndpointParamsQuery string `json:"endpointParamsQuery,omitempty" mapstructure:"endpointParamsQuery"`
 | 
			
		||||
	AuthStyle           int    `json:"authStyle" mapstructure:"authStyle"`
 | 
			
		||||
	PathFilter          string `json:"pathFilter" mapstructure:"pathFilter"`
 | 
			
		||||
 | 
			
		||||
	pathFilterRegex *regexp.Regexp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TokenProviderInterface provides a common interface to Mock the Token retrieval in unit tests.
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +73,7 @@ type Middleware struct {
 | 
			
		|||
	tokenProvider TokenProviderInterface
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetHandler retruns the HTTP handler provided by the middleware.
 | 
			
		||||
// GetHandler returns the HTTP handler provided by the middleware.
 | 
			
		||||
func (m *Middleware) GetHandler(_ context.Context, metadata middleware.Metadata) (func(next http.Handler) http.Handler, error) {
 | 
			
		||||
	meta, err := m.getNativeMetadata(metadata)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -98,27 +102,38 @@ func (m *Middleware) GetHandler(_ context.Context, metadata middleware.Metadata)
 | 
			
		|||
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
			var headerValue string
 | 
			
		||||
 | 
			
		||||
			// Check if valid token is in the cache
 | 
			
		||||
			cachedToken, found := m.tokenCache.Get(cacheKey)
 | 
			
		||||
			if !found {
 | 
			
		||||
				m.log.Debugf("Cached token not found, try get one")
 | 
			
		||||
 | 
			
		||||
				token, err := m.tokenProvider.GetToken(r.Context(), conf)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					m.log.Errorf("Error acquiring token: %s", err)
 | 
			
		||||
			if meta.pathFilterRegex != nil {
 | 
			
		||||
				matched := meta.pathFilterRegex.MatchString(r.URL.Path)
 | 
			
		||||
				if !matched {
 | 
			
		||||
					m.log.Debugf("PathFilter %s didn't match %s! Skipping!", meta.PathFilter, r.URL.Path)
 | 
			
		||||
					next.ServeHTTP(w, r)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
				tokenExpirationDuration := time.Until(token.Expiry)
 | 
			
		||||
				m.log.Debugf("Token expires at %s (%s from now)", token.Expiry, tokenExpirationDuration)
 | 
			
		||||
 | 
			
		||||
				headerValue = token.Type() + " " + token.AccessToken
 | 
			
		||||
				m.tokenCache.Set(cacheKey, headerValue, tokenExpirationDuration)
 | 
			
		||||
			} else {
 | 
			
		||||
			// Check if valid token is in the cache
 | 
			
		||||
			cachedToken, found := m.tokenCache.Get(cacheKey)
 | 
			
		||||
			if found {
 | 
			
		||||
				m.log.Debugf("Cached token found for key %s", cacheKey)
 | 
			
		||||
				headerValue = cachedToken.(string)
 | 
			
		||||
				r.Header.Add(meta.HeaderName, headerValue)
 | 
			
		||||
				next.ServeHTTP(w, r)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			m.log.Infof("Cached token not found, attempting to retrieve a new one")
 | 
			
		||||
			token, err := m.tokenProvider.GetToken(r.Context(), conf)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				m.log.Errorf("Error acquiring token: %s", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			tokenExpirationDuration := time.Until(token.Expiry)
 | 
			
		||||
			m.log.Infof("Token expires at %s (%s from now)", token.Expiry, tokenExpirationDuration)
 | 
			
		||||
 | 
			
		||||
			headerValue = token.Type() + " " + token.AccessToken
 | 
			
		||||
			m.tokenCache.Set(cacheKey, headerValue, tokenExpirationDuration)
 | 
			
		||||
 | 
			
		||||
			r.Header.Add(meta.HeaderName, headerValue)
 | 
			
		||||
			next.ServeHTTP(w, r)
 | 
			
		||||
		})
 | 
			
		||||
| 
						 | 
				
			
			@ -142,6 +157,14 @@ func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2Cli
 | 
			
		|||
	m.checkMetadataValueExists(&errorString, &middlewareMetadata.Scopes, "scopes")
 | 
			
		||||
	m.checkMetadataValueExists(&errorString, &middlewareMetadata.TokenURL, "tokenURL")
 | 
			
		||||
 | 
			
		||||
	if middlewareMetadata.PathFilter != "" {
 | 
			
		||||
		rx, err := regexp.Compile(middlewareMetadata.PathFilter)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errorString += "Parameter 'pathFilter' is not a valid regex: " + err.Error() + ". "
 | 
			
		||||
		}
 | 
			
		||||
		middlewareMetadata.pathFilterRegex = rx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Value-check AuthStyle
 | 
			
		||||
	if middlewareMetadata.AuthStyle < 0 || middlewareMetadata.AuthStyle > 2 {
 | 
			
		||||
		errorString += fmt.Sprintf("Parameter 'authStyle' can only have the values 0,1,2. Received: '%d'. ", middlewareMetadata.AuthStyle)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2025 The Dapr Authors
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package oauth2clientcredentials
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/golang/mock/gomock"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
 | 
			
		||||
	"github.com/dapr/components-contrib/middleware"
 | 
			
		||||
	mock "github.com/dapr/components-contrib/middleware/http/oauth2clientcredentials/mocks"
 | 
			
		||||
	"github.com/dapr/kit/logger"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func BenchmarkTestOAuth2ClientCredentialsGetHandler(b *testing.B) {
 | 
			
		||||
	mockCtrl := gomock.NewController(b)
 | 
			
		||||
	defer mockCtrl.Finish()
 | 
			
		||||
	mockTokenProvider := mock.NewMockTokenProviderInterface(mockCtrl)
 | 
			
		||||
	gomock.InOrder(
 | 
			
		||||
		mockTokenProvider.
 | 
			
		||||
			EXPECT().
 | 
			
		||||
			GetToken(gomock.Any()).
 | 
			
		||||
			Return(&oauth2.Token{
 | 
			
		||||
				AccessToken: "abcd",
 | 
			
		||||
				TokenType:   "Bearer",
 | 
			
		||||
				Expiry:      time.Now().Add(1 * time.Minute),
 | 
			
		||||
			}, nil).
 | 
			
		||||
			Times(1),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	var metadata middleware.Metadata
 | 
			
		||||
	metadata.Properties = map[string]string{
 | 
			
		||||
		"clientID":     "testId",
 | 
			
		||||
		"clientSecret": "testSecret",
 | 
			
		||||
		"scopes":       "ascope",
 | 
			
		||||
		"tokenURL":     "https://localhost:9999",
 | 
			
		||||
		"headerName":   "authorization",
 | 
			
		||||
		"authStyle":    "1",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log := logger.NewLogger("oauth2clientcredentials.test")
 | 
			
		||||
	oauth2clientcredentialsMiddleware, ok := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	require.True(b, ok)
 | 
			
		||||
	oauth2clientcredentialsMiddleware.SetTokenProvider(mockTokenProvider)
 | 
			
		||||
	handler, err := oauth2clientcredentialsMiddleware.GetHandler(b.Context(), metadata)
 | 
			
		||||
	require.NoError(b, err)
 | 
			
		||||
 | 
			
		||||
	for i := range b.N {
 | 
			
		||||
		url := fmt.Sprintf("http://dapr.io/api/v1/users/%d", i)
 | 
			
		||||
		r := httptest.NewRequest(http.MethodGet, url, nil)
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
		handler(http.HandlerFunc(mockedRequestHandler)).ServeHTTP(w, r)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BenchmarkTestOAuth2ClientCredentialsGetHandlerWithPathFilter(b *testing.B) {
 | 
			
		||||
	mockCtrl := gomock.NewController(b)
 | 
			
		||||
	defer mockCtrl.Finish()
 | 
			
		||||
	mockTokenProvider := mock.NewMockTokenProviderInterface(mockCtrl)
 | 
			
		||||
	gomock.InOrder(
 | 
			
		||||
		mockTokenProvider.
 | 
			
		||||
			EXPECT().
 | 
			
		||||
			GetToken(gomock.Any()).
 | 
			
		||||
			Return(&oauth2.Token{
 | 
			
		||||
				AccessToken: "abcd",
 | 
			
		||||
				TokenType:   "Bearer",
 | 
			
		||||
				Expiry:      time.Now().Add(1 * time.Minute),
 | 
			
		||||
			}, nil).
 | 
			
		||||
			Times(1),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	var metadata middleware.Metadata
 | 
			
		||||
	metadata.Properties = map[string]string{
 | 
			
		||||
		"clientID":     "testId",
 | 
			
		||||
		"clientSecret": "testSecret",
 | 
			
		||||
		"scopes":       "ascope",
 | 
			
		||||
		"tokenURL":     "https://localhost:9999",
 | 
			
		||||
		"headerName":   "authorization",
 | 
			
		||||
		"authStyle":    "1",
 | 
			
		||||
		"pathFilter":   "/api/v1/users/.*",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log := logger.NewLogger("oauth2clientcredentials.test")
 | 
			
		||||
	oauth2clientcredentialsMiddleware, ok := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	require.True(b, ok)
 | 
			
		||||
	oauth2clientcredentialsMiddleware.SetTokenProvider(mockTokenProvider)
 | 
			
		||||
	handler, err := oauth2clientcredentialsMiddleware.GetHandler(b.Context(), metadata)
 | 
			
		||||
	require.NoError(b, err)
 | 
			
		||||
 | 
			
		||||
	for i := range b.N {
 | 
			
		||||
		url := fmt.Sprintf("http://dapr.io/api/v1/users/%d", i)
 | 
			
		||||
		r := httptest.NewRequest(http.MethodGet, url, nil)
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
		handler(http.HandlerFunc(mockedRequestHandler)).ServeHTTP(w, r)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ import (
 | 
			
		|||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	oauth2 "golang.org/x/oauth2"
 | 
			
		||||
 | 
			
		||||
	"github.com/dapr/components-contrib/metadata"
 | 
			
		||||
	"github.com/dapr/components-contrib/middleware"
 | 
			
		||||
	mock "github.com/dapr/components-contrib/middleware/http/oauth2clientcredentials/mocks"
 | 
			
		||||
	"github.com/dapr/kit/logger"
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +108,8 @@ func TestOAuth2ClientCredentialsToken(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Initialize middleware component and inject mocked TokenProvider
 | 
			
		||||
	log := logger.NewLogger("oauth2clientcredentials.test")
 | 
			
		||||
	oauth2clientcredentialsMiddleware, _ := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	oauth2clientcredentialsMiddleware, ok := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	require.True(t, ok)
 | 
			
		||||
	oauth2clientcredentialsMiddleware.SetTokenProvider(mockTokenProvider)
 | 
			
		||||
	handler, err := oauth2clientcredentialsMiddleware.GetHandler(t.Context(), metadata)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +169,8 @@ func TestOAuth2ClientCredentialsCache(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Initialize middleware component and inject mocked TokenProvider
 | 
			
		||||
	log := logger.NewLogger("oauth2clientcredentials.test")
 | 
			
		||||
	oauth2clientcredentialsMiddleware, _ := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	oauth2clientcredentialsMiddleware, ok := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	require.True(t, ok)
 | 
			
		||||
	oauth2clientcredentialsMiddleware.SetTokenProvider(mockTokenProvider)
 | 
			
		||||
	handler, err := oauth2clientcredentialsMiddleware.GetHandler(t.Context(), metadata)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
| 
						 | 
				
			
			@ -199,3 +202,103 @@ func TestOAuth2ClientCredentialsCache(t *testing.T) {
 | 
			
		|||
	// Assertion
 | 
			
		||||
	assert.Equal(t, "MAC def", r.Header.Get("someHeader"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOAuth2ClientCredentialsPathFilterGetNativeMetadata(t *testing.T) {
 | 
			
		||||
	log := logger.NewLogger("oauth2clientcredentials.test")
 | 
			
		||||
	m, ok := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	require.True(t, ok)
 | 
			
		||||
 | 
			
		||||
	baseMiddlewareMetadata := middleware.Metadata{
 | 
			
		||||
		Base: metadata.Base{
 | 
			
		||||
			Properties: map[string]string{
 | 
			
		||||
				"clientID":     "testId",
 | 
			
		||||
				"clientSecret": "testSecret",
 | 
			
		||||
				"scopes":       "ascope",
 | 
			
		||||
				"tokenURL":     "https://localhost:9999",
 | 
			
		||||
				"headerName":   "someHeader",
 | 
			
		||||
				"authStyle":    "1",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tc := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		pathFilter string
 | 
			
		||||
		wantErr    bool
 | 
			
		||||
	}{
 | 
			
		||||
		{name: "empty pathFilter", pathFilter: "", wantErr: false},
 | 
			
		||||
		{name: "wildcard pathFilter", pathFilter: ".*", wantErr: false},
 | 
			
		||||
		{name: "api path pathFilter", pathFilter: "/api/v1/users", wantErr: false},
 | 
			
		||||
		{name: "debug endpoint pathFilter", pathFilter: "^/debug/?$", wantErr: false},
 | 
			
		||||
		{name: "user id pathFilter", pathFilter: "^/user/[0-9]+$", wantErr: false},
 | 
			
		||||
		{name: "invalid wildcard pathFilter", pathFilter: "*invalid", wantErr: true},
 | 
			
		||||
		{name: "unclosed parenthesis pathFilter", pathFilter: "invalid(", wantErr: true},
 | 
			
		||||
		{name: "unopened parenthesis pathFilter", pathFilter: "invalid)", wantErr: true},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tc {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			baseMiddlewareMetadata.Properties["pathFilter"] = tt.pathFilter
 | 
			
		||||
			_, err := m.getNativeMetadata(baseMiddlewareMetadata)
 | 
			
		||||
			if tt.wantErr {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestOAuth2ClientCredentialsPathFilterGetHandler(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	mockCtrl := gomock.NewController(t)
 | 
			
		||||
	defer mockCtrl.Finish()
 | 
			
		||||
 | 
			
		||||
	// Mock mockTokenProvider
 | 
			
		||||
	mockTokenProvider := mock.NewMockTokenProviderInterface(mockCtrl)
 | 
			
		||||
 | 
			
		||||
	gomock.InOrder(
 | 
			
		||||
		// First call returning abc and Bearer, expires within 1 second
 | 
			
		||||
		mockTokenProvider.
 | 
			
		||||
			EXPECT().
 | 
			
		||||
			GetToken(gomock.Any()).
 | 
			
		||||
			Return(&oauth2.Token{
 | 
			
		||||
				AccessToken: "abcd",
 | 
			
		||||
				TokenType:   "Bearer",
 | 
			
		||||
				Expiry:      time.Now().In(time.UTC).Add(1 * time.Second),
 | 
			
		||||
			}, nil).
 | 
			
		||||
			Times(1),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	var metadata middleware.Metadata
 | 
			
		||||
	metadata.Properties = map[string]string{
 | 
			
		||||
		"clientID":     "testId",
 | 
			
		||||
		"clientSecret": "testSecret",
 | 
			
		||||
		"scopes":       "ascope",
 | 
			
		||||
		"tokenURL":     "https://localhost:9999",
 | 
			
		||||
		"headerName":   "authorization",
 | 
			
		||||
		"authStyle":    "1",
 | 
			
		||||
		"pathFilter":   "/api/v1/users/.*",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log := logger.NewLogger("oauth2clientcredentials.test")
 | 
			
		||||
	oauth2clientcredentialsMiddleware, ok := NewOAuth2ClientCredentialsMiddleware(log).(*Middleware)
 | 
			
		||||
	require.True(t, ok)
 | 
			
		||||
	oauth2clientcredentialsMiddleware.SetTokenProvider(mockTokenProvider)
 | 
			
		||||
	handler, err := oauth2clientcredentialsMiddleware.GetHandler(t.Context(), metadata)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	// pathFilter should match
 | 
			
		||||
	r := httptest.NewRequest(http.MethodGet, "http://dapr.io/api/v1/users/123", nil)
 | 
			
		||||
	w := httptest.NewRecorder()
 | 
			
		||||
	handler(http.HandlerFunc(mockedRequestHandler)).ServeHTTP(w, r)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, "Bearer abcd", r.Header.Get("authorization"))
 | 
			
		||||
 | 
			
		||||
	// pathFilter should not match
 | 
			
		||||
	r = httptest.NewRequest(http.MethodGet, "http://dapr.io/api/v1/tokens/123", nil)
 | 
			
		||||
	w = httptest.NewRecorder()
 | 
			
		||||
	handler(http.HandlerFunc(mockedRequestHandler)).ServeHTTP(w, r)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, "", r.Header.Get("authorization"))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ require (
 | 
			
		|||
	github.com/cloudwego/kitex v0.5.0
 | 
			
		||||
	github.com/cloudwego/kitex-examples v0.1.1
 | 
			
		||||
	github.com/dapr/components-contrib v1.15.2
 | 
			
		||||
	github.com/dapr/dapr v1.15.4-0.20250522161419-bbf2e482dc39
 | 
			
		||||
	github.com/dapr/dapr v1.16.0-rc.1.0.20250723233324-b5569ff8862e
 | 
			
		||||
	github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5
 | 
			
		||||
	github.com/eclipse/paho.mqtt.golang v1.4.3
 | 
			
		||||
| 
						 | 
				
			
			@ -150,6 +150,7 @@ require (
 | 
			
		|||
	github.com/felixge/httpsnoop v1.0.4 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.9.0 // indirect
 | 
			
		||||
	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
 | 
			
		||||
	github.com/gage-technologies/mistral-go v1.1.0 // indirect
 | 
			
		||||
	github.com/go-chi/cors v1.2.1 // indirect
 | 
			
		||||
	github.com/go-ini/ini v1.67.0 // indirect
 | 
			
		||||
	github.com/go-jose/go-jose/v4 v4.0.5 // indirect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -434,8 +434,8 @@ github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53E
 | 
			
		|||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
 | 
			
		||||
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
 | 
			
		||||
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
 | 
			
		||||
github.com/dapr/dapr v1.15.4-0.20250522161419-bbf2e482dc39 h1:QHNFYrWjgFHmoyqcvlhOLNfmnblYplL1Fw0wHinPFHQ=
 | 
			
		||||
github.com/dapr/dapr v1.15.4-0.20250522161419-bbf2e482dc39/go.mod h1:9tlP+FA6WHcDPZMvuwKZQGaL/18yL8lZ9lgyU3G9LvA=
 | 
			
		||||
github.com/dapr/dapr v1.16.0-rc.1.0.20250723233324-b5569ff8862e h1:PQjnQkSuU7OtiFmmqIRUxvpb14A9va4ZbGh7oXgStbY=
 | 
			
		||||
github.com/dapr/dapr v1.16.0-rc.1.0.20250723233324-b5569ff8862e/go.mod h1:3R5TgtcMOyNx2/kzam2YwgbYpFAj+uPGufRYCTczGnk=
 | 
			
		||||
github.com/dapr/durabletask-go v0.7.3-0.20250711135247-7a35af6fe0e5 h1:l8oBGwcfCwqvSYDZwla0A2fhENmXFc1Wk4lR0VEq+is=
 | 
			
		||||
github.com/dapr/durabletask-go v0.7.3-0.20250711135247-7a35af6fe0e5/go.mod h1:0Ts4rXp74JyG19gDWPcwNo5V6NBZzhARzHF5XynmA7Q=
 | 
			
		||||
github.com/dapr/go-sdk v1.10.0-rc-1.0.20240507160435-33180dd89a46 h1:0/WKEqAfTGnFAiFrqMpIEBMkCHaAqt5H9efU0hyKiG4=
 | 
			
		||||
| 
						 | 
				
			
			@ -551,6 +551,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
 | 
			
		|||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 | 
			
		||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
 | 
			
		||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
 | 
			
		||||
github.com/gage-technologies/mistral-go v1.1.0 h1:POv1wM9jA/9OBXGV2YdPi9Y/h09+MjCbUF+9hRYlVUI=
 | 
			
		||||
github.com/gage-technologies/mistral-go v1.1.0/go.mod h1:tF++Xt7U975GcLlzhrjSQb8l/x+PrriO9QEdsgm9l28=
 | 
			
		||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
 | 
			
		||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 | 
			
		||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ go 1.24.4
 | 
			
		|||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/dapr/components-contrib v1.10.6-0.20230403162214-9ee9d56cb7ea
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763
 | 
			
		||||
	github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.14.0 h1:dEopBSOSjB5f
 | 
			
		|||
github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.14.0/go.mod h1:qDSbb0fgIfFNjZrNTPtS5MOMScAGyQtn1KlSvoOdqYw=
 | 
			
		||||
github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc=
 | 
			
		||||
github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6tjmaQBSvxcv4uE=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763 h1:9H0+baON+6+x4A/nQ2Lj+1JNk8MSlNv6sik6zfxdvsE=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250710140356-9d4f384c5763/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5 h1:Q26gmPxs6WnnBYoudOlznPHsmrbTawcYEpHg4VoB7v8=
 | 
			
		||||
github.com/dapr/kit v0.15.3-0.20250717140748-8b780b4d81c5/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue