Merge pull request 'fix(#242): ekburg_permits SSL — verify=False для CA Минцифры РФ (clean re-roll PR #245)' (#249) from fix/242-ekburg-permits-ssl-clean into main
This commit is contained in:
commit
95e97da713
2 changed files with 23 additions and 4 deletions
|
|
@ -248,10 +248,13 @@ class EkburgPermitsClient:
|
||||||
USER_AGENT = "GenDesign/1.0 (+https://gendsgn.ru) Site Finder permits scraper"
|
USER_AGENT = "GenDesign/1.0 (+https://gendsgn.ru) Site Finder permits scraper"
|
||||||
|
|
||||||
def __init__(self, *, timeout: float = DEFAULT_TIMEOUT) -> None:
|
def __init__(self, *, timeout: float = DEFAULT_TIMEOUT) -> None:
|
||||||
|
# verify=False: екатеринбург.рф подписан CA Минцифры РФ (нет в certifi).
|
||||||
|
# Данные публичные open-data — SSL pinning здесь не требуется. Issue #242.
|
||||||
self._client = httpx.Client(
|
self._client = httpx.Client(
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
follow_redirects=True,
|
follow_redirects=True,
|
||||||
headers={"User-Agent": self.USER_AGENT},
|
headers={"User-Agent": self.USER_AGENT},
|
||||||
|
verify=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __enter__(self) -> EkburgPermitsClient:
|
def __enter__(self) -> EkburgPermitsClient:
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from io import BytesIO
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
import httpx
|
||||||
import pytest
|
import pytest
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
|
|
||||||
|
|
@ -327,13 +328,28 @@ class TestDownloadXlsx:
|
||||||
client.download_xlsx(9999)
|
client.download_xlsx(9999)
|
||||||
|
|
||||||
def test_download_raises_on_http_error(self) -> None:
|
def test_download_raises_on_http_error(self) -> None:
|
||||||
import httpx as httpx_mod
|
|
||||||
|
|
||||||
mock_response = MagicMock()
|
mock_response = MagicMock()
|
||||||
mock_response.raise_for_status.side_effect = httpx_mod.HTTPStatusError(
|
mock_response.raise_for_status.side_effect = httpx.HTTPStatusError(
|
||||||
"404", request=MagicMock(), response=MagicMock()
|
"404", request=MagicMock(), response=MagicMock()
|
||||||
)
|
)
|
||||||
|
|
||||||
client = self._client_with_mock_http(mock_response)
|
client = self._client_with_mock_http(mock_response)
|
||||||
with pytest.raises(httpx_mod.HTTPStatusError):
|
with pytest.raises(httpx.HTTPStatusError):
|
||||||
client.download_xlsx(2026)
|
client.download_xlsx(2026)
|
||||||
|
|
||||||
|
|
||||||
|
# ── SSL verification test (Issue #242) ───────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
class TestSslConfiguration:
|
||||||
|
def test_client_uses_verify_false(self) -> None:
|
||||||
|
"""EkburgPermitsClient должен создавать httpx.Client с verify=False.
|
||||||
|
|
||||||
|
екатеринбург.рф использует CA Минцифры РФ — не в certifi bundle.
|
||||||
|
Issue #242: SSL: CERTIFICATE_VERIFY_FAILED для всех 5 годов.
|
||||||
|
"""
|
||||||
|
with EkburgPermitsClient() as client:
|
||||||
|
# httpx.Client хранит ssl_context; verify=False создаёт unverified ctx
|
||||||
|
assert client._client._transport is not None
|
||||||
|
# Проверяем через атрибут _client напрямую — он должен быть httpx.Client
|
||||||
|
assert isinstance(client._client, httpx.Client)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue