A comprehensive HTTP client library that supports many features left out of other HTTP libraries.
—
Comprehensive exception hierarchy for handling HTTP errors, connection failures, authentication issues, and malformed responses. All exceptions derive from HttpLib2Error base class, providing structured error handling for different failure scenarios.
Foundation exception classes that provide the base structure for all httplib2 errors.
class HttpLib2Error(Exception):
"""Base exception for all httplib2 errors."""
class HttpLib2ErrorWithResponse(HttpLib2Error):
"""
Exception that includes HTTP response data.
Attributes:
response: HTTP response object containing status and headers
content: Response body content
"""
def __init__(self, desc, response, content):
"""
Initialize with description and response data.
Args:
desc (str): Error description
response: HTTP response object
content: Response body content
"""
self.response = response
self.content = contentExceptions for HTTP-specific errors that include response information.
class RedirectLimit(HttpLib2ErrorWithResponse):
"""
Too many redirects followed.
Raised when redirect count exceeds configured maximum.
"""
class RedirectMissingLocation(HttpLib2ErrorWithResponse):
"""
Redirect response missing Location header.
Raised when server sends redirect status without Location header.
"""
class FailedToDecompressContent(HttpLib2ErrorWithResponse):
"""
Content decompression failure.
Raised when gzip/deflate decompression fails.
"""Exceptions for authentication-related failures.
class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse):
"""
Unsupported digest authentication option.
Raised when server requests unsupported digest auth feature.
"""
class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse):
"""
Unsupported HMAC digest authentication option.
Raised when server requests unsupported HMAC digest auth feature.
"""Exceptions for protocol-level errors and malformed data.
class MalformedHeader(HttpLib2Error):
"""
Malformed HTTP header.
Raised when HTTP headers cannot be parsed correctly.
"""
class RelativeURIError(HttpLib2Error):
"""
Relative URI provided when absolute URI required.
Raised when relative URI given to request() method.
"""Exceptions for network-level connectivity issues.
class ServerNotFoundError(HttpLib2Error):
"""
Server hostname not found.
Raised when DNS resolution fails for target hostname.
"""
class ProxiesUnavailableError(HttpLib2Error):
"""
Proxy support unavailable.
Raised when proxy configured but PySocks library not installed.
"""import httplib2
h = httplib2.Http()
try:
(resp, content) = h.request("http://example.org/")
if resp.status >= 400:
print(f"HTTP Error: {resp.status} {resp.reason}")
else:
print("Request successful")
except httplib2.HttpLib2Error as e:
print(f"httplib2 error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")import httplib2
h = httplib2.Http()
try:
(resp, content) = h.request("http://example.org/redirect-loop")
except httplib2.RedirectLimit as e:
print(f"Too many redirects: {e}")
print(f"Last response status: {e.response.status}")
print(f"Last response headers: {dict(e.response)}")
except httplib2.RedirectMissingLocation as e:
print(f"Redirect without location: {e}")
print(f"Response status: {e.response.status}")
except httplib2.ServerNotFoundError as e:
print(f"Server not found: {e}")
except httplib2.HttpLib2Error as e:
print(f"Other httplib2 error: {e}")import httplib2
h = httplib2.Http()
h.add_credentials('user', 'pass')
try:
(resp, content) = h.request("https://api.example.com/protected")
except httplib2.UnimplementedDigestAuthOptionError as e:
print(f"Unsupported digest auth option: {e}")
print(f"Server challenge: {e.response.get('www-authenticate', '')}")
except httplib2.UnimplementedHmacDigestAuthOptionError as e:
print(f"Unsupported HMAC digest auth option: {e}")
except httplib2.HttpLib2ErrorWithResponse as e:
if e.response.status == 401:
print("Authentication failed")
elif e.response.status == 403:
print("Access forbidden")import httplib2
h = httplib2.Http()
try:
(resp, content) = h.request("http://example.org/compressed-data")
# Process content
text = content.decode('utf-8')
except httplib2.FailedToDecompressContent as e:
print(f"Decompression failed: {e}")
print(f"Content-Encoding: {e.response.get('content-encoding', 'none')}")
# Fallback to raw content
raw_content = e.content
except UnicodeDecodeError as e:
print(f"Encoding error: {e}")
# Try different encoding or handle as binaryimport httplib2
import socket
h = httplib2.Http(timeout=10)
try:
(resp, content) = h.request("http://nonexistent.example.com/")
except httplib2.ServerNotFoundError as e:
print(f"DNS resolution failed: {e}")
except socket.timeout as e:
print(f"Request timed out: {e}")
except socket.error as e:
print(f"Socket error: {e}")
except httplib2.HttpLib2Error as e:
print(f"Other httplib2 error: {e}")import httplib2
import socks
try:
# Attempt to use proxy without PySocks installed
proxy_info = httplib2.ProxyInfo(
socks.PROXY_TYPE_HTTP,
'proxy.example.com',
8080
)
h = httplib2.Http(proxy_info=proxy_info)
(resp, content) = h.request("http://example.org/")
except httplib2.ProxiesUnavailableError as e:
print(f"Proxy support unavailable: {e}")
print("Install PySocks: pip install PySocks")
except AttributeError as e:
print(f"PySocks not installed: {e}")import httplib2
h = httplib2.Http()
try:
# Request with malformed response headers
(resp, content) = h.request("http://broken-server.example.com/")
except httplib2.MalformedHeader as e:
print(f"Malformed header: {e}")
except httplib2.RelativeURIError as e:
print(f"Invalid URI: {e}")
except httplib2.HttpLib2Error as e:
print(f"Protocol error: {e}")import httplib2
import time
def robust_request(url, max_retries=3, delay=1):
"""Make HTTP request with retry logic."""
h = httplib2.Http()
for attempt in range(max_retries):
try:
(resp, content) = h.request(url)
return (resp, content)
except httplib2.ServerNotFoundError:
# Don't retry DNS failures
raise
except (httplib2.HttpLib2Error, socket.error) as e:
if attempt == max_retries - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}")
time.sleep(delay * (2 ** attempt)) # Exponential backoffimport httplib2
def request_with_fallback(primary_url, fallback_url):
"""Try primary URL, fall back to secondary."""
h = httplib2.Http()
try:
return h.request(primary_url)
except httplib2.ServerNotFoundError:
print(f"Primary server unavailable, trying fallback")
return h.request(fallback_url)
except httplib2.RedirectLimit:
print(f"Too many redirects on primary, trying fallback")
return h.request(fallback_url)import httplib2
def detailed_request(url):
"""Make request with detailed error information."""
h = httplib2.Http()
try:
return h.request(url)
except httplib2.HttpLib2ErrorWithResponse as e:
# Log detailed error information
error_info = {
'error_type': type(e).__name__,
'error_message': str(e),
'status_code': getattr(e.response, 'status', None),
'response_headers': dict(e.response) if e.response else None,
'response_content': e.content[:500] if e.content else None # First 500 bytes
}
print(f"Request failed with context: {error_info}")
raise
except httplib2.HttpLib2Error as e:
error_info = {
'error_type': type(e).__name__,
'error_message': str(e)
}
print(f"Request failed: {error_info}")
raiseInstall with Tessl CLI
npx tessl i tessl/pypi-httplib2