Merge pull request #9 from abhishekbhakat/8-remove-content-type-header-for-zero-body-requests

8 remove content type header for zero body requests
This commit is contained in:
2025-02-23 16:09:18 +00:00
committed by GitHub
3 changed files with 27 additions and 6174 deletions

View File

@@ -98,7 +98,6 @@ class AirflowClient:
self.base_url = base_url.rstrip("/") self.base_url = base_url.rstrip("/")
self.headers = { self.headers = {
"Authorization": f"Basic {auth_token}", "Authorization": f"Basic {auth_token}",
"Content-Type": "application/json",
"Accept": "application/json", "Accept": "application/json",
} }
@@ -211,6 +210,10 @@ class AirflowClient:
logger.debug("Request body: %s", body) logger.debug("Request body: %s", body)
logger.debug("Request query params: %s", query_params) logger.debug("Request query params: %s", query_params)
# Dynamically set headers based on presence of body
request_headers = self.headers.copy()
if body is not None:
request_headers["Content-Type"] = "application/json"
# Make request # Make request
async with self._session.request( async with self._session.request(
method=method, method=method,
@@ -219,8 +222,23 @@ class AirflowClient:
json=body, json=body,
) as response: ) as response:
response.raise_for_status() response.raise_for_status()
logger.debug("Response: %s", await response.text()) content_type = response.headers.get("Content-Type", "").lower()
return await response.json() # Status codes that typically have no body
no_body_statuses = {204}
if response.status in no_body_statuses:
if content_type and "application/json" in content_type:
logger.warning("Unexpected JSON body with status %s", response.status)
return await response.json() # Parse if present, though rare
logger.debug("Received %s response with no body", response.status)
return response.status
# For statuses expecting a body, check mimetype
if "application/json" in content_type:
logger.debug("Response: %s", await response.text())
return await response.json()
# Unexpected mimetype with body
response_text = await response.text()
logger.error("Unexpected mimetype %s for status %s: %s", content_type, response.status, response_text)
raise ValueError(f"Cannot parse response with mimetype {content_type} as JSON")
except aiohttp.ClientError as e: except aiohttp.ClientError as e:
logger.error("Error executing operation %s: %s", operation_id, e) logger.error("Error executing operation %s: %s", operation_id, e)

View File

@@ -18,15 +18,11 @@ def create_valid_spec(paths: dict[str, Any] | None = None) -> dict[str, Any]:
@pytest.fixture @pytest.fixture
def spec_file() -> dict[str, Any]: def client() -> AirflowClient:
with resources.files("tests.client").joinpath("v1.yaml").open("r") as f: with resources.files("airflow_mcp_server.resources").joinpath("v1.yaml").open("rb") as f:
return yaml.safe_load(f) spec = yaml.safe_load(f)
@pytest.fixture
def client(spec_file: dict[str, Any]) -> AirflowClient:
return AirflowClient( return AirflowClient(
spec_path=spec_file, spec_path=spec,
base_url="http://localhost:8080/api/v1", base_url="http://localhost:8080/api/v1",
auth_token="test-token", auth_token="test-token",
) )
@@ -84,9 +80,9 @@ def test_ops_case_sensitive_operation(client: AirflowClient) -> None:
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_exec_without_context(spec_file: dict[str, Any]) -> None: async def test_exec_without_context() -> None:
client = AirflowClient( client = AirflowClient(
spec_path=spec_file, spec_path=create_valid_spec(),
base_url="http://test", base_url="http://test",
auth_token="test", auth_token="test",
) )

File diff suppressed because it is too large Load Diff