Skip to content

Commit 52c32ec

Browse files
committed
feat: allow HTTP connections; HTTPS is recommended but no longer required
1 parent bfafca4 commit 52c32ec

File tree

4 files changed

+21
-12
lines changed

4 files changed

+21
-12
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
- HTTP URLs (`http://`) are now permitted; HTTPS is strongly recommended but no longer enforced. Use HTTP only on trusted local networks or for development.
12+
1013
## [2.0.8] - 2025-02-01
1114

1215
### Added

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ asyncio.run(main())
4242

4343
### TLS and self-signed certificates
4444

45-
Find My Device always requires HTTPS; plain HTTP is not allowed by this client. If you need to connect to a server with a self-signed certificate, you have two options:
45+
HTTPS is strongly recommended for all connections to FMD server. HTTP is permitted for local development or trusted private networks, but should not be used in production. If you need to connect to a server with a self-signed certificate, you have two options:
4646

4747
- Preferred (secure): provide a custom SSLContext that trusts your CA or certificate
4848
- Last resort (not for production): disable certificate validation explicitly
@@ -68,13 +68,13 @@ insecure_client = FmdClient("https://fmd.example.com", ssl=False)
6868
```
6969

7070
Notes:
71-
- HTTP (http://) is rejected. Use only HTTPS URLs.
71+
- HTTPS is strongly recommended. Use HTTP only on trusted local networks or for development.
7272
- Prefer a custom SSLContext over disabling verification.
7373
- For higher security, consider pinning the server cert in your context.
7474

7575
> Warning
7676
>
77-
> Passing `ssl=False` disables TLS certificate validation and should only be used in development. For production, use a custom `ssl.SSLContext` that trusts your CA/certificate or pin the server certificate. The client enforces HTTPS and rejects `http://` URLs.
77+
> Passing `ssl=False` disables TLS certificate validation and should only be used in development. For production, use a custom `ssl.SSLContext` that trusts your CA/certificate or pin the server certificate. Using `http://` URLs sends credentials and data in plaintext — only use HTTP on trusted local networks or for development purposes.
7878
7979
#### Pinning the exact server certificate (recommended for self-signed)
8080

fmd_api/client.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ def __init__(
6464
conn_limit_per_host: Optional[int] = None,
6565
keepalive_timeout: Optional[float] = None,
6666
) -> None:
67-
# Enforce HTTPS only (FindMyDevice always uses TLS)
68-
if base_url.lower().startswith("http://"):
69-
raise ValueError("HTTPS is required for FmdClient base_url; plain HTTP is not allowed.")
67+
# Validate that the URL uses a supported scheme
68+
if not base_url.lower().startswith(("http://", "https://")):
69+
raise ValueError("base_url must use http:// or https://")
7070
self.base_url = base_url.rstrip("/")
7171
self.session_duration = session_duration
7272
self.cache_ttl = cache_ttl
@@ -127,7 +127,7 @@ async def create(
127127
Factory method to create and authenticate an FmdClient.
128128
129129
Args:
130-
base_url: HTTPS URL of the FMD server.
130+
base_url: URL of the FMD server (https:// strongly recommended; http:// permitted for local/dev use).
131131
fmd_id: User/device identifier.
132132
password: Authentication password.
133133
session_duration: Token validity in seconds (default 3600).
@@ -143,7 +143,7 @@ async def create(
143143
Authenticated FmdClient instance.
144144
145145
Raises:
146-
ValueError: If base_url uses HTTP instead of HTTPS.
146+
ValueError: If base_url does not start with http:// or https://.
147147
FmdApiException: If authentication fails or server returns an error.
148148
asyncio.TimeoutError: If the request times out.
149149
"""

tests/unit/test_client.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,16 @@ async def test_connector_configuration_applied():
100100
await client.close()
101101

102102

103-
def test_https_required():
104-
"""FmdClient should reject non-HTTPS base URLs."""
105-
with pytest.raises(ValueError, match="HTTPS is required"):
106-
FmdClient("http://fmd.example.com")
103+
def test_http_url_accepted():
104+
"""FmdClient should accept plain HTTP base URLs (HTTPS is strongly recommended but not required)."""
105+
client = FmdClient("http://fmd.example.com")
106+
assert client.base_url == "http://fmd.example.com"
107+
108+
109+
def test_invalid_scheme_rejected():
110+
"""FmdClient should reject URLs with unsupported schemes."""
111+
with pytest.raises(ValueError):
112+
FmdClient("ftp://fmd.example.com")
107113

108114

109115
@pytest.mark.asyncio

0 commit comments

Comments
 (0)