···23> Auto-generated summary of recommendations from analyzing HTTP client libraries across multiple languages.
4000000000000000000000000000000000000000000000000005## Executive Summary
67This comprehensive analysis synthesizes recommendations from 45+ HTTP client libraries across 10 programming languages (Python, JavaScript, Go, Rust, Haskell, PHP, Java, Swift, C++, Bash). The most consistent themes are: (1) Security features like certificate pinning, cross-origin header stripping, and HTTPS enforcement for sensitive auth; (2) Middleware/interceptor systems for extensibility; (3) HTTP proxy support; (4) Progress callbacks for uploads/downloads; (5) Request cancellation capabilities; (6) Detailed timing metrics; (7) Retry logic improvements including Retry-After capping and custom predicates. The prioritization emphasizes security fixes that could lead to credential leakage, followed by missing features that block enterprise adoption (proxy support), then enhancements that improve developer experience.
···1112## Security & Spec Compliance
1314-### 1. Strip sensitive headers on cross-origin redirects
001516When redirecting to a different origin (host/port/scheme), automatically strip Authorization, Cookie, Proxy-Authorization, and WWW-Authenticate headers to prevent credential leakage to unintended domains. Also strip headers on HTTPS→HTTP protocol downgrade.
17···21**Cross-Language Consensus:** 8 libraries
22**Source Libraries:** reqwest, got, node-fetch, okhttp, axios, superagent, http-client, needle
2324-**Affected Files:**
25-- `lib/requests.ml`
26-- `lib/one.ml`
27-- `lib/http_client.ml`
2829-**Implementation Notes:**
30-Implement same_origin check comparing scheme, host, and port. Create a list of sensitive headers to strip. Call strip_sensitive_headers before following any redirect where origin changes.
3132-### 2. Add certificate/public key pinning support
3334Allow pinning certificates or public keys (SPKI hashes) to protect against compromised certificate authorities. Support per-host pinning configuration with wildcard patterns.
35···46**Implementation Notes:**
47Add certificate_pins parameter to create() accepting (hostname * sha256_hash list) list. Verify pins during TLS handshake by extracting SPKI from certificate chain. Provide helpful error messages showing expected vs actual hashes.
4849-### 3. Enforce HTTPS for sensitive authentication methods
005051Reject Basic, Bearer, and Digest authentication over unencrypted HTTP connections by default. Provide explicit opt-out flag (allow_insecure_auth) for testing environments.
52···57**Cross-Language Consensus:** 2 libraries
58**Source Libraries:** req (Haskell), urllib3
5960-**Affected Files:**
61-- `lib/auth.ml`
62-- `lib/auth.mli`
63-- `lib/requests.ml`
64-- `lib/one.ml`
6566-**Implementation Notes:**
67-Add runtime check in auth application: if scheme is http (not https) and auth is Basic/Bearer/Digest, raise Security_error unless allow_insecure_auth=true. Log warning when flag is used.
6869-### 4. Validate Content-Length vs Transfer-Encoding precedence
7071Per RFC 9112, when both Content-Length and Transfer-Encoding headers are present, ignore Content-Length. This prevents HTTP request smuggling attacks.
72···76**Cross-Language Consensus:** 2 libraries
77**Source Libraries:** hyper, http-streams
7879-**Affected Files:**
80-- `lib/http_read.ml`
008182-**Implementation Notes:**
83-Audit http_read.ml to ensure Transfer-Encoding: chunked takes precedence. Log warning when both headers present (potential attack indicator). Add test case for this scenario.
8485-### 5. Cap maximum Retry-After delay to prevent DoS
8687Implement a configurable maximum backoff time (default 120s) that caps server-specified Retry-After values, preventing malicious servers from causing indefinite client blocking.
88···92**Cross-Language Consensus:** 2 libraries
93**Source Libraries:** req (Go), got
9495-**Affected Files:**
96-- `lib/retry.ml`
97-- `lib/retry.mli`
98-99-**Implementation Notes:**
100-Add backoff_max field to Retry.config. In calculate_backoff, apply: min retry_after backoff_max. Document that very long delays (>backoff_max) result in immediate failure rather than unbounded waiting.
101102103---
104105## Feature Enhancements
106107-### 6. Add HTTP proxy support with environment variable detection
00108109Implement HTTP/HTTPS proxy support including: proxy URL configuration, authentication (Basic), CONNECT method for HTTPS tunneling, and automatic detection from HTTP_PROXY, HTTPS_PROXY, NO_PROXY environment variables.
110···122- `lib/one.ml`
123124**Implementation Notes:**
125-Add proxy configuration type with host/port/auth. Implement HTTP CONNECT for HTTPS proxies. Parse environment variables on session creation. Add NO_PROXY pattern matching for bypass. Strip Proxy-Authorization on HTTPS connections.
00126127-### 7. Implement request/response middleware system
128129Add a composable middleware chain that allows intercepting and transforming requests before sending and responses after receiving. Enable cross-cutting concerns like logging, metrics, request signing, and custom caching.
130···138**Implementation Notes:**
139Define type middleware = Request.t -> (Request.t -> Response.t) -> Response.t. Store middleware list in session. Execute chain: apply each middleware wrapping the next. Provide default middleware for retry and redirect as replaceable components.
140141-### 8. Add progress callbacks for uploads and downloads
00142143Implement optional progress callbacks that report bytes transferred, total size (if known), and percent complete. Rate-limit callbacks to prevent performance degradation.
144···154**Implementation Notes:**
155Add optional progress:(transferred:int64 -> total:int64 option -> unit) parameter. Track bytes during streaming read/write. Throttle callbacks (e.g., max 3/second or every 64KB). Support both upload and download progress.
156157-### 9. Add request cancellation support
00158159Allow programmatic cancellation of in-flight requests. Integrate with Eio's cancellation system while providing explicit cancel() function or cancel token pattern.
160···169**Implementation Notes:**
170Return (Response.t * cancel_token) from request functions where cancel_token allows aborting the request. Internally use Eio.Cancel or Switch.fail to terminate the fiber. Raise Cancelled error on cancellation.
171172-### 10. Add concurrent request batching API (map/imap)
00173174Provide map() for executing multiple requests concurrently and returning results in order, and imap() for yielding responses as they complete. Include configurable concurrency limits and batch timeout.
175···183**Implementation Notes:**
184Implement using Eio.Fiber.all for map, Eio.Stream for imap. Add max_concurrent parameter using Eio.Semaphore. Provide exception_handler callback for partial failure handling. Add batch_timeout for overall operation limit.
185186-### 11. Add base URL support with relative path resolution
00187188Allow configuring a base URL on the session that is prepended to relative request URLs. Use proper RFC 3986 URI resolution for correct path joining.
189···193**Cross-Language Consensus:** 5 libraries
194**Source Libraries:** surf, axios, got, sling, req (Go)
195196-**Affected Files:**
197-- `lib/requests.ml`
198-- `lib/requests.mli`
199-200-**Implementation Notes:**
201-Add base_url field to session type. In request methods, check if URL is relative (no scheme); if so, use Uri.resolve to join with base_url. Document trailing slash importance per RFC 3986.
202203204---
205206## Architectural Improvements
207208-### 12. Add detailed timing metrics to responses
00209210Expose granular timing breakdown: DNS lookup time, TCP connection time, TLS handshake time, time to first byte (TTFB), download time, and total time. Include connection reuse tracking.
211212**Cross-Language Consensus:** 7 libraries
213**Source Libraries:** curl-rust, got, resty, req (Go), guzzle, okhttp, isahc
214215-**Affected Files:**
216-- `lib/response.ml`
217-- `lib/response.mli`
218-- `lib/http_client.ml`
00219220-**Implementation Notes:**
221-Define type timings = { dns: float option; connect: float; tls: float option; send: float; first_byte: float; download: float; total: float; connection_reused: bool }. Instrument http_client.ml with timestamps at each phase.
222223-### 13. Add automatic retry on stale connection detection
224225Detect when a pooled connection was closed by the server between requests (NoResponseDataReceived) and automatically retry with a fresh connection. Mark this error as always retryable.
226227**Cross-Language Consensus:** 2 libraries
228**Source Libraries:** http-client (Haskell), okhttp
229230-**Affected Files:**
231-- `lib/http_client.ml`
232-- `lib/error.ml`
233-- `lib/retry.ml`
234-- `lib/conpool.ml`
000235236-**Implementation Notes:**
237-Add No_response_data error variant. In http_client, catch empty response on reused connection. Track connection reuse status. In retry logic, always retry No_response_data even for non-idempotent methods since request wasn't sent.
238239-### 14. Add custom retry condition predicates
240241Allow users to provide custom retry decision functions beyond status codes and error types. Separate predicates for response-based retry (status/headers) and exception-based retry.
242243**Cross-Language Consensus:** 4 libraries
244**Source Libraries:** resty, got, req (Go), req (Haskell)
245246-**Affected Files:**
247-- `lib/retry.ml`
248-- `lib/retry.mli`
249-250-**Implementation Notes:**
251-Add retry_condition:(Response.t option -> exn option -> retry_status -> bool) to Retry.config. Provide default that checks status_forcelist and Error.is_retryable. Allow custom logic for specific error messages, custom headers, etc.
0252253254---
255256## Feature Enhancements
257258-### 15. Add response charset/encoding detection and conversion
00259260Automatically detect character encoding from Content-Type charset parameter and convert response text to UTF-8. Provide BOM sniffing fallback for encoding detection.
261···273**Implementation Notes:**
274Parse charset from Content-Type in Mime module. Add Response.text_utf8 that detects and converts encoding. Use uutf library for encoding conversion. Return raw bytes on conversion failure with access to detected charset.
275276-### 16. Add redirect policy customization
00277278Allow custom redirect policies with access to attempt status, URL, and previous URLs. Enable controlling method preservation (307/308 vs 301/302), header stripping, and cross-protocol redirect behavior.
279···295296## Architectural Improvements
297298-### 17. Add TCP keep-alive configuration
00299300Expose TCP keep-alive settings including enable/disable, interval, and retry count. This helps detect broken connections and maintain long-lived connections through firewalls/NAT.
301···314315## Feature Enhancements
316317-### 18. Add URL sanitization for error messages
00318319Automatically sanitize URLs in error messages to prevent leakage of credentials embedded in query parameters (API keys, tokens). Provide without_url() method to strip URLs entirely.
320···328**Implementation Notes:**
329Extend existing sanitize_url function to handle query parameter credentials. Add Error.without_url to remove URL entirely from error. Apply sanitization automatically in Error.to_string and pp functions.
330331-### 19. Add Link header parsing for pagination
00332333Parse RFC 8288 Link headers to extract relation types (next, prev, first, last) for API pagination. Provide helpers like Response.next_url for common patterns.
334···338**Cross-Language Consensus:** 3 libraries
339**Source Libraries:** got, superagent, just
340341-**Affected Files:**
342-- `lib/headers.ml`
343-- `lib/headers.mli`
344-- `lib/response.ml`
345-346-**Implementation Notes:**
347-Add type link_rel = { url: string; rel: string; params: (string * string) list }. Implement parse_link_header following RFC 8288. Add Response.links and Response.next_url/prev_url convenience functions.
0348349350---
351352## Architectural Improvements
353354-### 20. Add mock handler for testing
00355356Provide a mock handler that queues pre-defined responses and exceptions for testing HTTP client code without network calls. Support request inspection and assertion.
357···370371## Feature Enhancements
372373-### 21. Add Result-based error_for_status variant
00374375Provide check_status() that returns (Response.t, Error.error) result instead of raising, enabling functional error handling alongside the existing raise_for_status.
376377**Cross-Language Consensus:** 2 libraries
378**Source Libraries:** reqwest, grequests
379380-**Affected Files:**
381-- `lib/response.ml`
382-- `lib/response.mli`
00383384-**Implementation Notes:**
385-Add Response.check_status : t -> (t, Error.error) result that returns Ok response for 2xx, Error with Http_error for 4xx/5xx. Complement existing raise_for_status for different coding styles.
386387-### 22. Add request body rewind support for retries
388389Track whether request bodies are rewindable (seekable) and automatically replay them on retry. Raise clear error when retry requires body replay but body is a consumed stream.
390···404405## Architectural Improvements
406407-### 23. Add event listener/hooks for observability
00408409Provide comprehensive event hooks at each request lifecycle stage: DNS start/end, connection start/end, TLS handshake, request headers/body sent, response headers/body received. Enable metrics and tracing integration.
410···424425## Feature Enhancements
426427-### 24. Add XSRF/CSRF token handling
00428429Automatically read CSRF token from a configurable cookie name (default: XSRF-TOKEN) and add it to request headers (default: X-XSRF-TOKEN) for same-origin requests.
430431**Cross-Language Consensus:** 1 libraries
432**Source Libraries:** axios
433434-**Affected Files:**
435-- `lib/requests.ml`
436-- `lib/headers.ml`
437-438-**Implementation Notes:**
439-Add xsrf_cookie_name and xsrf_header_name config options. Before request, if cookie exists, add corresponding header. Only for same-origin requests. Disable by setting cookie name to empty.
440441442---
443444## Architectural Improvements
445446-### 25. Add decompression bomb protection
00447448Enforce configurable compression ratio limits (e.g., 100:1) to detect and abort decompression bomb attacks. Track compressed vs decompressed bytes during streaming.
449450**Cross-Language Consensus:** 1 libraries
451**Source Libraries:** axios
452453-**Affected Files:**
454-- `lib/http_read.ml`
455-- `lib/response_limits.ml`
456-457-**Implementation Notes:**
458-Add max_compression_ratio to Response_limits. During decompression, track input/output bytes. If ratio exceeds limit, raise Decompression_bomb error. Use existing error type from error.ml.
459460461---
462463## Feature Enhancements
464465-### 26. Add HTTP version to response metadata
00466467Expose the HTTP version used for the response (HTTP/1.0, HTTP/1.1, HTTP/2) in Response type. Useful for debugging protocol negotiation and monitoring HTTP/2 adoption.
468469**Cross-Language Consensus:** 3 libraries
470**Source Libraries:** reqwest, surf, curl-rust
471472-**Affected Files:**
473-- `lib/response.ml`
474-- `lib/response.mli`
475-- `lib/http_read.ml`
00476477-**Implementation Notes:**
478-Add http_version field to Response.t. Parse version from status line. Add Response.version accessor. Prepare for future HTTP/2 support.
479480-### 27. Add Unix domain socket support
481482Enable connecting to local services via Unix domain sockets (e.g., Docker daemon at /var/run/docker.sock) without TCP overhead.
483···497498## Security & Spec Compliance
499500-### 28. Restrict URL protocols to HTTP/HTTPS only
00501502Explicitly whitelist only http:// and https:// protocols to prevent protocol smuggling attacks via file://, ftp://, gopher://, etc. Reject invalid protocols early in URL parsing.
503504**Cross-Language Consensus:** 1 libraries
505**Source Libraries:** buzz
506507-**Affected Files:**
508-- `lib/http_client.ml`
509-- `lib/one.ml`
510-- `lib/requests.ml`
511-512-**Implementation Notes:**
513-Add URL scheme validation early in request processing. Reject any scheme other than http/https with Invalid_url error. Apply validation also to redirect URLs.
514515516---
517518## Feature Enhancements
519520-### 29. Add path parameter templating
00521522Support URL templates like /users/{id}/posts/{post_id} with placeholder substitution from a parameter map. Automatically URL-encode substituted values.
523···527**Cross-Language Consensus:** 3 libraries
528**Source Libraries:** sling, resty, req (Go)
529530-**Affected Files:**
531-- `lib/requests.ml`
532-- `lib/one.ml`
533-534-**Implementation Notes:**
535-Add path_params:(string * string) list parameter. Before URL resolution, scan for {key} patterns and substitute with URL-encoded values from map. Raise error if template has unmatched placeholders.
536537538---
539540## Architectural Improvements
541542-### 30. Add default User-Agent header
00543544Set a default User-Agent identifying the library (ocaml-requests/VERSION) unless user provides one. Helps server-side debugging and follows HTTP best practices.
545···549**Cross-Language Consensus:** 5 libraries
550**Source Libraries:** needle, resty, requests (Go), okhttp, guzzle
551552-**Affected Files:**
553-- `lib/requests.ml`
554-- `lib/one.ml`
555-556-**Implementation Notes:**
557-Add default User-Agent in default_headers if not set. Include library version and optionally OCaml version/platform. Allow override via explicit header or user_agent parameter.
558
···23> Auto-generated summary of recommendations from analyzing HTTP client libraries across multiple languages.
45+## Implementation Status Summary
6+7+| Status | Count | Description |
8+|--------|-------|-------------|
9+| ✅ Implemented | 15 | Fully implemented and tested |
10+| 🔧 Partial | 1 | Partially implemented |
11+| ❌ Not Started | 14 | Not yet implemented |
12+13+### Implemented Features
14+15+| # | Feature | Location |
16+|---|---------|----------|
17+| 1 | Strip sensitive headers on cross-origin redirects | `lib/requests.ml`, `lib/one.ml` |
18+| 3 | Enforce HTTPS for sensitive authentication | `lib/auth.ml` (`apply_secure`, `Insecure_auth` error) |
19+| 4 | Content-Length vs Transfer-Encoding precedence | `lib/http_read.ml` (RFC 9112 warning) |
20+| 5 | Cap maximum Retry-After delay | `lib/retry.ml` (`backoff_max` parameter) |
21+| 11 | Base URL support with relative path resolution | `lib/requests.ml` (`base_url`, `resolve_url`) |
22+| 12 | Detailed timing metrics | `lib/timing.ml` (new module) |
23+| 13 | Stale connection detection | `ocaml-conpool/lib/conpool.ml` (`is_healthy`) |
24+| 14 | Custom retry condition predicates | `lib/retry.ml` (`response_predicate`, `exception_predicate`) |
25+| 19 | Link header parsing for pagination | `lib/link.ml` (new module) |
26+| 21 | Result-based error_for_status variant | `lib/response.ml` (`check_status`) |
27+| 24 | XSRF/CSRF token handling | `lib/requests.ml` (`apply_xsrf_token`) |
28+| 25 | Decompression bomb protection | `lib/http_client.ml` (`check_decompression_limits`) |
29+| 26 | HTTP version in response metadata | `lib/http_read.ml` (`http_version` type) |
30+| 28 | Restrict URL protocols to HTTP/HTTPS | `lib/requests.ml`, `lib/one.ml` (`validate_redirect_url`) |
31+| 29 | Path parameter templating | `lib/requests.ml` (`substitute_path_params`) |
32+| 30 | Default User-Agent header | `lib/version.ml`, applied in `lib/requests.ml` |
33+34+### Not Yet Implemented
35+36+| # | Feature | Priority |
37+|---|---------|----------|
38+| 2 | Certificate/public key pinning | High |
39+| 6 | HTTP proxy support | High |
40+| 7 | Request/response middleware system | Medium |
41+| 8 | Progress callbacks | Medium |
42+| 9 | Request cancellation | Medium |
43+| 10 | Concurrent request batching | Low |
44+| 15 | Charset/encoding detection | Low |
45+| 16 | Redirect policy customization | Low |
46+| 17 | TCP keep-alive configuration | Low |
47+| 18 | URL sanitization for error messages | Low |
48+| 20 | Mock handler for testing | Medium |
49+| 22 | Request body rewind for retries | Medium |
50+| 23 | Event listener/hooks | Low |
51+| 27 | Unix domain socket support | Low |
52+53+---
54+55## Executive Summary
5657This comprehensive analysis synthesizes recommendations from 45+ HTTP client libraries across 10 programming languages (Python, JavaScript, Go, Rust, Haskell, PHP, Java, Swift, C++, Bash). The most consistent themes are: (1) Security features like certificate pinning, cross-origin header stripping, and HTTPS enforcement for sensitive auth; (2) Middleware/interceptor systems for extensibility; (3) HTTP proxy support; (4) Progress callbacks for uploads/downloads; (5) Request cancellation capabilities; (6) Detailed timing metrics; (7) Retry logic improvements including Retry-After capping and custom predicates. The prioritization emphasizes security fixes that could lead to credential leakage, followed by missing features that block enterprise adoption (proxy support), then enhancements that improve developer experience.
···6162## Security & Spec Compliance
6364+### 1. ✅ Strip sensitive headers on cross-origin redirects
65+66+**Status: IMPLEMENTED** in `lib/requests.ml` and `lib/one.ml`
6768When redirecting to a different origin (host/port/scheme), automatically strip Authorization, Cookie, Proxy-Authorization, and WWW-Authenticate headers to prevent credential leakage to unintended domains. Also strip headers on HTTPS→HTTP protocol downgrade.
69···73**Cross-Language Consensus:** 8 libraries
74**Source Libraries:** reqwest, got, node-fetch, okhttp, axios, superagent, http-client, needle
7576+**Implementation:**
77+- `same_origin` function compares scheme and host
78+- `strip_sensitive_headers` removes Authorization, Cookie, Proxy-Authorization, WWW-Authenticate
79+- Applied during redirect handling in `make_with_redirects`
8081+### 2. ❌ Add certificate/public key pinning support
08283+**Status: NOT IMPLEMENTED** - High priority for enterprise security
8485Allow pinning certificates or public keys (SPKI hashes) to protect against compromised certificate authorities. Support per-host pinning configuration with wildcard patterns.
86···97**Implementation Notes:**
98Add certificate_pins parameter to create() accepting (hostname * sha256_hash list) list. Verify pins during TLS handshake by extracting SPKI from certificate chain. Provide helpful error messages showing expected vs actual hashes.
99100+### 3. ✅ Enforce HTTPS for sensitive authentication methods
101+102+**Status: IMPLEMENTED** in `lib/auth.ml`
103104Reject Basic, Bearer, and Digest authentication over unencrypted HTTP connections by default. Provide explicit opt-out flag (allow_insecure_auth) for testing environments.
105···110**Cross-Language Consensus:** 2 libraries
111**Source Libraries:** req (Haskell), urllib3
112113+**Implementation:**
114+- `Auth.apply_secure` validates transport security before applying auth
115+- `Auth.validate_secure_transport` checks if HTTPS is required
116+- `Error.Insecure_auth` error type for clear error messages
117+- `allow_insecure_auth` parameter in request functions for testing
118119+### 4. ✅ Validate Content-Length vs Transfer-Encoding precedence
0120121+**Status: IMPLEMENTED** in `lib/http_read.ml`
122123Per RFC 9112, when both Content-Length and Transfer-Encoding headers are present, ignore Content-Length. This prevents HTTP request smuggling attacks.
124···128**Cross-Language Consensus:** 2 libraries
129**Source Libraries:** hyper, http-streams
130131+**Implementation:**
132+- Transfer-Encoding: chunked takes precedence over Content-Length
133+- Warning logged when both headers present (potential attack indicator)
134+- Per RFC 9112 Section 6.3 compliance
135136+### 5. ✅ Cap maximum Retry-After delay to prevent DoS
0137138+**Status: IMPLEMENTED** in `lib/retry.ml`
139140Implement a configurable maximum backoff time (default 120s) that caps server-specified Retry-After values, preventing malicious servers from causing indefinite client blocking.
141···145**Cross-Language Consensus:** 2 libraries
146**Source Libraries:** req (Go), got
147148+**Implementation:**
149+- `backoff_max` field in `Retry.config` (default: 120.0 seconds)
150+- `parse_retry_after` function accepts `?backoff_max` parameter
151+- Delays exceeding cap are logged as warnings and capped
00152153154---
155156## Feature Enhancements
157158+### 6. ❌ Add HTTP proxy support with environment variable detection
159+160+**Status: NOT IMPLEMENTED** - High priority, see `spec/PROXY_IMPLEMENTATION_PLAN.md`
161162Implement HTTP/HTTPS proxy support including: proxy URL configuration, authentication (Basic), CONNECT method for HTTPS tunneling, and automatic detection from HTTP_PROXY, HTTPS_PROXY, NO_PROXY environment variables.
163···175- `lib/one.ml`
176177**Implementation Notes:**
178+A comprehensive implementation plan exists in `spec/PROXY_IMPLEMENTATION_PLAN.md` with 8 phases covering proxy configuration, HTTP CONNECT tunneling, environment variable detection, NO_PROXY pattern matching, and proxy authentication.
179+180+### 7. ❌ Implement request/response middleware system
181182+**Status: NOT IMPLEMENTED** - Medium priority
183184Add a composable middleware chain that allows intercepting and transforming requests before sending and responses after receiving. Enable cross-cutting concerns like logging, metrics, request signing, and custom caching.
185···193**Implementation Notes:**
194Define type middleware = Request.t -> (Request.t -> Response.t) -> Response.t. Store middleware list in session. Execute chain: apply each middleware wrapping the next. Provide default middleware for retry and redirect as replaceable components.
195196+### 8. ❌ Add progress callbacks for uploads and downloads
197+198+**Status: NOT IMPLEMENTED** - Medium priority
199200Implement optional progress callbacks that report bytes transferred, total size (if known), and percent complete. Rate-limit callbacks to prevent performance degradation.
201···211**Implementation Notes:**
212Add optional progress:(transferred:int64 -> total:int64 option -> unit) parameter. Track bytes during streaming read/write. Throttle callbacks (e.g., max 3/second or every 64KB). Support both upload and download progress.
213214+### 9. ❌ Add request cancellation support
215+216+**Status: NOT IMPLEMENTED** - Medium priority (Eio provides natural cancellation via switches)
217218Allow programmatic cancellation of in-flight requests. Integrate with Eio's cancellation system while providing explicit cancel() function or cancel token pattern.
219···228**Implementation Notes:**
229Return (Response.t * cancel_token) from request functions where cancel_token allows aborting the request. Internally use Eio.Cancel or Switch.fail to terminate the fiber. Raise Cancelled error on cancellation.
230231+### 10. ❌ Add concurrent request batching API (map/imap)
232+233+**Status: NOT IMPLEMENTED** - Low priority (Eio.Fiber.all/both provides this)
234235Provide map() for executing multiple requests concurrently and returning results in order, and imap() for yielding responses as they complete. Include configurable concurrency limits and batch timeout.
236···244**Implementation Notes:**
245Implement using Eio.Fiber.all for map, Eio.Stream for imap. Add max_concurrent parameter using Eio.Semaphore. Provide exception_handler callback for partial failure handling. Add batch_timeout for overall operation limit.
246247+### 11. ✅ Add base URL support with relative path resolution
248+249+**Status: IMPLEMENTED** in `lib/requests.ml`
250251Allow configuring a base URL on the session that is prepended to relative request URLs. Use proper RFC 3986 URI resolution for correct path joining.
252···256**Cross-Language Consensus:** 5 libraries
257**Source Libraries:** surf, axios, got, sling, req (Go)
258259+**Implementation:**
260+- `base_url` parameter in `create` function
261+- `is_relative_url` checks if URL has scheme
262+- `resolve_url` uses `Uri.resolve` for RFC 3986 compliant resolution
263+- Trailing slashes automatically normalized
0264265266---
267268## Architectural Improvements
269270+### 12. ✅ Add detailed timing metrics to responses
271+272+**Status: IMPLEMENTED** in new `lib/timing.ml` module
273274Expose granular timing breakdown: DNS lookup time, TCP connection time, TLS handshake time, time to first byte (TTFB), download time, and total time. Include connection reuse tracking.
275276**Cross-Language Consensus:** 7 libraries
277**Source Libraries:** curl-rust, got, resty, req (Go), guzzle, okhttp, isahc
278279+**Implementation:**
280+- New `Timing` module with detailed metrics type
281+- Phases: `dns_lookup`, `tcp_connect`, `tls_handshake`, `request_sent`, `time_to_first_byte`, `content_transfer`, `total`
282+- `timer` type for incremental collection during requests
283+- `connection_time` and `server_time` computed metrics
284+- Pretty-printing with `pp` and `to_string`
285286+### 13. ✅ Add automatic retry on stale connection detection
0287288+**Status: IMPLEMENTED** in `ocaml-conpool` library
289290Detect when a pooled connection was closed by the server between requests (NoResponseDataReceived) and automatically retry with a fresh connection. Mark this error as always retryable.
291292**Cross-Language Consensus:** 2 libraries
293**Source Libraries:** http-client (Haskell), okhttp
294295+**Implementation:**
296+The `ocaml-conpool` library provides comprehensive stale connection detection via:
297+- `is_healthy` function checking age, idle time, and use count
298+- `max_idle_time` configuration (default: 60s)
299+- `max_connection_lifetime` configuration (default: 300s)
300+- `max_connection_uses` configuration (optional)
301+- Custom `health_check` callback support
302+- Pool `validate` function runs health checks before connection reuse
303304+### 14. ✅ Add custom retry condition predicates
0305306+**Status: IMPLEMENTED** in `lib/retry.ml`
307308Allow users to provide custom retry decision functions beyond status codes and error types. Separate predicates for response-based retry (status/headers) and exception-based retry.
309310**Cross-Language Consensus:** 4 libraries
311**Source Libraries:** resty, got, req (Go), req (Haskell)
312313+**Implementation:**
314+- `response_predicate` type: `Method.t -> int -> Headers.t -> bool`
315+- `exception_predicate` type: `exn -> bool`
316+- `retry_response` and `retry_exception` fields in `Retry.config`
317+- `should_retry_response` checks both built-in rules and custom predicates
318+- `should_retry_exn` for exception-based retry decisions
319+- Examples in module documentation
320321322---
323324## Feature Enhancements
325326+### 15. ❌ Add response charset/encoding detection and conversion
327+328+**Status: NOT IMPLEMENTED** - Low priority
329330Automatically detect character encoding from Content-Type charset parameter and convert response text to UTF-8. Provide BOM sniffing fallback for encoding detection.
331···343**Implementation Notes:**
344Parse charset from Content-Type in Mime module. Add Response.text_utf8 that detects and converts encoding. Use uutf library for encoding conversion. Return raw bytes on conversion failure with access to detected charset.
345346+### 16. ❌ Add redirect policy customization
347+348+**Status: NOT IMPLEMENTED** - Low priority
349350Allow custom redirect policies with access to attempt status, URL, and previous URLs. Enable controlling method preservation (307/308 vs 301/302), header stripping, and cross-protocol redirect behavior.
351···367368## Architectural Improvements
369370+### 17. ❌ Add TCP keep-alive configuration
371+372+**Status: NOT IMPLEMENTED** - Low priority
373374Expose TCP keep-alive settings including enable/disable, interval, and retry count. This helps detect broken connections and maintain long-lived connections through firewalls/NAT.
375···388389## Feature Enhancements
390391+### 18. ❌ Add URL sanitization for error messages
392+393+**Status: NOT IMPLEMENTED** - Low priority
394395Automatically sanitize URLs in error messages to prevent leakage of credentials embedded in query parameters (API keys, tokens). Provide without_url() method to strip URLs entirely.
396···404**Implementation Notes:**
405Extend existing sanitize_url function to handle query parameter credentials. Add Error.without_url to remove URL entirely from error. Apply sanitization automatically in Error.to_string and pp functions.
406407+### 19. ✅ Add Link header parsing for pagination
408+409+**Status: IMPLEMENTED** in new `lib/link.ml` module
410411Parse RFC 8288 Link headers to extract relation types (next, prev, first, last) for API pagination. Provide helpers like Response.next_url for common patterns.
412···416**Cross-Language Consensus:** 3 libraries
417**Source Libraries:** got, superagent, just
418419+**Implementation:**
420+- New `Link` module with RFC 8288 compliant parsing
421+- `Link.t` type with `uri`, `rel`, `title`, `media_type`, `hreflang`, `params`
422+- `parse` function handles comma-separated links with quoted values
423+- `from_headers` extracts Link header from response headers
424+- `pagination` returns `(first, prev, next, last)` tuple
425+- `next_url`, `prev_url`, `has_next` convenience functions
426+- Pretty-printing with `pp` and `to_string`
427428429---
430431## Architectural Improvements
432433+### 20. ❌ Add mock handler for testing
434+435+**Status: NOT IMPLEMENTED** - Medium priority
436437Provide a mock handler that queues pre-defined responses and exceptions for testing HTTP client code without network calls. Support request inspection and assertion.
438···451452## Feature Enhancements
453454+### 21. ✅ Add Result-based error_for_status variant
455+456+**Status: IMPLEMENTED** in `lib/response.ml`
457458Provide check_status() that returns (Response.t, Error.error) result instead of raising, enabling functional error handling alongside the existing raise_for_status.
459460**Cross-Language Consensus:** 2 libraries
461**Source Libraries:** reqwest, grequests
462463+**Implementation:**
464+- `Response.check_status : t -> (t, Error.t) result`
465+- Returns `Ok response` for 2xx status codes
466+- Returns `Error (Http_error {...})` for 4xx/5xx status codes
467+- Complements existing `raise_for_status` for functional style
468469+### 22. ❌ Add request body rewind support for retries
0470471+**Status: NOT IMPLEMENTED** - Medium priority
472473Track whether request bodies are rewindable (seekable) and automatically replay them on retry. Raise clear error when retry requires body replay but body is a consumed stream.
474···488489## Architectural Improvements
490491+### 23. ❌ Add event listener/hooks for observability
492+493+**Status: NOT IMPLEMENTED** - Low priority
494495Provide comprehensive event hooks at each request lifecycle stage: DNS start/end, connection start/end, TLS handshake, request headers/body sent, response headers/body received. Enable metrics and tracing integration.
496···510511## Feature Enhancements
512513+### 24. ✅ Add XSRF/CSRF token handling
514+515+**Status: IMPLEMENTED** in `lib/requests.ml`
516517Automatically read CSRF token from a configurable cookie name (default: XSRF-TOKEN) and add it to request headers (default: X-XSRF-TOKEN) for same-origin requests.
518519**Cross-Language Consensus:** 1 libraries
520**Source Libraries:** axios
521522+**Implementation:**
523+- `xsrf_cookie_name` parameter (default: `Some "XSRF-TOKEN"`)
524+- `xsrf_header_name` parameter (default: `"X-XSRF-TOKEN"`)
525+- `apply_xsrf_token` function reads cookie and injects header
526+- Set `xsrf_cookie_name` to `None` to disable
527+- Applied automatically in `make_request_internal`
528529530---
531532## Architectural Improvements
533534+### 25. ✅ Add decompression bomb protection
535+536+**Status: IMPLEMENTED** in `lib/http_client.ml`
537538Enforce configurable compression ratio limits (e.g., 100:1) to detect and abort decompression bomb attacks. Track compressed vs decompressed bytes during streaming.
539540**Cross-Language Consensus:** 1 libraries
541**Source Libraries:** axios
542543+**Implementation:**
544+- `check_decompression_limits` function validates size and ratio
545+- `max_decompressed_size` in `Response_limits` (absolute size limit)
546+- `max_compression_ratio` in `Response_limits` (ratio limit)
547+- `Error.Decompression_bomb` error type with limit and ratio info
548+- Applied during gzip/deflate/zlib decompression
549550551---
552553## Feature Enhancements
554555+### 26. ✅ Add HTTP version to response metadata
556+557+**Status: IMPLEMENTED** in `lib/http_read.ml`
558559Expose the HTTP version used for the response (HTTP/1.0, HTTP/1.1, HTTP/2) in Response type. Useful for debugging protocol negotiation and monitoring HTTP/2 adoption.
560561**Cross-Language Consensus:** 3 libraries
562**Source Libraries:** reqwest, surf, curl-rust
563564+**Implementation:**
565+- `http_version` type: `HTTP_1_0 | HTTP_1_1`
566+- `http_version_to_string` for display
567+- `status_line` returns `(http_version, status_code)` tuple
568+- `response` function returns `(http_version, status, headers, body)`
569+- `stream_response` includes `http_version` field
570571+### 27. ❌ Add Unix domain socket support
0572573+**Status: NOT IMPLEMENTED** - Low priority
574575Enable connecting to local services via Unix domain sockets (e.g., Docker daemon at /var/run/docker.sock) without TCP overhead.
576···590591## Security & Spec Compliance
592593+### 28. ✅ Restrict URL protocols to HTTP/HTTPS only
594+595+**Status: IMPLEMENTED** in `lib/requests.ml` and `lib/one.ml`
596597Explicitly whitelist only http:// and https:// protocols to prevent protocol smuggling attacks via file://, ftp://, gopher://, etc. Reject invalid protocols early in URL parsing.
598599**Cross-Language Consensus:** 1 libraries
600**Source Libraries:** buzz
601602+**Implementation:**
603+- `allowed_redirect_schemes = ["http"; "https"]`
604+- `validate_redirect_url` checks scheme on redirects
605+- `Error.Invalid_redirect` raised for disallowed schemes
606+- Applied during redirect following to prevent SSRF
00607608609---
610611## Feature Enhancements
612613+### 29. ✅ Add path parameter templating
614+615+**Status: IMPLEMENTED** in `lib/requests.ml`
616617Support URL templates like /users/{id}/posts/{post_id} with placeholder substitution from a parameter map. Automatically URL-encode substituted values.
618···622**Cross-Language Consensus:** 3 libraries
623**Source Libraries:** sling, resty, req (Go)
624625+**Implementation:**
626+- `substitute_path_params` function for RFC 6570 templating
627+- `path_params:(string * string) list` parameter on all request methods
628+- Automatic URL encoding via `Uri.pct_encode`
629+- Applied before base URL resolution in request pipeline
630+- Example: `get ~path_params:[("id", "123")] "/users/{id}"`
631632633---
634635## Architectural Improvements
636637+### 30. ✅ Add default User-Agent header
638+639+**Status: IMPLEMENTED** in `lib/version.ml`
640641Set a default User-Agent identifying the library (ocaml-requests/VERSION) unless user provides one. Helps server-side debugging and follows HTTP best practices.
642···646**Cross-Language Consensus:** 5 libraries
647**Source Libraries:** needle, resty, requests (Go), okhttp, guzzle
648649+**Implementation:**
650+- New `Version` module with library version info
651+- `Version.user_agent` returns `"ocaml-requests/0.1.0 (OCaml X.XX.X)"`
652+- Applied automatically if not already set in `make_request_internal`
653+- Can be overridden via explicit User-Agent header
0654