Skip to content

Commit 984ec5b

Browse files
committed
Try both encoded and formdata with error debugging
1 parent ce80926 commit 984ec5b

File tree

2 files changed

+90
-28
lines changed

2 files changed

+90
-28
lines changed

airos/base.py

Lines changed: 89 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def __init__(
7777
# Mostly 8.x API endpoints, login/status are the same in 6.x
7878
self._login_urls = {
7979
"default": f"{self.base_url}/api/auth",
80+
"v6_login_cgi": f"{self.base_url}/login.cgi",
8081
"v6_alternative": f"{self.base_url}/login.cgi?uri=/",
8182
}
8283
self._status_cgi_url = f"{self.base_url}/status.cgi"
@@ -228,7 +229,7 @@ async def _request_json(
228229
url: str,
229230
headers: dict[str, Any] | None = None,
230231
json_data: dict[str, Any] | None = None,
231-
form_data: dict[str, Any] | None = None,
232+
form_data: dict[str, Any] | aiohttp.FormData | None = None,
232233
authenticated: bool = False,
233234
ct_json: bool = False,
234235
ct_form: bool = False,
@@ -321,32 +322,93 @@ async def login(self) -> None:
321322
)
322323
_LOGGER.error("TESTv6 - Cookie response: %s", cookieresponse)
323324

324-
try: # Alternative URL
325-
v6_payload = {
326-
"username": self.username,
327-
"password": self.password,
328-
"uri": "/index.cgi",
329-
}
330-
login_headers = {
331-
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0",
332-
"Referer": self._login_urls["v6_alternative"],
333-
}
334-
335-
v6_response = await self._request_json(
336-
"POST",
337-
self._login_urls["v6_alternative"],
338-
headers=login_headers,
339-
form_data=v6_payload,
340-
ct_form=True,
341-
authenticated=True,
342-
)
343-
_LOGGER.error(
344-
"TESTv6 - Trying to authenticate v6 responded in : %s", v6_response
345-
)
346-
except AirOSConnectionSetupError as err:
347-
raise AirOSConnectionSetupError(
348-
"Failed to login to default and alternate AirOS device urls"
349-
) from err
325+
v6_urls_to_try = [
326+
self._login_urls["v6_alternative"],
327+
self._login_urls["v6_login_cgi"],
328+
]
329+
330+
# Prepare form-urlencoded data (simple dict for 'ct_form=True')
331+
v6_urlencoded_data = {
332+
"uri": "/index.cgi",
333+
"username": self.username,
334+
"password": self.password,
335+
}
336+
337+
# Prepare multipart/form-data (aiohttp.FormData)
338+
v6_multipart_form_data = aiohttp.FormData()
339+
v6_multipart_form_data.add_field("uri", "/index.cgi")
340+
v6_multipart_form_data.add_field("username", self.username)
341+
v6_multipart_form_data.add_field("password", self.password)
342+
343+
login_headers = {
344+
# Removed User-Agent as it's often optional/can be simplified
345+
"Referer": self._login_urls["v6_login_cgi"],
346+
}
347+
348+
for url_to_try in v6_urls_to_try:
349+
# --- Attempt 1: application/x-www-form-urlencoded (preferred modern method) ---
350+
try:
351+
_LOGGER.error(
352+
"TESTv6 - Trying to authenticate V6 POST to %s with application/x-www-form-urlencoded",
353+
url_to_try,
354+
)
355+
await self._request_json(
356+
"POST",
357+
url_to_try,
358+
headers=login_headers,
359+
form_data=v6_urlencoded_data,
360+
authenticated=True,
361+
ct_form=True, # Flag to tell _request_json to use form-urlencoded Content-Type
362+
)
363+
except AirOSUrlNotFoundError:
364+
_LOGGER.warning(
365+
"TESTv6 - V6 URL not found (%s) for form-urlencoded, trying multipart.",
366+
url_to_try,
367+
)
368+
except AirOSConnectionSetupError as err:
369+
_LOGGER.warning(
370+
"TESTv6 - V6 connection setup failed (%s) for form-urlencoded, trying multipart. Error: %s",
371+
url_to_try,
372+
err,
373+
)
374+
except AirOSConnectionAuthenticationError:
375+
raise
376+
else:
377+
return # Success
378+
379+
# --- Attempt 2: multipart/form-data (fallback for older/different servers) ---
380+
try:
381+
_LOGGER.error(
382+
"TESTv6 - Trying to authenticate V6 POST to %s with multipart/form-data",
383+
url_to_try,
384+
)
385+
await self._request_json(
386+
"POST",
387+
url_to_try,
388+
headers=login_headers,
389+
form_data=v6_multipart_form_data,
390+
authenticated=True,
391+
)
392+
except AirOSUrlNotFoundError:
393+
_LOGGER.warning(
394+
"TESTv6 - V6 URL not found (%s) for multipart, trying next URL.",
395+
url_to_try,
396+
)
397+
except AirOSConnectionSetupError as err:
398+
_LOGGER.warning(
399+
"TESTv6 - V6 connection setup failed (%s) for multipart, trying next URL. Error: %s",
400+
url_to_try,
401+
err,
402+
)
403+
except AirOSConnectionAuthenticationError:
404+
raise
405+
else:
406+
return # Success
407+
408+
# If the loop finishes without returning, login failed for all combinations
409+
raise AirOSConnectionSetupError(
410+
"Failed to login to default and alternate AirOS device urls"
411+
)
350412

351413
async def status(self) -> AirOSDataModel:
352414
"""Retrieve status from the device."""

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "airos"
7-
version = "0.5.7a2"
7+
version = "0.5.7a3"
88
license = "MIT"
99
description = "Ubiquiti airOS module(s) for Python 3."
1010
readme = "README.md"

0 commit comments

Comments
 (0)