mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Fix generic camera error when template renders to an invalid URL (#109737)
This commit is contained in:
parent
45f44e9216
commit
94ccd59123
@ -8,6 +8,7 @@ import logging
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
import voluptuous as vol
|
||||||
import yarl
|
import yarl
|
||||||
|
|
||||||
from homeassistant.components.camera import Camera, CameraEntityFeature
|
from homeassistant.components.camera import Camera, CameraEntityFeature
|
||||||
@ -140,6 +141,12 @@ class GenericCamera(Camera):
|
|||||||
_LOGGER.error("Error parsing template %s: %s", self._still_image_url, err)
|
_LOGGER.error("Error parsing template %s: %s", self._still_image_url, err)
|
||||||
return self._last_image
|
return self._last_image
|
||||||
|
|
||||||
|
try:
|
||||||
|
vol.Schema(vol.Url())(url)
|
||||||
|
except vol.Invalid as err:
|
||||||
|
_LOGGER.warning("Invalid URL '%s': %s, returning last image", url, err)
|
||||||
|
return self._last_image
|
||||||
|
|
||||||
if url == self._last_url and self._limit_refetch:
|
if url == self._last_url and self._limit_refetch:
|
||||||
return self._last_image
|
return self._last_image
|
||||||
|
|
||||||
|
@ -70,15 +70,20 @@ async def help_setup_mock_config_entry(
|
|||||||
|
|
||||||
@respx.mock
|
@respx.mock
|
||||||
async def test_fetching_url(
|
async def test_fetching_url(
|
||||||
hass: HomeAssistant, hass_client: ClientSessionGenerator, fakeimgbytes_png
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
fakeimgbytes_png,
|
||||||
|
caplog: pytest.CaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that it fetches the given url."""
|
"""Test that it fetches the given url."""
|
||||||
respx.get("http://example.com").respond(stream=fakeimgbytes_png)
|
hass.states.async_set("sensor.temp", "http://example.com/0a")
|
||||||
|
respx.get("http://example.com/0a").respond(stream=fakeimgbytes_png)
|
||||||
|
respx.get("http://example.com/1a").respond(stream=fakeimgbytes_png)
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
"name": "config_test",
|
"name": "config_test",
|
||||||
"platform": "generic",
|
"platform": "generic",
|
||||||
"still_image_url": "http://example.com",
|
"still_image_url": "{{ states.sensor.temp.state }}",
|
||||||
"username": "user",
|
"username": "user",
|
||||||
"password": "pass",
|
"password": "pass",
|
||||||
"authentication": "basic",
|
"authentication": "basic",
|
||||||
@ -101,6 +106,25 @@ async def test_fetching_url(
|
|||||||
resp = await client.get("/api/camera_proxy/camera.config_test")
|
resp = await client.get("/api/camera_proxy/camera.config_test")
|
||||||
assert respx.calls.call_count == 2
|
assert respx.calls.call_count == 2
|
||||||
|
|
||||||
|
# If the template renders to an invalid URL we return the last image from cache
|
||||||
|
hass.states.async_set("sensor.temp", "invalid url")
|
||||||
|
|
||||||
|
# sleep another .1 seconds to make cached image expire
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
resp = await client.get("/api/camera_proxy/camera.config_test")
|
||||||
|
assert resp.status == HTTPStatus.OK
|
||||||
|
assert respx.calls.call_count == 2
|
||||||
|
assert (
|
||||||
|
"Invalid URL 'invalid url': expected a URL, returning last image" in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
# Restore a valid URL
|
||||||
|
hass.states.async_set("sensor.temp", "http://example.com/1a")
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
resp = await client.get("/api/camera_proxy/camera.config_test")
|
||||||
|
assert resp.status == HTTPStatus.OK
|
||||||
|
assert respx.calls.call_count == 3
|
||||||
|
|
||||||
|
|
||||||
@respx.mock
|
@respx.mock
|
||||||
async def test_image_caching(
|
async def test_image_caching(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user