@@ -190,3 +190,91 @@ func getHttpResponseCodeCount(statusCode string) float64 {
190190 return 0
191191}
192192
193+ func TestHeaderForwarding (t * testing.T ) {
194+ tests := []struct {
195+ name string
196+ path string
197+ query string
198+ expectedHeaders map [string ]string
199+ }{
200+ {
201+ name : "fast path forwarded as header" ,
202+ path : "/fast" ,
203+ query : "" ,
204+ expectedHeaders : map [string ]string {
205+ "X-Original-Path" : "/fast" ,
206+ },
207+ },
208+ {
209+ name : "fast path with query forwarded as headers" ,
210+ path : "/fast" ,
211+ query : "hint=calldata&builder=flashbots" ,
212+ expectedHeaders : map [string ]string {
213+ "X-Original-Path" : "/fast" ,
214+ "X-Original-Query" : "hint=calldata&builder=flashbots" ,
215+ },
216+ },
217+ {
218+ name : "root path with query forwarded as headers" ,
219+ path : "/" ,
220+ query : "builder=rsync" ,
221+ expectedHeaders : map [string ]string {
222+ "X-Original-Query" : "builder=rsync" ,
223+ },
224+ },
225+ {
226+ name : "query only forwarded as header" ,
227+ path : "" ,
228+ query : "hint=hash" ,
229+ expectedHeaders : map [string ]string {
230+ "X-Original-Query" : "hint=hash" ,
231+ },
232+ },
233+ {
234+ name : "no path or query means no headers" ,
235+ path : "" ,
236+ query : "" ,
237+ expectedHeaders : map [string ]string {},
238+ },
239+ }
240+
241+ for _ , tt := range tests {
242+ t .Run (tt .name , func (t * testing.T ) {
243+ // Create context with path and query
244+ ctx := context .Background ()
245+ if tt .path != "" && tt .path != "/" {
246+ ctx = context .WithValue (ctx , ContextKeyPath , tt .path )
247+ }
248+ if tt .query != "" {
249+ ctx = context .WithValue (ctx , ContextKeyRawQuery , tt .query )
250+ }
251+
252+ // Create a mock HTTP request to verify headers are set
253+ req , err := http .NewRequestWithContext (ctx , "POST" , "http://backend:8080" , nil )
254+ require .NoError (t , err )
255+
256+ // Simulate the header forwarding logic from doForward()
257+ if path , ok := ctx .Value (ContextKeyPath ).(string ); ok && path != "" && path != "/" {
258+ req .Header .Set ("X-Original-Path" , path )
259+ }
260+ if rawQuery , ok := ctx .Value (ContextKeyRawQuery ).(string ); ok && rawQuery != "" {
261+ req .Header .Set ("X-Original-Query" , rawQuery )
262+ }
263+
264+ // Verify the expected headers are set correctly
265+ for expectedHeader , expectedValue := range tt .expectedHeaders {
266+ actualValue := req .Header .Get (expectedHeader )
267+ assert .Equal (t , expectedValue , actualValue , "Header %s should have value %s" , expectedHeader , expectedValue )
268+ }
269+
270+ // Verify no unexpected headers are set
271+ if _ , exists := tt .expectedHeaders ["X-Original-Path" ]; ! exists {
272+ assert .Empty (t , req .Header .Get ("X-Original-Path" ), "X-Original-Path should not be set" )
273+ }
274+ if _ , exists := tt .expectedHeaders ["X-Original-Query" ]; ! exists {
275+ assert .Empty (t , req .Header .Get ("X-Original-Query" ), "X-Original-Query should not be set" )
276+ }
277+ })
278+ }
279+ }
280+
0 commit comments