Use resource for index routing. (#24223)
This commit is contained in:
parent
440e4289e4
commit
3a0616c680
2 changed files with 66 additions and 82 deletions
|
@ -4,9 +4,10 @@ import logging
|
|||
import os
|
||||
import pathlib
|
||||
|
||||
from aiohttp import web
|
||||
from aiohttp import web, web_urldispatcher, hdrs
|
||||
import voluptuous as vol
|
||||
import jinja2
|
||||
from yarl import URL
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.components.http.view import HomeAssistantView
|
||||
|
@ -50,7 +51,6 @@ for size in (192, 384, 512, 1024):
|
|||
'type': 'image/png'
|
||||
})
|
||||
|
||||
DATA_FINALIZE_PANEL = 'frontend_finalize_panel'
|
||||
DATA_PANELS = 'frontend_panels'
|
||||
DATA_JS_VERSION = 'frontend_js_version'
|
||||
DATA_EXTRA_HTML_URL = 'frontend_extra_html_url'
|
||||
|
@ -97,28 +97,6 @@ SCHEMA_GET_TRANSLATIONS = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def generate_negative_index_regex():
|
||||
"""Generate regex for index."""
|
||||
skip = [
|
||||
# files
|
||||
"service_worker.js",
|
||||
"robots.txt",
|
||||
"onboarding.html",
|
||||
"manifest.json",
|
||||
]
|
||||
for folder in (
|
||||
"static",
|
||||
"frontend_latest",
|
||||
"frontend_es5",
|
||||
"local",
|
||||
"auth",
|
||||
"api",
|
||||
):
|
||||
# Regex matching static, static/, static/index.html
|
||||
skip.append("{}(/|/.+|)".format(folder))
|
||||
return r"(?!(" + "|".join(skip) + r")).*"
|
||||
|
||||
|
||||
class Panel:
|
||||
"""Abstract class for panels."""
|
||||
|
||||
|
@ -256,7 +234,7 @@ async def async_setup(hass, config):
|
|||
if os.path.isdir(local):
|
||||
hass.http.register_static_path("/local", local, not is_dev)
|
||||
|
||||
hass.http.register_view(IndexView(repo_path))
|
||||
hass.http.app.router.register_resource(IndexView(repo_path, hass))
|
||||
|
||||
for panel in ('kiosk', 'states', 'profile'):
|
||||
async_register_built_in_panel(hass, panel)
|
||||
|
@ -327,21 +305,64 @@ def _async_setup_themes(hass, themes):
|
|||
hass.services.async_register(DOMAIN, SERVICE_RELOAD_THEMES, reload_themes)
|
||||
|
||||
|
||||
class IndexView(HomeAssistantView):
|
||||
class IndexView(web_urldispatcher.AbstractResource):
|
||||
"""Serve the frontend."""
|
||||
|
||||
url = '/'
|
||||
name = 'frontend:index'
|
||||
requires_auth = False
|
||||
extra_urls = [
|
||||
"/{extra:%s}" % generate_negative_index_regex()
|
||||
]
|
||||
|
||||
def __init__(self, repo_path):
|
||||
def __init__(self, repo_path, hass):
|
||||
"""Initialize the frontend view."""
|
||||
super().__init__(name="frontend:index")
|
||||
self.repo_path = repo_path
|
||||
self.hass = hass
|
||||
self._template_cache = None
|
||||
|
||||
@property
|
||||
def canonical(self) -> str:
|
||||
"""Return resource's canonical path."""
|
||||
return '/'
|
||||
|
||||
@property
|
||||
def _route(self):
|
||||
"""Return the index route."""
|
||||
return web_urldispatcher.ResourceRoute('GET', self.get, self)
|
||||
|
||||
def url_for(self, **kwargs: str) -> URL:
|
||||
"""Construct url for resource with additional params."""
|
||||
return URL("/")
|
||||
|
||||
async def resolve(self, request: web.Request):
|
||||
"""Resolve resource.
|
||||
|
||||
Return (UrlMappingMatchInfo, allowed_methods) pair.
|
||||
"""
|
||||
if (request.path != '/' and
|
||||
request.url.parts[1] not in self.hass.data[DATA_PANELS]):
|
||||
return None, set()
|
||||
|
||||
if request.method != hdrs.METH_GET:
|
||||
return None, {'GET'}
|
||||
|
||||
return web_urldispatcher.UrlMappingMatchInfo({}, self._route), {'GET'}
|
||||
|
||||
def add_prefix(self, prefix: str) -> None:
|
||||
"""Add a prefix to processed URLs.
|
||||
|
||||
Required for subapplications support.
|
||||
"""
|
||||
|
||||
def get_info(self):
|
||||
"""Return a dict with additional info useful for introspection."""
|
||||
return {
|
||||
'panels': list(self.hass.data[DATA_PANELS])
|
||||
}
|
||||
|
||||
def freeze(self) -> None:
|
||||
"""Freeze the resource."""
|
||||
pass
|
||||
|
||||
def raw_match(self, path: str) -> bool:
|
||||
"""Perform a raw match against path."""
|
||||
pass
|
||||
|
||||
def get_template(self):
|
||||
"""Get template."""
|
||||
tpl = self._template_cache
|
||||
|
@ -357,14 +378,10 @@ class IndexView(HomeAssistantView):
|
|||
|
||||
return tpl
|
||||
|
||||
async def get(self, request, extra=None):
|
||||
"""Serve the index view."""
|
||||
async def get(self, request: web.Request):
|
||||
"""Serve the index page for panel pages."""
|
||||
hass = request.app['hass']
|
||||
|
||||
if (request.path != '/' and
|
||||
request.url.parts[1] not in hass.data[DATA_PANELS]):
|
||||
raise web.HTTPNotFound
|
||||
|
||||
if not hass.components.onboarding.async_is_onboarded():
|
||||
return web.Response(status=302, headers={
|
||||
'location': '/onboarding.html'
|
||||
|
@ -383,6 +400,14 @@ class IndexView(HomeAssistantView):
|
|||
content_type='text/html'
|
||||
)
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Return length of resource."""
|
||||
return 1
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over routes."""
|
||||
return iter([self._route])
|
||||
|
||||
|
||||
class ManifestJSONView(HomeAssistantView):
|
||||
"""View to return a manifest.json."""
|
||||
|
|
|
@ -8,8 +8,7 @@ import pytest
|
|||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.components.frontend import (
|
||||
DOMAIN, CONF_JS_VERSION, CONF_THEMES, CONF_EXTRA_HTML_URL,
|
||||
CONF_EXTRA_HTML_URL_ES5, generate_negative_index_regex,
|
||||
EVENT_PANELS_UPDATED)
|
||||
CONF_EXTRA_HTML_URL_ES5, EVENT_PANELS_UPDATED)
|
||||
from homeassistant.components.websocket_api.const import TYPE_RESULT
|
||||
|
||||
from tests.common import mock_coro, async_capture_events
|
||||
|
@ -348,43 +347,3 @@ async def test_auth_authorize(mock_http_client):
|
|||
resp = await mock_http_client.get(authorizejs.groups(0)[0])
|
||||
assert resp.status == 200
|
||||
assert 'public' in resp.headers.get('cache-control')
|
||||
|
||||
|
||||
def test_index_regex():
|
||||
"""Test the index regex."""
|
||||
pattern = re.compile('/' + generate_negative_index_regex())
|
||||
|
||||
for should_match in (
|
||||
'/',
|
||||
'/lovelace',
|
||||
'/lovelace/default_view',
|
||||
'/map',
|
||||
'/config',
|
||||
):
|
||||
assert pattern.match(should_match), should_match
|
||||
|
||||
for should_not_match in (
|
||||
'/service_worker.js',
|
||||
'/manifest.json',
|
||||
'/onboarding.html',
|
||||
'/manifest.json',
|
||||
'static',
|
||||
'static/',
|
||||
'static/index.html',
|
||||
'frontend_latest',
|
||||
'frontend_latest/',
|
||||
'frontend_latest/index.html',
|
||||
'frontend_es5',
|
||||
'frontend_es5/',
|
||||
'frontend_es5/index.html',
|
||||
'local',
|
||||
'local/',
|
||||
'local/index.html',
|
||||
'auth',
|
||||
'auth/',
|
||||
'auth/index.html',
|
||||
'/api',
|
||||
'/api/',
|
||||
'/api/logbook',
|
||||
):
|
||||
assert not pattern.match(should_not_match), should_not_match
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue