A comprehensive HTTP client library that supports many features left out of other HTTP libraries.
—
URI parsing, normalization, IRI to URI conversion, certificate management, and other utility functions supporting the main HTTP client functionality. These utilities handle the low-level details of HTTP protocol implementation.
Functions for parsing, normalizing, and converting URI formats.
def parse_uri(uri):
"""
Parse URI into components.
Args:
uri (str): URI to parse
Returns:
tuple: (scheme, authority, path, query, fragment)
"""
def urlnorm(uri):
"""
Normalize URI format for consistent processing.
Args:
uri (str): URI to normalize
Returns:
tuple: (scheme, authority, request_uri, defrag_uri)
"""
def iri2uri(uri):
"""
Convert IRI (Internationalized Resource Identifier) to URI.
Encodes non-ASCII characters in IRIs to create valid URIs.
IRIs must be passed as unicode strings.
Args:
uri (str): IRI to convert (must be unicode string)
Returns:
str: Valid URI with non-ASCII characters encoded
"""Functions for managing HTTP connections and timeouts.
def has_timeout(timeout):
"""
Check if timeout value is set and valid.
Args:
timeout: Timeout value to check
Returns:
bool: True if timeout is set and not default
"""Functions for generating safe cache filenames and keys.
def safename(filename):
"""
Generate safe filename for caching.
Converts potentially unsafe characters in filenames to safe alternatives
for cross-platform filesystem compatibility.
Args:
filename (str): Original filename
Returns:
str: Safe filename for filesystem storage
"""Functions and classes for managing SSL/TLS certificates.
# From httplib2.certs module
def where():
"""
Locate CA certificates file.
Searches for CA certificates in the following order:
1. HTTPLIB2_CA_CERTS environment variable
2. ca_certs_locater.get() if available
3. certifi.where() if available
4. Built-in CA certificates file
Returns:
str: Path to CA certificates file
Raises:
RuntimeError: If HTTPLIB2_CA_CERTS points to invalid file
"""
BUILTIN_CA_CERTS = "path/to/builtin/cacerts.txt"
"""Path to built-in CA certificates file."""Internal utilities for processing HTTP headers and content.
def _normalize_headers(headers):
"""
Normalize header names and values.
Args:
headers (dict): HTTP headers dictionary
Returns:
dict: Normalized headers with lowercase names
"""
def _parse_cache_control(headers):
"""
Parse Cache-Control header directives.
Args:
headers (dict): HTTP headers
Returns:
dict: Parsed cache control directives
"""
def _get_end2end_headers(response):
"""
Get end-to-end headers from response.
Filters out hop-by-hop headers that shouldn't be cached.
Args:
response: HTTP response object
Returns:
list: End-to-end header names
"""import httplib2
from httplib2 import parse_uri, urlnorm, iri2uri
# Parse URI components
uri = "https://example.com:8080/path/to/resource?param=value#section"
(scheme, authority, path, query, fragment) = parse_uri(uri)
print(f"Scheme: {scheme}")
print(f"Authority: {authority}")
print(f"Path: {path}")
print(f"Query: {query}")
print(f"Fragment: {fragment}")
# Normalize URI
(scheme, authority, request_uri, defrag_uri) = urlnorm(uri)
print(f"Request URI: {request_uri}")
print(f"Defragmented URI: {defrag_uri}")
# Convert IRI to URI
iri = "http://例え.テスト/パス" # Japanese IRI
uri = iri2uri(iri)
print(f"Converted URI: {uri}")import httplib2.certs
import os
# Get CA certificates location
ca_certs_path = httplib2.certs.where()
print(f"CA certificates: {ca_certs_path}")
# Use custom CA certificates
os.environ['HTTPLIB2_CA_CERTS'] = '/path/to/custom/cacerts.pem'
custom_ca_path = httplib2.certs.where()
print(f"Custom CA certificates: {custom_ca_path}")
# Create HTTP client with specific CA certificates
h = httplib2.Http(ca_certs=custom_ca_path)
(resp, content) = h.request("https://secure.example.com/")import httplib2
from httplib2 import safename
# Generate safe filenames for caching
unsafe_names = [
"http://example.com/path?param=value",
"file with spaces.txt",
"file/with/slashes.txt",
"file:with:colons.txt"
]
for name in unsafe_names:
safe = safename(name)
print(f"'{name}' -> '{safe}'")
# Use in custom cache implementation
class CustomCache:
def __init__(self, cache_dir):
self.cache_dir = cache_dir
def _get_path(self, key):
safe_key = safename(key)
return os.path.join(self.cache_dir, safe_key)
def get(self, key):
path = self._get_path(key)
try:
with open(path, 'rb') as f:
return f.read()
except FileNotFoundError:
return None
def set(self, key, value):
path = self._get_path(key)
with open(path, 'wb') as f:
f.write(value)import httplib2
import socket
# Check timeout configuration
timeouts = [None, 0, 30, socket._GLOBAL_DEFAULT_TIMEOUT]
for timeout in timeouts:
has_timeout = httplib2.has_timeout(timeout)
print(f"Timeout {timeout}: {'has timeout' if has_timeout else 'no timeout'}")
# Use with HTTP client
h = httplib2.Http(timeout=30)
if httplib2.has_timeout(30):
print("Client configured with timeout")import httplib2
# Internal header processing (normally handled automatically)
headers = {
'Content-Type': 'application/json',
'Cache-Control': 'max-age=3600, public',
'Connection': 'keep-alive'
}
# Normalize headers (internal function)
normalized = httplib2._normalize_headers(headers)
print(f"Normalized headers: {normalized}")
# Parse cache control
cache_directives = httplib2._parse_cache_control(normalized)
print(f"Cache directives: {cache_directives}")The iri2uri function handles internationalized resource identifiers:
import httplib2
# Examples of IRI to URI conversion
iris = [
"http://例え.テスト/", # Japanese domain
"http://пример.испытание/", # Russian domain
"http://example.com/café", # Accented characters in path
"http://example.com/?q=naïve", # Accented characters in query
"http://example.com/#español" # Accented characters in fragment
]
for iri in iris:
uri = httplib2.iri2uri(iri)
print(f"IRI: {iri}")
print(f"URI: {uri}")
print()The safename function ensures cache filenames work across different filesystems:
import httplib2
# Characters that need escaping in filenames
problematic_chars = [
"http://example.com/", # Slashes
"file?query=value", # Question marks
"file:with:colons", # Colons (Windows)
"file<with>brackets", # Angle brackets
"file|with|pipes", # Pipes
"file*with*asterisks", # Asterisks
"file\"with\"quotes", # Quotes
"very long filename " * 10 # Long names
]
for name in problematic_chars:
safe = httplib2.safename(name)
print(f"Original: {name[:50]}")
print(f"Safe: {safe[:50]}")
print()Internal utilities for authentication processing:
import httplib2.auth
# Parse WWW-Authenticate header
headers = {
'www-authenticate': 'Basic realm="Protected Area"'
}
auth_info = httplib2.auth._parse_www_authenticate(headers)
print(f"Authentication info: {auth_info}")
# Parse Authentication-Info header
auth_response_headers = {
'authentication-info': 'nextnonce="abcdef123456"'
}
auth_response = httplib2.auth._parse_authentication_info(auth_response_headers)
print(f"Authentication response: {auth_response}")These functions are primarily used internally but may be useful for advanced usage:
import httplib2
# Content decompression (handled automatically)
response_headers = {'content-encoding': 'gzip'}
# compressed_content = gzip.compress(b"Hello, World!")
# decompressed = httplib2._decompressContent(response_headers, compressed_content)
# Entry disposition for caching
request_headers = {'cache-control': 'no-cache'}
response_headers = {'cache-control': 'max-age=3600'}
disposition = httplib2._entry_disposition(response_headers, request_headers)
print(f"Cache disposition: {disposition}")
# Cache key generation (internal)
# Cache keys are generated from normalized URIs and relevant headersImportant constants used throughout httplib2:
import httplib2
# HTTP constants
print(f"Safe methods: {httplib2.SAFE_METHODS}")
print(f"Redirect codes: {httplib2.REDIRECT_CODES}")
print(f"Hop-by-hop headers: {httplib2.HOP_BY_HOP}")
print(f"Default max redirects: {httplib2.DEFAULT_MAX_REDIRECTS}")
print(f"Default retries: {httplib2.RETRIES}")
# SSL/TLS configuration
print(f"CA certificates: {httplib2.CA_CERTS}")import httplib2
import urllib.parse
def advanced_uri_processing(uri):
"""Demonstrate advanced URI processing."""
# Parse with httplib2
(scheme, authority, path, query, fragment) = httplib2.parse_uri(uri)
# Normalize
(norm_scheme, norm_authority, request_uri, defrag_uri) = httplib2.urlnorm(uri)
# Handle internationalization
if not uri.isascii():
uri = httplib2.iri2uri(uri)
# Additional parsing with urllib
parsed = urllib.parse.urlparse(uri)
return {
'original': uri,
'scheme': scheme,
'authority': authority,
'path': path,
'normalized_request_uri': request_uri,
'defragmented': defrag_uri,
'is_secure': scheme == 'https',
'default_port': 443 if scheme == 'https' else 80,
'hostname': parsed.hostname,
'port': parsed.port
}
# Example usage
uri_info = advanced_uri_processing("https://example.com:8080/path?q=test#top")
for key, value in uri_info.items():
print(f"{key}: {value}")Install with Tessl CLI
npx tessl i tessl/pypi-httplib2