2020
2121
2222class _FakeStreamingResponse :
23- def __init__ (self , status_code : int = 200 , headers : dict | None = None , chunks : list [bytes ] | None = None ):
23+ def __init__ (
24+ self , status_code : int = 200 , headers : dict | None = None , chunks : list [bytes ] | None = None
25+ ):
2426 self .status_code = status_code
25- self .headers = headers or {}
27+ self .headers = httpx . Headers ( headers or {})
2628 self ._chunks = chunks or []
2729
2830 async def aiter_bytes (self ):
@@ -81,8 +83,10 @@ def get_endpoint(sandbox_id: str, port: int, resolve_internal: bool = False) ->
8183 ** auth_headers ,
8284 "Authorization" : "Bearer top-secret" ,
8385 "Cookie" : "sid=secret" ,
84- "Connection" : "keep-alive" ,
86+ "Connection" : "keep-alive, X-Hop-Temp " ,
8587 "Upgrade" : "h2c" ,
88+ "Trailer" : "X-Checksum" ,
89+ "X-Hop-Temp" : "drop-me" ,
8690 "X-Trace" : "trace-1" ,
8791 }
8892
@@ -105,11 +109,54 @@ def get_endpoint(sandbox_id: str, port: int, resolve_internal: bool = False) ->
105109 assert "host" not in lowered_headers
106110 assert "connection" not in lowered_headers
107111 assert "upgrade" not in lowered_headers
112+ assert "trailer" not in lowered_headers
108113 assert "authorization" not in lowered_headers
109114 assert "cookie" not in lowered_headers
115+ assert "x-hop-temp" not in lowered_headers
110116 assert lowered_headers .get ("x-trace" ) == "trace-1"
111117
112118
119+ def test_proxy_filters_response_hop_by_hop_headers (
120+ client : TestClient ,
121+ auth_headers : dict ,
122+ monkeypatch ,
123+ ) -> None :
124+ class StubService :
125+ @staticmethod
126+ def get_endpoint (sandbox_id : str , port : int , resolve_internal : bool = False ) -> Endpoint :
127+ assert resolve_internal is True
128+ return Endpoint (endpoint = "10.57.1.91:40109" )
129+
130+ monkeypatch .setattr (lifecycle , "sandbox_service" , StubService ())
131+
132+ fake_client = _FakeAsyncClient ()
133+ fake_client .response = _FakeStreamingResponse (
134+ status_code = 200 ,
135+ headers = {
136+ "x-backend" : "yes" ,
137+ "Connection" : "keep-alive, X-Hop-Temp" ,
138+ "Keep-Alive" : "timeout=5" ,
139+ "Trailer" : "X-Checksum" ,
140+ "X-Hop-Temp" : "drop-me" ,
141+ },
142+ chunks = [b"proxy-ok" ],
143+ )
144+ client .app .state .http_client = fake_client
145+
146+ response = client .get (
147+ "/v1/sandboxes/sbx-123/proxy/44772/healthz" ,
148+ headers = auth_headers ,
149+ )
150+
151+ assert response .status_code == 200
152+ assert response .content == b"proxy-ok"
153+ assert response .headers .get ("x-backend" ) == "yes"
154+ assert response .headers .get ("connection" ) is None
155+ assert response .headers .get ("keep-alive" ) is None
156+ assert response .headers .get ("trailer" ) is None
157+ assert response .headers .get ("x-hop-temp" ) is None
158+
159+
113160def test_proxy_rejects_websocket_upgrade (
114161 client : TestClient ,
115162 auth_headers : dict ,
0 commit comments