mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-06-10 03:02:09 +00:00
fix(session): proxy auth on http targets and string params support
Drop the manually-set Proxy-Authorization header in the Service base class. It was malformed (base64 of user:pass with no "Basic" scheme) and redundant: both rnet (Proxy.all) and requests authenticate from the credentials embedded in the proxy URL. The broken header was tunnelled harmlessly on HTTPS (CONNECT) but handed to the proxy on plaintext-http forward requests, causing HTTP 407 (e.g. http MPD/segment URLs behind an authenticated geofence proxy). Also make RnetSession._build_url accept the same params shapes as requests (mapping, sequence of pairs, or a pre-built str/bytes query). urlencode() previously raised TypeError on a string params value.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import base64
|
||||
import logging
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from collections.abc import Callable, Generator
|
||||
@@ -213,15 +212,10 @@ class Service(metaclass=ABCMeta):
|
||||
|
||||
if proxy:
|
||||
self.session.proxies.update({"all": proxy})
|
||||
proxy_parse = urlparse(proxy)
|
||||
if proxy_parse.username and proxy_parse.password:
|
||||
self.session.headers.update(
|
||||
{
|
||||
"Proxy-Authorization": base64.b64encode(
|
||||
f"{proxy_parse.username}:{proxy_parse.password}".encode("utf8")
|
||||
).decode()
|
||||
}
|
||||
)
|
||||
# Don't set Proxy-Authorization manually: both rnet (Proxy.all) and
|
||||
# requests authenticate from the credentials embedded in the proxy URL.
|
||||
# A manual header here was malformed (no "Basic " scheme) and broke
|
||||
# plaintext-http forward-proxy requests with HTTP 407.
|
||||
# Always verify proxy IP - proxies can change exit nodes
|
||||
try:
|
||||
proxy_ip_info = get_ip_info(self.session)
|
||||
|
||||
@@ -523,15 +523,24 @@ class RnetSession:
|
||||
self.cookies._flush_to_client()
|
||||
return self._client
|
||||
|
||||
def _build_url(self, url: str, params: Optional[dict] = None) -> str:
|
||||
"""URL-encode params dict into the URL (rnet ignores params kwarg)."""
|
||||
def _build_url(self, url: str, params: Optional[Any] = None) -> str:
|
||||
"""Encode params into the URL (rnet ignores the params kwarg).
|
||||
|
||||
Accepts the same shapes as requests: a mapping, a sequence of pairs, or a
|
||||
pre-built query string/bytes. A string is appended verbatim (already encoded);
|
||||
urlencode() would raise TypeError on it.
|
||||
"""
|
||||
if not params:
|
||||
return url
|
||||
if isinstance(params, bytes):
|
||||
extra = params.decode("utf-8")
|
||||
elif isinstance(params, str):
|
||||
extra = params
|
||||
else:
|
||||
extra = urlencode(params, doseq=True)
|
||||
parsed = urlparse(url)
|
||||
separator = "&" if parsed.query else ""
|
||||
query = (
|
||||
parsed.query + separator + urlencode(params, doseq=True) if parsed.query else urlencode(params, doseq=True)
|
||||
)
|
||||
query = parsed.query + separator + extra if parsed.query else extra
|
||||
return urlunparse(parsed._replace(query=query))
|
||||
|
||||
def get_sleep_time(self, response: Optional[RnetResponse], attempt: int) -> Optional[float]:
|
||||
|
||||
Reference in New Issue
Block a user