datacenter IP + Akamai 대응. 매 요청 IP 변경은 쿠키-IP 불일치로 재챌린지를 유발하므로, sticky 세션(일정 시간 같은 IP) + 주기적 회전 방식 사용. - search/proxy.DecodoProxy: username 에 -session-<시간창id>-sessionduration-<분> 부착 → 창 안에선 같은 IP, 창이 지나면 새 IP. 자격증명은 .env(DECODO_*), 4개 다 있어야 활성 - coupang/adapter: proxy 주입 + 세션창 경과 시 브라우저 재기동(IP 회전). 무프록시면 직접 연결 - worker_main: 쿠팡에만 DecodoProxy 경유(네이버는 공식 API라 미적용) - .env.example: DECODO_HOST/PORT/USERNAME/PASSWORD/SESSION_MINUTES 슬롯 - tests: 활성조건·sticky username·server형식·세션창 회전 4건 → 전체 43/43 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""DECODO 프록시 제공자 테스트 (순수, 네트워크 불필요)."""
|
|
|
|
from services.search.proxy import DecodoProxy
|
|
|
|
|
|
def _p(**kw):
|
|
base = dict(host="gate.decodo.com", port="7000", username="user1", password="pw", session_minutes=10)
|
|
base.update(kw)
|
|
return DecodoProxy(**base)
|
|
|
|
|
|
def test_disabled_when_credentials_missing():
|
|
assert DecodoProxy(host="", port="", username="", password="").enabled is False
|
|
assert DecodoProxy(host="h", port="7000", username="", password="pw").enabled is False
|
|
assert _p().playwright_proxy() is not None # 다 채우면 활성
|
|
assert DecodoProxy(host="", port="", username="", password="").playwright_proxy() is None
|
|
|
|
|
|
def test_playwright_proxy_shape_and_sticky_username():
|
|
cfg = _p().playwright_proxy()
|
|
assert cfg["server"] == "http://gate.decodo.com:7000"
|
|
assert cfg["password"] == "pw"
|
|
# sticky: base username + 세션/유지시간 파라미터
|
|
assert cfg["username"].startswith("user1-session-")
|
|
assert cfg["username"].endswith("-sessionduration-10")
|
|
|
|
|
|
def test_non_sticky_uses_plain_username():
|
|
cfg = _p(sticky=False).playwright_proxy()
|
|
assert cfg["username"] == "user1"
|
|
|
|
|
|
def test_session_id_rotates_by_time_window():
|
|
p = _p(session_minutes=10)
|
|
sid = p._session_id()
|
|
assert isinstance(sid, int)
|
|
# 같은 창 안에서는 동일해야 함(연속 호출)
|
|
assert p._session_id() == sid
|
|
# 창 크기가 다르면(1분) 버킷 값도 달라짐(더 큰 수) — 시간창 분해 검증
|
|
assert _p(session_minutes=1)._session_id() > sid
|