mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Fix API POST endpoints json parsing error-handling (#134326)
* Fix API POST endpoints json parsing error-handling * Add tests * Fix mypy and ruff errors * Fix coverage by removing non-needed error handling * Correct error handling and improve tests --------- Co-authored-by: Robert Resch <robert@resch.dev> Co-authored-by: Erik <erik@montnemery.com>
This commit is contained in:
parent
809aced9cc
commit
e210681751
@ -260,11 +260,18 @@ class APIEntityStateView(HomeAssistantView):
|
||||
if not user.is_admin:
|
||||
raise Unauthorized(entity_id=entity_id)
|
||||
hass = request.app[KEY_HASS]
|
||||
|
||||
body = await request.text()
|
||||
|
||||
try:
|
||||
data = await request.json()
|
||||
data: Any = json_loads(body) if body else None
|
||||
except ValueError:
|
||||
return self.json_message("Invalid JSON specified.", HTTPStatus.BAD_REQUEST)
|
||||
|
||||
if not isinstance(data, dict):
|
||||
return self.json_message(
|
||||
"State data should be a JSON object.", HTTPStatus.BAD_REQUEST
|
||||
)
|
||||
if (new_state := data.get("state")) is None:
|
||||
return self.json_message("No state specified.", HTTPStatus.BAD_REQUEST)
|
||||
|
||||
@ -477,9 +484,19 @@ class APITemplateView(HomeAssistantView):
|
||||
@require_admin
|
||||
async def post(self, request: web.Request) -> web.Response:
|
||||
"""Render a template."""
|
||||
body = await request.text()
|
||||
|
||||
try:
|
||||
data: Any = json_loads(body) if body else None
|
||||
except ValueError:
|
||||
return self.json_message("Invalid JSON specified.", HTTPStatus.BAD_REQUEST)
|
||||
|
||||
if not isinstance(data, dict):
|
||||
return self.json_message(
|
||||
"Template data should be a JSON object.", HTTPStatus.BAD_REQUEST
|
||||
)
|
||||
tpl = _cached_template(data["template"], request.app[KEY_HASS])
|
||||
try:
|
||||
data = await request.json()
|
||||
tpl = _cached_template(data["template"], request.app[KEY_HASS])
|
||||
return tpl.async_render(variables=data.get("variables"), parse_result=False) # type: ignore[no-any-return]
|
||||
except (ValueError, TemplateError) as ex:
|
||||
return self.json_message(
|
||||
|
@ -129,6 +129,28 @@ async def test_api_state_change_with_bad_data(
|
||||
assert resp.status == HTTPStatus.BAD_REQUEST
|
||||
|
||||
|
||||
async def test_api_state_change_with_invalid_json(
|
||||
hass: HomeAssistant, mock_api_client: TestClient
|
||||
) -> None:
|
||||
"""Test if API sends appropriate error if send invalid json data."""
|
||||
resp = await mock_api_client.post("/api/states/test.test", data="{,}")
|
||||
|
||||
assert resp.status == HTTPStatus.BAD_REQUEST
|
||||
assert await resp.json() == {"message": "Invalid JSON specified."}
|
||||
|
||||
|
||||
async def test_api_state_change_with_string_body(
|
||||
hass: HomeAssistant, mock_api_client: TestClient
|
||||
) -> None:
|
||||
"""Test if API sends appropriate error if we send a string instead of a JSON object."""
|
||||
resp = await mock_api_client.post(
|
||||
"/api/states/bad.entity.id", json='"{"state": "new_state"}"'
|
||||
)
|
||||
|
||||
assert resp.status == HTTPStatus.BAD_REQUEST
|
||||
assert await resp.json() == {"message": "State data should be a JSON object."}
|
||||
|
||||
|
||||
async def test_api_state_change_to_zero_value(
|
||||
hass: HomeAssistant, mock_api_client: TestClient
|
||||
) -> None:
|
||||
@ -529,6 +551,31 @@ async def test_api_template_error(
|
||||
assert resp.status == HTTPStatus.BAD_REQUEST
|
||||
|
||||
|
||||
async def test_api_template_with_invalid_json(
|
||||
hass: HomeAssistant, mock_api_client: TestClient
|
||||
) -> None:
|
||||
"""Test if API sends appropriate error if send invalid json data."""
|
||||
resp = await mock_api_client.post(const.URL_API_TEMPLATE, data="{,}")
|
||||
|
||||
assert resp.status == HTTPStatus.BAD_REQUEST
|
||||
assert await resp.json() == {"message": "Invalid JSON specified."}
|
||||
|
||||
|
||||
async def test_api_template_error_with_string_body(
|
||||
hass: HomeAssistant, mock_api_client: TestClient
|
||||
) -> None:
|
||||
"""Test that the API returns an appropriate error when a string is sent in the body."""
|
||||
hass.states.async_set("sensor.temperature", 10)
|
||||
|
||||
resp = await mock_api_client.post(
|
||||
const.URL_API_TEMPLATE,
|
||||
json='"{"template": "{{ states.sensor.temperature.state"}"',
|
||||
)
|
||||
|
||||
assert resp.status == HTTPStatus.BAD_REQUEST
|
||||
assert await resp.json() == {"message": "Template data should be a JSON object."}
|
||||
|
||||
|
||||
async def test_stream(hass: HomeAssistant, mock_api_client: TestClient) -> None:
|
||||
"""Test the stream."""
|
||||
listen_count = _listen_count(hass)
|
||||
|
Loading…
x
Reference in New Issue
Block a user