Skip to content

Commit 27a97b0

Browse files
authored
fix: SSEResponse duplicate CORS headers issue (#1287)
* fix: SSEResponse duplicate CORS headers issue * update * fix tests * update * update
1 parent 35fbeb7 commit 27a97b0

3 files changed

Lines changed: 5 additions & 25 deletions

File tree

integration_tests/test_sse.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def test_sse_basic_headers(session):
1717
# Accept either clean optimized headers or legacy compatibility
1818
cache_control = response.headers.get("Cache-Control")
1919
assert cache_control in ["no-cache, no-store, must-revalidate", "no-cache, no-cache, no-store, must-revalidate"]
20-
assert "Access-Control-Allow-Origin" in response.headers
2120

2221

2322
@pytest.mark.benchmark
@@ -196,13 +195,17 @@ def test_sse_empty_stream(session):
196195

197196
@pytest.mark.benchmark
198197
def test_sse_custom_headers(session):
199-
"""Test SSE endpoint with custom headers"""
198+
"""Test SSE endpoint with custom headers; SSE responses should not include default CORS headers for cross-origin EventSource support"""
200199
response = requests.get(f"{BASE_URL}/sse/with_headers", stream=True)
201200

202201
assert response.status_code == 200
203202
assert response.headers.get("X-Custom-Header") == "custom-value"
204203
assert response.headers.get("Content-Type") == "text/event-stream"
205204

205+
# SSE responses should not include default CORS headers
206+
assert response.headers.get("Access-Control-Allow-Origin") is None
207+
assert response.headers.get("Access-Control-Allow-Headers") is None
208+
206209

207210
@pytest.mark.benchmark
208211
def test_sse_custom_status_code(session):
@@ -409,7 +412,6 @@ def test_sse_optimization_headers(session):
409412
assert response.headers.get("Pragma") == "no-cache"
410413
assert response.headers.get("Expires") == "0"
411414
assert response.headers.get("X-Accel-Buffering") == "no" # Nginx buffering disabled
412-
assert response.headers.get("Access-Control-Allow-Origin") == "*"
413415
# Connection header might be managed by underlying HTTP infrastructure
414416
connection = response.headers.get("Connection")
415417
assert connection is None or connection == "keep-alive"

robyn/responses.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,6 @@ def __init__(
146146
if media_type == "text/event-stream":
147147
self.headers.set("Content-Type", "text/event-stream")
148148
# Cache-Control and Connection headers are set by Rust layer with optimized headers
149-
self.headers.set("Access-Control-Allow-Origin", "*")
150-
self.headers.set("Access-Control-Allow-Headers", "Cache-Control")
151149

152150

153151
def SSEResponse(

src/types/response.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,6 @@ impl PyStreamingResponse {
315315
headers.set("Content-Type".to_string(), "text/event-stream".to_string());
316316
headers.set("Cache-Control".to_string(), "no-cache".to_string());
317317
headers.set("Connection".to_string(), "keep-alive".to_string());
318-
headers.set("Access-Control-Allow-Origin".to_string(), "*".to_string());
319-
headers.set(
320-
"Access-Control-Allow-Headers".to_string(),
321-
"Cache-Control".to_string(),
322-
);
323318
} else {
324319
// For non-SSE streaming responses, still set appropriate headers
325320
headers.set("Content-Type".to_string(), media_type.clone());
@@ -564,21 +559,6 @@ impl FromPyObject<'_, '_> for StreamingResponse {
564559
if headers.get("Connection".to_string()).is_none() {
565560
headers.set("Connection".to_string(), "keep-alive".to_string());
566561
}
567-
if headers
568-
.get("Access-Control-Allow-Origin".to_string())
569-
.is_none()
570-
{
571-
headers.set("Access-Control-Allow-Origin".to_string(), "*".to_string());
572-
}
573-
if headers
574-
.get("Access-Control-Allow-Headers".to_string())
575-
.is_none()
576-
{
577-
headers.set(
578-
"Access-Control-Allow-Headers".to_string(),
579-
"Cache-Control".to_string(),
580-
);
581-
}
582562
}
583563

584564
let content: pyo3::Py<PyAny> = match obj.getattr("content") {

0 commit comments

Comments
 (0)