📋 Product Owner view
Feature inventory, spec alignment, behavioural gaps · Product Owner, Product Manager
⚡ Agent trace · 13 steps · $0.0465 · click to expand
search_claims(query='feature capability user', category='any') →
search_claims(query='api endpoint route', category='any') →
search_claims(query='README spec documentation', category='informational') →
search_claims(query='app application', max_results=30) →
search_claims(query='user', max_results=30) →
search_claims(query='model', max_results=30) →
search_claims(query='session', max_results=30) →
search_claims(query='get post put delete request', max_results=30) →
search_claims(query='cookie redirect timeout', max_results=30) →
search_claims(query='redirect', max_results=30) →
search_claims(query='auth authentication', max_results=30) →
search_claims(query='error exception', max_results=30) →
search_claims(query='stream download upload file', max_results=30) →
search_claims(query='json data body parameter', max_results=30) →
search_claims(query='certificate verify ssl tls', max_results=30) →
search_claims(query='stream', max_results=30) →
search_claims(query='json', max_results=30) →
search_claims(query='verify cert ssl', max_results=30) →
search_claims(query='proxy', max_results=30) →
search_claims(query='hook', max_results=30) →
search_claims(query='timeout', max_results=30) →
read_source_file(file_path='src/requests/__init__.py', start_line=1) →
read_source_file(file_path='src/requests/api.py', start_line=1) →
read_source_file(file_path='src/requests/models.py', start_line=1) →
read_source_file(file_path='src/requests/api.py', start_line=62) →
read_source_file(file_path='src/requests/sessions.py', start_line=127) →
read_source_file(file_path='src/requests/sessions.py', start_line=440) →
read_source_file(file_path='src/requests/sessions.py', start_line=500) →
read_source_file(file_path='src/requests/sessions.py', start_line=557) →
read_source_file(file_path='src/requests/sessions.py', start_line=617) →
read_source_file(file_path='src/requests/sessions.py', start_line=700) →
read_source_file(file_path='src/requests/sessions.py', start_line=760) →
read_source_file(file_path='src/requests/models.py', start_line=860)
Product View: Python Requests Library
Feature Inventory
| Feature | Status | Confidence | Notes |
|---|---|---|---|
| HTTP Method Support (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) | Implemented | High | All 7 methods exposed via requests.get(), requests.post(), etc. (src/requests/api.py:74-120) and Session methods (src/requests/sessions.py:655-750) |
| Session Management (persistent settings, cookies, connection pooling) | Implemented | High | Full Session class with __enter__/__exit__ context manager, cookie persistence across requests, merged settings (src/requests/sessions.py:442-503) |
| JSON Request Body | Implemented | High | json parameter auto-sets Content-Type: application/json and UTF-8 encodes body (src/requests/models.py:422-449) |
| JSON Response Parsing | Implemented | High | Response.json() method with encoding detection, custom JSONDecodeError exception (src/requests/models.py:1031-1047) |
| File Upload (Multipart) | Implemented | High | files parameter supports 2-tuple, 3-tuple, 4-tuple format with custom headers (src/requests/api.py:38-42) |
| Basic Authentication | Implemented | High | HTTPBasicAuth class, tuple auth, netrc support (src/requests/auth.py:34-75, src/requests/auth.py:345-351) |
| Digest Authentication | Implemented | High | HTTPDigestAuth with per-thread state, 401 retry, redirect handling (src/requests/auth.py:124-354) |
| Proxy Support | Implemented | High | HTTP/HTTPS/SOCKS proxies, environment variable support, Windows registry bypass, Proxy-Authorization header (src/requests/adapters.py:66-67, src/requests/utils.py:99-146) |
| SSL/TLS Certificate Verification | Implemented | High | verify parameter (bool or path to CA bundle), cert parameter for client certs, mutual TLS support (src/requests/adapters.py:307-363) |
| Redirect Following | Implemented | High | Configurable via allow_redirects, max 30 redirects, auth stripping logic, 307/308 body preservation (src/requests/sessions.py:134-307) |
| Streaming Responses | Implemented | High | stream parameter, iter_content() and iter_lines() methods, Unicode decoding option (src/requests/models.py:912-973) |
| Timeout Configuration | Implemented | High | Tuple (connect, read) or single float, TimeoutSauce object, specific ConnectTimeout/ReadTimeout exceptions (src/requests/adapters.py:634-748) |
| Cookie Handling | Implemented | High | CookieJar persistence across session, cookie extraction from redirect chains (src/requests/sessions.py:752-829) |
| Response Hooks | Implemented | High | register_hook/deregister_hook on Request, dispatch_hook on response, session-level hooks merged with request hooks (src/requests/hooks.py:32-48, src/requests/models.py:258-269) |
| HEAD Request Default No-Redirect | Implemented | High | head() defaults allow_redirects=False — intentional design choice (src/requests/api.py:102-114) |
| Error/Exception Hierarchy | Implemented | High | 20+ exception types including ConnectionError, Timeout, SSLError, ProxyError, TooManyRedirects, InvalidJSONError (src/requests/exceptions.py:20-35) |
| Session Serialization (Pickling) | Implemented | High | __getstate__/__setstate__ for session persistence (src/requests/sessions.py:655-671) |
| Environment Variable Integration | Implemented | High | trust_env flag controls reading proxy, CA bundle, and netrc from environment (src/requests/sessions.py:831-868) |
| Custom Connection Adapters | Implemented | High | mount()/get_adapter() with prefix matching, case-insensitive (src/requests/sessions.py:500-503) |
| Windows Proxy Bypass | Implemented | High | Reads ProxyEnable/ProxyOverride from Windows registry, glob pattern matching (src/requests/utils.py:99-135) |
| Character Encoding Detection | Implemented | High | charset_normalizer or chardet fallback, apparent_encoding property (src/requests/models.py:894-902) |
| Help/Info Module | Implemented | High | requests.help() prints environment info as JSON (src/requests/help.py:69-125) |
Overall Assessment: All documented features are fully implemented. This is a mature, production-grade HTTP library. No features are partial or scaffolding.
What the Code Does That the Spec Doesn't Mention
-
HEAD requests silently disable redirects by default — The
head()function at both the API level (src/requests/api.py:113) and Session level (src/requests/sessions.py:684-693) setsallow_redirects=Falseby default. This is a deliberate design choice (HEAD responses should not follow redirects per HTTP semantics), but it's a behavioral difference from all other methods that users may not expect. -
dataandjsoncannot be used together — When bothdataandjsonare provided, onlydatais used in the body. Thejsonparameter is silently ignored (src/requests/models.py:422-449). Tests confirm this (tests/test_requests.py:2141-2149). This is not documented in the API docstrings. -
Session headers with
Nonevalues are excluded from requests — If a session header is set toNone, it is stripped from the prepared request rather than sent as an empty header (tests/test_requests.py:496-502). This is a user-facing behavior that could affect debugging. -
Redirect auth stripping has special-case logic — Authorization headers are stripped on cross-host redirects, but there's a specific exception: HTTP→HTTPS redirects on standard ports (80→443) are allowed to keep auth (
src/requests/sessions.py:154-184). This is a backward-compatibility decision not documented in the API reference. -
Non-ASCII redirect locations are re-encoded — The
get_redirect_targetmethod encodes theLocationheader in latin1 and then decodes as UTF-8 (src/requests/sessions.py:134-152). This handles a real-world encoding ambiguity but is an undocumented heuristic. -
Streaming bodies are seeked for redirect replay — When a request body is a stream, the library records the stream position and rewinds it for redirect retries. If rewinding fails, it raises
UnrewindableBodyError(src/requests/utils.py:1139-1155). This is critical for users sending file-like objects with redirects. -
Response.okis NOT a 200 check — Theokproperty returnsTruefor any status code < 400, not just 200 (src/requests/models.py:860-872). This is a common point of confusion for new users. -
Digest auth resets its 401 counter on redirect —
HTTPDigestAuth.handle_redirectresetsnum_401_callsto 1 on redirect responses (src/requests/auth.py:268-271). This prevents the auth from giving up after a redirect to another digest-protected resource. -
Session is a context manager that closes adapters — Using
with requests.Session() as s:closes all connection pools on exit (src/requests/sessions.py:505-509,src/requests/adapters.py:555-563). This prevents resource warnings but is an implicit behavior users may not realize. -
Response.nextis only populated when redirects are NOT followed — Thenextproperty returns aPreparedRequestfor the next redirect only whenallow_redirects=False(src/requests/sessions.py:818-820). When redirects are followed, the history is flattened intoresponse.history.
Spec Gaps
This codebase is the Python requests library (v2.x era, with type hints added). There is no separate spec/README file in the extracted claims — the "spec" is the docstrings and the public API. Based on the code:
-
No documented behavior for
data={}default — InSession.request(),datadefaults to{}(empty dict) when not provided (src/requests/sessions.py:628). This means every request without explicit data sends an empty form-encoded body. This could surprise users who expect no body at all for GET/DELETE requests. -
jsonparameter silently ignored whendatais also provided — The docstrings forpost()andSession.request()list bothdataandjsonas optional, but don't document thatdatatakes precedence. A user providing both would expect an error or merge behavior. -
No documented limit on redirect count — The default is 30 (
src/requests/sessions.py:488), but this is not mentioned in the API docstrings forrequest()orSession.request(). -
streamparameter default behavior is implicit — The Session defaultsstream=False(src/requests/sessions.py:466), meaning response content is always fully downloaded unless explicitly opted out. This is documented in therequest()docstring but not in the Session class docstring. -
No mention of
trust_envin convenience function docstrings — Therequests.get(),requests.post(), etc. docstrings don't mention that environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY, REQUESTS_CA_BUNDLE) are read by default.
Open Questions for Engineering
-
data={}default — bug or feature? InSession.request()line 628,datadefaults to{}(empty dict). This means asession.get(url)sends an emptyContent-Type: application/x-www-form-urlencodedbody. Is this intentional? It could break servers that reject unexpected request bodies on GET. Theapi.pyconvenience functions passdata=Noneby default, so this only affects directSession.request()usage. -
json+datasilent override — should this raise? When bothdataandjsonare provided,datawins silently. Should we raise aValueError(like we do fordata+filesconflicts atsrc/requests/models.py:422-449)? The current behavior is surprising and could lead to hard-to-debug issues. -
HEAD redirect behavior — is the default
Falseuniversally correct? Thehead()function defaultsallow_redirects=False. While this follows HTTP spec guidance, some APIs return 302 on HEAD and expect clients to follow. Should this be configurable without kwargs? The current implementation forces users to writerequests.head(url, allow_redirects=True)explicitly. -
Response.oknaming confusion — The property returnsTruefor any 2xx or 3xx status. Users frequently assume it means "status == 200". Consider whether a deprecation or clearer documentation is warranted. -
Session pickling — what's the use case? The
__getstate__/__setstate__implementation serializes session attributes but not connection pools. Is this for caching session configuration (headers, auth, cookies) across process restarts? The current implementation would lose live connections. -
No rate limiting or retry built-in — The library delegates retry logic to urllib3. Users who want automatic retries must configure
HTTPAdapterwithmax_retries. Should this be a first-class parameter onSession.request()? -
certparameter accepts a tuple but docstrings only mention string — Thecertparameter can be a('cert', 'key')tuple, but the docstring atsrc/requests/api.py:55says "if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair." — this is actually documented correctly in the API but the Session docstring at line 615 only mentions the string case. Inconsistency.