Remove base_url fallback (#46316)
This commit is contained in:
parent
a6358430b4
commit
22389043eb
9 changed files with 38 additions and 706 deletions
|
@ -4,7 +4,6 @@ from ipaddress import ip_network
|
|||
import logging
|
||||
import os
|
||||
import ssl
|
||||
from traceback import extract_stack
|
||||
from typing import Dict, Optional, cast
|
||||
|
||||
from aiohttp import web
|
||||
|
@ -125,69 +124,6 @@ class ApiConfig:
|
|||
self.port = port
|
||||
self.use_ssl = use_ssl
|
||||
|
||||
host = host.rstrip("/")
|
||||
if host.startswith(("http://", "https://")):
|
||||
self.deprecated_base_url = host
|
||||
elif use_ssl:
|
||||
self.deprecated_base_url = f"https://{host}"
|
||||
else:
|
||||
self.deprecated_base_url = f"http://{host}"
|
||||
|
||||
if port is not None:
|
||||
self.deprecated_base_url += f":{port}"
|
||||
|
||||
@property
|
||||
def base_url(self) -> str:
|
||||
"""Proxy property to find caller of this deprecated property."""
|
||||
found_frame = None
|
||||
for frame in reversed(extract_stack()[:-1]):
|
||||
for path in ("custom_components/", "homeassistant/components/"):
|
||||
try:
|
||||
index = frame.filename.index(path)
|
||||
|
||||
# Skip webhook from the stack
|
||||
if frame.filename[index:].startswith(
|
||||
"homeassistant/components/webhook/"
|
||||
):
|
||||
continue
|
||||
|
||||
found_frame = frame
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if found_frame is not None:
|
||||
break
|
||||
|
||||
# Did not source from an integration? Hard error.
|
||||
if found_frame is None:
|
||||
raise RuntimeError(
|
||||
"Detected use of deprecated `base_url` property in the Home Assistant core. Please report this issue."
|
||||
)
|
||||
|
||||
# If a frame was found, it originated from an integration
|
||||
if found_frame:
|
||||
start = index + len(path)
|
||||
end = found_frame.filename.index("/", start)
|
||||
|
||||
integration = found_frame.filename[start:end]
|
||||
|
||||
if path == "custom_components/":
|
||||
extra = " to the custom component author"
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
_LOGGER.warning(
|
||||
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.get_url` method instead. Please report issue%s for %s using this method at %s, line %s: %s",
|
||||
extra,
|
||||
integration,
|
||||
found_frame.filename[index:],
|
||||
found_frame.lineno,
|
||||
found_frame.line.strip(),
|
||||
)
|
||||
|
||||
return self.deprecated_base_url
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up the HTTP API and debug interface."""
|
||||
|
@ -256,20 +192,16 @@ async def async_setup(hass, config):
|
|||
|
||||
hass.http = server
|
||||
|
||||
host = conf.get(CONF_BASE_URL)
|
||||
local_ip = await hass.async_add_executor_job(hass_util.get_local_ip)
|
||||
|
||||
if host:
|
||||
port = None
|
||||
elif server_host is not None:
|
||||
host = local_ip
|
||||
if server_host is not None:
|
||||
# Assume the first server host name provided as API host
|
||||
host = server_host[0]
|
||||
port = server_port
|
||||
else:
|
||||
host = local_ip
|
||||
port = server_port
|
||||
|
||||
hass.config.api = ApiConfig(local_ip, host, port, ssl_certificate is not None)
|
||||
hass.config.api = ApiConfig(
|
||||
local_ip, host, server_port, ssl_certificate is not None
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import asyncio
|
|||
import datetime
|
||||
import enum
|
||||
import functools
|
||||
from ipaddress import ip_address
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
|
@ -70,7 +69,7 @@ from homeassistant.exceptions import (
|
|||
ServiceNotFound,
|
||||
Unauthorized,
|
||||
)
|
||||
from homeassistant.util import location, network
|
||||
from homeassistant.util import location
|
||||
from homeassistant.util.async_ import (
|
||||
fire_coroutine_threadsafe,
|
||||
run_callback_threadsafe,
|
||||
|
@ -1687,39 +1686,7 @@ class Config:
|
|||
)
|
||||
data = await store.async_load()
|
||||
|
||||
async def migrate_base_url(_: Event) -> None:
|
||||
"""Migrate base_url to internal_url/external_url."""
|
||||
if self.hass.config.api is None:
|
||||
return
|
||||
|
||||
base_url = yarl.URL(self.hass.config.api.deprecated_base_url)
|
||||
|
||||
# Check if this is an internal URL
|
||||
if str(base_url.host).endswith(".local") or (
|
||||
network.is_ip_address(str(base_url.host))
|
||||
and network.is_private(ip_address(base_url.host))
|
||||
):
|
||||
await self.async_update(
|
||||
internal_url=network.normalize_url(str(base_url))
|
||||
)
|
||||
return
|
||||
|
||||
# External, ensure this is not a loopback address
|
||||
if not (
|
||||
network.is_ip_address(str(base_url.host))
|
||||
and network.is_loopback(ip_address(base_url.host))
|
||||
):
|
||||
await self.async_update(
|
||||
external_url=network.normalize_url(str(base_url))
|
||||
)
|
||||
|
||||
if data:
|
||||
# Try to migrate base_url to internal_url/external_url
|
||||
if "external_url" not in data:
|
||||
self.hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_START, migrate_base_url
|
||||
)
|
||||
|
||||
self._update(
|
||||
source=SOURCE_STORAGE,
|
||||
latitude=data.get("latitude"),
|
||||
|
|
|
@ -8,13 +8,7 @@ from homeassistant.components import http
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.loader import bind_hass
|
||||
from homeassistant.util.network import (
|
||||
is_ip_address,
|
||||
is_local,
|
||||
is_loopback,
|
||||
is_private,
|
||||
normalize_url,
|
||||
)
|
||||
from homeassistant.util.network import is_ip_address, is_loopback, normalize_url
|
||||
|
||||
TYPE_URL_INTERNAL = "internal_url"
|
||||
TYPE_URL_EXTERNAL = "external_url"
|
||||
|
@ -151,19 +145,6 @@ def _get_internal_url(
|
|||
):
|
||||
return normalize_url(str(internal_url))
|
||||
|
||||
# Fallback to old base_url
|
||||
try:
|
||||
return _get_deprecated_base_url(
|
||||
hass,
|
||||
internal=True,
|
||||
allow_ip=allow_ip,
|
||||
require_current_request=require_current_request,
|
||||
require_ssl=require_ssl,
|
||||
require_standard_port=require_standard_port,
|
||||
)
|
||||
except NoURLAvailableError:
|
||||
pass
|
||||
|
||||
# Fallback to detected local IP
|
||||
if allow_ip and not (
|
||||
require_ssl or hass.config.api is None or hass.config.api.use_ssl
|
||||
|
@ -217,17 +198,6 @@ def _get_external_url(
|
|||
):
|
||||
return normalize_url(str(external_url))
|
||||
|
||||
try:
|
||||
return _get_deprecated_base_url(
|
||||
hass,
|
||||
allow_ip=allow_ip,
|
||||
require_current_request=require_current_request,
|
||||
require_ssl=require_ssl,
|
||||
require_standard_port=require_standard_port,
|
||||
)
|
||||
except NoURLAvailableError:
|
||||
pass
|
||||
|
||||
if allow_cloud:
|
||||
try:
|
||||
return _get_cloud_url(hass, require_current_request=require_current_request)
|
||||
|
@ -250,50 +220,3 @@ def _get_cloud_url(hass: HomeAssistant, require_current_request: bool = False) -
|
|||
return normalize_url(str(cloud_url))
|
||||
|
||||
raise NoURLAvailableError
|
||||
|
||||
|
||||
@bind_hass
|
||||
def _get_deprecated_base_url(
|
||||
hass: HomeAssistant,
|
||||
*,
|
||||
internal: bool = False,
|
||||
allow_ip: bool = True,
|
||||
require_current_request: bool = False,
|
||||
require_ssl: bool = False,
|
||||
require_standard_port: bool = False,
|
||||
) -> str:
|
||||
"""Work with the deprecated `base_url`, used as fallback."""
|
||||
if hass.config.api is None or not hass.config.api.deprecated_base_url:
|
||||
raise NoURLAvailableError
|
||||
|
||||
base_url = yarl.URL(hass.config.api.deprecated_base_url)
|
||||
# Rules that apply to both internal and external
|
||||
if (
|
||||
(allow_ip or not is_ip_address(str(base_url.host)))
|
||||
and (not require_current_request or base_url.host == _get_request_host())
|
||||
and (not require_ssl or base_url.scheme == "https")
|
||||
and (not require_standard_port or base_url.is_default_port())
|
||||
):
|
||||
# Check to ensure an internal URL
|
||||
if internal and (
|
||||
str(base_url.host).endswith(".local")
|
||||
or (
|
||||
is_ip_address(str(base_url.host))
|
||||
and not is_loopback(ip_address(base_url.host))
|
||||
and is_private(ip_address(base_url.host))
|
||||
)
|
||||
):
|
||||
return normalize_url(str(base_url))
|
||||
|
||||
# Check to ensure an external URL (a little)
|
||||
if (
|
||||
not internal
|
||||
and not str(base_url.host).endswith(".local")
|
||||
and not (
|
||||
is_ip_address(str(base_url.host))
|
||||
and is_local(ip_address(str(base_url.host)))
|
||||
)
|
||||
):
|
||||
return normalize_url(str(base_url))
|
||||
|
||||
raise NoURLAvailableError
|
||||
|
|
|
@ -5,6 +5,7 @@ import ambiclimate
|
|||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.ambiclimate import config_flow
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import aiohttp
|
||||
|
@ -12,9 +13,11 @@ from homeassistant.util import aiohttp
|
|||
|
||||
async def init_config_flow(hass):
|
||||
"""Init a configuration flow."""
|
||||
await async_setup_component(
|
||||
hass, "http", {"http": {"base_url": "https://hass.com"}}
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"external_url": "https://example.com"},
|
||||
)
|
||||
await async_setup_component(hass, "http", {})
|
||||
|
||||
config_flow.register_flow_implementation(hass, "id", "secret")
|
||||
flow = config_flow.AmbiclimateFlowHandler()
|
||||
|
@ -58,20 +61,20 @@ async def test_full_flow_implementation(hass):
|
|||
assert result["step_id"] == "auth"
|
||||
assert (
|
||||
result["description_placeholders"]["cb_url"]
|
||||
== "https://hass.com/api/ambiclimate"
|
||||
== "https://example.com/api/ambiclimate"
|
||||
)
|
||||
|
||||
url = result["description_placeholders"]["authorization_url"]
|
||||
assert "https://api.ambiclimate.com/oauth2/authorize" in url
|
||||
assert "client_id=id" in url
|
||||
assert "response_type=code" in url
|
||||
assert "redirect_uri=https%3A%2F%2Fhass.com%2Fapi%2Fambiclimate" in url
|
||||
assert "redirect_uri=https%3A%2F%2Fexample.com%2Fapi%2Fambiclimate" in url
|
||||
|
||||
with patch("ambiclimate.AmbiclimateOAuth.get_access_token", return_value="test"):
|
||||
result = await flow.async_step_code("123ABC")
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == "Ambiclimate"
|
||||
assert result["data"]["callback_url"] == "https://hass.com/api/ambiclimate"
|
||||
assert result["data"]["callback_url"] == "https://example.com/api/ambiclimate"
|
||||
assert result["data"][CONF_CLIENT_SECRET] == "secret"
|
||||
assert result["data"][CONF_CLIENT_ID] == "id"
|
||||
|
||||
|
|
|
@ -60,73 +60,6 @@ async def test_registering_view_while_running(
|
|||
hass.http.register_view(TestView)
|
||||
|
||||
|
||||
def test_api_base_url_with_domain(mock_stack):
|
||||
"""Test setting API URL with domain."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "example.com")
|
||||
assert api_config.base_url == "http://example.com:8123"
|
||||
|
||||
|
||||
def test_api_base_url_with_ip(mock_stack):
|
||||
"""Test setting API URL with IP."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "1.1.1.1")
|
||||
assert api_config.base_url == "http://1.1.1.1:8123"
|
||||
|
||||
|
||||
def test_api_base_url_with_ip_and_port(mock_stack):
|
||||
"""Test setting API URL with IP and port."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "1.1.1.1", 8124)
|
||||
assert api_config.base_url == "http://1.1.1.1:8124"
|
||||
|
||||
|
||||
def test_api_base_url_with_protocol(mock_stack):
|
||||
"""Test setting API URL with protocol."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "https://example.com")
|
||||
assert api_config.base_url == "https://example.com:8123"
|
||||
|
||||
|
||||
def test_api_base_url_with_protocol_and_port(mock_stack):
|
||||
"""Test setting API URL with protocol and port."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "https://example.com", 433)
|
||||
assert api_config.base_url == "https://example.com:433"
|
||||
|
||||
|
||||
def test_api_base_url_with_ssl_enable(mock_stack):
|
||||
"""Test setting API URL with use_ssl enabled."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "example.com", use_ssl=True)
|
||||
assert api_config.base_url == "https://example.com:8123"
|
||||
|
||||
|
||||
def test_api_base_url_with_ssl_enable_and_port(mock_stack):
|
||||
"""Test setting API URL with use_ssl enabled and port."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "1.1.1.1", use_ssl=True, port=8888)
|
||||
assert api_config.base_url == "https://1.1.1.1:8888"
|
||||
|
||||
|
||||
def test_api_base_url_with_protocol_and_ssl_enable(mock_stack):
|
||||
"""Test setting API URL with specific protocol and use_ssl enabled."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "http://example.com", use_ssl=True)
|
||||
assert api_config.base_url == "http://example.com:8123"
|
||||
|
||||
|
||||
def test_api_base_url_removes_trailing_slash(mock_stack):
|
||||
"""Test a trialing slash is removed when setting the API URL."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "http://example.com/")
|
||||
assert api_config.base_url == "http://example.com:8123"
|
||||
|
||||
|
||||
def test_api_local_ip(mock_stack):
|
||||
"""Test a trialing slash is removed when setting the API URL."""
|
||||
api_config = http.ApiConfig("127.0.0.1", "http://example.com/")
|
||||
assert api_config.local_ip == "127.0.0.1"
|
||||
|
||||
|
||||
async def test_api_no_base_url(hass, mock_stack):
|
||||
"""Test setting api url."""
|
||||
result = await async_setup_component(hass, "http", {"http": {}})
|
||||
assert result
|
||||
assert hass.config.api.base_url == "http://127.0.0.1:8123"
|
||||
|
||||
|
||||
async def test_not_log_password(hass, aiohttp_client, caplog, legacy_auth):
|
||||
"""Test access with password doesn't get logged."""
|
||||
assert await async_setup_component(hass, "api", {"http": {}})
|
||||
|
@ -263,127 +196,3 @@ async def test_storing_config(hass, aiohttp_client, aiohttp_unused_port):
|
|||
restored["trusted_proxies"][0] = ip_network(restored["trusted_proxies"][0])
|
||||
|
||||
assert restored == http.HTTP_SCHEMA(config)
|
||||
|
||||
|
||||
async def test_use_of_base_url(hass):
|
||||
"""Test detection base_url usage when called without integration context."""
|
||||
await async_setup_component(hass, "http", {"http": {}})
|
||||
with patch(
|
||||
"homeassistant.components.http.extract_stack",
|
||||
return_value=[
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/core.py",
|
||||
lineno="21",
|
||||
line="do_something()",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/core.py",
|
||||
lineno="42",
|
||||
line="url = hass.config.api.base_url",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/example/client.py",
|
||||
lineno="21",
|
||||
line="something()",
|
||||
),
|
||||
],
|
||||
), pytest.raises(RuntimeError):
|
||||
hass.config.api.base_url
|
||||
|
||||
|
||||
async def test_use_of_base_url_integration(hass, caplog):
|
||||
"""Test detection base_url usage when called with integration context."""
|
||||
await async_setup_component(hass, "http", {"http": {}})
|
||||
with patch(
|
||||
"homeassistant.components.http.extract_stack",
|
||||
return_value=[
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/core.py",
|
||||
lineno="21",
|
||||
line="do_something()",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/components/example/__init__.py",
|
||||
lineno="42",
|
||||
line="url = hass.config.api.base_url",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/example/client.py",
|
||||
lineno="21",
|
||||
line="something()",
|
||||
),
|
||||
],
|
||||
):
|
||||
assert hass.config.api.base_url == "http://127.0.0.1:8123"
|
||||
|
||||
assert (
|
||||
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.get_url` method instead. Please report issue for example using this method at homeassistant/components/example/__init__.py, line 42: url = hass.config.api.base_url"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
|
||||
async def test_use_of_base_url_integration_webhook(hass, caplog):
|
||||
"""Test detection base_url usage when called with integration context."""
|
||||
await async_setup_component(hass, "http", {"http": {}})
|
||||
with patch(
|
||||
"homeassistant.components.http.extract_stack",
|
||||
return_value=[
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/core.py",
|
||||
lineno="21",
|
||||
line="do_something()",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/components/example/__init__.py",
|
||||
lineno="42",
|
||||
line="url = hass.config.api.base_url",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/components/webhook/__init__.py",
|
||||
lineno="42",
|
||||
line="return get_url(hass)",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/example/client.py",
|
||||
lineno="21",
|
||||
line="something()",
|
||||
),
|
||||
],
|
||||
):
|
||||
assert hass.config.api.base_url == "http://127.0.0.1:8123"
|
||||
|
||||
assert (
|
||||
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.get_url` method instead. Please report issue for example using this method at homeassistant/components/example/__init__.py, line 42: url = hass.config.api.base_url"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
|
||||
async def test_use_of_base_url_custom_component(hass, caplog):
|
||||
"""Test detection base_url usage when called with custom component context."""
|
||||
await async_setup_component(hass, "http", {"http": {}})
|
||||
with patch(
|
||||
"homeassistant.components.http.extract_stack",
|
||||
return_value=[
|
||||
Mock(
|
||||
filename="/home/frenck/homeassistant/core.py",
|
||||
lineno="21",
|
||||
line="do_something()",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/.homeassistant/custom_components/example/__init__.py",
|
||||
lineno="42",
|
||||
line="url = hass.config.api.base_url",
|
||||
),
|
||||
Mock(
|
||||
filename="/home/frenck/example/client.py",
|
||||
lineno="21",
|
||||
line="something()",
|
||||
),
|
||||
],
|
||||
):
|
||||
assert hass.config.api.base_url == "http://127.0.0.1:8123"
|
||||
|
||||
assert (
|
||||
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.get_url` method instead. Please report issue to the custom component author for example using this method at custom_components/example/__init__.py, line 42: url = hass.config.api.base_url"
|
||||
in caplog.text
|
||||
)
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
"""Test the init file of IFTTT."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components import ifttt
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.core import callback
|
||||
|
||||
|
||||
async def test_config_flow_registers_webhook(hass, aiohttp_client):
|
||||
"""Test setting up IFTTT and sending webhook."""
|
||||
with patch("homeassistant.util.get_local_ip", return_value="example.com"):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"ifttt", context={"source": "user"}
|
||||
)
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"internal_url": "http://example.local:8123"},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"ifttt", context={"source": "user"}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM, result
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
"""Test the init file of Twilio."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components import twilio
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.core import callback
|
||||
|
||||
|
||||
async def test_config_flow_registers_webhook(hass, aiohttp_client):
|
||||
"""Test setting up Twilio and sending webhook."""
|
||||
with patch("homeassistant.util.get_local_ip", return_value="example.com"):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"twilio", context={"source": "user"}
|
||||
)
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"internal_url": "http://example.local:8123"},
|
||||
)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"twilio", context={"source": "user"}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM, result
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
|
|
|
@ -9,7 +9,6 @@ from homeassistant.core import HomeAssistant
|
|||
from homeassistant.helpers.network import (
|
||||
NoURLAvailableError,
|
||||
_get_cloud_url,
|
||||
_get_deprecated_base_url,
|
||||
_get_external_url,
|
||||
_get_internal_url,
|
||||
_get_request_host,
|
||||
|
@ -166,9 +165,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
|
|||
"""Test getting an instance URL when the user has not set an internal URL."""
|
||||
assert hass.config.internal_url is None
|
||||
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=8123, deprecated_base_url=None, local_ip="192.168.123.123"
|
||||
)
|
||||
hass.config.api = Mock(use_ssl=False, port=8123, local_ip="192.168.123.123")
|
||||
assert _get_internal_url(hass) == "http://192.168.123.123:8123"
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
|
@ -180,9 +177,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
|
|||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass, require_ssl=True)
|
||||
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=80, deprecated_base_url=None, local_ip="192.168.123.123"
|
||||
)
|
||||
hass.config.api = Mock(use_ssl=False, port=80, local_ip="192.168.123.123")
|
||||
assert _get_internal_url(hass) == "http://192.168.123.123"
|
||||
assert (
|
||||
_get_internal_url(hass, require_standard_port=True) == "http://192.168.123.123"
|
||||
|
@ -194,7 +189,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
|
|||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass, require_ssl=True)
|
||||
|
||||
hass.config.api = Mock(use_ssl=True, port=443, deprecated_base_url=None)
|
||||
hass.config.api = Mock(use_ssl=True, port=443)
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass)
|
||||
|
||||
|
@ -208,9 +203,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
|
|||
_get_internal_url(hass, require_ssl=True)
|
||||
|
||||
# Do no accept any local loopback address as fallback
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=80, deprecated_base_url=None, local_ip="127.0.0.1"
|
||||
)
|
||||
hass.config.api = Mock(use_ssl=False, port=80, local_ip="127.0.0.1")
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass)
|
||||
|
||||
|
@ -457,9 +450,7 @@ async def test_get_url(hass: HomeAssistant):
|
|||
with pytest.raises(NoURLAvailableError):
|
||||
get_url(hass)
|
||||
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=8123, deprecated_base_url=None, local_ip="192.168.123.123"
|
||||
)
|
||||
hass.config.api = Mock(use_ssl=False, port=8123, local_ip="192.168.123.123")
|
||||
assert get_url(hass) == "http://192.168.123.123:8123"
|
||||
assert get_url(hass, prefer_external=True) == "http://192.168.123.123:8123"
|
||||
|
||||
|
@ -543,274 +534,11 @@ async def test_get_request_host(hass: HomeAssistant):
|
|||
assert _get_request_host() == "example.com"
|
||||
|
||||
|
||||
async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
|
||||
"""Test getting an internal instance URL from the deprecated base_url."""
|
||||
# Test with SSL local URL
|
||||
hass.config.api = Mock(deprecated_base_url="https://example.local")
|
||||
assert _get_deprecated_base_url(hass, internal=True) == "https://example.local"
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, internal=True, allow_ip=False)
|
||||
== "https://example.local"
|
||||
)
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, internal=True, require_ssl=True)
|
||||
== "https://example.local"
|
||||
)
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, internal=True, require_standard_port=True)
|
||||
== "https://example.local"
|
||||
)
|
||||
|
||||
# Test with no SSL, local IP URL
|
||||
hass.config.api = Mock(deprecated_base_url="http://10.10.10.10:8123")
|
||||
assert _get_deprecated_base_url(hass, internal=True) == "http://10.10.10.10:8123"
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, allow_ip=False)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, require_standard_port=True)
|
||||
|
||||
# Test with SSL, local IP URL
|
||||
hass.config.api = Mock(deprecated_base_url="https://10.10.10.10")
|
||||
assert _get_deprecated_base_url(hass, internal=True) == "https://10.10.10.10"
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, internal=True, require_ssl=True)
|
||||
== "https://10.10.10.10"
|
||||
)
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, internal=True, require_standard_port=True)
|
||||
== "https://10.10.10.10"
|
||||
)
|
||||
|
||||
# Test external URL
|
||||
hass.config.api = Mock(deprecated_base_url="https://example.com")
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, require_standard_port=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, allow_ip=False)
|
||||
|
||||
# Test with loopback
|
||||
hass.config.api = Mock(deprecated_base_url="https://127.0.0.42")
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
assert _get_deprecated_base_url(hass, internal=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, allow_ip=False)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, internal=True, require_standard_port=True)
|
||||
|
||||
|
||||
async def test_get_deprecated_base_url_external(hass: HomeAssistant):
|
||||
"""Test getting an external instance URL from the deprecated base_url."""
|
||||
# Test with SSL and external domain on standard port
|
||||
hass.config.api = Mock(deprecated_base_url="https://example.com:443/")
|
||||
assert _get_deprecated_base_url(hass) == "https://example.com"
|
||||
assert _get_deprecated_base_url(hass, require_ssl=True) == "https://example.com"
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, require_standard_port=True)
|
||||
== "https://example.com"
|
||||
)
|
||||
|
||||
# Test without SSL and external domain on non-standard port
|
||||
hass.config.api = Mock(deprecated_base_url="http://example.com:8123/")
|
||||
assert _get_deprecated_base_url(hass) == "http://example.com:8123"
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_standard_port=True)
|
||||
|
||||
# Test SSL on external IP
|
||||
hass.config.api = Mock(deprecated_base_url="https://1.1.1.1")
|
||||
assert _get_deprecated_base_url(hass) == "https://1.1.1.1"
|
||||
assert _get_deprecated_base_url(hass, require_ssl=True) == "https://1.1.1.1"
|
||||
assert (
|
||||
_get_deprecated_base_url(hass, require_standard_port=True) == "https://1.1.1.1"
|
||||
)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, allow_ip=False)
|
||||
|
||||
# Test with private IP
|
||||
hass.config.api = Mock(deprecated_base_url="https://10.10.10.10")
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
assert _get_deprecated_base_url(hass)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, allow_ip=False)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_standard_port=True)
|
||||
|
||||
# Test with local domain
|
||||
hass.config.api = Mock(deprecated_base_url="https://example.local")
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
assert _get_deprecated_base_url(hass)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, allow_ip=False)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_standard_port=True)
|
||||
|
||||
# Test with loopback
|
||||
hass.config.api = Mock(deprecated_base_url="https://127.0.0.42")
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
assert _get_deprecated_base_url(hass)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, allow_ip=False)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_ssl=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_deprecated_base_url(hass, require_standard_port=True)
|
||||
|
||||
|
||||
async def test_get_internal_url_with_base_url_fallback(hass: HomeAssistant):
|
||||
"""Test getting an internal instance URL with the deprecated base_url fallback."""
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=8123, deprecated_base_url=None, local_ip="192.168.123.123"
|
||||
)
|
||||
assert hass.config.internal_url is None
|
||||
assert _get_internal_url(hass) == "http://192.168.123.123:8123"
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass, allow_ip=False)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass, require_standard_port=True)
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_internal_url(hass, require_ssl=True)
|
||||
|
||||
# Add base_url
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=8123, deprecated_base_url="https://example.local"
|
||||
)
|
||||
assert _get_internal_url(hass) == "https://example.local"
|
||||
assert _get_internal_url(hass, allow_ip=False) == "https://example.local"
|
||||
assert (
|
||||
_get_internal_url(hass, require_standard_port=True) == "https://example.local"
|
||||
)
|
||||
assert _get_internal_url(hass, require_ssl=True) == "https://example.local"
|
||||
|
||||
# Add internal URL
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"internal_url": "https://internal.local"},
|
||||
)
|
||||
assert _get_internal_url(hass) == "https://internal.local"
|
||||
assert _get_internal_url(hass, allow_ip=False) == "https://internal.local"
|
||||
assert (
|
||||
_get_internal_url(hass, require_standard_port=True) == "https://internal.local"
|
||||
)
|
||||
assert _get_internal_url(hass, require_ssl=True) == "https://internal.local"
|
||||
|
||||
# Add internal URL, mixed results
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"internal_url": "http://internal.local:8123"},
|
||||
)
|
||||
assert _get_internal_url(hass) == "http://internal.local:8123"
|
||||
assert _get_internal_url(hass, allow_ip=False) == "http://internal.local:8123"
|
||||
assert (
|
||||
_get_internal_url(hass, require_standard_port=True) == "https://example.local"
|
||||
)
|
||||
assert _get_internal_url(hass, require_ssl=True) == "https://example.local"
|
||||
|
||||
# Add internal URL set to an IP
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"internal_url": "http://10.10.10.10:8123"},
|
||||
)
|
||||
assert _get_internal_url(hass) == "http://10.10.10.10:8123"
|
||||
assert _get_internal_url(hass, allow_ip=False) == "https://example.local"
|
||||
assert (
|
||||
_get_internal_url(hass, require_standard_port=True) == "https://example.local"
|
||||
)
|
||||
assert _get_internal_url(hass, require_ssl=True) == "https://example.local"
|
||||
|
||||
|
||||
async def test_get_external_url_with_base_url_fallback(hass: HomeAssistant):
|
||||
"""Test getting an external instance URL with the deprecated base_url fallback."""
|
||||
hass.config.api = Mock(use_ssl=False, port=8123, deprecated_base_url=None)
|
||||
assert hass.config.internal_url is None
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
_get_external_url(hass)
|
||||
|
||||
# Test with SSL and external domain on standard port
|
||||
hass.config.api = Mock(deprecated_base_url="https://example.com:443/")
|
||||
assert _get_external_url(hass) == "https://example.com"
|
||||
assert _get_external_url(hass, allow_ip=False) == "https://example.com"
|
||||
assert _get_external_url(hass, require_ssl=True) == "https://example.com"
|
||||
assert _get_external_url(hass, require_standard_port=True) == "https://example.com"
|
||||
|
||||
# Add external URL
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"external_url": "https://external.example.com"},
|
||||
)
|
||||
assert _get_external_url(hass) == "https://external.example.com"
|
||||
assert _get_external_url(hass, allow_ip=False) == "https://external.example.com"
|
||||
assert (
|
||||
_get_external_url(hass, require_standard_port=True)
|
||||
== "https://external.example.com"
|
||||
)
|
||||
assert _get_external_url(hass, require_ssl=True) == "https://external.example.com"
|
||||
|
||||
# Add external URL, mixed results
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"external_url": "http://external.example.com:8123"},
|
||||
)
|
||||
assert _get_external_url(hass) == "http://external.example.com:8123"
|
||||
assert _get_external_url(hass, allow_ip=False) == "http://external.example.com:8123"
|
||||
assert _get_external_url(hass, require_standard_port=True) == "https://example.com"
|
||||
assert _get_external_url(hass, require_ssl=True) == "https://example.com"
|
||||
|
||||
# Add external URL set to an IP
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"external_url": "http://1.1.1.1:8123"},
|
||||
)
|
||||
assert _get_external_url(hass) == "http://1.1.1.1:8123"
|
||||
assert _get_external_url(hass, allow_ip=False) == "https://example.com"
|
||||
assert _get_external_url(hass, require_standard_port=True) == "https://example.com"
|
||||
assert _get_external_url(hass, require_ssl=True) == "https://example.com"
|
||||
|
||||
|
||||
async def test_get_current_request_url_with_known_host(
|
||||
hass: HomeAssistant, current_request
|
||||
):
|
||||
"""Test getting current request URL with known hosts addresses."""
|
||||
hass.config.api = Mock(
|
||||
use_ssl=False, port=8123, local_ip="127.0.0.1", deprecated_base_url=None
|
||||
)
|
||||
hass.config.api = Mock(use_ssl=False, port=8123, local_ip="127.0.0.1")
|
||||
assert hass.config.internal_url is None
|
||||
|
||||
with pytest.raises(NoURLAvailableError):
|
||||
|
|
|
@ -1294,41 +1294,6 @@ def test_valid_entity_id():
|
|||
assert ha.valid_entity_id(valid), valid
|
||||
|
||||
|
||||
async def test_migration_base_url(hass, hass_storage):
|
||||
"""Test that we migrate base url to internal/external url."""
|
||||
config = ha.Config(hass)
|
||||
stored = {"version": 1, "data": {}}
|
||||
hass_storage[ha.CORE_STORAGE_KEY] = stored
|
||||
with patch.object(hass.bus, "async_listen_once") as mock_listen:
|
||||
# Empty config
|
||||
await config.async_load()
|
||||
assert len(mock_listen.mock_calls) == 0
|
||||
|
||||
# With just a name
|
||||
stored["data"] = {"location_name": "Test Name"}
|
||||
await config.async_load()
|
||||
assert len(mock_listen.mock_calls) == 1
|
||||
|
||||
# With external url
|
||||
stored["data"]["external_url"] = "https://example.com"
|
||||
await config.async_load()
|
||||
assert len(mock_listen.mock_calls) == 1
|
||||
|
||||
# Test that the event listener works
|
||||
assert mock_listen.mock_calls[0][1][0] == EVENT_HOMEASSISTANT_START
|
||||
|
||||
# External
|
||||
hass.config.api = Mock(deprecated_base_url="https://loaded-example.com")
|
||||
await mock_listen.mock_calls[0][1][1](None)
|
||||
assert config.external_url == "https://loaded-example.com"
|
||||
|
||||
# Internal
|
||||
for internal in ("http://hass.local", "http://192.168.1.100:8123"):
|
||||
hass.config.api = Mock(deprecated_base_url=internal)
|
||||
await mock_listen.mock_calls[0][1][1](None)
|
||||
assert config.internal_url == internal
|
||||
|
||||
|
||||
async def test_additional_data_in_core_config(hass, hass_storage):
|
||||
"""Test that we can handle additional data in core configuration."""
|
||||
config = ha.Config(hass)
|
||||
|
|
Loading…
Add table
Reference in a new issue