|
1 | 1 | import logging |
2 | 2 | from typing import Any, Dict, cast |
3 | 3 |
|
| 4 | +import httpx |
4 | 5 | import pytest |
| 6 | +from respx import MockRouter |
5 | 7 |
|
| 8 | +from openai import OpenAI |
6 | 9 | from openai._utils import SensitiveHeadersFilter, redact_sensitive_headers |
7 | 10 |
|
8 | 11 |
|
@@ -113,3 +116,29 @@ def test_response_headers_redaction() -> None: |
113 | 116 | assert filtered["authorization"] == "<redacted>" |
114 | 117 | assert filtered["api-key"] == "<redacted>" |
115 | 118 | assert filtered["x-request-id"] == "req_abc123" |
| 119 | + |
| 120 | + |
| 121 | +@pytest.mark.respx(base_url="https://api.openai.com/v1") |
| 122 | +def test_response_header_redaction_in_client( |
| 123 | + respx_mock: MockRouter, |
| 124 | + caplog: pytest.LogCaptureFixture, |
| 125 | +) -> None: |
| 126 | + """Integration test: verify _base_client.py redacts sensitive response headers in actual log output.""" |
| 127 | + respx_mock.post("/chat/completions").mock( |
| 128 | + return_value=httpx.Response( |
| 129 | + 200, |
| 130 | + json={"id": "chatcmpl-test", "object": "chat.completion", "choices": [], "created": 0, "model": "gpt-4"}, |
| 131 | + headers={"authorization": "Bearer secret", "x-request-id": "req_123"}, |
| 132 | + ) |
| 133 | + ) |
| 134 | + |
| 135 | + client = OpenAI(api_key="test-key", base_url="https://api.openai.com/v1") |
| 136 | + |
| 137 | + with caplog.at_level(logging.DEBUG, logger="openai"): |
| 138 | + client.chat.completions.create(messages=[], model="gpt-4") |
| 139 | + |
| 140 | + response_logs = [r for r in caplog.records if r.getMessage().startswith("HTTP Response:")] |
| 141 | + assert len(response_logs) >= 1, "Expected at least one 'HTTP Response:' log line" |
| 142 | + msg = response_logs[0].getMessage() |
| 143 | + assert "secret" not in msg, "Sensitive header value should be redacted in log output" |
| 144 | + assert "<redacted>" in msg, "Redacted placeholder should appear in log output" |
0 commit comments