Advocate HTTP Client
raw JSON → 1.0.0 verified Thu Apr 16 auth: no python
Advocate is a Python library providing a safe wrapper around the popular `requests` library for making HTTP requests on behalf of a third party. It helps prevent common security pitfalls like SSRF by allowing developers to define strict URL validation patterns, limit redirects, set timeouts, and control request options. The current version is 1.0.0, and it maintains a stable release cadence focused on security and reliability.
pip install advocate Common errors
error advocate.exceptions.InvalidURLError: URL 'http://evil.com' does not match configured regex pattern. ↓
cause The URL provided to an Advocate request method (e.g., `get`, `post`) does not match the regular expression pattern defined in the `url_regex_pattern` parameter during `Advocate` initialization.
fix
Review your
Advocate instance's url_regex_pattern to ensure it correctly allows the URLs you intend to access. If the URL is genuinely invalid, do not attempt to access it. If it should be allowed, adjust the regex pattern carefully. error advocate.exceptions.RedirectError: Request resulted in a redirect to 'https://new-location.com' but raise_on_redirect is True. ↓
cause The requested URL returned an HTTP redirect, but the `Advocate` instance was configured with `raise_on_redirect=True`, which explicitly forbids following redirects.
fix
If you intend to follow redirects, set
raise_on_redirect=False during Advocate initialization. If redirects are a security concern (as often recommended for third-party requests), investigate why the target URL is redirecting. error AttributeError: 'Advocate' object has no attribute 'json' ↓
cause You are attempting to call a response method like `.json()`, `.text`, or `.status_code` directly on the `Advocate` instance itself, instead of on the `response` object returned by its request methods.
fix
Store the result of
advocate.get() (or post, etc.) in a variable, then call response methods on that variable. Example: response = advocate.get(url); data = response.json(). Warnings
gotcha The `url_regex_pattern` is critical for security. If it's too broad or incorrectly specified, it can negate Advocate's safety features, potentially exposing your application to Server-Side Request Forgery (SSRF) vulnerabilities. ↓
fix Thoroughly test your `url_regex_pattern` to ensure it only permits intended URLs. Use online regex testers and consider edge cases. It's often safer to define a whitelist of allowed domains/paths rather than trying to blacklist.
gotcha Misconfiguring `max_redirects` and `raise_on_redirect` can lead to unexpected behavior or security issues. For third-party requests, unsolicited redirects might point to malicious or unintended destinations. ↓
fix For sensitive third-party requests, it's generally recommended to set `max_redirects=0` and `raise_on_redirect=True` to explicitly control and prevent redirects. Only allow redirects if you fully trust the redirect chain.
gotcha Advocate adds overhead due to URL validation and other safety checks. Using it for requests where there is no third-party involvement or trust concern can introduce unnecessary performance penalties. ↓
fix Only use `Advocate` when making HTTP requests on behalf of an untrusted third party or when strict URL validation and request control are required for security. For internal or trusted requests, use `requests` directly.
Imports
- Advocate
from advocate import Advocate
Quickstart
from advocate import Advocate
# Configure Advocate for safe third-party requests
# This example allows requests only to google.com/search
advocate = Advocate(
url_regex_pattern="^https://www\.google\.com/search",
max_redirects=0, # Disallow redirects for this sensitive operation
raise_on_redirect=True,
timeout=5, # Set a timeout to prevent hanging requests
requests_options={
"headers": {"User-Agent": "MySafeClient/1.0"},
"verify": True # Ensure SSL verification is on
}
)
try:
# Make a safe GET request
response = advocate.get("https://www.google.com/search?q=python+advocate")
response.raise_for_status() # Raise an exception for HTTP errors (4xx or 5xx)
print(f"Request successful! Status: {response.status_code}")
print("First 200 characters of response:")
print(response.text[:200])
except advocate.exceptions.InvalidURLError as e:
print(f"Invalid URL error: {e}")
except advocate.exceptions.RedirectError as e:
print(f"Redirect error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example of a disallowed URL (will raise InvalidURLError)
try:
advocate.get("http://internal-api.example.com/sensitive-data")
except advocate.exceptions.InvalidURLError as e:
print(f"Successfully blocked disallowed URL: {e}")
except Exception as e:
print(f"Unexpected error for disallowed URL: {e}")