Hass.io: logo support / timeout handling (#8668)
* Disable auth on logo / no timeout for addons update/install * fix tests
This commit is contained in:
parent
9e6817b6d0
commit
51108b8fe9
2 changed files with 51 additions and 6 deletions
|
@ -25,8 +25,15 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
DOMAIN = 'hassio'
|
DOMAIN = 'hassio'
|
||||||
DEPENDENCIES = ['http']
|
DEPENDENCIES = ['http']
|
||||||
|
|
||||||
TIMEOUT = 10
|
NO_TIMEOUT = {
|
||||||
NO_TIMEOUT = set(['homeassistant/update', 'host/update', 'supervisor/update'])
|
re.compile(r'^homeassistant/update$'), re.compile(r'^host/update$'),
|
||||||
|
re.compile(r'^supervisor/update$'), re.compile(r'^addons/[^/]*/update$'),
|
||||||
|
re.compile(r'^addons/[^/]*/install$')
|
||||||
|
}
|
||||||
|
|
||||||
|
NO_AUTH = {
|
||||||
|
re.compile(r'^panel$'), re.compile(r'^addons/[^/]*/logo$')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
@ -71,7 +78,7 @@ class HassIO(object):
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(TIMEOUT, loop=self.loop):
|
with async_timeout.timeout(10, loop=self.loop):
|
||||||
request = yield from self.websession.get(
|
request = yield from self.websession.get(
|
||||||
"http://{}{}".format(self._ip, "/supervisor/ping")
|
"http://{}{}".format(self._ip, "/supervisor/ping")
|
||||||
)
|
)
|
||||||
|
@ -97,12 +104,12 @@ class HassIO(object):
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
read_timeout = 0 if path in NO_TIMEOUT else 300
|
read_timeout = _get_timeout(path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = None
|
data = None
|
||||||
headers = None
|
headers = None
|
||||||
with async_timeout.timeout(TIMEOUT, loop=self.loop):
|
with async_timeout.timeout(10, loop=self.loop):
|
||||||
data = yield from request.read()
|
data = yield from request.read()
|
||||||
if data:
|
if data:
|
||||||
headers = {CONTENT_TYPE: request.content_type}
|
headers = {CONTENT_TYPE: request.content_type}
|
||||||
|
@ -140,7 +147,7 @@ class HassIOView(HomeAssistantView):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _handle(self, request, path):
|
def _handle(self, request, path):
|
||||||
"""Route data to hassio."""
|
"""Route data to hassio."""
|
||||||
if path != 'panel' and not request[KEY_AUTHENTICATED]:
|
if _need_auth(path) and not request[KEY_AUTHENTICATED]:
|
||||||
return web.Response(status=401)
|
return web.Response(status=401)
|
||||||
|
|
||||||
client = yield from self.hassio.command_proxy(path, request)
|
client = yield from self.hassio.command_proxy(path, request)
|
||||||
|
@ -173,3 +180,19 @@ def _create_response_log(client, data):
|
||||||
status=client.status,
|
status=client.status,
|
||||||
content_type=CONTENT_TYPE_TEXT_PLAIN,
|
content_type=CONTENT_TYPE_TEXT_PLAIN,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_timeout(path):
|
||||||
|
"""Return timeout for a url path."""
|
||||||
|
for re_path in NO_TIMEOUT:
|
||||||
|
if re_path.match(path):
|
||||||
|
return 0
|
||||||
|
return 300
|
||||||
|
|
||||||
|
|
||||||
|
def _need_auth(path):
|
||||||
|
"""Return if a path need a auth."""
|
||||||
|
for re_path in NO_AUTH:
|
||||||
|
if re_path.match(path):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
|
@ -106,6 +106,28 @@ def test_forward_request_no_auth_for_panel(hassio_client):
|
||||||
assert mresp.mock_calls[0][1] == (response, 'data')
|
assert mresp.mock_calls[0][1] == (response, 'data')
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_forward_request_no_auth_for_logo(hassio_client):
|
||||||
|
"""Test no auth needed for ."""
|
||||||
|
response = MagicMock()
|
||||||
|
response.read.return_value = mock_coro('data')
|
||||||
|
|
||||||
|
with patch('homeassistant.components.hassio.HassIO.command_proxy',
|
||||||
|
Mock(return_value=mock_coro(response))), \
|
||||||
|
patch('homeassistant.components.hassio._create_response') as mresp:
|
||||||
|
mresp.return_value = 'response'
|
||||||
|
resp = yield from hassio_client.get('/api/hassio/addons/bl_b392/logo')
|
||||||
|
|
||||||
|
# Check we got right response
|
||||||
|
assert resp.status == 200
|
||||||
|
body = yield from resp.text()
|
||||||
|
assert body == 'response'
|
||||||
|
|
||||||
|
# Check we forwarded command
|
||||||
|
assert len(mresp.mock_calls) == 1
|
||||||
|
assert mresp.mock_calls[0][1] == (response, 'data')
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_forward_log_request(hassio_client):
|
def test_forward_log_request(hassio_client):
|
||||||
"""Test fetching normal log path."""
|
"""Test fetching normal log path."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue