A batteries included HTTP/1.1 client in OCaml

recs

+11020
+170
third_party/bash-shell/ain.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "bash-shell/ain", 5 + "source_language": "Go", 6 + "criticality": "high", 7 + "change_type": "enhancement", 8 + "title": "Enhanced error messages with context and line numbers", 9 + "description": "Ain provides rich error messages with file context, showing the problematic line with surrounding context (1 line before/after), line numbers, and expanded variable/template values. The OCaml library's error messages are basic and don't provide this level of detail, making debugging harder for users.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/requests.ml", 13 + "lib/one.ml", 14 + "lib/http_client.ml" 15 + ], 16 + "rationale": "When requests fail, users often need to debug complex scenarios involving authentication, headers, URLs, and body content. Ain's approach of showing context with line numbers and expanded values (especially for Digest auth challenges, URL parsing errors, header issues) would significantly improve developer experience. The OCaml library should enhance error messages to include: (1) the exact URL being requested, (2) relevant header values when auth fails, (3) parsed vs raw values for digest challenges, (4) context about which connection pool was used, (5) timeout values that were exceeded. This is particularly important for InvalidURL, AuthenticationError, and HTTPError exceptions." 17 + }, 18 + { 19 + "source_repo": "bash-shell/ain", 20 + "source_language": "Go", 21 + "criticality": "medium", 22 + "change_type": "enhancement", 23 + "title": "Intelligent suggestions for typos in headers and auth parameters", 24 + "description": "Ain uses Levenshtein distance (max distance 2) to suggest similar variable names when environment variables are not found. The OCaml library doesn't provide helpful suggestions when users mistype header names, authentication parameters, or configuration options.", 25 + "affected_files": [ 26 + "lib/headers.ml", 27 + "lib/auth.ml", 28 + "lib/error.ml" 29 + ], 30 + "rationale": "User experience can be significantly improved by suggesting corrections for common typos. For example, if a user tries to set a header 'Athorization' instead of 'Authorization', or 'Content-Typ' instead of 'Content-Type', the library could suggest the correct spelling. Similarly, when digest authentication fails to parse WWW-Authenticate header parameters, suggesting valid parameter names would help. This requires implementing a Levenshtein distance function and maintaining a list of common HTTP headers and auth parameters. The implementation should suggest up to 3 alternatives with distance ≤ 2." 31 + }, 32 + { 33 + "source_repo": "bash-shell/ain", 34 + "source_language": "Go", 35 + "criticality": "medium", 36 + "change_type": "enhancement", 37 + "title": "Explicit timeout enforcement with clear timeout context in errors", 38 + "description": "Ain reports which specific timeout was exceeded (connect, read, or total) and includes the timeout duration in error messages. The OCaml library has timeout configuration but error messages don't clearly distinguish which timeout was exceeded or report the configured values.", 39 + "affected_files": [ 40 + "lib/timeout.ml", 41 + "lib/error.ml", 42 + "lib/http_client.ml" 43 + ], 44 + "rationale": "When a timeout occurs, users need to know: (1) which timeout was exceeded (connect vs read vs total), (2) what the timeout value was, (3) how long the operation actually took before timing out. Ain's approach of including timeout duration in error messages ('timed out after 30 seconds') helps users quickly adjust their timeout configuration. The OCaml library should enhance the Timeout exception to include structured information: timeout_type (Connect/Read/Total), configured_value, elapsed_time. The Error.pp function should format these details clearly." 45 + }, 46 + { 47 + "source_repo": "bash-shell/ain", 48 + "source_language": "Go", 49 + "criticality": "medium", 50 + "change_type": "feature", 51 + "title": "Signal handling and graceful cancellation with cleanup", 52 + "description": "Ain monitors SIGINT and SIGTERM signals, cancels ongoing operations via context, cleans up temporary files even on cancellation, and returns Unix-standard exit codes (128+signal). The OCaml library doesn't provide explicit signal handling patterns or examples.", 53 + "affected_files": [ 54 + "lib/requests.mli", 55 + "lib/one.mli", 56 + "test/test_localhost.ml" 57 + ], 58 + "rationale": "Production HTTP clients need to handle interrupts gracefully. While Eio's structured concurrency provides cancellation via switches, the library should document patterns for signal handling and provide examples showing how to use Eio's signal handling with requests. This includes: (1) showing how to setup signal handlers that cancel request switches, (2) ensuring connection pools are properly cleaned up on cancellation, (3) documenting how cancelled requests propagate through retry logic. Add a section to requests.mli demonstrating signal handling patterns with code examples using Eio.Condition and Switch.on_release." 59 + }, 60 + { 61 + "source_repo": "bash-shell/ain", 62 + "source_language": "Go", 63 + "criticality": "low", 64 + "change_type": "enhancement", 65 + "title": "Retry-After header support with HTTP date parsing", 66 + "description": "Ain's retry module parses Retry-After headers (both integer seconds and HTTP dates) and respects them during backoff calculation. The OCaml library's Retry module has a parse_retry_after function but it's not integrated into the actual retry logic in with_retry.", 67 + "affected_files": [ 68 + "lib/retry.ml", 69 + "lib/requests.ml" 70 + ], 71 + "rationale": "RFC 7231 specifies the Retry-After header for rate limiting and temporary service unavailability. The OCaml library has parse_retry_after implemented but it's never called in with_retry. The function should be integrated so that when a 429 (Too Many Requests) or 503 (Service Unavailable) response includes Retry-After, the library uses that value instead of the calculated exponential backoff. The implementation should: (1) check response headers for Retry-After when status is in status_forcelist, (2) parse the value using the existing parse_retry_after function, (3) use max(calculated_backoff, retry_after_value) to respect server preferences while maintaining minimum backoff." 72 + }, 73 + { 74 + "source_repo": "bash-shell/ain", 75 + "source_language": "Go", 76 + "criticality": "high", 77 + "change_type": "security", 78 + "title": "Enhanced input validation and sanitization for URLs and headers", 79 + "description": "Ain performs extensive input validation including: shell escaping for command arguments, intelligent URL encoding that preserves existing encoded sequences, validation that variables are non-empty, and detection of unterminated quotes with context. The OCaml library performs basic validation but could be more defensive.", 80 + "affected_files": [ 81 + "lib/headers.ml", 82 + "lib/body.ml", 83 + "lib/requests.ml" 84 + ], 85 + "rationale": "Security best practice requires defense-in-depth validation. The OCaml library should add: (1) validation that header values don't contain newlines (CRLF injection prevention), (2) validation that header names are valid tokens per RFC 7230, (3) better error messages when invalid header values are detected, (4) validation of URL schemes (only http/https allowed), (5) validation that authentication credentials don't contain control characters. Currently, invalid inputs might be passed through to underlying layers, causing confusing errors. Adding validation at the API boundary with clear error messages improves security and debuggability." 86 + }, 87 + { 88 + "source_repo": "bash-shell/ain", 89 + "source_language": "Go", 90 + "criticality": "medium", 91 + "change_type": "enhancement", 92 + "title": "Comprehensive end-to-end test framework with embedded directives", 93 + "description": "Ain's e2e test framework embeds test directives as YAML comments in test files, specifying expected stdout, stderr, exit codes, environment variables, and command-line arguments. Tests cover success and failure cases with clear naming (ok-*, nok-*). The OCaml library has basic tests but lacks comprehensive edge case coverage.", 94 + "affected_files": [ 95 + "test/httpbin.t", 96 + "test/test_simple.ml", 97 + "test/test_localhost.ml" 98 + ], 99 + "rationale": "The current test suite focuses on happy paths and basic functionality. Following Ain's approach, the OCaml library should add: (1) tests for all error conditions (timeout, connection error, authentication failure, SSL errors, invalid URLs), (2) tests for edge cases (empty bodies, missing headers, malformed responses), (3) tests for retry behavior (verifying backoff timing, max retry enforcement, status_forcelist behavior), (4) tests for digest authentication (challenge parsing, response computation, nonce handling), (5) tests for redirect edge cases (cross-origin, auth stripping, max redirects). The httpbin.t test should be expanded to cover these scenarios systematically." 100 + }, 101 + { 102 + "source_repo": "bash-shell/ain", 103 + "source_language": "Go", 104 + "criticality": "low", 105 + "change_type": "enhancement", 106 + "title": "Detailed operation logging with timing and retry context", 107 + "description": "Ain logs operations at appropriate levels: INFO for retry attempts with timing, WARN for failures before retry, ERROR for final failures, DEBUG for configuration details. Logs include attempt numbers, delay calculations, and reasons for retry. The OCaml library has logging but could be more comprehensive.", 108 + "affected_files": [ 109 + "lib/retry.ml", 110 + "lib/requests.ml", 111 + "lib/http_client.ml", 112 + "lib/auth.ml" 113 + ], 114 + "rationale": "Production debugging requires detailed logs. The OCaml library should enhance logging to include: (1) in retry.ml, log each retry attempt with 'Retry attempt X/Y in Z seconds. Reason: <error>', (2) in requests.ml, log connection pool selection and reuse, (3) in auth.ml, log authentication method being applied (without sensitive data), (4) in http_client.ml, log connection establishment and reuse from pool. The log_retry function exists but isn't called from with_retry. Logs should use appropriate levels: Debug for configuration, Info for significant operations, Warn for retries, Error for failures. This helps users understand retry behavior without verbose protocol dumps." 115 + }, 116 + { 117 + "source_repo": "bash-shell/ain", 118 + "source_language": "Go", 119 + "criticality": "medium", 120 + "change_type": "refactor", 121 + "title": "Structured error accumulation for validation errors", 122 + "description": "Ain accumulates multiple validation errors and reports them all at once, rather than failing on the first error. This allows users to fix all issues in one pass. The OCaml library fails on the first error encountered.", 123 + "affected_files": [ 124 + "lib/body.ml", 125 + "lib/headers.ml", 126 + "lib/auth.ml" 127 + ], 128 + "rationale": "When constructing complex requests with multiple headers, multipart bodies, and authentication, multiple issues might exist simultaneously. Following Ain's pattern, the library should validate all inputs and accumulate errors, then raise an InvalidRequest exception with all errors listed. For example, when creating a multipart body, validate all parts and report all issues (missing names, invalid content types, inaccessible files) rather than stopping at the first. This is especially valuable for the multipart constructor in body.ml where multiple parts are validated. Implementation: create a validation context that accumulates errors, perform all validations, then check if errors exist and raise with formatted message listing all issues." 129 + }, 130 + { 131 + "source_repo": "bash-shell/ain", 132 + "source_language": "Go", 133 + "criticality": "low", 134 + "change_type": "enhancement", 135 + "title": "Response body preview in error messages", 136 + "description": "Ain's error messages can include the response body (when available) to help debug API errors. The OCaml library's HTTPError exception has an optional body field but it's rarely populated with the actual response content.", 137 + "affected_files": [ 138 + "lib/error.ml", 139 + "lib/response.ml", 140 + "lib/requests.ml" 141 + ], 142 + "rationale": "When an HTTP request returns an error status (4xx/5xx), the response body often contains valuable debugging information (error codes, validation messages, stack traces). The HTTPError exception includes a body field, but it's typically None. The library should enhance error handling to: (1) read response bodies for error status codes (up to a reasonable limit like 4KB), (2) populate the body field in HTTPError, (3) include body preview in error messages via Error.pp. This is particularly useful for API errors where the server returns JSON error details. The response.ml module should provide a helper to safely read bodies with size limits for error scenarios." 143 + }, 144 + { 145 + "source_repo": "bash-shell/ain", 146 + "source_language": "Go", 147 + "criticality": "medium", 148 + "change_type": "feature", 149 + "title": "Parallel execution tracking and timeout enforcement across operations", 150 + "description": "Ain executes multiple shell commands in parallel using goroutines with WaitGroup, applies a single timeout to all operations collectively, and provides clear error context for each failed operation. The OCaml library doesn't provide patterns or utilities for parallel request execution with unified timeout.", 151 + "affected_files": [ 152 + "lib/requests.mli", 153 + "lib/timeout.ml" 154 + ], 155 + "rationale": "The library documentation shows examples of parallel requests using Eio.Fiber.both and Fiber.all, but doesn't demonstrate how to apply a total timeout across all parallel operations. Following Ain's pattern, the library should: (1) document patterns for timeout enforcement across parallel requests, (2) show how to use Eio.Time.with_timeout to wrap Fiber.all, (3) provide examples of collecting results from parallel requests with proper error handling. Add a section to requests.mli titled 'Parallel Requests with Timeout' demonstrating: creating multiple concurrent requests with Fiber.all, wrapping in a total timeout using Eio.Time.with_timeout, handling partial failures where some requests succeed and others fail." 156 + }, 157 + { 158 + "source_repo": "bash-shell/ain", 159 + "source_language": "Go", 160 + "criticality": "high", 161 + "change_type": "bug", 162 + "title": "Missing integration of retry_after header parsing in retry logic", 163 + "description": "The retry.ml module implements parse_retry_after to extract retry delays from Retry-After headers, but the with_retry function never calls it or checks response headers. This is a feature that's partially implemented but not connected.", 164 + "affected_files": [ 165 + "lib/retry.ml" 166 + ], 167 + "rationale": "The parse_retry_after function exists (lines 73-93 in retry.ml) but is never called from with_retry. To properly support rate limiting, with_retry should: (1) accept response headers as an optional parameter, (2) when retrying due to HTTP status (429, 503), check for Retry-After header, (3) parse the header using parse_retry_after, (4) use the parsed delay instead of calculated backoff if present and config.respect_retry_after is true. The current implementation calculates backoff but ignores server guidance, which can lead to premature retries and rate limit violations. This is a high-priority bug fix because respecting Retry-After is important for being a good HTTP client citizen." 168 + } 169 + ] 170 + }
+276
third_party/bash-shell/aria2.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/bash-shell/aria2", 5 + "source_language": "C++", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add hostname verification for TLS certificates", 9 + "description": "Aria2 implements RFC 6125 compliant hostname verification (net::verifyHostname) that validates certificate DNSNames and CN against the requested hostname. The OCaml library currently relies on the TLS library's basic verification but should add explicit hostname verification to prevent MITM attacks when certificates are valid but for the wrong host.", 10 + "affected_files": [ 11 + "lib/one.ml", 12 + "lib/requests.ml" 13 + ], 14 + "rationale": "Hostname verification is a critical security feature. Without it, an attacker could present a valid certificate for a different domain. Aria2's implementation shows this is a production-critical feature that validates both Subject Alternative Names (SANs) and Common Name (CN) fields according to RFC 6125." 15 + }, 16 + { 17 + "source_repo": "third_party/bash-shell/aria2", 18 + "source_language": "C++", 19 + "criticality": "medium", 20 + "change_type": "feature", 21 + "title": "Add HTTP proxy support with CONNECT tunneling", 22 + "description": "Aria2 implements comprehensive HTTP/HTTPS proxy support including CONNECT method tunneling for HTTPS through HTTP proxies (HttpProxyRequestCommand, AbstractProxyRequestCommand). The library should add proxy configuration with support for HTTP_PROXY and HTTPS_PROXY environment variables, proxy authentication, and CONNECT tunneling.", 23 + "affected_files": [ 24 + "lib/requests.mli", 25 + "lib/requests.ml", 26 + "lib/one.mli", 27 + "lib/one.ml", 28 + "lib/http_client.ml" 29 + ], 30 + "rationale": "Proxy support is essential for enterprise environments where direct internet access is restricted. Aria2's architecture demonstrates proper handling of proxy authentication, CONNECT tunneling for HTTPS, and environment variable configuration (HTTP_PROXY, HTTPS_PROXY, NO_PROXY)." 31 + }, 32 + { 33 + "source_repo": "third_party/bash-shell/aria2", 34 + "source_language": "C++", 35 + "criticality": "medium", 36 + "change_type": "enhancement", 37 + "title": "Implement conditional requests with If-Modified-Since and ETag", 38 + "description": "Aria2's HttpRequest supports conditional GET requests using If-Modified-Since and If-None-Match headers for cache validation. Add support for conditional requests to enable efficient caching with 304 Not Modified responses.", 39 + "affected_files": [ 40 + "lib/response.mli", 41 + "lib/response.ml", 42 + "lib/headers.mli", 43 + "lib/headers.ml", 44 + "lib/requests.ml" 45 + ], 46 + "rationale": "Conditional requests reduce bandwidth and server load by allowing clients to validate cached content. Aria2's implementation shows this is important for production HTTP clients, especially for repeated requests to the same resource. The library already has response headers but lacks conditional request generation." 47 + }, 48 + { 49 + "source_repo": "third_party/bash-shell/aria2", 50 + "source_language": "C++", 51 + "criticality": "medium", 52 + "change_type": "enhancement", 53 + "title": "Add Range request support for partial content downloads", 54 + "description": "Aria2 implements sophisticated Range request handling with validation (isRangeSatisfied) for resumable downloads and multi-segment downloads. Add support for Range headers, Accept-Ranges validation, and 206 Partial Content response handling.", 55 + "affected_files": [ 56 + "lib/headers.ml", 57 + "lib/headers.mli", 58 + "lib/one.ml", 59 + "lib/response.ml", 60 + "lib/status.ml" 61 + ], 62 + "rationale": "Range requests enable resumable downloads, bandwidth optimization, and parallel downloads of large files. Aria2's extensive Range implementation (getRange, isRangeSatisfied, segment management) demonstrates this is a core feature for production download clients." 63 + }, 64 + { 65 + "source_repo": "third_party/bash-shell/aria2", 66 + "source_language": "C++", 67 + "criticality": "high", 68 + "change_type": "bug", 69 + "title": "Add comprehensive error codes for HTTP-specific failures", 70 + "description": "Aria2 defines detailed error codes (error_code.h) including HTTP_PROTOCOL_ERROR, HTTP_TOO_MANY_REDIRECTS, HTTP_AUTH_FAILED, HTTP_SERVICE_UNAVAILABLE, NAME_RESOLVE_ERROR, CHECKSUM_ERROR. The current Error module should add more granular error types to distinguish between different failure modes for better error handling and retry logic.", 71 + "affected_files": [ 72 + "lib/error.mli", 73 + "lib/error.ml" 74 + ], 75 + "rationale": "Granular error codes enable appropriate retry strategies and user feedback. Aria2's 32 distinct error codes allow the client to differentiate between transient (TIME_OUT, NETWORK_PROBLEM, HTTP_SERVICE_UNAVAILABLE) and permanent failures (RESOURCE_NOT_FOUND, HTTP_AUTH_FAILED, CHECKSUM_ERROR). The current library only has 11 error types." 76 + }, 77 + { 78 + "source_repo": "third_party/bash-shell/aria2", 79 + "source_language": "C++", 80 + "criticality": "medium", 81 + "change_type": "enhancement", 82 + "title": "Implement recoverable exception pattern for retry signaling", 83 + "description": "Aria2 uses DlRetryEx (RecoverableException) to distinguish retryable errors from permanent failures. The library should enhance the Error module's is_retryable function and consider adding a RecoverableError variant to make retry semantics more explicit in the type system.", 84 + "affected_files": [ 85 + "lib/error.mli", 86 + "lib/error.ml", 87 + "lib/retry.ml" 88 + ], 89 + "rationale": "The recoverable exception pattern clarifies retry semantics. Aria2's DlRetryEx carries error codes and allows nested exceptions for context. The current is_retryable function is limited and doesn't capture the full semantics of which errors are temporary vs permanent." 90 + }, 91 + { 92 + "source_repo": "third_party/bash-shell/aria2", 93 + "source_language": "C++", 94 + "criticality": "low", 95 + "change_type": "enhancement", 96 + "title": "Add connection lifetime tracking and forced eviction", 97 + "description": "Aria2 implements EvictSocketPoolCommand for periodic cleanup with configurable intervals to prevent stale connections and resource exhaustion. While the library has connection_lifetime parameter, it should add active eviction logging and metrics to help debug connection pool issues.", 98 + "affected_files": [ 99 + "lib/requests.ml" 100 + ], 101 + "rationale": "Aria2's time-based eviction command prevents connection staleness and resource leaks. The current Conpool implementation has lifetime parameters but could benefit from Aria2's pattern of periodic active cleanup with logging to help operators understand pool behavior." 102 + }, 103 + { 104 + "source_repo": "third_party/bash-shell/aria2", 105 + "source_language": "C++", 106 + "criticality": "medium", 107 + "change_type": "security", 108 + "title": "Add configurable TLS version support (TLS 1.2, TLS 1.3)", 109 + "description": "Aria2's TLSContext supports explicit TLS version configuration (TLS1.1, TLS1.2, TLS1.3) allowing security-conscious deployments to enforce minimum versions. Add configuration options to specify minimum and maximum TLS versions.", 110 + "affected_files": [ 111 + "lib/requests.mli", 112 + "lib/requests.ml", 113 + "lib/one.mli", 114 + "lib/one.ml" 115 + ], 116 + "rationale": "TLS version configuration is important for security compliance and compatibility. Aria2's explicit version support allows administrators to disable older protocols (TLS 1.0/1.1) that have known vulnerabilities. The library currently uses default TLS settings without version control." 117 + }, 118 + { 119 + "source_repo": "third_party/bash-shell/aria2", 120 + "source_language": "C++", 121 + "criticality": "low", 122 + "change_type": "enhancement", 123 + "title": "Add User-Agent customization and Accept header configuration", 124 + "description": "Aria2 implements detailed User-Agent management (HttpRequest::USER_AGENT) and Accept header customization for content negotiation. While the library supports custom headers, it should provide dedicated User-Agent configuration similar to Aria2's approach.", 125 + "affected_files": [ 126 + "lib/requests.mli", 127 + "lib/requests.ml", 128 + "lib/one.mli" 129 + ], 130 + "rationale": "Many servers require or customize responses based on User-Agent headers. Aria2's dedicated User-Agent field and Accept header configuration (including metalink types) shows this is important for compatibility and content negotiation. The library has user_agent in Cmd but not as a first-class session parameter." 131 + }, 132 + { 133 + "source_repo": "third_party/bash-shell/aria2", 134 + "source_language": "C++", 135 + "criticality": "medium", 136 + "change_type": "feature", 137 + "title": "Add .netrc file support for credential management", 138 + "description": "Aria2 implements NetrcAuthResolver for reading credentials from .netrc files, a standard Unix authentication mechanism. Add support for parsing .netrc files to automatically supply credentials for hosts without hardcoding them in applications.", 139 + "affected_files": [ 140 + "lib/auth.mli", 141 + "lib/auth.ml", 142 + "lib/requests.ml" 143 + ], 144 + "rationale": "The .netrc file is a standard Unix mechanism for storing credentials. Aria2's NetrcAuthResolver demonstrates production-grade credential management that keeps secrets out of code and environment variables. This is especially valuable for CLI tools and automated systems." 145 + }, 146 + { 147 + "source_repo": "third_party/bash-shell/aria2", 148 + "source_language": "C++", 149 + "criticality": "low", 150 + "change_type": "enhancement", 151 + "title": "Add Pragma: no-cache and Cache-Control: no-cache support", 152 + "description": "Aria2's HttpRequest includes optional no-cache headers (noCache_ flag) that adds both Pragma: no-cache and Cache-Control: no-cache. Add a cache_control parameter to requests to bypass intermediate caches when needed.", 153 + "affected_files": [ 154 + "lib/headers.mli", 155 + "lib/headers.ml", 156 + "lib/requests.mli", 157 + "lib/one.mli" 158 + ], 159 + "rationale": "Cache control headers are important for ensuring fresh content from servers and bypassing stale intermediate caches. Aria2's implementation shows this is valuable for download utilities that need authoritative responses. The library can add headers manually but lacks a dedicated cache control abstraction." 160 + }, 161 + { 162 + "source_repo": "third_party/bash-shell/aria2", 163 + "source_language": "C++", 164 + "criticality": "medium", 165 + "change_type": "enhancement", 166 + "title": "Enhance HTTP error responses with response body in exceptions", 167 + "description": "Aria2's HTTPError exception includes URL, status code, reason, AND the response body. The current Error.HTTPError includes body as string option but it's not consistently populated. Ensure error responses always capture the body for debugging.", 168 + "affected_files": [ 169 + "lib/error.ml", 170 + "lib/requests.ml", 171 + "lib/one.ml" 172 + ], 173 + "rationale": "Error response bodies often contain critical debugging information (API error messages, HTML error pages). Aria2's inclusion of body in HTTPError shows this is a production necessity. The library has the field but should ensure it's populated from the actual response." 174 + }, 175 + { 176 + "source_repo": "third_party/bash-shell/aria2", 177 + "source_language": "C++", 178 + "criticality": "high", 179 + "change_type": "bug", 180 + "title": "Add explicit connection timeout separate from read timeout", 181 + "description": "Aria2's SocketCore distinguishes between connection establishment timeouts and read/write operation timeouts. The current Timeout module has connect and read timeouts but the implementation should ensure they're applied separately: connect for TCP handshake and TLS setup, read for ongoing data transfer.", 182 + "affected_files": [ 183 + "lib/timeout.ml", 184 + "lib/one.ml", 185 + "lib/requests.ml" 186 + ], 187 + "rationale": "Connection and read timeouts have different characteristics: connections can fail quickly due to network issues while reads might legitimately be slow for large responses. Aria2's separate timeout handling (SocketCore::isReadable/isWritable with timeout) prevents false negatives. Verify the library properly distinguishes these." 188 + }, 189 + { 190 + "source_repo": "third_party/bash-shell/aria2", 191 + "source_language": "C++", 192 + "criticality": "low", 193 + "change_type": "enhancement", 194 + "title": "Add TCP_NODELAY and socket option configuration", 195 + "description": "Aria2's SocketCore configures TCP_NODELAY and DSCP for performance optimization. Consider adding socket option configuration for users who need to tune TCP behavior for latency-sensitive applications.", 196 + "affected_files": [ 197 + "lib/one.ml", 198 + "lib/requests.ml" 199 + ], 200 + "rationale": "TCP_NODELAY disables Nagle's algorithm which can reduce latency for small HTTP requests. Aria2's socket configuration shows this matters for production clients. While most users won't need this, advanced users working with latency-sensitive APIs would benefit from the option." 201 + }, 202 + { 203 + "source_repo": "third_party/bash-shell/aria2", 204 + "source_language": "C++", 205 + "criticality": "medium", 206 + "change_type": "refactor", 207 + "title": "Separate HTTP status line parsing and validation logic", 208 + "description": "Aria2 uses dedicated HttpHeaderProcessor with state machine for parsing headers separately from HttpResponse. The current http_client.ml combines parsing and processing. Consider separating status line parsing from response construction for better testability and error handling.", 209 + "affected_files": [ 210 + "lib/http_client.ml" 211 + ], 212 + "rationale": "Aria2's HttpHeaderProcessor demonstrates the value of separating protocol parsing from business logic. This enables better error messages, easier testing, and reuse. The current parse_status_line is mixed with request processing, making it harder to test edge cases." 213 + }, 214 + { 215 + "source_repo": "third_party/bash-shell/aria2", 216 + "source_language": "C++", 217 + "criticality": "low", 218 + "change_type": "enhancement", 219 + "title": "Add test suite coverage for edge cases and protocol compliance", 220 + "description": "Aria2 has extensive unit tests (HttpHeaderProcessorTest, SocketCoreTest, NetrcAuthResolverTest, MessageDigestTest, Base64Test, etc.) covering edge cases. The current test suite (test_simple.ml, test_localhost.ml) should be expanded with protocol-level tests for chunked encoding edge cases, malformed headers, and timeout scenarios.", 221 + "affected_files": [ 222 + "test/test_simple.ml", 223 + "test/test_localhost.ml" 224 + ], 225 + "rationale": "Aria2's test directory shows comprehensive testing of protocol edge cases, authentication, and network primitives. The current test suite is minimal and focuses on integration tests. Adding unit tests for http_client.ml functions (parse_status_line, parse_headers, read_chunked_body) would improve reliability." 226 + }, 227 + { 228 + "source_repo": "third_party/bash-shell/aria2", 229 + "source_language": "C++", 230 + "criticality": "medium", 231 + "change_type": "feature", 232 + "title": "Add support for HTTP pipelining detection and queue management", 233 + "description": "Aria2's HttpConnection maintains a queue of outstanding HttpRequests supporting pipelining with HttpRequestEntries. While HTTP/1.1 pipelining is rarely used due to head-of-line blocking, the queue architecture enables request batching. Consider documenting the current connection model and whether pipelining could be supported.", 234 + "affected_files": [ 235 + "lib/http_client.ml" 236 + ], 237 + "rationale": "Aria2's HttpConnection::sendRequest and queue management show support for pipelining multiple requests over a single connection. While HTTP/2 is the modern solution, documenting whether the current architecture supports request queueing helps users understand the connection model." 238 + }, 239 + { 240 + "source_repo": "third_party/bash-shell/aria2", 241 + "source_language": "C++", 242 + "criticality": "medium", 243 + "change_type": "enhancement", 244 + "title": "Add configurable backoff jitter to prevent thundering herd", 245 + "description": "Aria2's retry logic and EvictSocketPoolCommand demonstrate awareness of distributed system patterns. The current Retry module has a jitter parameter but should ensure it's properly applied with randomization. Add exponential backoff with full jitter (not just additive) to prevent thundering herd when many clients retry simultaneously.", 246 + "affected_files": [ 247 + "lib/retry.ml" 248 + ], 249 + "rationale": "Aria2's architecture shows awareness of coordinating multiple concurrent operations. The jitter parameter exists but the implementation should verify it uses full jitter (multiplying by random factor) rather than additive jitter for optimal thundering herd prevention, especially important when the library is used in distributed systems." 250 + }, 251 + { 252 + "source_repo": "third_party/bash-shell/aria2", 253 + "source_language": "C++", 254 + "criticality": "low", 255 + "change_type": "enhancement", 256 + "title": "Add logging for connection pool statistics and lifecycle events", 257 + "description": "Aria2's command-based architecture with EvictSocketPoolCommand includes logging for connection lifecycle. Enhance Conpool logging to include detailed statistics: active connections, idle connections, evictions, connection lifetime, and pool pressure to help debug production issues.", 258 + "affected_files": [ 259 + "lib/requests.ml" 260 + ], 261 + "rationale": "Production debugging of connection pool issues requires visibility into pool state. Aria2's architecture shows the importance of logging connection lifecycle events. While the library has some pool logging, adding structured statistics logging (connections created/reused/evicted) would help operators understand pool behavior." 262 + }, 263 + { 264 + "source_repo": "third_party/bash-shell/aria2", 265 + "source_language": "C++", 266 + "criticality": "low", 267 + "change_type": "feature", 268 + "title": "Add FTP protocol support following the modular protocol design", 269 + "description": "Aria2 supports multiple protocols (HTTP, HTTPS, FTP) through a unified request interface with protocol-specific handling (FTP_PROTOCOL_ERROR in error codes). While out of scope for most HTTP clients, the modular design allows protocol extensions. Document the extension points if users need FTP support.", 270 + "affected_files": [ 271 + "lib/requests.mli" 272 + ], 273 + "rationale": "Aria2's multi-protocol design (HTTP, FTP, BitTorrent) shows a clean abstraction for different transfer protocols. While FTP is legacy, the architectural pattern of protocol-agnostic requests with protocol-specific handlers could be documented for users who need to extend the library." 274 + } 275 + ] 276 + }
+271
third_party/bash-shell/curl.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/bash-shell/resty", 5 + "source_language": "bash/shell", 6 + "criticality": "medium", 7 + "change_type": "feature", 8 + "title": "Add dry-run mode for debugging HTTP requests", 9 + "description": "Resty provides a --dry-run flag that outputs the curl command without executing it, which is invaluable for debugging and script development. The OCaml library should add a similar capability to inspect the exact HTTP request that will be sent, including headers, body, method, and URL, without making the actual network call.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/requests.mli", 13 + "lib/one.ml", 14 + "lib/one.mli" 15 + ], 16 + "rationale": "Debugging HTTP requests is a common task. Currently, users must rely on verbose logging to understand what's being sent. A dry-run mode would allow users to inspect the complete request structure (method, URL, headers, body) in a structured format before execution. This is especially useful for: (1) debugging authentication headers, (2) verifying request construction, (3) CLI tools that need to show what would be sent, and (4) testing/development workflows. Implementation could return a record type containing all request components instead of executing the request." 17 + }, 18 + { 19 + "source_repo": "third_party/bash-shell/resty", 20 + "source_language": "bash/shell", 21 + "criticality": "medium", 22 + "change_type": "enhancement", 23 + "title": "Add per-method and per-host default configuration", 24 + "description": "Resty allows storing default curl options globally, per-host, and per-method in configuration files (~/.resty/resty for global, ~/.resty/domain for host-specific). This enables different authentication or headers for different endpoints. The OCaml library should support per-host configuration persistence, allowing users to set default headers, auth, and timeouts for specific domains that persist across requests.", 25 + "affected_files": [ 26 + "lib/requests.ml", 27 + "lib/requests.mli", 28 + "bin/ocurl.ml" 29 + ], 30 + "rationale": "The current OCaml library requires users to manually specify authentication and headers for each request or session. Many users work with multiple APIs that require different authentication methods. Resty's per-host configuration is loaded automatically based on the target domain, making it seamless to switch between APIs. For the OCaml library, this could be implemented as: (1) XDG-compliant config files (already has XDG support via xdge library), (2) a config directory structure like ~/.config/requests/hosts/<domain>.conf, (3) automatic loading of host-specific config when creating sessions. This would significantly improve ergonomics for CLI tools and multi-API applications." 31 + }, 32 + { 33 + "source_repo": "third_party/bash-shell/resty", 34 + "source_language": "bash/shell", 35 + "criticality": "low", 36 + "change_type": "feature", 37 + "title": "Add interactive request body editing capability", 38 + "description": "Resty's -V flag allows editing request data interactively in an editor (vi/EDITOR) before sending, using temporary files created securely with mktemp. This is useful for crafting complex request bodies. The OCaml library could add a similar feature, especially valuable for the CLI tool, allowing users to compose JSON/XML bodies in their preferred editor.", 39 + "affected_files": [ 40 + "bin/ocurl.ml" 41 + ], 42 + "rationale": "While this is primarily a CLI convenience feature, it significantly improves usability for interactive API exploration and testing. Users often need to craft complex request bodies (JSON, XML, multipart) and editing them inline or in files separately is cumbersome. Resty's approach: (1) creates a secure temp file with mktemp, (2) pre-populates it with stdin data if available, (3) opens the user's EDITOR, (4) reads the edited content and sends it. For the OCaml CLI tool, this could be implemented as a --edit flag that opens $EDITOR on a temp file before sending POST/PUT/PATCH requests. Security considerations: use secure temp file creation (already available in OCaml stdlib as Filename.temp_file) and ensure proper cleanup." 43 + }, 44 + { 45 + "source_repo": "third_party/bash-shell/resty", 46 + "source_language": "bash/shell", 47 + "criticality": "medium", 48 + "change_type": "enhancement", 49 + "title": "Add automatic HTML rendering/formatting for HTML responses", 50 + "description": "Resty automatically detects HTML responses (via Content-Type header) and pipes them through lynx/html2text for readable terminal output, with special processing to clean up reference links. The OCaml library could add optional HTML-to-text rendering for better CLI experience when dealing with HTML endpoints.", 51 + "affected_files": [ 52 + "lib/response.ml", 53 + "lib/response.mli", 54 + "bin/ocurl.ml" 55 + ], 56 + "rationale": "Many REST APIs return HTML for documentation endpoints or error pages. Raw HTML in terminal output is difficult to read. Resty's auto-detection approach: (1) checks Content-Type header for 'text/html', (2) pipes through available formatters (lynx -dump, html2text, or cat as fallback), (3) cleans up lynx's reference link formatting. For OCaml: (1) Response.text could have an optional ~format parameter, (2) CLI could auto-format based on Content-Type, (3) could shell out to lynx/html2text if available, or (4) optionally integrate a pure OCaml HTML-to-text library like lambdasoup for parsing. The -Z (raw) flag equivalent should disable this formatting." 57 + }, 58 + { 59 + "source_repo": "third_party/bash-shell/resty", 60 + "source_language": "bash/shell", 61 + "criticality": "high", 62 + "change_type": "enhancement", 63 + "title": "Improve error output routing to stderr", 64 + "description": "Resty has clear separation: successful responses (2xx) go to stdout, error responses (non-2xx) and curl errors go to stderr. This allows proper shell composition and error handling. The OCaml CLI tool should ensure consistent error output routing: non-2xx responses should print to stderr, not stdout, to enable better shell scripting.", 65 + "affected_files": [ 66 + "bin/ocurl.ml" 67 + ], 68 + "rationale": "Proper separation of stdout/stderr is critical for shell scripting and CLI composition. Resty's approach (lines 261-267): (1) 2xx responses → stdout with exit code 0, (2) non-2xx responses → stderr with exit code matching first digit of status (4 for 4xx, 5 for 5xx), (3) network errors → stderr with curl's exit code. This enables patterns like 'GET /api | jq .' to work correctly, as errors won't be piped to jq. The current OCaml CLI likely prints all response bodies to stdout. It should: (1) check response status, (2) write non-2xx bodies to stderr, (3) set appropriate exit codes (0 for 2xx, 1 for network errors, 4 for 4xx, 5 for 5xx)." 69 + }, 70 + { 71 + "source_repo": "third_party/bash-shell/resty", 72 + "source_language": "bash/shell", 73 + "criticality": "medium", 74 + "change_type": "enhancement", 75 + "title": "Return meaningful exit codes based on HTTP status", 76 + "description": "Resty returns the first digit of the HTTP status code as the exit code (1xx→1, 3xx→3, 4xx→4, 5xx→5, 2xx→0), allowing shell scripts to easily handle different response types. The OCaml CLI tool should implement similar exit code semantics for better shell integration.", 77 + "affected_files": [ 78 + "bin/ocurl.ml" 79 + ], 80 + "rationale": "Exit codes are essential for shell scripting and automation. Resty's exit code strategy (line 263): extracts first digit of HTTP status code and returns it as exit code. This enables shell patterns like: 'GET /api && echo success || echo failed' and 'if GET /health; then ...'. Currently unknown if the OCaml CLI has this behavior, but it's common for HTTP clients to return 0 for any completed request regardless of status code. Recommended exit codes: (1) 0 for 2xx success, (2) 1 for network/connection errors, (3) 3 for 3xx redirects (when not followed), (4) 4 for 4xx client errors, (5) 5 for 5xx server errors. This matches curl and Resty behavior." 81 + }, 82 + { 83 + "source_repo": "third_party/bash-shell/resty", 84 + "source_language": "bash/shell", 85 + "criticality": "low", 86 + "change_type": "enhancement", 87 + "title": "Add query string builder with URL encoding", 88 + "description": "Resty provides -q flag for adding query strings easily without manual URL encoding. The OCaml library has params support in get() but could enhance it with better builder ergonomics and ensure proper URL encoding of special characters, matching Resty's comprehensive encoding list (%, [, ], |, $, &, +, etc.).", 89 + "affected_files": [ 90 + "lib/requests.ml", 91 + "lib/one.ml" 92 + ], 93 + "rationale": "Resty's URL encoding (line 177) handles a comprehensive set of special characters: %, [, ], |, $, &, +, ,, :, ;, =, ?, @, #, {, }, \\, ^, ~, ` and spaces. The OCaml library uses the Uri library for URL construction, which should handle encoding, but there's value in: (1) explicit documentation of encoding behavior, (2) a -Q equivalent flag to disable encoding when needed (for pre-encoded URLs), (3) convenient query parameter builders. The current params support in get() is good but could be enhanced with: (1) query parameter type that supports multiple values for same key, (2) option to disable encoding for advanced use cases, (3) helper functions for common query patterns." 94 + }, 95 + { 96 + "source_repo": "third_party/bash-shell/resty", 97 + "source_language": "bash/shell", 98 + "criticality": "low", 99 + "change_type": "feature", 100 + "title": "Add convenience flags for JSON and XML content types", 101 + "description": "Resty provides --json and --xml flags that automatically add appropriate Accept and Content-Type headers. The OCaml library could add similar convenience constructors or combinators for common content type scenarios.", 102 + "affected_files": [ 103 + "lib/headers.ml", 104 + "lib/headers.mli", 105 + "lib/body.ml", 106 + "lib/body.mli" 107 + ], 108 + "rationale": "Resty's --json flag (line 170) adds both 'Accept: application/json' and 'Content-Type: application/json' headers in one flag. This reduces boilerplate for the common case of JSON APIs. The OCaml library has separate Body.json for request bodies and could enhance this with: (1) Headers.for_json combinator that sets both headers, (2) Headers.for_xml similarly, (3) Request-level shortcuts like request ~json:true that automatically configures headers. The CLI tool could have --json/--xml flags. Current approach requires manual header setting: ~headers:(Headers.empty |> Headers.content_type Mime.json |> Headers.set \"Accept\" \"application/json\"). A simpler API: ~headers:(Headers.for_json) would improve ergonomics." 109 + }, 110 + { 111 + "source_repo": "third_party/bash-shell/resty", 112 + "source_language": "bash/shell", 113 + "criticality": "medium", 114 + "change_type": "enhancement", 115 + "title": "Add path persistence feature for consecutive requests", 116 + "description": "Resty remembers the last request path in $_RESTY_PATH (unless disabled with RESTY_NO_PRESERVE_PATH), allowing users to make multiple requests to the same endpoint without repeating the full path. The OCaml library could add optional path/URL persistence to sessions for interactive CLI usage.", 117 + "affected_files": [ 118 + "lib/requests.ml", 119 + "lib/requests.mli", 120 + "bin/ocurl.ml" 121 + ], 122 + "rationale": "Path persistence (lines 182-187) reduces repetition in interactive usage. When testing an API endpoint with multiple operations, users can: (1) GET /api/users/123, (2) PUT (same path) with updated data, (3) DELETE (same path). Resty stores the last path in an environment variable. For OCaml: (1) Sessions could track last_url, (2) Request methods could accept optional URL (defaulting to last_url if None), (3) CLI could offer a --repeat or --again flag to reuse last URL. This is primarily valuable for interactive REPL-style usage and CLI tools. The session type already has mutable statistics, so adding mutable last_url wouldn't be out of place. Can be disabled globally or per-request for users who don't want this behavior." 123 + }, 124 + { 125 + "source_repo": "third_party/bash-shell/resty", 126 + "source_language": "bash/shell", 127 + "criticality": "low", 128 + "change_type": "enhancement", 129 + "title": "Add verbose flag to show request/response headers inline", 130 + "description": "Resty's -v flag shows verbose output including HTTP headers on stderr, similar to curl -v. While the OCaml library has comprehensive logging, a dedicated verbose flag that formats request/response headers in a readable way (like curl -v or httpie) would improve CLI debugging experience.", 131 + "affected_files": [ 132 + "bin/ocurl.ml" 133 + ], 134 + "rationale": "The OCaml library already has excellent logging infrastructure with module-level log sources (line 792-833 in requests.ml). However, structured logs may not be as immediately readable as curl's verbose format for quick debugging. Resty passes -v to curl which shows: (1) request line and headers prefixed with '>', (2) response status and headers prefixed with '<', (3) TLS handshake details. The OCaml library does log this (lines 343-350, 373-378) but may not be formatted ideally for CLI users. Enhancement: (1) CLI --verbose flag that configures logging to use a curl-like format, (2) request headers prefixed with '> ', (3) response headers prefixed with '< ', (4) clear visual separation. The existing logging is debug-oriented; this would be human-readable verbose output." 135 + }, 136 + { 137 + "source_repo": "third_party/bash-shell/resty", 138 + "source_language": "bash/shell", 139 + "criticality": "low", 140 + "change_type": "enhancement", 141 + "title": "Add option to disable history/persistence for security", 142 + "description": "Resty provides -W flag to prevent writing to history file, useful for scripts to avoid polluting user's configuration with automated requests. The OCaml library could add a no_persist or ephemeral mode that prevents any disk writes (cookies, config, cache) for security-sensitive operations.", 143 + "affected_files": [ 144 + "lib/requests.ml", 145 + "lib/requests.mli" 146 + ], 147 + "rationale": "Resty's -W flag (line 338) sets _RESTY_NO_HISTORY to prevent writing the target URL to disk. This prevents: (1) secrets in URLs from being persisted, (2) automated scripts from cluttering user config. The OCaml library has persist_cookies flag but could extend this to a comprehensive ephemeral mode. Use cases: (1) CI/CD environments where no persistent state should be created, (2) security-sensitive operations with credentials in requests, (3) testing that shouldn't affect user's saved state. Implementation: (1) add ~ephemeral:bool parameter to create(), (2) when true, disable all disk writes (cookies, config, cache), (3) possibly use in-memory XDG directories. Could combine with existing persist_cookies but be more comprehensive." 148 + }, 149 + { 150 + "source_repo": "third_party/bash-shell/resty", 151 + "source_language": "bash/shell", 152 + "criticality": "medium", 153 + "change_type": "enhancement", 154 + "title": "Improve HTTP/1.1 chunked encoding error handling", 155 + "description": "While the OCaml library implements chunked encoding (http_client.ml:210-236), it could improve robustness by handling malformed chunk sizes, invalid hex parsing, and incomplete chunks more gracefully with specific error messages, similar to how production HTTP clients handle these edge cases.", 156 + "affected_files": [ 157 + "lib/http_client.ml", 158 + "lib/error.ml" 159 + ], 160 + "rationale": "The current chunked encoding implementation (lines 211-236) uses int_of_string with '0x' prefix for hex parsing but doesn't have extensive error handling for: (1) invalid hex characters, (2) chunk size mismatches, (3) missing trailing CRLF, (4) oversized chunks (decompression bomb protection). While Resty delegates to curl for this, production HTTP clients need robust handling. Improvements: (1) wrap int_of_string in try-catch with specific EncodingError, (2) validate chunk sizes against limits, (3) detect and report truncated responses, (4) handle chunk extensions properly (currently ignored after ';' which is correct per RFC 7230, but could log them). This prevents crashes on malformed responses and provides actionable error messages." 161 + }, 162 + { 163 + "source_repo": "third_party/bash-shell/resty", 164 + "source_language": "bash/shell", 165 + "criticality": "high", 166 + "change_type": "bug", 167 + "title": "Add connection timeout to retry logic", 168 + "description": "The retry module (retry.ml) doesn't explicitly use connection timeout when calculating retry delays. While individual requests can timeout, the retry logic should account for connection timeouts separately from read timeouts to avoid long wait times on network issues. Resty delegates timeout handling to curl's built-in mechanisms.", 169 + "affected_files": [ 170 + "lib/retry.ml", 171 + "lib/retry.mli", 172 + "lib/requests.ml" 173 + ], 174 + "rationale": "Current retry implementation (retry.ml:95-123) wraps function calls and catches exceptions but doesn't explicitly integrate with timeout configuration. When requests timeout, the retry delay is calculated but the next attempt may have the same timeout issues. Improvements: (1) reduce timeouts on retry attempts (e.g., if attempt 1 timeout is 30s, attempt 2 might be 20s), (2) fail fast after connection timeout on retry (network down vs server overloaded), (3) log timeout reasons separately. In requests.ml:551-557, retry catches exceptions including timeouts, but there's no adjustment of timeout parameters for subsequent attempts. Consider: (1) passing timeout config to retry logic, (2) adjusting timeouts based on retry attempt number, (3) distinguishing connection vs read timeouts in retry decisions." 175 + }, 176 + { 177 + "source_repo": "third_party/bash-shell/resty", 178 + "source_language": "bash/shell", 179 + "criticality": "medium", 180 + "change_type": "enhancement", 181 + "title": "Add support for Retry-After header in retry logic", 182 + "description": "While the retry module has a parse_retry_after function (retry.ml:73-93) and respect_retry_after config option, this functionality appears not to be fully integrated into the actual retry decision-making in with_retry. The retry delay should honor server-provided Retry-After headers from 429/503 responses.", 183 + "affected_files": [ 184 + "lib/retry.ml", 185 + "lib/requests.ml" 186 + ], 187 + "rationale": "The parse_retry_after function (lines 73-93) can parse both integer seconds and HTTP-date formats, and the config has respect_retry_after flag (line 15, 25, 46), but in with_retry (lines 95-123) and the requests.ml retry logic (lines 526-559), there's no code that actually extracts the Retry-After header from response headers and uses it to override the calculated backoff delay. This is a partially implemented feature. To complete it: (1) in requests.ml, when a retryable status like 429 or 503 is received, extract Retry-After header from response, (2) if present and respect_retry_after is true, use parse_retry_after to get the delay, (3) use this delay instead of calculate_backoff, (4) respect backoff_max as upper bound. This prevents violating server rate limits and reduces unnecessary retries." 188 + }, 189 + { 190 + "source_repo": "third_party/bash-shell/resty", 191 + "source_language": "bash/shell", 192 + "criticality": "medium", 193 + "change_type": "enhancement", 194 + "title": "Add request/response size limits for security", 195 + "description": "Resty inherits curl's built-in limits, but the OCaml library should add explicit configurable limits on request body size and response body size to prevent memory exhaustion from malicious or misconfigured servers, especially important given the current use of unbuffered reads.", 196 + "affected_files": [ 197 + "lib/http_client.ml", 198 + "lib/response.ml", 199 + "lib/timeout.ml", 200 + "lib/body.ml" 201 + ], 202 + "rationale": "The http_client.ml read functions (read_fixed_body line 197-208, read_chunked_body line 211-236) read responses into memory without size limits beyond Int64 for Content-Length. This is vulnerable to: (1) decompression bombs (partially addressed with decompression error handling but no size limits), (2) memory exhaustion from large responses, (3) malicious servers sending infinite chunked responses. Resty benefits from curl's built-in protections. For OCaml: (1) add max_response_size to Timeout config (or separate LimitsConfig), (2) check Content-Length before reading and reject if > limit, (3) track bytes read in chunked encoding and abort if > limit, (4) add max_request_size for uploads. Defaults could be 100MB response, 10MB request. This is critical for long-running services and CLI tools processing untrusted endpoints." 203 + }, 204 + { 205 + "source_repo": "third_party/bash-shell/resty", 206 + "source_language": "bash/shell", 207 + "criticality": "low", 208 + "change_type": "enhancement", 209 + "title": "Add streaming response body support for large downloads", 210 + "description": "While Response.body returns an Eio.Flow, the library currently reads entire responses into memory in http_client.ml. For large files, streaming support that doesn't buffer the entire response would reduce memory usage. Resty handles this via curl's streaming by default.", 211 + "affected_files": [ 212 + "lib/http_client.ml", 213 + "lib/response.ml", 214 + "lib/one.ml" 215 + ], 216 + "rationale": "Current implementation in http_client.ml (read_fixed_body and read_chunked_body) reads the entire response body into a Buffer before returning it as a string. This is then converted to an Eio.Flow with Eio.Flow.string_source (requests.ml:436, one.ml:207). For a 1GB file download, this requires 1GB+ memory. Resty/curl streams by default. The library has download() function in one.ml:269-297 that does Eio.Flow.copy, but this still works on the fully buffered response. To fix: (1) refactor http_client to return an Eio.Flow directly instead of reading into string, (2) for chunked encoding, create a flow that reads chunks on-demand, (3) for Content-Length, create a flow that reads in chunks. This is complex with Eio but would enable true streaming. Alternative: document current buffering behavior and add max_response_size limits." 217 + }, 218 + { 219 + "source_repo": "third_party/bash-shell/resty", 220 + "source_language": "bash/shell", 221 + "criticality": "low", 222 + "change_type": "enhancement", 223 + "title": "Add progress callbacks for uploads and downloads", 224 + "description": "Resty doesn't have progress tracking, but the OCaml library has placeholder code for on_progress callbacks in upload/download functions (one.ml:254, 269) that are not fully implemented. Complete this feature to enable progress bars in CLI tools and better UX for large transfers.", 225 + "affected_files": [ 226 + "lib/one.ml", 227 + "lib/one.mli" 228 + ], 229 + "rationale": "The download and upload functions have on_progress parameters (lines 249-297) but the implementation has TODO comments. For download (lines 286-291), progress_fn is called only at start (0L) and end (total), not during transfer. Upload (line 261) has a comment saying progress tracking is not implemented due to complexity of wrapping Eio.Flow.source. This incomplete feature should either be: (1) fully implemented by wrapping flows with byte-counting interceptors, (2) removed from the API if not feasible, or (3) documented as 'start/end only' if that's sufficient. For full implementation: create a wrapper flow that intercepts read/write operations and invokes callback with byte counts. This is valuable for CLI tools (progress bars with libraries like Progress) and long-running operations. Reference implementation could use Eio's flow composition capabilities." 230 + }, 231 + { 232 + "source_repo": "third_party/bash-shell/resty", 233 + "source_language": "bash/shell", 234 + "criticality": "high", 235 + "change_type": "security", 236 + "title": "Validate and sanitize Content-Length header to prevent overflow", 237 + "description": "The http_client.ml parses Content-Length header with Int64.of_string (line 260) without validation. Malicious servers could send negative, zero, or absurdly large values. This should be validated to prevent integer overflow issues or memory allocation failures.", 238 + "affected_files": [ 239 + "lib/http_client.ml" 240 + ], 241 + "rationale": "Line 260: 'let content_length = Headers.get \"content-length\" resp_headers |> Option.map Int64.of_string'. This is vulnerable to: (1) negative Content-Length causing incorrect buffer allocation, (2) Content-Length > available memory causing allocation failure, (3) Int64.of_string exceptions on malformed values (though wrapped in Option.map it would return None). The code then uses this in read_fixed_body (line 197) which creates a buffer with Int64.to_int. Issues: (1) no validation that length >= 0, (2) no check that length <= reasonable max, (3) Int64.to_int can raise exception if value > max_int on 32-bit. Fixes: (1) wrap Int64.of_string in try-catch, (2) validate length > 0L && length < max_response_size, (3) on 32-bit, check length fits in int before to_int, (4) reject invalid/malicious lengths with EncodingError." 242 + }, 243 + { 244 + "source_repo": "third_party/bash-shell/resty", 245 + "source_language": "bash/shell", 246 + "criticality": "medium", 247 + "change_type": "enhancement", 248 + "title": "Add automatic base URL resolution for relative redirects", 249 + "description": "The library handles relative redirects (requests.ml:398-408, one.ml:177-194) by resolving against the current URL using Uri.resolve. However, this should also handle edge cases like protocol-relative URLs (//example.com/path) and ensure proper resolution according to RFC 3986.", 250 + "affected_files": [ 251 + "lib/requests.ml", 252 + "lib/one.ml" 253 + ], 254 + "rationale": "Current redirect handling (requests.ml lines 398-409): checks if Location header has a host, if not treats as relative and resolves against base URI using Uri.resolve. This is correct for most cases but could be enhanced: (1) handle protocol-relative URLs (//cdn.example.com/resource) which should preserve https/http of original request, (2) validate resolved URIs don't redirect to file://, javascript:, or other dangerous schemes (security), (3) handle fragment identifiers in Location headers (should be preserved), (4) log when relative redirects are resolved for debugging. The Uri library likely handles most of this correctly, but explicit validation and logging would improve robustness. Edge case: ensure redirects to localhost or 127.0.0.1 are rejected in production use (SSRF prevention) unless explicitly allowed." 255 + }, 256 + { 257 + "source_repo": "third_party/bash-shell/resty", 258 + "source_language": "bash/shell", 259 + "criticality": "low", 260 + "change_type": "enhancement", 261 + "title": "Add configurable User-Agent with version information", 262 + "description": "While the library has User-Agent support in Cmd module (line 683), there's no default User-Agent header. Following best practices from curl and other HTTP clients, the library should set a default User-Agent like 'ocaml-requests/VERSION' unless overridden by users.", 263 + "affected_files": [ 264 + "lib/requests.ml", 265 + "lib/one.ml", 266 + "lib/headers.ml" 267 + ], 268 + "rationale": "Many servers require or expect a User-Agent header. HTTP/1.1 RFC recommends it. Curl sends 'curl/VERSION', Resty inherits this. The OCaml library: (1) Cmd module has user_agent parameter (line 683), (2) but default sessions don't set User-Agent automatically. This can cause issues with: (1) servers that block requests without User-Agent, (2) analytics/logging that use User-Agent, (3) debugging (can't identify requests from this library in logs). Recommendation: (1) add default User-Agent to Headers.empty in common request paths, (2) format as 'ocaml-requests/VERSION (https://github.com/...)', (3) easily overridable via headers parameter, (4) document User-Agent behavior. Get version from dune or META file." 269 + } 270 + ] 271 + }
+199
third_party/bash-shell/http-prompt.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/bash-shell/http-prompt", 5 + "source_language": "Python", 6 + "criticality": "medium", 7 + "change_type": "feature", 8 + "title": "Add session persistence/restoration functionality", 9 + "description": "http-prompt persists context (headers, query params, body params, options) to disk and restores on startup. The OCaml library has cookie persistence but lacks comprehensive session state persistence including headers, auth, and other request parameters.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/requests.mli" 13 + ], 14 + "rationale": "http-prompt's contextio.py serializes the entire request context (headers, querystring_params, body_params, options) to ~/.local/share/http-prompt/context.hp and restores it on startup. This provides continuity across sessions. The OCaml library currently only persists cookies when persist_cookies=true. Adding a save_session/load_session API would allow users to preserve default_headers, auth, timeout, retry config, and other settings across application restarts. This is particularly useful for CLI tools and interactive applications." 15 + }, 16 + { 17 + "source_repo": "third_party/bash-shell/http-prompt", 18 + "source_language": "Python", 19 + "criticality": "low", 20 + "change_type": "enhancement", 21 + "title": "Add User-Agent default header with library version", 22 + "description": "Set a default User-Agent header identifying the library and version, following standard HTTP client practices.", 23 + "affected_files": [ 24 + "lib/requests.ml", 25 + "lib/headers.ml" 26 + ], 27 + "rationale": "http-prompt (through HTTPie) automatically sets a User-Agent header like 'HTTPie/3.x.x'. The OCaml library currently requires users to manually set User-Agent via default_headers. Best practice for HTTP clients is to identify themselves with a User-Agent header. This helps server administrators debug issues, track client usage, and can be important for API rate limiting or access policies. Recommendation: Set default User-Agent to 'ocaml-requests/VERSION' (extracting version from dune-project) but allow users to override it." 28 + }, 29 + { 30 + "source_repo": "third_party/bash-shell/http-prompt", 31 + "source_language": "Python", 32 + "criticality": "medium", 33 + "change_type": "feature", 34 + "title": "Add request/response history tracking", 35 + "description": "Implement a history mechanism to track recent requests and responses, useful for debugging and interactive use.", 36 + "affected_files": [ 37 + "lib/requests.ml", 38 + "lib/requests.mli" 39 + ], 40 + "rationale": "http-prompt maintains request context and allows inspection of the environment state with 'env' command. While the OCaml library tracks statistics (requests_made, total_time, retries_count), it doesn't maintain a history of actual requests/responses. Adding an optional history feature (e.g., max 10 recent requests) would help with debugging, logging, and interactive/CLI applications. This could be implemented as: type history_entry = { request: request_info; response: Response.t; timestamp: float } with methods like get_history : t -> history_entry list and clear_history : t -> unit. Make it opt-in via a ~track_history:bool parameter to avoid memory overhead." 41 + }, 42 + { 43 + "source_repo": "third_party/bash-shell/http-prompt", 44 + "source_language": "Python", 45 + "criticality": "high", 46 + "change_type": "security", 47 + "title": "Add security warnings for unsafe configurations", 48 + "description": "Log warnings when security-sensitive options are disabled (verify_tls=false) to prevent accidental insecure deployments.", 49 + "affected_files": [ 50 + "lib/requests.ml", 51 + "lib/one.ml" 52 + ], 53 + "rationale": "http-prompt uses HTTPie which warns users about insecure operations. The OCaml library allows verify_tls=false without any warnings. This is dangerous because developers might disable TLS verification during development and forget to re-enable it in production. Recommendation: Add a Warning-level log message when creating a client with verify_tls=false: 'TLS certificate verification is disabled. This is insecure and should only be used in development.' This follows security best practices of making insecure configurations obvious and auditable." 54 + }, 55 + { 56 + "source_repo": "third_party/bash-shell/http-prompt", 57 + "source_language": "Python", 58 + "criticality": "low", 59 + "change_type": "enhancement", 60 + "title": "Add cookie acceptance policy configuration", 61 + "description": "Implement configurable cookie acceptance policies (auto, ask, off) rather than binary persist/don't persist.", 62 + "affected_files": [ 63 + "lib/requests.ml", 64 + "lib/requests.mli" 65 + ], 66 + "rationale": "http-prompt's defaultconfig.py has 'set_cookies' with values 'auto', 'ask', 'off' to control cookie behavior. The OCaml library has persist_cookies:bool but no granular control. While 'ask' mode doesn't make sense for non-interactive clients, adding a cookie_policy type with variants like `Accept_all, `Accept_none, `Accept_same_origin could improve security by allowing users to reject third-party cookies or all cookies. This is particularly important for security-conscious applications and web scraping that want to avoid tracking." 67 + }, 68 + { 69 + "source_repo": "third_party/bash-shell/http-prompt", 70 + "source_language": "Python", 71 + "criticality": "medium", 72 + "change_type": "enhancement", 73 + "title": "Enhance error messages with request context", 74 + "description": "Include URL, method, and attempt number in error messages for better debugging.", 75 + "affected_files": [ 76 + "lib/error.ml", 77 + "lib/error.mli", 78 + "lib/retry.ml" 79 + ], 80 + "rationale": "http-prompt's execution.py provides detailed error context including parse position, key names in KeyError, and full command context. The OCaml Error module has good exception types but error messages could be more helpful. Current HTTPError includes url/status/reason/body but ConnectionError and Timeout are generic. Recommendations: (1) Enhance Timeout exception to include the URL and timeout config that was exceeded. (2) Enhance ConnectionError to include the URL, method, and underlying network error. (3) In retry.ml, include attempt number and total attempts in error messages. Example: 'Connection timeout after 30s for GET https://example.com (attempt 2/3)'." 81 + }, 82 + { 83 + "source_repo": "third_party/bash-shell/http-prompt", 84 + "source_language": "Python", 85 + "criticality": "low", 86 + "change_type": "feature", 87 + "title": "Add output redirection/piping support for CLI tools", 88 + "description": "Provide utilities for writing responses to files or piping to external commands, useful for CLI applications.", 89 + "affected_files": [ 90 + "lib/response.ml", 91 + "lib/response.mli" 92 + ], 93 + "rationale": "http-prompt's execution.py supports output redirection (>, >>) and piping (|) to shell commands or files. While the OCaml library has streaming via Response.body, it doesn't provide convenience methods for common CLI use cases. Adding methods like Response.save_to_file : t -> path:_ Eio.Path.t -> unit and Response.pipe_to_command : t -> cmd:string -> unit would be valuable for CLI tools built with this library. These are common patterns in tools like curl/wget/httpie." 94 + }, 95 + { 96 + "source_repo": "third_party/bash-shell/http-prompt", 97 + "source_language": "Python", 98 + "criticality": "medium", 99 + "change_type": "enhancement", 100 + "title": "Improve Retry-After header parsing", 101 + "description": "The current Retry-After parsing in retry.ml uses Ptime.of_rfc3339 but HTTP dates use RFC 2822/5322 format, not RFC 3339.", 102 + "affected_files": [ 103 + "lib/retry.ml" 104 + ], 105 + "rationale": "In retry.ml:83-93, the parse_retry_after function tries to parse HTTP dates using Ptime.of_rfc3339, but HTTP Retry-After headers use IMF-fixdate format (RFC 7231) which is different from RFC 3339. Example: 'Wed, 21 Oct 2015 07:28:00 GMT' vs '2015-10-21T07:28:00Z'. This will cause parsing failures. http-prompt relies on httpie/requests which correctly handles both formats. Recommendation: Use a proper HTTP-date parser or add a conversion function. The ptime library supports RFC 3339 but not IMF-fixdate directly. Consider using the existing HTTP date parsing from other OCaml libraries or implement RFC 7231 date parsing." 106 + }, 107 + { 108 + "source_repo": "third_party/bash-shell/http-prompt", 109 + "source_language": "Python", 110 + "criticality": "low", 111 + "change_type": "enhancement", 112 + "title": "Add convenience methods for common header checks", 113 + "description": "Add helper methods to Response for checking common headers like is_json, is_html, charset, etc.", 114 + "affected_files": [ 115 + "lib/response.ml", 116 + "lib/response.mli" 117 + ], 118 + "rationale": "http-prompt and HTTPie provide easy access to response metadata through their context objects. The OCaml library has content_type : t -> Mime.t option but lacks convenience methods. Adding methods like: is_json : t -> bool, is_xml : t -> bool, is_html : t -> bool, encoding : t -> string (extract charset from Content-Type), is_chunked : t -> bool, would improve API ergonomics. These are common checks that every HTTP client needs to do and having them built-in reduces boilerplate." 119 + }, 120 + { 121 + "source_repo": "third_party/bash-shell/http-prompt", 122 + "source_language": "Python", 123 + "criticality": "high", 124 + "change_type": "bug", 125 + "title": "Fix potential infinite loop in redirect following", 126 + "description": "Add detection for redirect loops where a URL redirects to itself or creates a cycle.", 127 + "affected_files": [ 128 + "lib/requests.ml", 129 + "lib/one.ml" 130 + ], 131 + "rationale": "The current implementation counts redirects (max_redirects) but doesn't detect redirect loops where URL A -> URL B -> URL A. This can cause the client to make max_redirects requests even though it's stuck in a 2-URL cycle. http-prompt (via httpie/requests) likely has loop detection. Recommendation: Track visited URLs in a Set during redirect following and raise TooManyRedirects early if the same URL is encountered twice. This saves network requests and provides better error messages. Implementation: In the redirect-following code, maintain a String_set of visited URLs and check before each redirect." 132 + }, 133 + { 134 + "source_repo": "third_party/bash-shell/http-prompt", 135 + "source_language": "Python", 136 + "criticality": "medium", 137 + "change_type": "enhancement", 138 + "title": "Add support for conditional retry based on exception type", 139 + "description": "Allow more granular control over which exceptions/errors trigger retries beyond just status codes.", 140 + "affected_files": [ 141 + "lib/retry.ml", 142 + "lib/retry.mli" 143 + ], 144 + "rationale": "The current retry.ml has should_retry_exn:(exn -> bool) parameter in with_retry, which is good. However, the public API in retry.mli only exposes should_retry based on status codes. http-prompt and similar tools retry on various conditions. Recommendation: Enhance the retry config to include retryable_exceptions : (exn -> bool) option to allow users to customize which exceptions trigger retries. Default could be: SSLError (handshake failures are often transient), ConnectionError, Timeout, but NOT AuthenticationError or InvalidURL. This gives users more control while maintaining safe defaults." 145 + }, 146 + { 147 + "source_repo": "third_party/bash-shell/http-prompt", 148 + "source_language": "Python", 149 + "criticality": "low", 150 + "change_type": "feature", 151 + "title": "Add request/response event hooks", 152 + "description": "Implement before_request and after_response hooks to allow users to inspect/modify requests and responses.", 153 + "affected_files": [ 154 + "lib/requests.ml", 155 + "lib/requests.mli" 156 + ], 157 + "rationale": "http-prompt has an ExecutionListener with context_changed and response_returned callbacks. While this is CLI-specific, the pattern of hooks/events is valuable for HTTP clients. Popular libraries (Python requests, JavaScript axios) support hooks. Use cases: logging, metrics collection, request signing, response caching, error recovery. Recommendation: Add optional hooks to the session config: type hooks = { before_request : (method:Method.t -> url:string -> headers:Headers.t -> Headers.t) option; after_response : (Response.t -> unit) option; on_error : (exn -> unit) option }. This allows instrumentation without modifying core request logic." 158 + }, 159 + { 160 + "source_repo": "third_party/bash-shell/http-prompt", 161 + "source_language": "Python", 162 + "criticality": "low", 163 + "change_type": "enhancement", 164 + "title": "Add connection pool statistics and monitoring", 165 + "description": "Expose connection pool metrics (active connections, idle connections, wait times) for monitoring and debugging.", 166 + "affected_files": [ 167 + "lib/requests.ml", 168 + "lib/requests.mli" 169 + ], 170 + "rationale": "The Requests.t type tracks basic statistics (requests_made, total_time, retries_count) but doesn't expose connection pool health. For production applications, monitoring connection pool saturation is crucial. The underlying Conpool likely has this data. Recommendation: Add a method pool_stats : t -> pool_statistics that returns metrics like: active_connections, idle_connections, total_connections, max_connections, connection_wait_time_ms, connection_lifetime_avg_s. This helps users diagnose performance issues, tune max_connections_per_host, and identify connection leaks." 171 + }, 172 + { 173 + "source_repo": "third_party/bash-shell/http-prompt", 174 + "source_language": "Python", 175 + "criticality": "medium", 176 + "change_type": "enhancement", 177 + "title": "Add configurable output formatting/syntax highlighting for CLI use", 178 + "description": "Provide utilities for pretty-printing HTTP requests/responses with syntax highlighting for CLI applications.", 179 + "affected_files": [ 180 + "lib/response.ml", 181 + "lib/response.mli" 182 + ], 183 + "rationale": "http-prompt provides extensive output formatting with syntax highlighting (command_style, output_style config). While the OCaml library is not specifically a CLI tool, adding opt-in pretty-printing utilities would benefit CLI applications built with it. Recommendation: Add a Response.Pretty module with functions like format_headers : Headers.t -> string, format_json_body : string -> string (indented), format_http_exchange : method:Method.t -> url:string -> Response.t -> string. These could integrate with existing OCaml pretty-printing libraries. Make it optional to avoid dependencies for non-CLI users." 184 + }, 185 + { 186 + "source_repo": "third_party/bash-shell/http-prompt", 187 + "source_language": "Python", 188 + "criticality": "medium", 189 + "change_type": "feature", 190 + "title": "Add support for environment-specific configuration profiles", 191 + "description": "Allow users to define and switch between different configuration profiles (dev, staging, prod) similar to http-prompt's config system.", 192 + "affected_files": [ 193 + "lib/requests.ml", 194 + "lib/requests.mli" 195 + ], 196 + "rationale": "http-prompt loads configuration from config.py with defaults and user overrides (defaultconfig.py, load_default(), load_user()). The OCaml library has extensive Cmdliner integration but no concept of named configuration profiles. Use case: A developer might want different settings for local dev (verify_tls=false, verbose logging) vs staging (verify_tls=true, moderate logging) vs prod (strict timeouts, minimal logging). Recommendation: Add a Requests.Config module that can load/save named profiles to XDG directories: save_profile : name:string -> t -> unit and load_profile : name:string -> t. Profiles could be stored as s-expressions or JSON in ~/.config/requests/profiles/." 197 + } 198 + ] 199 + }
+214
third_party/bash-shell/httpie.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "httpie", 5 + "source_language": "python", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": ".netrc authentication support", 9 + "description": "HTTPie supports reading credentials from ~/.netrc file for automatic authentication. This allows users to store credentials for different hosts securely and have them automatically applied without passing --auth flags. The OCaml library currently requires explicit auth configuration for every request.", 10 + "affected_files": [ 11 + "lib/auth.ml", 12 + "lib/auth.mli", 13 + "lib/requests.ml" 14 + ], 15 + "rationale": "HTTPie's .netrc support (via requests library) is a standard Unix mechanism for credential storage that improves usability and security. Users can configure credentials once per host in ~/.netrc and the library automatically applies them. This is particularly useful for APIs that require authentication and reduces the risk of hardcoding credentials. The OCaml library would benefit from implementing netrc parsing to automatically load credentials based on the request host, falling back to explicit auth if provided." 16 + }, 17 + { 18 + "source_repo": "httpie", 19 + "source_language": "python", 20 + "criticality": "medium", 21 + "change_type": "security", 22 + "title": "Configurable TLS version and cipher suites", 23 + "description": "HTTPie provides explicit control over SSL/TLS versions (ssl2.3, ssl3, tls1, tls1.1, tls1.2, tls1.3) and cipher suites through command-line options and adapter configuration. The OCaml library uses default TLS configuration from the tls library without exposing version or cipher control.", 24 + "affected_files": [ 25 + "lib/requests.ml", 26 + "lib/requests.mli" 27 + ], 28 + "rationale": "While the OCaml TLS library provides secure defaults, enterprise users and security researchers need fine-grained control over TLS parameters for compliance, testing, and compatibility. HTTPie's ssl_version and ciphers parameters allow users to enforce minimum TLS versions (e.g., TLS 1.2+) or test against specific cipher suites. The OCaml library should expose TLS configuration options in the session creation API, allowing users to specify minimum_tls_version, maximum_tls_version, and allowed_ciphers while maintaining secure defaults." 29 + }, 30 + { 31 + "source_repo": "httpie", 32 + "source_language": "python", 33 + "criticality": "medium", 34 + "change_type": "security", 35 + "title": "Client certificate authentication with encrypted key support", 36 + "description": "HTTPie supports client certificates (--cert flag) with separate key files (--cert-key) and handles password-protected private keys (--cert-key-pass). The implementation detects encrypted keys and prompts for passwords. The OCaml library currently doesn't expose client certificate authentication in the public API.", 37 + "affected_files": [ 38 + "lib/requests.ml", 39 + "lib/requests.mli", 40 + "lib/auth.ml" 41 + ], 42 + "rationale": "Client certificate authentication (mutual TLS) is required for many enterprise APIs, government systems, and high-security environments. HTTPie's support for encrypted private keys with password prompts provides a secure workflow. The OCaml library should add client_cert and client_key parameters to session creation, with support for password-protected keys via a callback function. This enables mTLS authentication while maintaining key security through encryption." 43 + }, 44 + { 45 + "source_repo": "httpie", 46 + "source_language": "python", 47 + "criticality": "medium", 48 + "change_type": "enhancement", 49 + "title": "Respect Retry-After header in retry logic", 50 + "description": "HTTPie (via urllib3/requests) respects the Retry-After header in 429 (Too Many Requests) and 503 (Service Unavailable) responses, which tells clients exactly how long to wait before retrying. The OCaml retry module has respect_retry_after field in config but doesn't implement the parsing or enforcement logic.", 51 + "affected_files": [ 52 + "lib/retry.ml", 53 + "lib/requests.ml" 54 + ], 55 + "rationale": "The Retry-After header (RFC 7231) is the standard way for servers to communicate rate limits and maintenance windows. Respecting it prevents unnecessary retries, reduces server load, and improves client behavior during rate limiting or service degradation. HTTPie's parse_retry_after function handles both delay-seconds format and HTTP-date format. The OCaml library already has the config flag but needs implementation: parse Retry-After from response headers, override calculated backoff with the header value when present, and ensure it doesn't exceed backoff_max for safety." 56 + }, 57 + { 58 + "source_repo": "httpie", 59 + "source_language": "python", 60 + "criticality": "medium", 61 + "change_type": "feature", 62 + "title": "HTTP proxy support", 63 + "description": "HTTPie supports HTTP and HTTPS proxies through environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY) and command-line options (--proxy). It handles proxy authentication, CONNECT tunneling for HTTPS, and proxy bypass rules. The OCaml library has no proxy support.", 64 + "affected_files": [ 65 + "lib/requests.ml", 66 + "lib/requests.mli", 67 + "lib/http_client.ml" 68 + ], 69 + "rationale": "Proxy support is essential for corporate environments, CI/CD systems, and users behind firewalls. Many organizations require all HTTP traffic to go through authenticated proxies. HTTPie's implementation shows the key features: read proxy configuration from standard environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY), support proxy authentication via URL or Basic auth, handle CONNECT method for HTTPS tunneling, and respect NO_PROXY for bypass rules. The OCaml library should add proxy configuration to session creation with support for both HTTP and SOCKS proxies." 70 + }, 71 + { 72 + "source_repo": "httpie", 73 + "source_language": "python", 74 + "criticality": "low", 75 + "change_type": "enhancement", 76 + "title": "Multiple header value preservation", 77 + "description": "HTTPie uses HTTPHeadersDict to preserve multiple headers with the same name (e.g., multiple Set-Cookie headers), ensuring all values are accessible. Standard dict-based approaches only keep the last value. The OCaml library stores multiple values per header in its internal representation but get() only returns the first value.", 78 + "affected_files": [ 79 + "lib/headers.ml", 80 + "lib/headers.mli" 81 + ], 82 + "rationale": "While the OCaml library's get_all function already supports retrieving all values for a header, the API could be clearer about this capability. HTTP specifications allow multiple headers with the same name (like Set-Cookie, Warning, Link), and losing values can cause bugs. HTTPie's approach ensures no data loss. The OCaml library should: document that get() returns only the first value, encourage use of get_all() for headers that may appear multiple times, and consider adding convenience functions for common multi-value headers like get_cookies() that returns all Set-Cookie values." 83 + }, 84 + { 85 + "source_repo": "httpie", 86 + "source_language": "python", 87 + "criticality": "low", 88 + "change_type": "enhancement", 89 + "title": "Offline mode for testing and development", 90 + "description": "HTTPie provides an --offline flag that prevents actual network requests, useful for testing request construction, debugging authentication, and validating request formatting without hitting servers. The OCaml library always makes real network requests.", 91 + "affected_files": [ 92 + "lib/requests.ml", 93 + "lib/requests.mli" 94 + ], 95 + "rationale": "An offline/dry-run mode is valuable for development, testing, and debugging. It allows developers to validate request construction (headers, auth, body encoding) without making network calls, which is useful for testing against production APIs safely. HTTPie's --offline mode constructs the full request but skips the send step. The OCaml library could add an optional dry_run parameter that returns a constructed request representation (method, URL, headers, body preview) without executing it, or add a prepare_request function that returns request details for inspection before sending." 96 + }, 97 + { 98 + "source_repo": "httpie", 99 + "source_language": "python", 100 + "criticality": "low", 101 + "change_type": "enhancement", 102 + "title": "Configurable maximum response headers limit", 103 + "description": "HTTPie sets http.client._MAXHEADERS dynamically based on --max-headers flag to handle responses with many headers (common in APIs with extensive metadata). Python's default is 100 headers. The OCaml library doesn't have explicit header count limits but may hit parser limits.", 104 + "affected_files": [ 105 + "lib/http_client.ml" 106 + ], 107 + "rationale": "Some APIs (especially legacy or metadata-heavy systems) return hundreds of headers. HTTPie addresses this with configurable limits, preventing failures on valid but unusual responses. While the OCaml HTTP parser may not have the same hard limits as Python's http.client, adding a configurable maximum provides protection against malicious responses with excessive headers (potential DoS vector) while allowing legitimate use cases. Consider adding max_response_headers to session config with a high default (e.g., 1000) and enforce it in the HTTP parser." 108 + }, 109 + { 110 + "source_repo": "httpie", 111 + "source_language": "python", 112 + "criticality": "high", 113 + "change_type": "bug", 114 + "title": "Separate connect and read timeout enforcement", 115 + "description": "HTTPie and requests library enforce connect and read timeouts separately - connect timeout applies only to establishing the connection, read timeout to receiving each chunk of response. The OCaml library only implements total timeout, which can cause slow servers to timeout even if they're actively sending data.", 116 + "affected_files": [ 117 + "lib/timeout.ml", 118 + "lib/requests.ml", 119 + "lib/http_client.ml" 120 + ], 121 + "rationale": "The OCaml timeout module defines connect, read, and total timeout fields but only enforces total timeout in requests.ml:366-369. This means a slow but responsive server (e.g., streaming a large file) will timeout even though it's actively sending data. HTTPie's approach uses connect timeout only during connection establishment and read timeout per read operation. The OCaml library should: implement connect timeout during Conpool connection acquisition, implement read timeout for each Flow.read operation on the response body using Eio.Time.with_timeout, and keep total timeout as an overall upper bound. This prevents false positives while still catching truly stalled connections." 122 + }, 123 + { 124 + "source_repo": "httpie", 125 + "source_language": "python", 126 + "criticality": "medium", 127 + "change_type": "enhancement", 128 + "title": "Preserve request/response history for debugging", 129 + "description": "HTTPie's request object maintains a .history attribute containing all requests and responses in a redirect chain, making debugging and logging easier. The OCaml library processes redirects but discards intermediate responses, only returning the final response.", 130 + "affected_files": [ 131 + "lib/response.ml", 132 + "lib/response.mli", 133 + "lib/requests.ml" 134 + ], 135 + "rationale": "When debugging redirect issues, authentication flows, or API migrations, seeing the full redirect chain is invaluable. HTTPie's history tracking shows each step: which URLs were visited, what status codes were returned, and which headers were set at each step. This is particularly useful for debugging OAuth flows, SSO, and complex redirect chains. The OCaml library should add an optional history field to Response.t containing a list of (url, status, headers) tuples for each redirect, exposed via Response.history or Response.redirect_chain. This could be gated behind a track_redirects flag to avoid overhead when not needed." 136 + }, 137 + { 138 + "source_repo": "httpie", 139 + "source_language": "python", 140 + "criticality": "low", 141 + "change_type": "enhancement", 142 + "title": "Path-as-is option to preserve exact URL paths", 143 + "description": "HTTPie's --path-as-is flag prevents URL path normalization (collapsing ../, ./, //) which is important for testing servers with unusual path handling or exploiting specific behaviors. The OCaml library uses Uri which normalizes paths.", 144 + "affected_files": [ 145 + "lib/requests.ml", 146 + "lib/http_client.ml" 147 + ], 148 + "rationale": "While path normalization is generally desirable for security, some legitimate use cases require sending non-normalized paths: testing server path traversal protections, working with legacy systems that expect specific path formats, security research and penetration testing, or testing edge cases in path parsing. HTTPie's implementation preserves the original path string by bypassing URL normalization. The OCaml library could add a normalize_path parameter (default: true) that when false, bypasses Uri normalization and sends the path exactly as provided." 149 + }, 150 + { 151 + "source_repo": "httpie", 152 + "source_language": "python", 153 + "criticality": "medium", 154 + "change_type": "feature", 155 + "title": "Plugin system for extensible authentication", 156 + "description": "HTTPie has a plugin architecture that allows third-party authentication methods, custom output formatters, and protocol handlers. Plugins can register new auth types (AWS SigV4, OAuth, custom schemes) without modifying core code. The OCaml library has a fixed set of auth methods.", 157 + "affected_files": [ 158 + "lib/auth.ml", 159 + "lib/auth.mli" 160 + ], 161 + "rationale": "While the OCaml library's Auth.custom function allows custom header manipulation, a more structured approach would improve reusability and composability. HTTPie's plugin system shows the value of extensible auth: users can install aws-sigv4, oauth, jwt, and other auth plugins. The OCaml library already has the Auth.Custom variant which accepts a function, which is actually a good foundation. Consider: adding more examples and documentation of Auth.custom usage for common patterns (AWS SigV4, JWT refresh, custom OAuth), potentially adding a registry pattern for reusable auth schemes, or creating a companion library with common auth plugins that build on Auth.custom. The current design is actually quite flexible - it mainly needs better documentation and examples." 162 + }, 163 + { 164 + "source_repo": "httpie", 165 + "source_language": "python", 166 + "criticality": "low", 167 + "change_type": "enhancement", 168 + "title": "Configurable User-Agent with application metadata", 169 + "description": "HTTPie sets a default User-Agent header (HTTPie/version) and allows customization via --user-agent flag. This helps server operators identify client types in logs. The OCaml library doesn't set a default User-Agent.", 170 + "affected_files": [ 171 + "lib/requests.ml" 172 + ], 173 + "rationale": "User-Agent headers help server operators understand their client base, debug client-specific issues, and track library adoption. HTTPie includes its version in the User-Agent by default. The OCaml library should: set a default User-Agent like 'ocaml-requests/VERSION OCaml/VERSION' in session creation, allow users to override it via default_headers, and document the User-Agent in session configuration. This provides value to server operators while allowing flexibility for users who need custom User-Agents." 174 + }, 175 + { 176 + "source_repo": "httpie", 177 + "source_language": "python", 178 + "criticality": "medium", 179 + "change_type": "enhancement", 180 + "title": "Request body compression support", 181 + "description": "HTTPie supports compressing request bodies with --compress flag, automatically setting Content-Encoding: gzip and compressing the request payload. This reduces bandwidth for large uploads. The OCaml library only supports response decompression, not request compression.", 182 + "affected_files": [ 183 + "lib/body.ml", 184 + "lib/body.mli", 185 + "lib/requests.ml" 186 + ], 187 + "rationale": "While response decompression is common, request compression is valuable for uploading large payloads (logs, backups, data exports) over slow connections or to bandwidth-limited servers. HTTPie's --compress flag with threshold-based activation (--compress > 1 for always, --compress for heuristic) shows good UX. The OCaml library should add Body.compress function that takes a Body.t and returns a compressed version with appropriate Content-Encoding, add optional compress parameter to request functions, and consider automatic compression for large bodies (e.g., > 1KB) when compress is enabled. The library already has decompress library integrated for response decompression, so adding compression is straightforward." 188 + }, 189 + { 190 + "source_repo": "httpie", 191 + "source_language": "python", 192 + "criticality": "high", 193 + "change_type": "security", 194 + "title": "Explicit expired cookie handling in sessions", 195 + "description": "HTTPie explicitly tracks and removes expired cookies from sessions using get_expired_cookies function, preventing accumulation of stale cookies and potential security issues. The OCaml library stores cookies but may not actively clean up expired ones during session save.", 196 + "affected_files": [ 197 + "lib/requests.ml" 198 + ], 199 + "rationale": "The OCaml library uses Cookeio_jar which likely handles expiration during cookie retrieval (Cookeio_jar.get_cookies in requests.ml:328), but HTTPie's explicit cleanup during session save (client.py:139-140) ensures expired cookies are removed from persistent storage. This prevents session files from growing indefinitely and ensures expired sensitive cookies are purged. The implementation should: verify that Cookeio_jar.save already filters expired cookies, add explicit expired cookie removal before save if not already done, and log warnings when removing expired cookies to aid debugging. This is particularly important for persist_cookies mode where cookies are written to disk." 200 + }, 201 + { 202 + "source_repo": "httpie", 203 + "source_language": "python", 204 + "criticality": "low", 205 + "change_type": "enhancement", 206 + "title": "Session migration and version tracking", 207 + "description": "HTTPie includes migration paths for session file format changes (v3_1_0_session_cookie_format, v3_2_0_session_header_format) and stores version metadata in session files. This allows backward compatibility and graceful upgrades. The OCaml library doesn't version session data.", 208 + "affected_files": [ 209 + "lib/requests.ml" 210 + ], 211 + "rationale": "As the library evolves, session file formats may need to change (adding fields, changing serialization, fixing bugs). HTTPie's approach of storing version metadata and providing migration functions prevents breaking existing users' sessions. The OCaml library should: add __meta__ section to saved session data with library version, implement version detection when loading sessions, add migration functions for format changes, and document the session file format for stability. This is especially important as the library approaches 1.0 and users rely on persistent sessions." 212 + } 213 + ] 214 + }
+257
third_party/bash-shell/resty.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/bash-shell/resty", 5 + "source_language": "bash", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add dry-run mode to preview requests without execution", 9 + "description": "Implement a --dry-run flag that displays the exact request that would be sent (method, URL, headers, body) without actually executing it. This is invaluable for debugging, learning, and validating request construction before execution.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "bin/ocurl.ml" 13 + ], 14 + "rationale": "Resty implements a --dry-run mode (lines 169, 219-222) that outputs the curl command without executing it. This feature is extremely helpful for debugging and understanding what the library is doing under the hood. The OCaml library currently lacks this capability, forcing users to rely on verbose logging which doesn't show the final constructed request in a clear, actionable format. This would be particularly useful in the ocurl CLI tool." 15 + }, 16 + { 17 + "source_repo": "third_party/bash-shell/resty", 18 + "source_language": "bash", 19 + "criticality": "low", 20 + "change_type": "enhancement", 21 + "title": "Add interactive request body editing capability", 22 + "description": "Implement an interactive mode (similar to resty's -V flag) that allows users to edit request bodies in their preferred editor before sending. This enables powerful workflows like GET /resource | edit | PUT /resource for updating resources.", 23 + "affected_files": [ 24 + "bin/ocurl.ml", 25 + "lib/body.ml" 26 + ], 27 + "rationale": "Resty's -V flag (lines 164, 200-206) opens the request body in an editor for interactive editing before sending. This creates a powerful workflow for REST API interaction, especially useful for complex JSON payloads. The OCaml library could implement this as a CLI feature in ocurl, enhancing developer productivity when crafting complex requests." 28 + }, 29 + { 30 + "source_repo": "third_party/bash-shell/resty", 31 + "source_language": "bash", 32 + "criticality": "medium", 33 + "change_type": "enhancement", 34 + "title": "Add per-host and per-method default configuration", 35 + "description": "Implement hierarchical configuration that allows setting different default options per host (e.g., example.com:8080) and per HTTP method (e.g., different headers for GET vs POST). This provides fine-grained control without repetitive command-line arguments.", 36 + "affected_files": [ 37 + "lib/requests.ml", 38 + "bin/ocurl.ml" 39 + ], 40 + "rationale": "Resty implements a sophisticated configuration hierarchy (lines 76-101) with global defaults (~/.resty/resty), per-host configs (~/.resty/example.com:8080), and per-method overrides within each. This allows users to set authentication per API host, different headers per method, etc. The OCaml library currently only supports session-level defaults. Adding file-based per-host/per-method configs would significantly improve ergonomics for users working with multiple APIs." 41 + }, 42 + { 43 + "source_repo": "third_party/bash-shell/resty", 44 + "source_language": "bash", 45 + "criticality": "low", 46 + "change_type": "enhancement", 47 + "title": "Add automatic HTML-to-text conversion for HTML responses", 48 + "description": "Implement automatic detection of HTML responses and provide optional conversion to readable text using tools like lynx, html2text, or a native OCaml HTML parser. This improves the CLI experience when dealing with HTML endpoints.", 49 + "affected_files": [ 50 + "lib/response.ml", 51 + "bin/ocurl.ml" 52 + ], 53 + "rationale": "Resty automatically detects HTML content-types (line 237) and converts them to readable text using lynx/html2text (lines 19-20, 237-259). This greatly improves the command-line experience when accidentally hitting HTML endpoints. The OCaml library could implement similar functionality, either via external tools or a lightweight OCaml HTML-to-text library." 54 + }, 55 + { 56 + "source_repo": "third_party/bash-shell/resty", 57 + "source_language": "bash", 58 + "criticality": "medium", 59 + "change_type": "enhancement", 60 + "title": "Implement smart path preservation for stateful sessions", 61 + "description": "Add the ability to preserve the last requested path in stateful sessions, allowing relative path requests. For example, after GET /api/users/123, a subsequent GET /comments would request /api/users/123/comments. Include a flag to disable this behavior when needed.", 62 + "affected_files": [ 63 + "lib/requests.ml" 64 + ], 65 + "rationale": "Resty preserves the last path in $_RESTY_PATH (lines 182-187) allowing users to navigate REST resources like a filesystem. This reduces typing for related requests. The OCaml library's stateful session API could implement similar path tracking with a base_path field that gets updated on each request, with an option to disable via REQUESTS_NO_PRESERVE_PATH environment variable." 66 + }, 67 + { 68 + "source_repo": "third_party/bash-shell/resty", 69 + "source_language": "bash", 70 + "criticality": "high", 71 + "change_type": "bug", 72 + "title": "Fix potential credential exposure in verbose logging", 73 + "description": "Review and ensure that verbose logging modes never output sensitive headers (Authorization, Cookie, etc.) or credentials. Implement redaction for sensitive data in all logging output.", 74 + "affected_files": [ 75 + "lib/requests.ml", 76 + "lib/http_client.ml", 77 + "lib/auth.ml" 78 + ], 79 + "rationale": "Resty has a security concern where verbose mode (line 162, 233) can leak Authorization headers and credentials in stderr. The OCaml library currently logs request headers at Info level (lines 346-350 in requests.ml) which could expose Authorization headers, bearer tokens, and cookies. This needs careful review to ensure sensitive data is redacted in all log levels. Consider implementing a sanitize_headers function that redacts sensitive header values before logging." 80 + }, 81 + { 82 + "source_repo": "third_party/bash-shell/resty", 83 + "source_language": "bash", 84 + "criticality": "low", 85 + "change_type": "enhancement", 86 + "title": "Add convenience flags for common content-types (--json, --xml)", 87 + "description": "Implement shortcut flags like --json and --xml that automatically set both Accept and Content-Type headers to the appropriate MIME types, reducing boilerplate for common use cases.", 88 + "affected_files": [ 89 + "bin/ocurl.ml" 90 + ], 91 + "rationale": "Resty provides --json and --xml flags (lines 170-171) that automatically set Accept and Content-Type headers. The OCaml library's ocurl tool currently requires manual -H flags for these common cases. Adding these convenience flags would match the ergonomics of modern HTTP clients like httpie and improve user experience." 92 + }, 93 + { 94 + "source_repo": "third_party/bash-shell/resty", 95 + "source_language": "bash", 96 + "criticality": "medium", 97 + "change_type": "enhancement", 98 + "title": "Improve error output routing to stderr vs stdout", 99 + "description": "Ensure that all error messages, non-2xx HTTP responses, and diagnostic information go to stderr, while only successful response bodies go to stdout. This enables proper composition with Unix pipes.", 100 + "affected_files": [ 101 + "bin/ocurl.ml", 102 + "lib/response.ml" 103 + ], 104 + "rationale": "Resty has excellent stdout/stderr separation (lines 261-267): 2xx responses to stdout with exit 0, non-2xx to stderr with appropriate exit codes. This enables proper pipeline composition. The OCaml library should review its ocurl tool to ensure similar behavior - success bodies to stdout, errors/diagnostics to stderr, and meaningful exit codes (e.g., 1 for 1xx, 3 for 3xx, 4 for 4xx, 5 for 5xx)." 105 + }, 106 + { 107 + "source_repo": "third_party/bash-shell/resty", 108 + "source_language": "bash", 109 + "criticality": "medium", 110 + "change_type": "enhancement", 111 + "title": "Add configurable URL encoding with disable option", 112 + "description": "Implement automatic URL encoding of special characters in paths by default, with a flag (-Q or --no-url-encode) to disable it when users need to send pre-encoded URLs or special characters literally.", 113 + "affected_files": [ 114 + "lib/requests.ml", 115 + "bin/ocurl.ml" 116 + ], 117 + "rationale": "Resty automatically encodes special characters in URLs (line 177) to prevent URL injection attacks and handle special characters properly, with a -Q flag to disable when needed. The OCaml library relies on the Uri library which may or may not encode automatically. Adding explicit URL encoding (particularly for path segments) with an opt-out flag would improve security and usability." 118 + }, 119 + { 120 + "source_repo": "third_party/bash-shell/resty", 121 + "source_language": "bash", 122 + "criticality": "low", 123 + "change_type": "enhancement", 124 + "title": "Add query parameter builder syntax to CLI", 125 + "description": "Implement flexible query parameter handling in the CLI that supports both inline (?foo=bar) and flag-based (-q 'foo=bar') syntax. This improves ergonomics for requests with many parameters.", 126 + "affected_files": [ 127 + "bin/ocurl.ml" 128 + ], 129 + "rationale": "Resty supports multiple query parameter syntaxes: inline with -Q (line 167), flag-based with -q (lines 168, 159), and curl's -d with -G. The OCaml library's ocurl tool could benefit from similar flexibility. While the library supports params programmatically, the CLI would be more ergonomic with a dedicated -q flag for adding query parameters." 130 + }, 131 + { 132 + "source_repo": "third_party/bash-shell/resty", 133 + "source_language": "bash", 134 + "criticality": "low", 135 + "change_type": "enhancement", 136 + "title": "Add raw output mode flag to disable automatic processing", 137 + "description": "Implement a --raw or -Z flag that completely disables automatic content processing (HTML conversion, JSON pretty-printing, decompression, etc.) and returns the exact bytes received from the server.", 138 + "affected_files": [ 139 + "bin/ocurl.ml", 140 + "lib/response.ml" 141 + ], 142 + "rationale": "Resty's -Z flag (lines 165, 237) disables all automatic processing and returns raw output. This is essential for binary downloads, debugging compression issues, or when automatic transformations are undesired. The OCaml library has auto_decompress but lacks a comprehensive raw mode. Adding a --raw flag that disables all automatic processing would be valuable." 143 + }, 144 + { 145 + "source_repo": "third_party/bash-shell/resty", 146 + "source_language": "bash", 147 + "criticality": "medium", 148 + "change_type": "enhancement", 149 + "title": "Add stateful base URL with wildcard path placeholder", 150 + "description": "Implement a session mode where users set a base URL with a wildcard placeholder (e.g., http://api.example.com/v1/*) that gets replaced with the requested path. This reduces repetition in interactive usage.", 151 + "affected_files": [ 152 + "lib/requests.ml", 153 + "bin/ocurl.ml" 154 + ], 155 + "rationale": "Resty's core design uses a base URL with * placeholder (lines 63, 190) that gets replaced with the requested path. This enables terse syntax: 'resty api.example.com/v1', then 'GET /users'. The OCaml library requires full URLs for each request. Adding an optional base URL mechanism would improve ergonomics for interactive API exploration and could be particularly useful in a REPL-style interface." 156 + }, 157 + { 158 + "source_repo": "third_party/bash-shell/resty", 159 + "source_language": "bash", 160 + "criticality": "low", 161 + "change_type": "feature", 162 + "title": "Add HTTP method validation with helpful error messages", 163 + "description": "Implement explicit validation of HTTP methods with clear error messages when invalid methods are provided, helping users catch typos early.", 164 + "affected_files": [ 165 + "lib/method.ml", 166 + "bin/ocurl.ml" 167 + ], 168 + "rationale": "Resty validates HTTP methods (line 107) and provides clear error messages ('First arg must be an HTTP verb'). The OCaml library has type-safe polymorphic variants for methods, which prevents invalid methods at the API level, but the CLI tool should validate string inputs and provide helpful messages for common mistakes." 169 + }, 170 + { 171 + "source_repo": "third_party/bash-shell/resty", 172 + "source_language": "bash", 173 + "criticality": "medium", 174 + "change_type": "enhancement", 175 + "title": "Improve cookie file organization with per-domain separation", 176 + "description": "Enhance cookie storage to use separate files per domain (e.g., cookies/example.com, cookies/api.github.com) instead of a single monolithic cookie file. This improves security by preventing cookie leakage and makes cookie management easier.", 177 + "affected_files": [ 178 + "lib/requests.ml" 179 + ], 180 + "rationale": "Resty stores cookies in separate per-domain files (lines 126, 132-134, 217) at $XDG_DATA_HOME/resty/c/$domain. This provides better isolation and security. The OCaml library currently uses a single cookies.txt file (line 137 in requests.ml). While the Cookeio library likely handles domain scoping internally, using separate files per domain would improve cookie management, debugging, and allow selective cookie clearing." 181 + }, 182 + { 183 + "source_repo": "third_party/bash-shell/resty", 184 + "source_language": "bash", 185 + "criticality": "low", 186 + "change_type": "enhancement", 187 + "title": "Add help text generation for all CLI flags and options", 188 + "description": "Implement comprehensive help text for all commands and options, including examples of common usage patterns. Use cmdliner's documentation features to generate man pages.", 189 + "affected_files": [ 190 + "bin/ocurl.ml" 191 + ], 192 + "rationale": "Resty has built-in help via -h/--help (lines 37-44, 112-119, 315-334) with clear descriptions and examples. The OCaml library uses cmdliner which supports this well, but should ensure all commands have comprehensive help text with examples. This is already partially implemented but could be expanded with more usage examples." 193 + }, 194 + { 195 + "source_repo": "third_party/bash-shell/resty", 196 + "source_language": "bash", 197 + "criticality": "high", 198 + "change_type": "security", 199 + "title": "Add option to prevent credential logging to shell history", 200 + "description": "Implement a mechanism to prevent sensitive requests (those with authentication) from being logged to shell history files. This could be a flag or automatic detection of sensitive headers.", 201 + "affected_files": [ 202 + "bin/ocurl.ml" 203 + ], 204 + "rationale": "Resty's -W flag (lines 166, 338) prevents writing to shell history when credentials are involved. This prevents passwords from leaking into .bash_history. While OCaml CLI tools don't directly control shell history, the documentation should warn users about this risk and suggest using environment variables or config files for credentials instead of command-line arguments." 205 + }, 206 + { 207 + "source_repo": "third_party/bash-shell/resty", 208 + "source_language": "bash", 209 + "criticality": "medium", 210 + "change_type": "enhancement", 211 + "title": "Standardize exit codes to reflect HTTP status code classes", 212 + "description": "Implement meaningful exit codes in the CLI tool: 0 for success (2xx), 1 for client errors (4xx), 2 for server errors (5xx), 3 for redirects (3xx), and distinguish connection/timeout errors with specific codes.", 213 + "affected_files": [ 214 + "bin/ocurl.ml" 215 + ], 216 + "rationale": "Resty maps HTTP status codes to exit codes (lines 229, 261-267): exit 0 for 2xx, exit 1 for 1xx, exit 3 for 3xx, exit 4 for 4xx, exit 5 for 5xx. This enables powerful shell scripting (e.g., 'if ocurl api.example.com/health; then ...'). The OCaml CLI should implement similar exit code conventions for scriptability." 217 + }, 218 + { 219 + "source_repo": "third_party/bash-shell/resty", 220 + "source_language": "bash", 221 + "criticality": "low", 222 + "change_type": "enhancement", 223 + "title": "Add support for reading request body from stdin", 224 + "description": "Ensure the CLI tool can read request body data from stdin (not just files or command-line strings), enabling powerful Unix pipeline compositions like 'cat data.json | ocurl -X POST url'.", 225 + "affected_files": [ 226 + "bin/ocurl.ml" 227 + ], 228 + "rationale": "Resty supports reading request body from stdin (lines 193-197) when stdin is not a TTY, enabling pipeline compositions. The OCaml library's ocurl should explicitly support this pattern, making it clear in the documentation and ensuring proper handling of stdin vs file vs inline data." 229 + }, 230 + { 231 + "source_repo": "third_party/bash-shell/resty", 232 + "source_language": "bash", 233 + "criticality": "low", 234 + "change_type": "refactor", 235 + "title": "Add visual separators in verbose request/response logging", 236 + "description": "Improve logging output with clear visual separators between requests and responses, making it easier to follow the flow in verbose mode. Use symbols like === or --- to demarcate sections.", 237 + "affected_files": [ 238 + "lib/requests.ml", 239 + "lib/http_client.ml" 240 + ], 241 + "rationale": "The OCaml library already has good structured logging (lines 343-350, 373-378 in requests.ml) with request/response sections. However, adding more prominent visual separators (like resty does implicitly via curl's verbose output) would improve readability. Consider adding === Request === and === Response === markers." 242 + }, 243 + { 244 + "source_repo": "third_party/bash-shell/resty", 245 + "source_language": "bash", 246 + "criticality": "medium", 247 + "change_type": "enhancement", 248 + "title": "Implement Retry-After header parsing and respect", 249 + "description": "The retry module has respect_retry_after flag but the parsing function (parse_retry_after) is not currently being used in the request flow. Implement actual Retry-After header detection and delay adjustment in the retry logic.", 250 + "affected_files": [ 251 + "lib/retry.ml", 252 + "lib/requests.ml" 253 + ], 254 + "rationale": "The retry.ml module has parse_retry_after function (lines 73-93) and respect_retry_after config flag (line 15, 25) but this doesn't appear to be actively used in the request retry flow in requests.ml (lines 526-558). Resty implicitly relies on curl for this. The OCaml library should extract Retry-After from 429/503 responses and use it to override the exponential backoff delay, providing better behavior with rate-limited APIs." 255 + } 256 + ] 257 + }
+235
third_party/c++/cpp-httplib.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/c++/cpp-httplib", 5 + "source_language": "C++", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add granular SSL/TLS error reporting with OpenSSL error codes", 9 + "description": "The current SSLError exception captures only a generic string message. cpp-httplib provides multiple SSL error fields: ssl_error (SSL layer), ssl_openssl_error (OpenSSL error codes), and specific error variants for SSLLoadingCerts, SSLServerVerification, and SSLServerHostnameVerification. This granularity is critical for debugging certificate issues and providing actionable error messages to users.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/error.mli" 13 + ], 14 + "rationale": "When SSL/TLS connections fail, users need to know WHY they failed. Currently, the OCaml library collapses all SSL errors into a single SSLError with a string. cpp-httplib demonstrates that SSL errors should be categorized into: (1) certificate loading failures, (2) certificate chain verification failures, (3) hostname verification failures, (4) connection-level SSL errors. Each category requires different remediation. For example, X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT vs X509_V_ERR_HOSTNAME_MISMATCH require completely different fixes. The Error.t variant type should add: `SSLLoadingCerts, `SSLServerVerification, `SSLHostnameVerification, and potentially include numeric error codes from the underlying TLS library for advanced debugging." 15 + }, 16 + { 17 + "source_repo": "third_party/c++/cpp-httplib", 18 + "source_language": "C++", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Add separate write timeout distinct from read timeout", 22 + "description": "The timeout module currently has connect, read, and total timeouts, but no write timeout. cpp-httplib has a separate CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_SECOND (default: 5 seconds) distinct from read timeout (default: 300 seconds). This is important for detecting stalled uploads vs stalled downloads, especially when uploading large bodies.", 23 + "affected_files": [ 24 + "lib/timeout.ml", 25 + "lib/timeout.mli", 26 + "lib/http_client.ml", 27 + "lib/requests.ml" 28 + ], 29 + "rationale": "Read and write operations have different timeout characteristics. Uploads can stall due to client bandwidth limits or server receive buffer issues, while downloads stall for different reasons. cpp-httplib sets write timeout to 5s by default vs 300s for reads, recognizing that write stalls indicate more severe problems. The OCaml library currently uses only read timeout for both operations. Adding a write timeout field to Timeout.t and applying it during Flow.copy_string operations would provide better control over upload behavior and faster failure detection for stalled uploads." 30 + }, 31 + { 32 + "source_repo": "third_party/c++/cpp-httplib", 33 + "source_language": "C++", 34 + "criticality": "medium", 35 + "change_type": "feature", 36 + "title": "Add progress callback support for uploads and downloads", 37 + "description": "cpp-httplib provides ContentReceiver and ContentProvider callbacks with progress tracking: std::function<bool(uint64_t current, uint64_t total)>. These callbacks enable progress bars, bandwidth throttling, and cancellation (by returning false). The OCaml library lacks progress monitoring for long transfers.", 38 + "affected_files": [ 39 + "lib/body.ml", 40 + "lib/body.mli", 41 + "lib/response.ml", 42 + "lib/response.mli", 43 + "lib/requests.ml", 44 + "lib/requests.mli" 45 + ], 46 + "rationale": "Progress callbacks are essential for user-facing applications. cpp-httplib demonstrates clean API: optional callbacks that receive (current_bytes, total_bytes) and can return false to cancel. The OCaml library already has Body.of_stream for lazy uploads but lacks progress hooks. Adding optional progress callbacks to Body.t and Response.body/text functions would enable: (1) progress bars in CLI tools like bin/ocurl.ml, (2) bandwidth monitoring, (3) user cancellation of long transfers, (4) timeout adjustments based on transfer rate. Implementation could use Eio.Flow with periodic callback invocation during chunked reads/writes." 47 + }, 48 + { 49 + "source_repo": "third_party/c++/cpp-httplib", 50 + "source_language": "C++", 51 + "criticality": "low", 52 + "change_type": "enhancement", 53 + "title": "Add Brotli compression support in addition to gzip/deflate", 54 + "description": "cpp-httplib supports brotli compression in addition to gzip, deflate, and zstd (Accept-Encoding: 'br, gzip, deflate, zstd'). The OCaml library only supports gzip and deflate. Brotli provides 20-30% better compression than gzip and is widely supported by browsers and CDNs.", 55 + "affected_files": [ 56 + "lib/http_client.ml", 57 + "lib/requests.ml" 58 + ], 59 + "rationale": "Brotli compression is now standard on the web and provides significantly better compression ratios than gzip, especially for text content. cpp-httplib includes it in default Accept-Encoding. The OCaml library has decompress library support but only uses gzip/deflate. Adding Brotli support via the decompress library (which includes Brotli decompression) would reduce bandwidth usage. This is especially valuable for mobile/metered connections. The change is straightforward: extend decompress_body to handle 'br' encoding and add 'br' to the Accept-Encoding header in requests.ml:253." 60 + }, 61 + { 62 + "source_repo": "third_party/c++/cpp-httplib", 63 + "source_language": "C++", 64 + "criticality": "medium", 65 + "change_type": "feature", 66 + "title": "Implement proxy support with authentication", 67 + "description": "cpp-httplib has comprehensive proxy support with set_proxy(host, port) and set_proxy_basic_auth/set_proxy_bearer_token_auth/set_proxy_digest_auth. The OCaml library has ProxyError in the error types but no actual proxy implementation.", 68 + "affected_files": [ 69 + "lib/requests.ml", 70 + "lib/requests.mli", 71 + "lib/http_client.ml" 72 + ], 73 + "rationale": "Proxy support is essential for enterprise environments and many CI/CD systems. The OCaml library declares a ProxyError variant but has no proxy implementation. cpp-httplib shows that proxy support requires: (1) separate connection to proxy host:port, (2) HTTP CONNECT method for HTTPS tunneling, (3) Proxy-Authorization headers for authenticated proxies, (4) handling proxy authentication challenges. Without proxy support, the library cannot be used in many corporate networks. Implementation would add optional proxy_host/proxy_port/proxy_auth fields to the Requests.t type and modify connection establishment to connect via proxy when configured." 74 + }, 75 + { 76 + "source_repo": "third_party/c++/cpp-httplib", 77 + "source_language": "C++", 78 + "criticality": "low", 79 + "change_type": "enhancement", 80 + "title": "Add configurable limits for request/response sizes and header counts", 81 + "description": "cpp-httplib defines comprehensive limits: CPPHTTPLIB_REQUEST_URI_MAX_LENGTH (8192), CPPHTTPLIB_HEADER_MAX_LENGTH (8192), CPPHTTPLIB_HEADER_MAX_COUNT (100), CPPHTTPLIB_PAYLOAD_MAX_LENGTH, CPPHTTPLIB_RECV_BUFSIZ (16384), CPPHTTPLIB_SEND_BUFSIZ (16384). The OCaml library has hardcoded buffer sizes and no enforced limits.", 82 + "affected_files": [ 83 + "lib/http_client.ml", 84 + "lib/requests.ml", 85 + "lib/response.ml" 86 + ], 87 + "rationale": "Resource limits protect against malicious or malformed responses that could cause memory exhaustion. cpp-httplib enforces limits on header size (8KB), header count (100), and URI length (8KB) to prevent attacks. The OCaml library uses max_int for Buf_read.of_flow, which could allow unbounded memory usage. Adding configurable limits (with safe defaults) to Requests.create would enable: (1) protection against decompression bombs, (2) header amplification attack prevention, (3) memory usage control in resource-constrained environments. Implementation would add max_response_size, max_header_count, max_header_length fields and enforce them during parsing in http_client.ml." 88 + }, 89 + { 90 + "source_repo": "third_party/c++/cpp-httplib", 91 + "source_language": "C++", 92 + "criticality": "high", 93 + "change_type": "security", 94 + "title": "Add SSL/TLS hostname verification as separate control from certificate verification", 95 + "description": "cpp-httplib separates enable_server_certificate_verification and enable_server_hostname_verification into distinct controls. The OCaml library only has verify_tls which presumably does both. Hostname verification should be independently controllable for certain valid use cases (e.g., testing with valid certs on different hostnames).", 96 + "affected_files": [ 97 + "lib/requests.ml", 98 + "lib/requests.mli" 99 + ], 100 + "rationale": "Certificate verification and hostname verification are distinct security checks that should be independently controllable. cpp-httplib recognizes this by providing separate enable_server_certificate_verification and enable_server_hostname_verification methods. Certificate verification checks the chain of trust; hostname verification checks that the certificate matches the requested hostname. Valid use cases for separating them include: (1) testing against production certificates on staging hostnames, (2) using certificates with wildcard or SAN entries where hostname matching needs customization, (3) debugging certificate issues. The OCaml library should expose verify_hostname as a separate option from verify_tls, both defaulting to true for security." 101 + }, 102 + { 103 + "source_repo": "third_party/c++/cpp-httplib", 104 + "source_language": "C++", 105 + "criticality": "medium", 106 + "change_type": "enhancement", 107 + "title": "Add error logging callback for connection-level errors", 108 + "description": "cpp-httplib provides separate Logger and ErrorLogger callbacks. Logger logs successful requests (Request, Response), while ErrorLogger logs errors with context (Error, Request*). The OCaml library logs to Logs.Src but provides no callback mechanism for application-level error handling.", 109 + "affected_files": [ 110 + "lib/requests.ml", 111 + "lib/requests.mli", 112 + "lib/error.ml" 113 + ], 114 + "rationale": "Error logging callbacks enable applications to implement custom error handling, metrics collection, and alerting without parsing logs. cpp-httplib demonstrates that error context should include both the error type and the request that caused it (when available). The OCaml library uses Logs.Src which is good for development but insufficient for production monitoring. Adding optional error_callback: (Error.t -> request_url option -> unit) to Requests.create would enable: (1) error metrics collection (count by error type), (2) custom alerting, (3) error reporting to external services, (4) application-specific retry policies. This complements rather than replaces the existing Logs integration." 115 + }, 116 + { 117 + "source_repo": "third_party/c++/cpp-httplib", 118 + "source_language": "C++", 119 + "criticality": "low", 120 + "change_type": "feature", 121 + "title": "Add support for multipart/form-data parsing in responses", 122 + "description": "cpp-httplib has extensive multipart/form-data support with structured access to fields and files via MultipartFormData with get_field/get_file/has_field helpers. The OCaml library can send multipart requests but has no structured parsing for multipart responses.", 123 + "affected_files": [ 124 + "lib/response.ml", 125 + "lib/response.mli" 126 + ], 127 + "rationale": "Some APIs return multipart/form-data responses (e.g., GraphQL batched responses, mixed content APIs). cpp-httplib demonstrates that multipart parsing should provide structured access with helper methods for fields and files, handling boundary parsing and headers automatically. While less common than JSON responses, multipart parsing would complete the library's protocol support. The OCaml ecosystem has the multipart_form library which could be integrated to provide Response.multipart() -> (string * string) list result for field access." 128 + }, 129 + { 130 + "source_repo": "third_party/c++/cpp-httplib", 131 + "source_language": "C++", 132 + "criticality": "medium", 133 + "change_type": "enhancement", 134 + "title": "Add streaming response API that provides headers before body download", 135 + "description": "cpp-httplib provides a stream::Get API that returns headers immediately while allowing incremental body consumption via .next() iterator. The OCaml library buffers the entire response body in http_client.ml before returning, preventing early header access and true streaming.", 136 + "affected_files": [ 137 + "lib/http_client.ml", 138 + "lib/response.ml", 139 + "lib/requests.ml" 140 + ], 141 + "rationale": "True streaming requires header access before body download completion. cpp-httplib's README-stream.md explains three API tiers: (1) buffered Client::Get, (2) low-level open_stream, (3) iterator-style stream::Get that yields chunks. The OCaml library currently buffers the entire body in http_client.ml:262-275 before creating the Response object. For large downloads, this prevents: (1) checking Content-Length before downloading, (2) early abort based on Content-Type, (3) memory-efficient processing of large files. Refactoring http_client.ml to return headers and a Flow separately, then wrapping the Flow in Response.t, would enable true streaming while maintaining the existing API for backward compatibility." 142 + }, 143 + { 144 + "source_repo": "third_party/c++/cpp-httplib", 145 + "source_language": "C++", 146 + "criticality": "low", 147 + "change_type": "enhancement", 148 + "title": "Add connection reuse metrics and statistics", 149 + "description": "cpp-httplib tracks socket_requests_in_flight and connection lifetime for keep-alive management. While the OCaml library uses the Conpool library which has statistics, the Requests API doesn't expose these metrics to users.", 150 + "affected_files": [ 151 + "lib/requests.ml", 152 + "lib/requests.mli" 153 + ], 154 + "rationale": "Connection pool metrics are valuable for performance tuning and debugging. The OCaml library tracks requests_made, total_time, and retries_count in Requests.t but doesn't expose Conpool statistics. cpp-httplib tracks connection reuse which helps users understand if keep-alive is working. Adding a statistics() function to Requests that exposes Conpool.all_stats would provide: (1) connection reuse ratio, (2) pool efficiency, (3) connection lifetime data, (4) help debug connection pool exhaustion. This is especially useful for the test suite (test_localhost.ml already uses Conpool.all_stats directly, showing the demand)." 155 + }, 156 + { 157 + "source_repo": "third_party/c++/cpp-httplib", 158 + "source_language": "C++", 159 + "criticality": "high", 160 + "change_type": "bug", 161 + "title": "Fix potential response body double-read issue", 162 + "description": "The Response.text function in response.ml:69-73 calls Eio.Buf_read.of_flow and take_all which consumes the body flow. However, Response.t stores the flow directly (body field), not a cached string. Calling text() multiple times or calling text() then json() will fail. cpp-httplib stores the response body as a string once retrieved, allowing multiple accesses.", 163 + "affected_files": [ 164 + "lib/response.ml", 165 + "lib/response.mli" 166 + ], 167 + "rationale": "The current implementation has a subtle bug: Response.body returns the flow (line 67), Response.text consumes the flow (line 73), and Response.json calls text (line 76). If a user calls response |> Response.text |> ignore then Response.json response, the second call will fail because the flow is exhausted. cpp-httplib buffers the body string, allowing multiple accesses. The OCaml implementation should either: (1) cache the body string after first read in a mutable field, (2) document that body/text/json can only be called once, or (3) store the body as a string in Response.t instead of a Flow. Option 1 is safest and matches user expectations from libraries like Python requests." 168 + }, 169 + { 170 + "source_repo": "third_party/c++/cpp-httplib", 171 + "source_language": "C++", 172 + "criticality": "medium", 173 + "change_type": "feature", 174 + "title": "Add request cancellation mechanism", 175 + "description": "cpp-httplib progress callbacks can return false to cancel an in-flight request. The OCaml library uses Eio switches for cancellation but provides no application-level cancellation mechanism during a long download/upload.", 176 + "affected_files": [ 177 + "lib/requests.ml", 178 + "lib/http_client.ml", 179 + "lib/body.ml", 180 + "lib/response.ml" 181 + ], 182 + "rationale": "Users need to cancel long-running requests based on application logic (e.g., user cancellation, timeout based on progress rate, exceeded quota). cpp-httplib's progress callbacks return bool to support cancellation. While Eio provides switch-based cancellation, this requires the caller to manage switches separately. A cleaner API would add optional should_continue callbacks to request functions that are invoked during body upload/download. These callbacks could check application state and return false to abort. This complements the existing timeout mechanism by allowing dynamic cancellation based on progress, not just elapsed time." 183 + }, 184 + { 185 + "source_repo": "third_party/c++/cpp-httplib", 186 + "source_language": "C++", 187 + "criticality": "low", 188 + "change_type": "enhancement", 189 + "title": "Add support for HTTP/1.0 responses in addition to HTTP/1.1", 190 + "description": "cpp-httplib parses both 'HTTP/1.1' and 'HTTP/1.0' status lines (httplib.h status line parsing accepts both). The OCaml library's http_client.ml:174-178 also accepts both, so this is already implemented. However, the library could explicitly test HTTP/1.0 compatibility.", 191 + "affected_files": [ 192 + "test/test_localhost.ml" 193 + ], 194 + "rationale": "While http_client.ml:174-178 already accepts HTTP/1.0 responses, the test suite should include HTTP/1.0 compatibility tests. Some legacy systems and proxies still use HTTP/1.0. cpp-httplib explicitly handles both versions in parsing. Adding test cases for HTTP/1.0 responses (especially differences like lack of chunked encoding support, different keep-alive semantics) would ensure compatibility. This is a testing gap rather than a code gap, but important for production robustness." 195 + }, 196 + { 197 + "source_repo": "third_party/c++/cpp-httplib", 198 + "source_language": "C++", 199 + "criticality": "medium", 200 + "change_type": "security", 201 + "title": "Add validation for redirect Location header to prevent open redirect vulnerabilities", 202 + "description": "cpp-httplib handles redirect URL parsing carefully and protects against redirect count exhaustion. The OCaml library resolves relative redirects (requests.ml:398-408) but doesn't validate the redirect target, potentially allowing redirects to file://, javascript:, or other dangerous schemes.", 203 + "affected_files": [ 204 + "lib/requests.ml" 205 + ], 206 + "rationale": "Open redirect vulnerabilities allow attackers to redirect users to malicious sites. While the OCaml library handles redirect count limits (preventing infinite loops), it doesn't validate the redirect Location header scheme. cpp-httplib's careful handling suggests validation is important. The OCaml library should validate that redirect URLs use http:// or https:// schemes only (requests.ml:399), rejecting file://, javascript://, data:, or other potentially dangerous schemes. This prevents the library from being used as an open redirect vector. Add scheme validation before following redirects: match Uri.scheme location_uri with | Some (\"http\" | \"https\") -> ... | _ -> return error." 207 + }, 208 + { 209 + "source_repo": "third_party/c++/cpp-httplib", 210 + "source_language": "C++", 211 + "criticality": "low", 212 + "change_type": "refactor", 213 + "title": "Refactor retry logic to respect Retry-After header from server responses", 214 + "description": "The retry.ml module has parse_retry_after (line 73-93) and respect_retry_after config flag (line 15, 25), but the retry logic in requests.ml:526-558 doesn't actually use the Retry-After header from responses. cpp-httplib's SSE example shows proper Retry-After handling.", 215 + "affected_files": [ 216 + "lib/retry.ml", 217 + "lib/requests.ml" 218 + ], 219 + "rationale": "The code has parse_retry_after implemented but it's not called anywhere. When servers return 429 (Too Many Requests) or 503 (Service Unavailable), they often include a Retry-After header indicating when to retry. Ignoring this header can lead to: (1) retrying too quickly and triggering rate limits again, (2) wasting resources on requests that will fail. cpp-httplib respects Retry-After. The OCaml library should extract Retry-After from response headers in requests.ml:536-549 and use it instead of calculate_backoff when present and respect_retry_after is true. This is a gap between declared functionality (the config flag exists) and actual behavior." 220 + }, 221 + { 222 + "source_repo": "third_party/c++/cpp-httplib", 223 + "source_language": "C++", 224 + "criticality": "medium", 225 + "change_type": "enhancement", 226 + "title": "Add support for custom CA certificate paths and directories", 227 + "description": "cpp-httplib provides set_ca_cert_path(file_path, dir_path) to specify custom CA certificates. The OCaml library uses ca-certs which loads system certificates but doesn't support custom CA paths for corporate or private CAs.", 228 + "affected_files": [ 229 + "lib/requests.ml", 230 + "lib/requests.mli" 231 + ], 232 + "rationale": "Corporate environments often use private Certificate Authorities for internal services. cpp-httplib allows specifying custom CA certificate files and directories via set_ca_cert_path. The OCaml library uses Ca_certs.authenticator() which loads system certificates only (requests.ml:95). Users with private CAs must either: (1) install certs system-wide (requires admin), (2) disable verification (insecure). Adding optional ca_cert_file and ca_cert_dir parameters to Requests.create would enable custom CA support. Implementation would use X509 and Tls libraries to load custom certificates and construct a custom authenticator instead of the system one." 233 + } 234 + ] 235 + }
+195
third_party/c++/cpp-netlib.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/c++/cpp-netlib", 5 + "source_language": "C++", 6 + "criticality": "high", 7 + "change_type": "bug", 8 + "title": "Add automatic retry on EOF/connection reset errors for pooled connections", 9 + "description": "The cpp-netlib pooled_connection_policy implements a single automatic retry when encountering EOF errors during response reading. This handles cases where a server closes an idle keep-alive connection between the time the client borrows it from the pool and when it actually sends the request. The OCaml library currently lacks this critical edge case handling, which can lead to spurious connection errors that require manual retry by the application.", 10 + "affected_files": [ 11 + "lib/http_client.ml", 12 + "lib/requests.ml" 13 + ], 14 + "rationale": "In pooled connection scenarios, a connection may appear valid when borrowed from the pool but be closed by the server before the request is sent. The cpp-netlib code at sync_base.hpp:115-124 shows a try-catch block that specifically catches EOF errors, reconnects, and retries once. This is a common HTTP client pattern that prevents user-visible errors for transient connection issues. The OCaml library should implement similar logic in Http_client.make_request or at the connection pool level to automatically detect stale connections and retry transparently." 15 + }, 16 + { 17 + "source_repo": "third_party/c++/cpp-netlib", 18 + "source_language": "C++", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Add streaming body callback support for memory-efficient large response handling", 22 + "description": "The cpp-netlib library provides body_callback_function_type that allows processing response bodies incrementally as chunks are received, rather than buffering the entire response in memory. This is implemented via iterator_range callbacks that fire as data arrives. The OCaml library currently only supports reading the full body into memory or streaming to a Flow, but lacks a callback-based incremental processing API that would allow users to process chunks without holding the entire response.", 23 + "affected_files": [ 24 + "lib/response.ml", 25 + "lib/http_client.ml", 26 + "lib/requests.ml" 27 + ], 28 + "rationale": "For large file downloads or streaming APIs, holding the entire response body in memory is inefficient. The cpp-netlib pattern in pooled_connection.hpp:36-37 shows a body_callback_function_type that receives iterator_range chunks. The OCaml library could add a similar ~body_handler:(string -> unit) parameter to request functions that would be called for each chunk as it's read from the socket. This would enable memory-efficient processing of large responses, progress reporting, and early termination scenarios." 29 + }, 30 + { 31 + "source_repo": "third_party/c++/cpp-netlib", 32 + "source_language": "C++", 33 + "criticality": "medium", 34 + "change_type": "feature", 35 + "title": "Add body generator function support for streaming request bodies", 36 + "description": "The cpp-netlib library supports body_generator_function_type, a callback that allows generating request body data incrementally rather than materializing it all upfront. The generator function returns true if more data is available and false when complete. This is essential for uploading large files or streaming data without loading everything into memory. The OCaml library only supports pre-materialized request bodies (strings, forms, JSON) and lacks support for streaming request body generation.", 37 + "affected_files": [ 38 + "lib/body.ml", 39 + "lib/http_client.ml", 40 + "lib/requests.ml" 41 + ], 42 + "rationale": "For large file uploads or generated content (e.g., database dumps, log streaming), materializing the entire request body before sending is memory-inefficient and slow. The cpp-netlib shows in pooled_connection.hpp:39 a body_generator_function_type that returns chunks on demand. The OCaml library should add a Body.generator variant that takes a unit -> string option function, calling it repeatedly to fetch chunks until None is returned. This would enable memory-efficient uploads and would integrate with Eio's structured concurrency for backpressure handling." 43 + }, 44 + { 45 + "source_repo": "third_party/c++/cpp-netlib", 46 + "source_language": "C++", 47 + "criticality": "low", 48 + "change_type": "enhancement", 49 + "title": "Add configurable redirect count limit as a constant or configuration parameter", 50 + "description": "The cpp-netlib defines BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT (default 5) as a compile-time constant that can be overridden by the user. The OCaml library has a max_redirects parameter but defaults to 10, which is higher than common HTTP client defaults. Additionally, the error handling when exceeding the limit should be more informative, showing the exact limit that was exceeded.", 51 + "affected_files": [ 52 + "lib/requests.ml", 53 + "lib/error.ml" 54 + ], 55 + "rationale": "Different applications have different redirect tolerance requirements. The cpp-netlib approach in pooled_connection.hpp:19-21 shows a preprocessor constant with a relatively conservative default of 5. The OCaml library's default of 10 is generous but might allow redirect loops to persist longer. While the OCaml library already allows configuration, aligning the default to a more conservative value (5-7) or making the constant more discoverable would improve security posture. The error message in Error.TooManyRedirects is already good, showing count and max." 56 + }, 57 + { 58 + "source_repo": "third_party/c++/cpp-netlib", 59 + "source_language": "C++", 60 + "criticality": "high", 61 + "change_type": "bug", 62 + "title": "Validate HTTP version in response status line parsing", 63 + "description": "The cpp-netlib performs explicit validation that the HTTP version in the response starts with 'HTTP/' (sync_base.hpp:71-72), throwing an error if the response is malformed. The OCaml library's parse_status_line function in http_client.ml:173-178 handles HTTP/1.1 and HTTP/1.0 but doesn't explicitly validate the format or handle malformed responses gracefully, which could lead to pattern match failures or unexpected behavior with non-HTTP responses.", 64 + "affected_files": [ 65 + "lib/http_client.ml" 66 + ], 67 + "rationale": "When connecting to non-HTTP services or encountering protocol errors, the response may not be valid HTTP. The cpp-netlib validation ensures the response is well-formed before processing. The OCaml library should add explicit validation in parse_status_line to check that the response starts with 'HTTP/' and has a parseable status code, raising a clear InvalidResponse error rather than allowing a pattern match failure or int_of_string exception to propagate." 68 + }, 69 + { 70 + "source_repo": "third_party/c++/cpp-netlib", 71 + "source_language": "C++", 72 + "criticality": "medium", 73 + "change_type": "enhancement", 74 + "title": "Add support for continuation header lines (header folding)", 75 + "description": "The cpp-netlib handles HTTP header folding/continuation, where a header value can span multiple lines if subsequent lines start with whitespace (sync_base.hpp:87-92). The OCaml library's parse_headers function in http_client.ml:181-194 only handles single-line headers and would treat a continuation line as a malformed header. While RFC 7230 deprecated header folding, legacy servers and some APIs still use it.", 76 + "affected_files": [ 77 + "lib/http_client.ml" 78 + ], 79 + "rationale": "Though header folding is deprecated in RFC 7230, some legacy servers and APIs still use it. The cpp-netlib shows defensive programming by handling continuation lines (lines starting with space are appended to the previous header). The OCaml library should add similar logic to accumulate continuation lines into the previous header value, improving compatibility with older HTTP implementations. This is a low-risk enhancement that would prevent parsing failures with certain servers." 80 + }, 81 + { 82 + "source_repo": "third_party/c++/cpp-netlib", 83 + "source_language": "C++", 84 + "criticality": "low", 85 + "change_type": "enhancement", 86 + "title": "Add configurable chunk marker removal option", 87 + "description": "The cpp-netlib provides a remove_chunk_markers option in client configuration that controls whether chunked transfer encoding markers are stripped from the response body. This gives applications fine-grained control over body processing. The OCaml library automatically parses chunked encoding (http_client.ml:210-236) and always removes markers, which is correct for most use cases but doesn't offer the flexibility for applications that need raw chunk information.", 88 + "affected_files": [ 89 + "lib/http_client.ml", 90 + "lib/requests.ml", 91 + "lib/response.ml" 92 + ], 93 + "rationale": "While automatic chunk parsing is the right default, some debugging or proxy scenarios require preserving chunk markers. The cpp-netlib test files show remove_chunk_markers(true) as an option. The OCaml library could add a remove_chunk_markers or preserve_chunks option to the request/session configuration. However, this is low priority as the current behavior (always removing markers) is correct for 99% of use cases." 94 + }, 95 + { 96 + "source_repo": "third_party/c++/cpp-netlib", 97 + "source_language": "C++", 98 + "criticality": "medium", 99 + "change_type": "security", 100 + "title": "Add explicit socket cleanup on HTTP/1.0 responses", 101 + "description": "The cpp-netlib pooled connection policy explicitly closes sockets after HTTP/1.0 responses (pooled_connection.hpp:140-142) since HTTP/1.0 doesn't support keep-alive by default. The OCaml library doesn't appear to have special handling for HTTP/1.0 vs HTTP/1.1 connection persistence, which could lead to connection leaks or reuse of connections that should be closed.", 102 + "affected_files": [ 103 + "lib/http_client.ml", 104 + "lib/requests.ml" 105 + ], 106 + "rationale": "HTTP/1.0 doesn't support persistent connections by default (unless explicitly indicated by Connection: Keep-Alive), while HTTP/1.1 does. The cpp-netlib properly handles this protocol difference by closing connections after HTTP/1.0 responses. The OCaml library should add logic after reading the response to check the HTTP version from the status line and either mark the connection for closure (if 1.0) or respect the Connection header (if 1.1). This prevents incorrect connection reuse and potential data corruption." 107 + }, 108 + { 109 + "source_repo": "third_party/c++/cpp-netlib", 110 + "source_language": "C++", 111 + "criticality": "medium", 112 + "change_type": "enhancement", 113 + "title": "Skip body reading for 204 No Content and 304 Not Modified responses", 114 + "description": "The cpp-netlib explicitly skips reading response bodies for specific status codes: 304 Not Modified, 204 No Content, and 1xx informational responses (pooled_connection.hpp:128-132). These status codes, by RFC specification, must not contain a message body. The OCaml library doesn't appear to have explicit logic to skip body reading for these status codes, which could cause parsing issues or hangs if a malformed server sends body data.", 115 + "affected_files": [ 116 + "lib/http_client.ml" 117 + ], 118 + "rationale": "Per HTTP RFC, certain status codes must not have a response body: 204 No Content, 304 Not Modified, and 1xx informational responses. The cpp-netlib shows best practice by explicitly checking for these codes and skipping body reading. The OCaml library should add similar logic in make_request to check the status code and skip body reading (set body to empty string) for these special cases. This improves RFC compliance and prevents issues with non-compliant servers." 119 + }, 120 + { 121 + "source_repo": "third_party/c++/cpp-netlib", 122 + "source_language": "C++", 123 + "criticality": "low", 124 + "change_type": "enhancement", 125 + "title": "Add configurable DNS resolver caching", 126 + "description": "The cpp-netlib provides a cache_resolved option that allows caching DNS resolution results to avoid repeated lookups for the same host. This is mentioned in the test files and improves performance for applications making many requests to the same hosts. The OCaml library performs DNS resolution on each connection establishment without caching at the application level (though the OS and Eio may cache at lower levels).", 127 + "affected_files": [ 128 + "lib/requests.ml" 129 + ], 130 + "rationale": "DNS resolution can be a significant overhead for applications making many requests to the same hosts. While the connection pool reuses TCP connections which avoids repeated resolution, new connections (after timeouts or pool exhaustion) require re-resolution. The cpp-netlib cache_resolved option provides application-level DNS caching. The OCaml library could add a similar option to cache resolved addresses at the session level, though this is lower priority since Eio and the OS typically provide adequate caching." 131 + }, 132 + { 133 + "source_repo": "third_party/c++/cpp-netlib", 134 + "source_language": "C++", 135 + "criticality": "high", 136 + "change_type": "security", 137 + "title": "Add validation to prevent header injection attacks", 138 + "description": "The cpp-netlib includes header validation and trimming logic to prevent malformed headers. The OCaml library should validate that header names don't contain colons, newlines, or other control characters that could enable header injection attacks. Currently, header construction trusts user input without validation, which could allow attackers to inject additional headers or corrupt the HTTP request if header values contain CRLF sequences.", 139 + "affected_files": [ 140 + "lib/headers.ml" 141 + ], 142 + "rationale": "Header injection is a serious security vulnerability where attackers can inject newlines (\\r\\n) into header values to add arbitrary headers or even inject response content. While the OCaml library uses proper CRLF formatting in http_client.ml:166, it doesn't validate user-provided header values to ensure they don't contain newlines or other control characters. The library should add validation in Headers.add and Headers.set to reject or escape header values containing \\r, \\n, or other control characters, preventing header injection attacks." 143 + }, 144 + { 145 + "source_repo": "third_party/c++/cpp-netlib", 146 + "source_language": "C++", 147 + "criticality": "medium", 148 + "change_type": "feature", 149 + "title": "Add support for custom SSL/TLS options and cipher configuration", 150 + "description": "The cpp-netlib provides extensive SSL configuration options including custom cipher suites (openssl_ciphers), raw OpenSSL options (openssl_options), SNI hostname configuration, and separate certificate/private key files for client authentication. The OCaml library has basic TLS support via tls_config but doesn't expose fine-grained control over cipher suites, SSL/TLS protocol versions, or client certificate authentication.", 151 + "affected_files": [ 152 + "lib/requests.ml" 153 + ], 154 + "rationale": "Different security environments require different TLS configurations. Some organizations require specific cipher suites, TLS version restrictions, or client certificate authentication. The cpp-netlib ssl_delegate.hpp shows extensive TLS configuration options. The OCaml library should expose more TLS.Config.client options, allowing users to specify cipher suites, protocol versions, client certificates, and other security parameters. This is particularly important for enterprise environments with strict security requirements." 155 + }, 156 + { 157 + "source_repo": "third_party/c++/cpp-netlib", 158 + "source_language": "C++", 159 + "criticality": "low", 160 + "change_type": "enhancement", 161 + "title": "Add comprehensive test coverage for edge cases", 162 + "description": "The cpp-netlib includes extensive test coverage including timeout tests, streaming tests, SSL tests, localhost tests, and error handling tests using Google Test framework. The OCaml library has basic connection pool tests but lacks comprehensive coverage for timeout enforcement, retry logic, chunked encoding edge cases, header parsing errors, SSL/TLS scenarios, and error conditions.", 163 + "affected_files": [ 164 + "test/" 165 + ], 166 + "rationale": "The cpp-netlib demonstrates best practices with dedicated test files for different scenarios: client_get_timeout_test.cpp for timeout validation, client_get_streaming_test.cpp for body callbacks, client_localhost_ssl_test.cpp for HTTPS. The OCaml library should expand test coverage to include: timeout enforcement tests, retry logic with mocked failures, chunked encoding edge cases (0-size chunks, extensions, trailers), malformed response handling, TLS certificate validation, and header injection prevention. This would improve reliability and prevent regressions." 167 + }, 168 + { 169 + "source_repo": "third_party/c++/cpp-netlib", 170 + "source_language": "C++", 171 + "criticality": "low", 172 + "change_type": "enhancement", 173 + "title": "Add support for chunk extension parsing in chunked transfer encoding", 174 + "description": "The cpp-netlib handles chunked transfer encoding thoroughly, including support for chunk extensions (metadata after the chunk size and semicolon). The OCaml library's read_chunked_body function in http_client.ml:216-218 strips chunk extensions but doesn't parse or expose them to the application. While extensions are rarely used, some applications may need access to them.", 175 + "affected_files": [ 176 + "lib/http_client.ml", 177 + "lib/response.ml" 178 + ], 179 + "rationale": "The HTTP chunked transfer encoding specification allows chunk extensions (key=value pairs after the chunk size, separated by semicolons). The OCaml library correctly handles their presence by stripping them, but doesn't expose them to applications. While chunk extensions are rarely used in practice, some specialized applications (streaming protocols, custom metadata) might need access. Adding optional chunk extension parsing would improve spec compliance, though this is very low priority." 180 + }, 181 + { 182 + "source_repo": "third_party/c++/cpp-netlib", 183 + "source_language": "C++", 184 + "criticality": "medium", 185 + "change_type": "enhancement", 186 + "title": "Add detailed logging/tracing of connection lifecycle events", 187 + "description": "The cpp-netlib architecture with separate connection delegates and policy classes provides clear separation of concerns and makes it easy to trace connection lifecycle. The OCaml library has good logging coverage via the Logs library but could benefit from more detailed connection-level events such as: connection borrowed from pool, connection returned to pool, connection closed due to timeout, DNS resolution cache hit/miss, and TLS handshake completion.", 188 + "affected_files": [ 189 + "lib/requests.ml", 190 + "lib/http_client.ml" 191 + ], 192 + "rationale": "The cpp-netlib's architecture makes connection lifecycle very explicit through the connection delegate pattern. The OCaml library could enhance observability by adding more detailed log events for connection pool operations. This would help users debug connection issues, understand pool behavior, and optimize configuration. Specific events to add: connection pool stats (active/idle count), connection reuse vs new connection decision, connection closure reason (idle timeout, lifetime, error, HTTP/1.0), and per-request timing breakdown." 193 + } 194 + ] 195 + }
+201
third_party/c++/nfhttp.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/c++/nfhttp", 5 + "source_language": "C++", 6 + "criticality": "medium", 7 + "change_type": "feature", 8 + "title": "Add request/response modifier hooks for extensibility", 9 + "description": "The C++ library implements request and response modifier functions that allow intercepting and modifying requests before they are sent and responses before they are returned to the caller. This enables powerful middleware patterns for logging, metrics, authentication injection, and automatic retry logic. The OCaml library should add similar hooks using higher-order functions that take (request -> request) and (response -> response option) transformers, where None signals a retry.", 10 + "affected_files": [ 11 + "lib/requests.mli", 12 + "lib/requests.ml" 13 + ], 14 + "rationale": "The ClientModifierImplementation in nfhttp demonstrates a sophisticated middleware pattern that allows request/response interception. This enables users to implement cross-cutting concerns like request signing, response validation, automatic token refresh, and custom retry logic without modifying library internals. The OCaml library currently lacks this extensibility point, forcing users to wrap the library or fork it for such use cases." 15 + }, 16 + { 17 + "source_repo": "third_party/c++/nfhttp", 18 + "source_language": "C++", 19 + "criticality": "high", 20 + "change_type": "security", 21 + "title": "Disable SSL verification on macOS and Android is a security vulnerability", 22 + "description": "The C++ library's ClientCurl.cpp contains hardcoded SSL verification disabling on Apple and Android platforms (lines 291-294). This is a critical security vulnerability that should never be replicated. The OCaml library correctly implements TLS verification by default with the Ca_certs package, which should be maintained and never conditionally disabled based on platform.", 23 + "affected_files": [ 24 + "lib/requests.ml" 25 + ], 26 + "rationale": "The nfhttp library disables SSL peer and host verification on macOS and Android with preprocessor directives. This makes all HTTPS connections vulnerable to man-in-the-middle attacks on those platforms. The OCaml library's approach of using Ca_certs.authenticator() and allowing explicit opt-out via verify_tls parameter is the correct pattern and should be maintained. This recommendation documents what NOT to do." 27 + }, 28 + { 29 + "source_repo": "third_party/c++/nfhttp", 30 + "source_language": "C++", 31 + "criticality": "medium", 32 + "change_type": "feature", 33 + "title": "Add request cancellation token support", 34 + "description": "The C++ library implements RequestToken for request cancellation, allowing clients to cancel in-flight requests. The OCaml library should leverage Eio's fiber cancellation mechanism more explicitly by exposing a cancellable request function that accepts a cancel_hook or returns a cancel function alongside the response promise.", 35 + "affected_files": [ 36 + "lib/requests.mli", 37 + "lib/requests.ml", 38 + "lib/one.mli", 39 + "lib/one.ml" 40 + ], 41 + "rationale": "nfhttp's RequestToken provides explicit cancellation via token.cancel(), tracking cancellation state across redirect chains and retry attempts. While Eio provides fiber cancellation via Switch, the library should expose a more ergonomic cancellation API for users who need fine-grained control over individual requests without cancelling entire switches. This is especially useful for timeout handling, user-initiated cancels, and request racing patterns." 42 + }, 43 + { 44 + "source_repo": "third_party/c++/nfhttp", 45 + "source_language": "C++", 46 + "criticality": "low", 47 + "change_type": "feature", 48 + "title": "Add response pinning/persistence API for offline support", 49 + "description": "The C++ library implements response pinning functionality allowing responses to be stored and retrieved by identifier for offline support. Consider adding similar functionality to the OCaml library using an optional persistence layer that can store responses to disk and retrieve them when offline, integrated with the XDG directory support.", 50 + "affected_files": [ 51 + "lib/requests.mli", 52 + "lib/requests.ml" 53 + ], 54 + "rationale": "nfhttp's pinResponse/unpinResponse/pinnedResponsesForIdentifier API enables offline-first applications by allowing specific responses to be persisted beyond cache TTL. While the OCaml library previously had caching support (now disabled), this pinning feature is distinct and valuable for mobile/offline scenarios. Implementation could leverage the existing xdg directory support and Cookeio_jar persistence patterns." 55 + }, 56 + { 57 + "source_repo": "third_party/c++/nfhttp", 58 + "source_language": "C++", 59 + "criticality": "medium", 60 + "change_type": "enhancement", 61 + "title": "Add Cache-Control header parsing and respecting", 62 + "description": "The C++ library implements detailed Cache-Control parsing for both requests and responses, extracting directives like max-age, max-stale, no-cache, only-if-cached, etc. While the OCaml library has disabled caching, it should still parse and expose Cache-Control headers in the Response type to allow application-level caching decisions.", 63 + "affected_files": [ 64 + "lib/response.mli", 65 + "lib/response.ml", 66 + "lib/headers.mli", 67 + "lib/headers.ml" 68 + ], 69 + "rationale": "The RequestImplementation::cacheControl() method in nfhttp parses Cache-Control headers into structured data. Even without built-in caching, exposing this as a parsed type (e.g., Response.cache_control : t -> Cache_control.t option) would help users implement application-level caching, validate freshness, and respect server cache directives. The parsing logic handles directives with and without values." 70 + }, 71 + { 72 + "source_repo": "third_party/c++/nfhttp", 73 + "source_language": "C++", 74 + "criticality": "low", 75 + "change_type": "enhancement", 76 + "title": "Add request hashing for deduplication and cache key generation", 77 + "description": "The C++ library implements request hashing that creates a unique hash from URL, headers (respecting Vary), and body. This is useful for request deduplication, cache key generation, and identifying identical in-flight requests. Add a Request.hash function that returns a stable string hash of a request.", 78 + "affected_files": [ 79 + "lib/requests.mli", 80 + "lib/body.mli" 81 + ], 82 + "rationale": "The RequestImplementation::hash() method generates SHA-256 hashes of requests, properly handling Vary headers to exclude certain headers from the hash. This enables request deduplication (avoiding duplicate in-flight requests), cache key generation, and request tracking. The OCaml library could implement this using Digestif, which it already depends on for Digest auth." 83 + }, 84 + { 85 + "source_repo": "third_party/c++/nfhttp", 86 + "source_language": "C++", 87 + "criticality": "low", 88 + "change_type": "enhancement", 89 + "title": "Add synchronous request API wrapper", 90 + "description": "The C++ library provides performRequestSynchronously() that wraps the async API with a condition variable. While the OCaml library's primary API is already synchronous with Eio, document this design choice clearly and ensure the One module provides truly stateless one-off requests for users who don't want connection pooling.", 91 + "affected_files": [ 92 + "lib/requests.mli", 93 + "lib/one.mli" 94 + ], 95 + "rationale": "The Client::performRequestSynchronously implementation shows a clear pattern of blocking on async operations. The OCaml library already does this correctly with Eio's structured concurrency, but the documentation could better explain when to use the stateful Requests.t API versus the One module for truly one-off requests." 96 + }, 97 + { 98 + "source_repo": "third_party/c++/nfhttp", 99 + "source_language": "C++", 100 + "criticality": "high", 101 + "change_type": "bug", 102 + "title": "Hardcoded 30-second timeout may be too aggressive for some use cases", 103 + "description": "The C++ library hardcodes CURLOPT_TIMEOUT to 30 seconds in ClientCurl.cpp line 289. The OCaml library correctly makes timeouts configurable via Timeout.t, but should ensure this is well-documented and that reasonable defaults are provided (current default is connect=10s, read=30s, which is good).", 104 + "affected_files": [ 105 + "lib/timeout.ml", 106 + "lib/timeout.mli" 107 + ], 108 + "rationale": "The hardcoded 30-second timeout in nfhttp can cause issues for legitimate long-running requests (large file uploads/downloads, slow APIs). The OCaml library's configurable timeout with separate connect, read, and total timeout options is superior. Ensure documentation emphasizes timeout configuration for different use cases and that the defaults are appropriate." 109 + }, 110 + { 111 + "source_repo": "third_party/c++/nfhttp", 112 + "source_language": "C++", 113 + "criticality": "medium", 114 + "change_type": "enhancement", 115 + "title": "Add request/response serialization for debugging and replay", 116 + "description": "The C++ library implements request serialization to/from JSON for debugging, testing, and request replay scenarios. Add similar functionality to the OCaml library using a human-readable format (JSON or S-expressions) that can serialize/deserialize requests and responses.", 117 + "affected_files": [ 118 + "lib/requests.mli", 119 + "lib/response.mli" 120 + ], 121 + "rationale": "RequestImplementation::serialise() converts requests to JSON for debugging, logging, and replay testing. This is valuable for debugging production issues (log the exact request that failed) and for test fixtures. The OCaml library could implement this using Yojson or the existing JSON support in Body, exposing Request.to_json and Response.to_json functions." 122 + }, 123 + { 124 + "source_repo": "third_party/c++/nfhttp", 125 + "source_language": "C++", 126 + "criticality": "high", 127 + "change_type": "bug", 128 + "title": "Retry-After header parsing is incomplete", 129 + "description": "The OCaml library's Retry.parse_retry_after function attempts to parse HTTP dates using RFC3339 format, but HTTP dates use RFC 7231 format (IMF-fixdate). This will fail to parse valid Retry-After headers. Implement proper HTTP-date parsing or use an existing library like Ptime.Http (if available) or parse IMF-fixdate format.", 130 + "affected_files": [ 131 + "lib/retry.ml" 132 + ], 133 + "rationale": "The current implementation in retry.ml line 85 uses Ptime.of_rfc3339 for parsing HTTP date headers, but HTTP dates are in IMF-fixdate format (e.g., 'Wed, 21 Oct 2015 07:28:00 GMT'), not RFC3339. This means the library will fail to respect valid Retry-After headers from servers, potentially causing unnecessary retries or violating rate limits. The nfhttp library doesn't implement this either, but it's a known gap that should be fixed." 134 + }, 135 + { 136 + "source_repo": "third_party/c++/nfhttp", 137 + "source_language": "C++", 138 + "criticality": "medium", 139 + "change_type": "enhancement", 140 + "title": "Add user-agent header configuration at client level", 141 + "description": "The C++ createClient function accepts a user_agent parameter that can be set once at client creation. The OCaml library supports this via default_headers but could make it more explicit with a dedicated user_agent parameter in the create function and a set_user_agent helper.", 142 + "affected_files": [ 143 + "lib/requests.mli", 144 + "lib/requests.ml" 145 + ], 146 + "rationale": "While the OCaml library can set User-Agent via default_headers or the Cmd module, making it a first-class parameter would improve API ergonomics. Many HTTP clients treat User-Agent specially because it's required by many APIs and helps with debugging. The nfhttp API design shows this is a common enough pattern to warrant dedicated support." 147 + }, 148 + { 149 + "source_repo": "third_party/c++/nfhttp", 150 + "source_language": "C++", 151 + "criticality": "low", 152 + "change_type": "enhancement", 153 + "title": "Add multi-request batching for improved performance", 154 + "description": "The C++ library includes ClientMultiRequestImplementation for batching multiple requests efficiently. While Eio's fiber-based concurrency already enables this via Fiber.both/Fiber.all, consider adding a batching helper that automatically manages concurrent request execution with configurable concurrency limits.", 155 + "affected_files": [ 156 + "lib/requests.mli", 157 + "lib/requests.ml" 158 + ], 159 + "rationale": "ClientMultiRequestImplementation enables efficient parallel request execution. While users can achieve this with Fiber.all, a helper like Requests.batch : t -> Request.t list -> max_concurrent:int -> Response.t list would provide a convenient API for common patterns like 'fetch these 100 URLs with at most 10 concurrent connections'." 160 + }, 161 + { 162 + "source_repo": "third_party/c++/nfhttp", 163 + "source_language": "C++", 164 + "criticality": "medium", 165 + "change_type": "enhancement", 166 + "title": "Add explicit Range header handling for partial downloads", 167 + "description": "The C++ library's ClientCurl::HandleInfo::configureHeaders specially handles the Range header by mapping it to CURLOPT_RANGE. Add similar support in the OCaml library by providing Range header helpers and documenting partial content (206) response handling.", 168 + "affected_files": [ 169 + "lib/headers.mli", 170 + "lib/headers.ml", 171 + "lib/status.mli" 172 + ], 173 + "rationale": "The special handling of Range headers in ClientCurl.cpp line 268-271 shows this is a common enough use case to warrant dedicated support. The OCaml library should add Headers.range helper functions, document 206 Partial Content response handling, and potentially add a Response.content_range parser for the Content-Range response header." 174 + }, 175 + { 176 + "source_repo": "third_party/c++/nfhttp", 177 + "source_language": "C++", 178 + "criticality": "high", 179 + "change_type": "security", 180 + "title": "Add Vary header support for cache key generation", 181 + "description": "The C++ library's request hashing respects Vary headers by excluding varying headers from the hash. If HTTP caching is re-enabled in the future, ensure the cache implementation properly handles Vary headers to avoid serving incorrect cached responses.", 182 + "affected_files": [ 183 + "lib/headers.mli", 184 + "lib/headers.ml" 185 + ], 186 + "rationale": "The RequestImplementation::hash() code (lines 98-108) shows proper Vary header handling, which is critical for correct HTTP caching. The Vary header tells caches which request headers affect the response, so 'Vary: Authorization' means the same URL can have different responses based on the Authorization header. If caching is restored, this must be implemented correctly to avoid security issues where user A sees user B's cached data." 187 + }, 188 + { 189 + "source_repo": "third_party/c++/nfhttp", 190 + "source_language": "C++", 191 + "criticality": "low", 192 + "change_type": "refactor", 193 + "title": "Consider architectural pattern of wrapping clients for layered functionality", 194 + "description": "The C++ library uses a layered architecture (CurlClient -> CachingClient -> MultiRequestClient -> ModifierClient) where each layer wraps the previous one. The OCaml library currently implements all features in a single type. Consider whether separating concerns (pooling, retry, auth, cookies) into composable layers would improve testability and maintainability.", 195 + "affected_files": [ 196 + "lib/requests.ml" 197 + ], 198 + "rationale": "The nfhttp architecture in Client.cpp shows createClient() composes four layers: native transport, caching, multi-request, and modifiers. Each layer has a single responsibility. The OCaml Requests.t type currently combines pooling, cookies, auth, retry, and configuration. While this is simpler for users, a more modular architecture might improve testability and allow users to compose only the features they need, reducing overhead for simple use cases." 199 + } 200 + ] 201 + }
+260
third_party/c++/proxygen.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "proxygen", 5 + "source_language": "C++", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add rate limiting for security protection", 9 + "description": "Proxygen implements comprehensive rate limiting for headers, control messages, and RST frames to prevent DoS attacks. The OCaml library lacks any rate limiting mechanism, making it vulnerable to malicious servers that could send excessive headers or control frames.", 10 + "affected_files": [ 11 + "lib/http_client.ml", 12 + "lib/requests.ml", 13 + "lib/error.ml" 14 + ], 15 + "rationale": "Proxygen's RateLimitFilter prevents abuse by limiting headers per interval, control messages, and resets with configurable thresholds. Without rate limits, the OCaml client could be attacked by malicious servers sending unbounded headers or rapid control messages, leading to memory exhaustion or CPU overload. This is a security-critical feature for production use." 16 + }, 17 + { 18 + "source_repo": "proxygen", 19 + "source_language": "C++", 20 + "criticality": "high", 21 + "change_type": "security", 22 + "title": "Implement decompression size limits", 23 + "description": "Proxygen enforces maximum uncompressed size limits during decompression to prevent decompression bombs. The OCaml library's decompress_gzip/deflate/zlib functions lack size bounds, creating a security vulnerability where a small compressed payload could expand to exhaust memory.", 24 + "affected_files": [ 25 + "lib/http_client.ml" 26 + ], 27 + "rationale": "The current decompression implementation in http_client.ml:14-117 creates buffers based on compressed size without checking expansion limits. A malicious server could send a tiny gzip payload that decompresses to gigabytes, causing OOM. Proxygen enforces configurable max_uncompressed_bytes limits to prevent this attack vector." 28 + }, 29 + { 30 + "source_repo": "proxygen", 31 + "source_language": "C++", 32 + "criticality": "high", 33 + "change_type": "security", 34 + "title": "Add 0-RTT replay safety mechanisms", 35 + "description": "Proxygen implements replay safety callbacks and blocking for TLS 0-RTT early data to prevent replay attacks. The OCaml library uses TLS but doesn't handle 0-RTT replay safety, potentially allowing idempotent-sensitive operations to be replayed.", 36 + "affected_files": [ 37 + "lib/requests.ml", 38 + "lib/one.ml", 39 + "lib/http_client.ml" 40 + ], 41 + "rationale": "Proxygen's addWaitingForReplaySafety/onReplaySafe mechanism ensures requests are not sent over 0-RTT connections until transport becomes replay-safe. Without this, POST/PUT requests could be replayed by attackers capturing 0-RTT data, violating idempotency assumptions and potentially causing duplicate operations." 42 + }, 43 + { 44 + "source_repo": "proxygen", 45 + "source_language": "C++", 46 + "criticality": "medium", 47 + "change_type": "enhancement", 48 + "title": "Enhance error types with directional context", 49 + "description": "Proxygen's HTTPException includes Direction (INGRESS/EGRESS/BOTH) to distinguish which side of the connection failed. The OCaml library's error types lack this distinction, making debugging harder when errors occur during request vs response phases.", 50 + "affected_files": [ 51 + "lib/error.ml" 52 + ], 53 + "rationale": "Proxygen's error system in ProxygenErrorEnum.h includes 70+ specific error codes with directional awareness. The OCaml library has only 11 error types without direction context. Adding direction tags would help users distinguish 'connection failed during request send' from 'connection failed during response read', improving debuggability." 54 + }, 55 + { 56 + "source_repo": "proxygen", 57 + "source_language": "C++", 58 + "criticality": "medium", 59 + "change_type": "enhancement", 60 + "title": "Add granular timeout types beyond connect/read/total", 61 + "description": "Proxygen implements multiple timeout types: WriteTimeout, FlowControlTimeout, DrainTimeout, and PingProber with independent configuration. The OCaml library only has connect/read/total timeouts, lacking granularity for complex scenarios.", 62 + "affected_files": [ 63 + "lib/timeout.ml", 64 + "lib/requests.ml" 65 + ], 66 + "rationale": "The current timeout.ml only supports 3 types. Proxygen's fine-grained timeouts enable scenarios like: write timeouts for slow uploads, flow control timeouts for stream windows, drain timeouts for graceful shutdown, and ping intervals for keep-alive detection. These would improve reliability in production environments with flaky networks." 67 + }, 68 + { 69 + "source_repo": "proxygen", 70 + "source_language": "C++", 71 + "criticality": "medium", 72 + "change_type": "feature", 73 + "title": "Implement connection health probing with ping/pong", 74 + "description": "Proxygen uses PingProber with configurable intervals and timeouts to detect dead connections proactively. The OCaml library has no connection health checking beyond timeouts, leading to longer failure detection times.", 75 + "affected_files": [ 76 + "lib/requests.ml", 77 + "lib/http_client.ml" 78 + ], 79 + "rationale": "Proxygen's PingProber sends periodic pings (with extendIntervalOnIngress option) and declares connections dead if pong isn't received within timeout. This enables fast failure detection for idle pooled connections. Without probing, the OCaml client only discovers dead connections when attempting actual requests, wasting time and retry attempts." 80 + }, 81 + { 82 + "source_repo": "proxygen", 83 + "source_language": "C++", 84 + "criticality": "medium", 85 + "change_type": "enhancement", 86 + "title": "Add connection max age limit enforcement", 87 + "description": "Proxygen's SessionPool enforces both idle timeout and max connection lifetime (max_age). The OCaml library has connection_idle_timeout (60s) and connection_lifetime (300s) configured but lacks explicit max age enforcement for security token rotation.", 88 + "affected_files": [ 89 + "lib/requests.ml" 90 + ], 91 + "rationale": "While requests.ml:74 sets connection_lifetime=300s, there's no documented behavior for rotating connections based on age regardless of activity. Proxygen explicitly enforces max_age to ensure periodic connection recycling, which is important for security (TLS session rotation, credential refreshing) and detecting silent connection degradation." 92 + }, 93 + { 94 + "source_repo": "proxygen", 95 + "source_language": "C++", 96 + "criticality": "medium", 97 + "change_type": "enhancement", 98 + "title": "Expand error taxonomy with protocol-specific errors", 99 + "description": "Proxygen defines 70+ granular error codes including network errors (kErrorNetworkSwitch), DNS errors (kErrorDNSResolutionErr, kErrorDNSNoResults), stream errors (kErrorDuplicatedStreamId, kErrorParentStreamNotExist), and TLS errors (kErrorEarlyDataRejected). The OCaml library has only 11 broad error categories.", 100 + "affected_files": [ 101 + "lib/error.ml" 102 + ], 103 + "rationale": "The current error.ml lacks specificity for common failure modes: DNS resolution failures are lumped into ConnectionError, network switches aren't distinguished, header/body parse errors are combined. Adding finer-grained errors would enable better error handling (e.g., retry DNS failures differently than connection refused) and improve observability." 104 + }, 105 + { 106 + "source_repo": "proxygen", 107 + "source_language": "C++", 108 + "criticality": "medium", 109 + "change_type": "feature", 110 + "title": "Add statistics and observability framework", 111 + "description": "Proxygen implements comprehensive HTTPSessionStats with metrics for transactions opened/closed/served, session reuse, idle time, stalls, buffered bytes, rate limiting events, and periodic ping timeouts. The OCaml library only tracks requests_made, total_time, and retries_count.", 112 + "affected_files": [ 113 + "lib/requests.ml", 114 + "lib/response.ml", 115 + "lib/http_client.ml" 116 + ], 117 + "rationale": "Proxygen's stats system tracks 20+ metrics including sessionReused, sessionIdleTime, transactionStalled, pendingBufferedReadBytes, controlMsgsRateLimited, periodicPingProbeTimeout. The OCaml library's minimal stats (requests.ml:55-57) don't capture connection pool efficiency, backpressure events, or health metrics needed for production monitoring and performance tuning." 118 + }, 119 + { 120 + "source_repo": "proxygen", 121 + "source_language": "C++", 122 + "criticality": "medium", 123 + "change_type": "feature", 124 + "title": "Implement byte event tracking for performance measurement", 125 + "description": "Proxygen's ByteEventTracker monitors events with byte offsets (first header byte, body bytes, ACKs) for latency measurements and detailed timing analysis. The OCaml library only tracks total elapsed time per request.", 126 + "affected_files": [ 127 + "lib/response.ml", 128 + "lib/requests.ml" 129 + ], 130 + "rationale": "Proxygen tracks 9 byte event types (FIRST_HEADER_BYTE_WRITE, FIRST_BODY_BYTE_ACK, etc.) with timestamps and optional ACK tracking. This enables precise latency analysis: time-to-first-byte, upload throughput, network RTT. The OCaml library's single elapsed metric (response.ml:14) doesn't distinguish connection establishment, request send, server processing, and response transfer phases." 131 + }, 132 + { 133 + "source_repo": "proxygen", 134 + "source_language": "C++", 135 + "criticality": "low", 136 + "change_type": "feature", 137 + "title": "Add observer pattern for transaction lifecycle events", 138 + "description": "Proxygen implements HTTPTransactionObserverInterface for non-intrusive monitoring of byte events, state changes, and lifecycle hooks without modifying core logic. The OCaml library lacks an observer/hook mechanism.", 139 + "affected_files": [ 140 + "lib/requests.ml", 141 + "lib/response.ml" 142 + ], 143 + "rationale": "Proxygen's observer pattern allows attaching multiple observers to track events (onBytesEvent, transaction lifecycle) without coupling. This enables features like distributed tracing, custom metrics, and logging without modifying request handling code. An OCaml equivalent using callbacks or effect handlers would improve extensibility." 144 + }, 145 + { 146 + "source_repo": "proxygen", 147 + "source_language": "C++", 148 + "criticality": "low", 149 + "change_type": "enhancement", 150 + "title": "Add partial message preservation in error context", 151 + "description": "Proxygen's HTTPException stores partialMsg and currentIngressBuf to preserve incomplete data when parsing fails, aiding debugging. The OCaml library's HTTPError only stores the final body string if available.", 152 + "affected_files": [ 153 + "lib/error.ml" 154 + ], 155 + "rationale": "When Proxygen encounters parse errors, it captures the incomplete message and buffer state for debugging. The OCaml HTTPError (error.ml:16-22) only includes body for HTTP errors, not parse failures. Preserving partial data would help debug malformed responses from buggy servers." 156 + }, 157 + { 158 + "source_repo": "proxygen", 159 + "source_language": "C++", 160 + "criticality": "low", 161 + "change_type": "enhancement", 162 + "title": "Add session reuse tracking and optimization hints", 163 + "description": "Proxygen tracks session reuse via isReusable() checks and recordSessionReused() stats to optimize connection pooling. The OCaml library doesn't explicitly track or expose reuse metrics.", 164 + "affected_files": [ 165 + "lib/requests.ml" 166 + ], 167 + "rationale": "Proxygen's isReusable/isReplaySafe/isClosing checks determine connection eligibility for reuse. Recording sessionReused metrics helps tune pool sizes and connection lifetimes. The OCaml library delegates to Conpool but doesn't expose reuse statistics, making it harder to diagnose connection pool efficiency issues." 168 + }, 169 + { 170 + "source_repo": "proxygen", 171 + "source_language": "C++", 172 + "criticality": "low", 173 + "change_type": "feature", 174 + "title": "Implement filter/middleware chain architecture", 175 + "description": "Proxygen uses a filter chain pattern (HTTPCodecFilter, FlowControlFilter, RateLimitFilter) allowing modular addition of cross-cutting concerns without modifying core codec logic. The OCaml library lacks a middleware abstraction.", 176 + "affected_files": [ 177 + "lib/http_client.ml", 178 + "lib/requests.ml" 179 + ], 180 + "rationale": "Proxygen's PassThroughHTTPCodecFilter enables composable filters for flow control, rate limiting, compression, logging, and stats. This architectural pattern would allow OCaml users to add custom behavior (request/response logging, custom headers, caching) without forking the library. Currently, such features require modifying http_client.ml directly." 181 + }, 182 + { 183 + "source_repo": "proxygen", 184 + "source_language": "C++", 185 + "criticality": "low", 186 + "change_type": "enhancement", 187 + "title": "Add DNS-specific error handling", 188 + "description": "Proxygen distinguishes DNS resolution errors (kErrorDNSResolutionErr, kErrorDNSNoResults, kErrorDNSOtherServer) from connection errors. The OCaml library treats all pre-connection failures as ConnectionError.", 189 + "affected_files": [ 190 + "lib/error.ml", 191 + "lib/http_client.ml" 192 + ], 193 + "rationale": "DNS failures have different retry strategies than connection failures: DNS timeouts might warrant longer backoffs or fallback DNS servers, while connection refused should retry quickly. Proxygen's separate DNS error codes enable smarter retry logic. The OCaml library should distinguish these in error.ml to enable DNS-aware retry policies." 194 + }, 195 + { 196 + "source_repo": "proxygen", 197 + "source_language": "C++", 198 + "criticality": "high", 199 + "change_type": "bug", 200 + "title": "Fix missing Connection: keep-alive validation", 201 + "description": "While the OCaml library sets Connection: keep-alive header (http_client.ml:150), there's no validation that the server actually supports keep-alive or enforcement of connection closure when server sends Connection: close. Proxygen explicitly tracks connection state and enforces close semantics.", 202 + "affected_files": [ 203 + "lib/http_client.ml" 204 + ], 205 + "rationale": "The code at http_client.ml:150 ensures Connection header is set, but doesn't parse server's Connection header in the response. If a server sends 'Connection: close', the connection should not be returned to the pool for reuse. Proxygen's session state management explicitly tracks this and prevents connection reuse when server signals closure, avoiding broken connection errors." 206 + }, 207 + { 208 + "source_repo": "proxygen", 209 + "source_language": "C++", 210 + "criticality": "medium", 211 + "change_type": "enhancement", 212 + "title": "Add backpressure and flow control visibility", 213 + "description": "Proxygen implements explicit flow control with Window management, pause/resume states (PAUSED/UNPAUSED), and backpressure signaling. The OCaml library relies on Eio's backpressure but doesn't expose flow control state or provide manual pause/resume controls.", 214 + "affected_files": [ 215 + "lib/http_client.ml", 216 + "lib/response.ml" 217 + ], 218 + "rationale": "Proxygen's FlowControlFilter with Window tracking (reserve/free/setCapacity) and SocketState enum allows fine-grained backpressure control. The OCaml library streams responses via Eio.Flow but doesn't expose whether backpressure is active or allow users to pause/resume transfers. Adding flow control visibility would help debug slow transfers and implement custom rate limiting." 219 + }, 220 + { 221 + "source_repo": "proxygen", 222 + "source_language": "C++", 223 + "criticality": "medium", 224 + "change_type": "feature", 225 + "title": "Add support for Expect: 100-continue handling", 226 + "description": "Proxygen supports Expect: 100-continue for large uploads, allowing servers to reject requests before body transmission. The OCaml library has no Expect header handling, potentially wasting bandwidth uploading large bodies that servers will reject.", 227 + "affected_files": [ 228 + "lib/http_client.ml", 229 + "lib/body.ml" 230 + ], 231 + "rationale": "For large uploads, the Expect: 100-continue mechanism allows clients to send headers first and wait for server's 100 Continue response before transmitting the body. This saves bandwidth when servers reject requests due to auth/validation failures. The OCaml library should add support in body upload flows, especially for multipart and file uploads." 232 + }, 233 + { 234 + "source_repo": "proxygen", 235 + "source_language": "C++", 236 + "criticality": "medium", 237 + "change_type": "feature", 238 + "title": "Add support for HTTP trailers", 239 + "description": "Proxygen supports HTTP trailers (headers sent after body in chunked encoding) via onTrailers/onTrailersComplete callbacks. The OCaml library doesn't handle trailers, potentially losing metadata sent by servers.", 240 + "affected_files": [ 241 + "lib/http_client.ml", 242 + "lib/response.ml", 243 + "lib/headers.ml" 244 + ], 245 + "rationale": "Trailers are used for checksums (Content-MD5), signatures, or dynamic metadata only known after body generation. Proxygen's onTrailersComplete handler captures these. The OCaml response type (response.ml:9-16) only includes headers field for initial headers, not trailers. Adding trailer support would enable validation of streaming content integrity." 246 + }, 247 + { 248 + "source_repo": "proxygen", 249 + "source_language": "C++", 250 + "criticality": "low", 251 + "change_type": "enhancement", 252 + "title": "Add errno capture in error context", 253 + "description": "Proxygen's HTTPException includes errno_ field to preserve system error codes. The OCaml library's ConnectionError and SSLError are just strings, losing the underlying error code context.", 254 + "affected_files": [ 255 + "lib/error.ml" 256 + ], 257 + "rationale": "When connection failures occur, the underlying errno (ECONNREFUSED, ETIMEDOUT, etc.) provides crucial debugging information. Proxygen preserves this in exceptions. The OCaml library should enhance ConnectionError to include optional error codes (Unix.error) for better diagnostics and error-specific retry logic." 258 + } 259 + ] 260 + }
+248
third_party/c++/webcc.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/c++/webcc", 5 + "source_language": "C++", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add subsequent read timeout for granular streaming control", 9 + "description": "Implement a separate 'subsequent_read_timeout' in addition to the global 'read' timeout. This allows setting a shorter timeout for each individual read operation during response streaming, while maintaining a longer overall timeout for the complete response. This prevents indefinite hangs when servers send data slowly in chunks.", 10 + "affected_files": [ 11 + "lib/timeout.ml", 12 + "lib/timeout.mli", 13 + "lib/http_client.ml", 14 + "lib/requests.ml" 15 + ], 16 + "rationale": "webcc implements three distinct timeout types: connect_timeout (connection establishment), read_timeout (overall response), and subsequent_read_timeout (each chunk during streaming, default 10s vs 30s overall). The OCaml library only has connect and read timeouts. This gap means the OCaml library cannot detect when a server stalls between chunks - it will wait the full read_timeout for each chunk. Adding subsequent_read_timeout provides better control over streaming operations and prevents resource exhaustion from slowly-responding servers." 17 + }, 18 + { 19 + "source_repo": "third_party/c++/webcc", 20 + "source_language": "C++", 21 + "criticality": "medium", 22 + "change_type": "enhancement", 23 + "title": "Add dedicated SSL/TLS shutdown timeout", 24 + "description": "Add a configurable timeout specifically for SSL/TLS shutdown operations (default 10 seconds). When closing HTTPS connections, the SSL shutdown handshake can hang indefinitely if the server doesn't respond. A dedicated timeout ensures clean termination without blocking resources.", 25 + "affected_files": [ 26 + "lib/timeout.ml", 27 + "lib/timeout.mli", 28 + "lib/requests.ml", 29 + "lib/one.ml" 30 + ], 31 + "rationale": "webcc implements ssl_shutdown_timeout with a dedicated timer that cancels the async_shutdown operation if it exceeds the timeout (ssl_client.cc:40-48). The OCaml library lacks this, meaning TLS connection shutdowns could potentially hang indefinitely. While Eio's structured concurrency helps, an explicit timeout for SSL shutdown provides better resource management and prevents cascading failures when servers misbehave during connection teardown." 32 + }, 33 + { 34 + "source_repo": "third_party/c++/webcc", 35 + "source_language": "C++", 36 + "criticality": "low", 37 + "change_type": "feature", 38 + "title": "Add progress callback support for upload/download operations", 39 + "description": "Add optional progress callbacks that are invoked during streaming operations to report bytes transferred. The callback should provide current bytes transferred, total bytes (if known), and whether it's a read or write operation. This enables applications to display progress bars, implement bandwidth throttling, or monitor transfer status.", 40 + "affected_files": [ 41 + "lib/one.mli", 42 + "lib/requests.mli", 43 + "lib/http_client.ml" 44 + ], 45 + "rationale": "webcc provides ProgressCallback support (client_base.h:68-73, client_base.cc:244-246, 295-302) that reports progress during both request sending and response reading. The OCaml library has progress callbacks only in the One.upload and One.download functions, but not in the main session API or for non-streaming requests. Extending this to all requests and making it part of the session configuration would improve observability and enable better UX for long-running transfers." 46 + }, 47 + { 48 + "source_repo": "third_party/c++/webcc", 49 + "source_language": "C++", 50 + "criticality": "high", 51 + "change_type": "security", 52 + "title": "Implement Server Name Indication (SNI) verification for TLS connections", 53 + "description": "Ensure that TLS connections explicitly set the SNI hostname and verify it matches the certificate. Many HTTPS servers require SNI to serve the correct certificate, and missing SNI verification can lead to security vulnerabilities or connection failures.", 54 + "affected_files": [ 55 + "lib/requests.ml", 56 + "lib/one.ml" 57 + ], 58 + "rationale": "webcc explicitly sets SNI hostname using SSL_set_tlsext_host_name and configures host_name_verification callback when ssl_verify is enabled (ssl_client.cc:84-92). This is critical for security - without SNI, servers may present the wrong certificate, and without hostname verification, MITM attacks become possible. The OCaml library should verify that the tls-eio library properly handles SNI (it likely does, but explicit configuration may be needed) and ensure hostname verification is enabled when verify_tls=true." 59 + }, 60 + { 61 + "source_repo": "third_party/c++/webcc", 62 + "source_language": "C++", 63 + "criticality": "medium", 64 + "change_type": "enhancement", 65 + "title": "Add timeout flag to error types for explicit timeout detection", 66 + "description": "Add a dedicated 'timeout' boolean field to the error type, separate from the error code. This allows callers to easily distinguish timeout errors from other connection/network errors without pattern matching on error codes or messages.", 67 + "affected_files": [ 68 + "lib/error.ml", 69 + "lib/error.mli" 70 + ], 71 + "rationale": "webcc's Error class has a dedicated timeout_ flag (error.h) that's set independently of the error code, allowing clients to easily check if an error was a timeout using error.timeout(). The OCaml library only has a `Timeout variant in the error type. While this works, adding an is_timeout predicate function and ensuring timeouts are consistently represented would improve ergonomics, especially for retry logic that needs to quickly determine if an error is retryable." 72 + }, 73 + { 74 + "source_repo": "third_party/c++/webcc", 75 + "source_language": "C++", 76 + "criticality": "low", 77 + "change_type": "enhancement", 78 + "title": "Add granular error codes for different failure types", 79 + "description": "Expand the error type to include more specific error codes distinguishing between: resolve errors (DNS), connect errors (TCP), handshake errors (TLS), socket read/write errors, parse errors, file I/O errors, and data errors. This enables better error handling, logging, and retry strategies.", 80 + "affected_files": [ 81 + "lib/error.ml", 82 + "lib/error.mli" 83 + ], 84 + "rationale": "webcc defines 12 distinct error codes (error.h: kResolveError, kConnectError, kHandshakeError, kSocketReadError, kSocketWriteError, kParseError, etc.). The OCaml library has broader error categories (ConnectionError, SSLError, etc.) but doesn't distinguish DNS failures from TCP connection failures, or TLS handshake errors from general SSL errors. More granular errors would enable better diagnostics, targeted retry logic (e.g., retry DNS failures but not TLS handshake failures), and clearer error messages." 85 + }, 86 + { 87 + "source_repo": "third_party/c++/webcc", 88 + "source_language": "C++", 89 + "criticality": "low", 90 + "change_type": "enhancement", 91 + "title": "Add configurable buffer size for response reading", 92 + "description": "Allow users to configure the buffer size used when reading responses from the network. Default could remain at a reasonable value (e.g., 8KB), but allow tuning for specific use cases like high-throughput downloads (larger buffers) or memory-constrained environments (smaller buffers).", 93 + "affected_files": [ 94 + "lib/requests.ml", 95 + "lib/requests.mli", 96 + "lib/one.ml", 97 + "lib/one.mli", 98 + "lib/http_client.ml" 99 + ], 100 + "rationale": "webcc allows configuring buffer_size via set_buffer_size (client_base.h:44-48), defaulting to kBufferSize. The buffer is resized if needed before each request (client_base.cc:104-107). The OCaml library appears to use fixed buffer sizes. Allowing buffer size configuration would enable performance tuning for different workloads: large buffers reduce syscalls for bulk transfers, small buffers reduce memory usage for many concurrent connections." 101 + }, 102 + { 103 + "source_repo": "third_party/c++/webcc", 104 + "source_language": "C++", 105 + "criticality": "medium", 106 + "change_type": "enhancement", 107 + "title": "Implement automatic retry with Retry-After header support", 108 + "description": "Enhance the retry mechanism to parse and respect the HTTP Retry-After header from 429 (Too Many Requests) and 503 (Service Unavailable) responses. When present, use the server-specified delay instead of exponential backoff.", 109 + "affected_files": [ 110 + "lib/retry.ml", 111 + "lib/requests.ml" 112 + ], 113 + "rationale": "The OCaml library has parse_retry_after function and respect_retry_after config flag in retry.ml (lines 73-93), but it's not clear if this is actually used during request execution. webcc doesn't implement retry logic at all (left to application), but the OCaml library has the infrastructure partially built. Ensure that when retrying requests that receive 429/503 responses, the Retry-After header is parsed and honored. This is critical for good internet citizenship and avoiding service bans." 114 + }, 115 + { 116 + "source_repo": "third_party/c++/webcc", 117 + "source_language": "C++", 118 + "criticality": "low", 119 + "change_type": "enhancement", 120 + "title": "Add payload iteration interface for efficient memory management", 121 + "description": "Implement an iterator-based interface for request/response bodies that allows processing data in chunks without loading everything into memory. This is especially important for streaming uploads and downloads of large files.", 122 + "affected_files": [ 123 + "lib/body.ml", 124 + "lib/body.mli" 125 + ], 126 + "rationale": "webcc implements a NextPayload iterator interface (body.h:45-57) that allows bodies to be sent/received in chunks, with an option to free previous chunks (free_previous=true). This enables efficient memory usage for large files. The OCaml library has streaming support via Eio flows, which is actually superior to webcc's approach. However, documenting this capability more prominently and ensuring all body types properly support streaming would improve clarity. The current implementation is good but could benefit from explicit documentation about memory efficiency guarantees." 127 + }, 128 + { 129 + "source_repo": "third_party/c++/webcc", 130 + "source_language": "C++", 131 + "criticality": "low", 132 + "change_type": "feature", 133 + "title": "Add automatic file body MIME type detection", 134 + "description": "Expand the MIME type guessing logic for file bodies to support more common file extensions. Currently only .json, .html, .xml, and .txt are detected. Add support for images (.jpg, .png, .gif, .svg), documents (.pdf, .doc), archives (.zip, .tar.gz), and other common types.", 135 + "affected_files": [ 136 + "lib/body.ml", 137 + "lib/mime.ml" 138 + ], 139 + "rationale": "The OCaml library has basic MIME type detection in body.ml:37-50, but it's very limited. webcc doesn't appear to do automatic MIME detection, leaving it to the application. However, having a more comprehensive MIME type database would improve developer ergonomics. Consider using a library like 'magic-mime' or a more complete MIME database. The TODO.md mentions 'Body MIME guessing seems like it could' (incomplete note), suggesting this is a known limitation." 140 + }, 141 + { 142 + "source_repo": "third_party/c++/webcc", 143 + "source_language": "C++", 144 + "criticality": "medium", 145 + "change_type": "enhancement", 146 + "title": "Add keep-alive connection state tracking and validation", 147 + "description": "Track whether connections are in a valid state for reuse after each request completes. Validate that responses have Connection: keep-alive header and that the response was fully read before returning the connection to the pool. Detect broken connections early to avoid errors on subsequent requests.", 148 + "affected_files": [ 149 + "lib/http_client.ml", 150 + "lib/requests.ml" 151 + ], 152 + "rationale": "webcc explicitly checks IsConnectionKeepAlive() after each response (client_base.cc:309-313) and only keeps the connection alive if the header is present. The OCaml library uses the Conpool library for connection pooling, which handles lifecycle management. However, ensuring that the HTTP client properly signals to Conpool when a connection should NOT be reused (e.g., if Connection: close header is present, or if an error occurred mid-response) would improve reliability and prevent 'connection reset by peer' errors." 153 + }, 154 + { 155 + "source_repo": "third_party/c++/webcc", 156 + "source_language": "C++", 157 + "criticality": "high", 158 + "change_type": "bug", 159 + "title": "Ensure proper connection cleanup on partial reads and errors", 160 + "description": "When a request fails mid-stream (timeout, connection error, parse error), ensure the connection is immediately closed and removed from the pool rather than being returned for reuse. Partial reads leave the connection in an undefined state that will cause subsequent requests to fail.", 161 + "affected_files": [ 162 + "lib/http_client.ml", 163 + "lib/requests.ml" 164 + ], 165 + "rationale": "webcc calls Close() on errors during parsing or reading (client_base.cc:276, 291), which shuts down and closes the socket, preventing connection reuse. The OCaml library should ensure that any error during request/response processing results in the connection being closed rather than returned to the pool. This is critical for correctness - reusing a connection that failed mid-response will cause the next request to read leftover data from the previous response." 166 + }, 167 + { 168 + "source_repo": "third_party/c++/webcc", 169 + "source_language": "C++", 170 + "criticality": "medium", 171 + "change_type": "security", 172 + "title": "Implement proper TLS context caching and reuse", 173 + "description": "Cache and reuse TLS contexts across connections to the same host, rather than creating a new context for each connection. This improves performance and allows proper session resumption. Ensure thread-safe access to the context cache.", 174 + "affected_files": [ 175 + "lib/requests.ml", 176 + "lib/one.ml" 177 + ], 178 + "rationale": "webcc uses SslContextManager as a thread-safe singleton that caches SSL contexts by key, with a default context for most connections. This enables TLS session resumption and reduces handshake overhead. The OCaml library creates TLS config in the session constructor (requests.ml:91-106) and passes it to the HTTPS pool, which should handle caching. Verify that tls-eio or the underlying TLS implementation properly caches and reuses contexts. If not, implement explicit context caching at the session level." 179 + }, 180 + { 181 + "source_repo": "third_party/c++/webcc", 182 + "source_language": "C++", 183 + "criticality": "low", 184 + "change_type": "enhancement", 185 + "title": "Add optional compression support for request bodies", 186 + "description": "Add the ability to compress request bodies (not just decompress responses) when sending large payloads. Allow opt-in compression with configurable threshold (e.g., only compress bodies larger than 1KB) and automatically set Content-Encoding header.", 187 + "affected_files": [ 188 + "lib/body.ml", 189 + "lib/body.mli", 190 + "lib/http_client.ml" 191 + ], 192 + "rationale": "webcc has optional GZIP compression support (WEBCC_ENABLE_GZIP) that can compress both requests and responses (body.h:29-43). The compression is skipped if data size <= 1400 bytes threshold. The OCaml library only supports decompression of responses, not compression of requests. Adding request compression would reduce bandwidth usage for large uploads, especially for JSON/text data. This should be opt-in with a size threshold to avoid overhead on small payloads." 193 + }, 194 + { 195 + "source_repo": "third_party/c++/webcc", 196 + "source_language": "C++", 197 + "criticality": "medium", 198 + "change_type": "refactor", 199 + "title": "Complete Digest authentication implementation", 200 + "description": "The Digest authentication mechanism appears incomplete according to TODO.md. Ensure full RFC 7616 compliance including proper handling of all qop modes, algorithm variations, and nonce management. Add comprehensive tests for Digest auth.", 201 + "affected_files": [ 202 + "lib/auth.ml", 203 + "lib/auth.mli", 204 + "test/httpbin.t" 205 + ], 206 + "rationale": "TODO.md states 'Auth.Digest seems incomplete'. While the OCaml library has Digest auth with MD5, SHA-256, and SHA-512 support (auth.ml), webcc doesn't implement Digest auth at all (only Basic and Token). However, the TODO note suggests the OCaml implementation may be missing edge cases or advanced features from RFC 7616. This should be verified against the spec and tested thoroughly, especially the qop=auth mode and nonce handling." 207 + }, 208 + { 209 + "source_repo": "third_party/c++/webcc", 210 + "source_language": "C++", 211 + "criticality": "low", 212 + "change_type": "enhancement", 213 + "title": "Add request/response dump functionality for debugging", 214 + "description": "Add optional logging or dump functions that output the full HTTP request (headers + body) and response (headers + body) in a human-readable format. This is invaluable for debugging protocol issues, authentication problems, and API integration.", 215 + "affected_files": [ 216 + "lib/requests.ml", 217 + "lib/response.ml", 218 + "lib/http_client.ml" 219 + ], 220 + "rationale": "webcc implements Dump() methods for logging requests and responses with configurable prefixes (client_base.cc:306, body.h:60). The OCaml library uses the Logs library extensively but doesn't appear to have structured dump functions. Adding pretty-printing functions for Request and Response types, along with log integration at VERBOSE/DEBUG level, would significantly improve debuggability. This is especially useful when troubleshooting why a request fails or returns unexpected data." 221 + }, 222 + { 223 + "source_repo": "third_party/c++/webcc", 224 + "source_language": "C++", 225 + "criticality": "low", 226 + "change_type": "feature", 227 + "title": "Add HEAD request optimization to skip body parsing", 228 + "description": "When making HEAD requests, optimize the response parser to skip body parsing entirely, even if Content-Length header is present. HEAD responses must not include a body, so attempting to read one wastes time and resources.", 229 + "affected_files": [ 230 + "lib/http_client.ml" 231 + ], 232 + "rationale": "webcc explicitly sets ignore_body flag for HEAD requests (client_base.cc:116-121) to skip body parsing, even if Content-Length is present. The OCaml library should similarly optimize HEAD requests by not attempting to read a response body. This avoids unnecessary waiting for data that will never arrive and prevents potential timeout errors when servers incorrectly send Content-Length on HEAD responses." 233 + }, 234 + { 235 + "source_repo": "third_party/c++/webcc", 236 + "source_language": "C++", 237 + "criticality": "low", 238 + "change_type": "enhancement", 239 + "title": "Add session statistics tracking", 240 + "description": "Track and expose session-level statistics including: total requests made, total bytes sent/received, total time spent, retry counts, connection pool hit rate, and error counts by type. This enables performance monitoring and debugging.", 241 + "affected_files": [ 242 + "lib/requests.ml", 243 + "lib/requests.mli" 244 + ], 245 + "rationale": "The OCaml library has basic statistics (requests_made, total_time, retries_count in requests.ml:51-57) but with a caveat that they're not shared when using record update syntax. webcc doesn't have built-in statistics. Expanding the statistics and making them properly shared (using a mutable record or ref) would provide valuable observability. Consider adding: bytes_sent, bytes_received, connection_errors, timeout_errors, pool_hits, pool_misses, etc. Make statistics accessible via a stats() function." 246 + } 247 + ] 248 + }
+201
third_party/go/req.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/go/req", 5 + "source_language": "Go", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add Request/Response Tracing for Performance Debugging", 9 + "description": "Implement detailed request/response timing traces similar to Go's TraceInfo structure. This would capture DNS lookup time, TCP connect time, TLS handshake time, first byte time, and total time. Include a 'Blame()' function that automatically identifies the slowest component (e.g., 'spent 2.5s on TLS handshake'). This is critical for debugging production performance issues.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/http_client.ml", 13 + "lib/requests.ml" 14 + ], 15 + "rationale": "The Go library's TraceInfo feature provides invaluable debugging information by tracking timing at each stage of the request lifecycle. OCaml library currently only tracks total elapsed time (Response.elapsed). Adding granular timing would help users identify whether slowness is due to DNS, network, TLS, or server response time. This is especially useful in production environments where connection pooling behavior needs analysis." 16 + }, 17 + { 18 + "source_repo": "third_party/go/req", 19 + "source_language": "Go", 20 + "criticality": "medium", 21 + "change_type": "feature", 22 + "title": "Add Error Hooks for Centralized Error Handling", 23 + "description": "Add support for error hooks/callbacks that execute when errors occur, similar to Go's ErrorHook. This allows users to implement centralized error logging, metrics collection, or error reporting (e.g., to Sentry) without wrapping every request in try-catch blocks. The hook should receive the request context, response (if available), and error.", 24 + "affected_files": [ 25 + "lib/requests.ml", 26 + "lib/error.ml" 27 + ], 28 + "rationale": "The Go library's OnError hook enables centralized error handling across all requests. Currently, OCaml users must wrap each request individually to handle errors uniformly. Adding error hooks would enable: (1) centralized error logging/monitoring, (2) automatic error reporting to APM systems, (3) custom retry logic based on error types, and (4) better separation of business logic from error handling infrastructure." 29 + }, 30 + { 31 + "source_repo": "third_party/go/req", 32 + "source_language": "Go", 33 + "criticality": "medium", 34 + "change_type": "feature", 35 + "title": "Add Upload/Download Progress Callbacks", 36 + "description": "Implement progress callbacks for upload and download operations. Callbacks should receive current bytes transferred, total bytes (if known), and transfer rate. This enables progress bars, upload/download monitoring, and user feedback during long transfers. Include configurable callback intervals to avoid excessive invocations.", 37 + "affected_files": [ 38 + "lib/requests.ml", 39 + "lib/body.ml", 40 + "lib/response.ml" 41 + ], 42 + "rationale": "The Go library provides UploadCallback and DownloadCallback with configurable intervals for monitoring transfer progress. The OCaml library currently offers no visibility into ongoing transfers. This feature is important for: (1) CLI tools that need progress bars (like the ocurl binary), (2) applications uploading/downloading large files, (3) detecting stalled transfers, and (4) providing user feedback. Can be implemented using Eio's streaming primitives with periodic progress reports." 43 + }, 44 + { 45 + "source_repo": "third_party/go/req", 46 + "source_language": "Go", 47 + "criticality": "medium", 48 + "change_type": "enhancement", 49 + "title": "Add Support for Automatic Error Result Unmarshalling", 50 + "description": "Add ability to specify a common error response type that automatically unmarshals error responses (4xx/5xx) into a structured error object. Similar to Go's SetCommonErrorResult, this would allow users to define API-specific error formats once and have them automatically parsed on error responses, with the error object attached to the HTTPError exception.", 51 + "affected_files": [ 52 + "lib/error.ml", 53 + "lib/response.ml", 54 + "lib/requests.ml" 55 + ], 56 + "rationale": "Many REST APIs return structured error responses (JSON with error codes, messages, details). The Go library's SetCommonErrorResult automatically unmarshals these into typed error objects. Currently, OCaml users must manually read response.body and parse errors. This feature would: (1) reduce boilerplate for API error handling, (2) provide type-safe access to API error details, (3) enable better error messages with API-specific error codes, and (4) simplify debugging by automatically capturing error response details." 57 + }, 58 + { 59 + "source_repo": "third_party/go/req", 60 + "source_language": "Go", 61 + "criticality": "medium", 62 + "change_type": "feature", 63 + "title": "Add Middleware/Hook System for Request/Response Processing", 64 + "description": "Implement a middleware system with before-request and after-response hooks. Before-request middleware can modify requests (add headers, logging, metrics). After-response middleware can process responses (logging, metrics, custom error handling). Both should support per-request and session-level registration, with execution order guarantees.", 65 + "affected_files": [ 66 + "lib/requests.ml", 67 + "lib/response.ml" 68 + ], 69 + "rationale": "The Go library's RequestMiddleware and ResponseMiddleware provide extensibility points for cross-cutting concerns. The OCaml library currently has no middleware system - all behavior is built-in. Adding middleware would enable: (1) custom request/response logging, (2) metrics collection (e.g., Prometheus), (3) request signing/authentication schemes not built-in, (4) response caching layers, (5) custom retry policies, and (6) easier testing via middleware injection. This is a fundamental architectural pattern for HTTP clients." 70 + }, 71 + { 72 + "source_repo": "third_party/go/req", 73 + "source_language": "Go", 74 + "criticality": "low", 75 + "change_type": "enhancement", 76 + "title": "Add Retry-After Header Support with HTTP Date Parsing", 77 + "description": "The retry logic already has parse_retry_after in retry.ml that attempts to parse Retry-After headers (both integer seconds and HTTP dates using Ptime.of_rfc3339). However, this parsed value is never actually used in the retry delay calculation. Modify with_retry or the retry implementation to honor the Retry-After header when present, using it instead of the exponential backoff delay when respect_retry_after is true.", 78 + "affected_files": [ 79 + "lib/retry.ml", 80 + "lib/requests.ml" 81 + ], 82 + "rationale": "The Go library respects Retry-After headers from 429 (rate limit) and 503 (service unavailable) responses. The OCaml library has parse_retry_after but doesn't use it - all retries use exponential backoff regardless of server hints. Supporting Retry-After would: (1) respect rate limits properly, (2) reduce unnecessary retry attempts when servers indicate exact retry times, (3) improve API client citizenship, and (4) avoid thundering herd problems when servers coordinate client retries." 83 + }, 84 + { 85 + "source_repo": "third_party/go/req", 86 + "source_language": "Go", 87 + "criticality": "low", 88 + "change_type": "enhancement", 89 + "title": "Add Path Parameters Support for URL Templating", 90 + "description": "Add support for path parameters that allow URL templating (e.g., '/users/{id}/posts/{postId}' with params {id: '123', postId: '456'} -> '/users/123/posts/456'). The Go library's PathParams provides this as a more ergonomic alternative to string concatenation or manual URL construction for RESTful APIs.", 91 + "affected_files": [ 92 + "lib/requests.ml" 93 + ], 94 + "rationale": "The Go library's PathParams feature enables cleaner RESTful API interactions. Currently, OCaml users must manually construct URLs with string concatenation or Uri building. Path parameters would: (1) reduce URL construction boilerplate, (2) provide type-safe parameter substitution, (3) improve code readability for RESTful clients, and (4) prevent common URL construction bugs (missing slashes, double slashes, improper encoding). This is a quality-of-life improvement for API consumers." 95 + }, 96 + { 97 + "source_repo": "third_party/go/req", 98 + "source_language": "Go", 99 + "criticality": "low", 100 + "change_type": "enhancement", 101 + "title": "Add Ordered Form Data Support", 102 + "description": "Add support for ordered form data submission where the order of form fields matters (some legacy APIs validate field order). The Go library maintains OrderedFormData alongside FormData to preserve insertion order when needed. This could be implemented with a new Body.form_ordered constructor that preserves field order.", 103 + "affected_files": [ 104 + "lib/body.ml" 105 + ], 106 + "rationale": "While most modern APIs don't care about form field order, some legacy systems or signature-based APIs require specific field ordering. The Go library's OrderedFormData addresses this edge case. Currently, OCaml's Body.form uses a list which preserves order, but this should be documented and potentially enhanced with an explicit ordering guarantee. This is a low-priority enhancement for edge cases with legacy systems." 107 + }, 108 + { 109 + "source_repo": "third_party/go/req", 110 + "source_language": "Go", 111 + "criticality": "medium", 112 + "change_type": "enhancement", 113 + "title": "Add Response Body Streaming with Auto-decompression", 114 + "description": "Currently auto_decompress only works on buffered response bodies. Enhance the streaming body support to decompress on-the-fly for large responses, allowing users to stream decompressed content without buffering the entire response. This requires wrapping the Eio.Flow with a decompression layer that transparently handles gzip/deflate.", 115 + "affected_files": [ 116 + "lib/http_client.ml", 117 + "lib/response.ml" 118 + ], 119 + "rationale": "The Go library automatically decompresses response bodies while streaming. The OCaml library buffers the entire response before decompression (see http_client.ml decompress_gzip which operates on full strings). For large responses (multi-GB downloads), this causes unnecessary memory usage. Streaming decompression would: (1) reduce memory footprint for large compressed downloads, (2) enable processing responses as they arrive, (3) improve performance for large file downloads, and (4) better align with Eio's streaming philosophy." 120 + }, 121 + { 122 + "source_repo": "third_party/go/req", 123 + "source_language": "Go", 124 + "criticality": "medium", 125 + "change_type": "feature", 126 + "title": "Add Response Result State Classification", 127 + "description": "Add a result state classification system that categorizes responses as Success (2xx), Error (4xx/5xx), or Unknown (1xx/3xx). Allow users to define custom result state checkers. This would enable different handling paths for successful vs error responses beyond simple status code checks, and automatic unmarshaling of success vs error response bodies into different types.", 128 + "affected_files": [ 129 + "lib/response.ml", 130 + "lib/status.ml", 131 + "lib/requests.ml" 132 + ], 133 + "rationale": "The Go library's ResultState (SuccessState, ErrorState, UnknownState) provides semantic categorization beyond raw status codes. The OCaml library has Status.is_success/is_client_error/is_server_error but no unified result state concept. Adding this would: (1) enable automatic success/error response unmarshaling into different types, (2) simplify API client code that treats successes and errors differently, (3) provide clearer semantics than status code checks, and (4) allow custom result state logic for non-standard APIs." 134 + }, 135 + { 136 + "source_repo": "third_party/go/req", 137 + "source_language": "Go", 138 + "criticality": "low", 139 + "change_type": "enhancement", 140 + "title": "Add Request Retry Attempt Counter to Response", 141 + "description": "Add a field to Response that indicates how many retry attempts were made before the request succeeded (or failed). This helps with debugging, monitoring, and understanding retry behavior. The Go library's Request.RetryAttempt tracks this. Expose it as Response.retry_count.", 142 + "affected_files": [ 143 + "lib/response.ml", 144 + "lib/requests.ml" 145 + ], 146 + "rationale": "The Go library exposes retry attempt counts in Request.RetryAttempt. The OCaml library increments t.retries_count at the session level but doesn't expose per-request retry counts. Adding this would: (1) help diagnose flaky endpoints, (2) enable retry-count-based metrics/alerts, (3) provide visibility into retry behavior, and (4) help tune retry configurations. This is a simple addition with high observability value." 147 + }, 148 + { 149 + "source_repo": "third_party/go/req", 150 + "source_language": "Go", 151 + "criticality": "high", 152 + "change_type": "bug", 153 + "title": "Fix Missing Retry-After Header Usage in Retry Logic", 154 + "description": "The parse_retry_after function exists in retry.ml but is never invoked. The retry logic in requests.ml (lines 526-559) only uses calculate_backoff for delays and ignores Retry-After headers. Integrate parse_retry_after into the retry flow: after receiving a retryable response, check for Retry-After header, parse it, and use that delay instead of backoff when respect_retry_after is true and the header is present.", 155 + "affected_files": [ 156 + "lib/requests.ml", 157 + "lib/retry.ml" 158 + ], 159 + "rationale": "This is a bug - the code has parse_retry_after (line 73-93 in retry.ml) but never uses it. The respect_retry_after config field (default: true) has no effect. The Go library properly honors Retry-After headers. Not respecting Retry-After: (1) can violate rate limiting agreements, (2) leads to excessive retry attempts when servers indicate specific delays, (3) increases server load unnecessarily, and (4) can trigger more aggressive rate limiting. This is marked high criticality as it affects proper API client behavior." 160 + }, 161 + { 162 + "source_repo": "third_party/go/req", 163 + "source_language": "Go", 164 + "criticality": "medium", 165 + "change_type": "enhancement", 166 + "title": "Add Support for Custom JSON/XML Marshalers", 167 + "description": "Allow users to provide custom JSON marshaling/unmarshaling functions at the session level, similar to Go's SetJsonMarshal/SetJsonUnmarshal. This enables using different JSON libraries (yojson, ocaml-json, etc.) or custom serialization logic. Currently the library is hardcoded to use jsont/jsont_bytesrw.", 168 + "affected_files": [ 169 + "lib/requests.ml", 170 + "lib/body.ml", 171 + "lib/response.ml" 172 + ], 173 + "rationale": "The Go library allows pluggable JSON/XML marshalers via SetJsonMarshal/SetJsonUnmarshal. The OCaml library is hardcoded to jsont (see response.ml line 76-79 and body.ml for JSON handling). Supporting custom marshalers would: (1) enable integration with existing codebases using different JSON libraries, (2) allow custom serialization logic (dates, enums, custom types), (3) support alternative formats (msgpack, protobuf with custom handlers), and (4) provide flexibility for performance optimization with specific JSON libraries." 174 + }, 175 + { 176 + "source_repo": "third_party/go/req", 177 + "source_language": "Go", 178 + "criticality": "low", 179 + "change_type": "enhancement", 180 + "title": "Add Debug Mode with Request/Response Dumping", 181 + "description": "Add a debug mode (similar to Go's EnableDumpAll) that automatically logs full request/response details including headers and bodies. This should be configurable globally or per-request, with options to control dump output (stdout, logger, custom writer). Include options to redact sensitive headers (Authorization, Cookie).", 182 + "affected_files": [ 183 + "lib/requests.ml", 184 + "lib/http_client.ml" 185 + ], 186 + "rationale": "The Go library's EnableDumpAll/DebugLog provides comprehensive request/response logging for debugging. The OCaml library has extensive logging but no single \"debug mode\" toggle. Currently it logs at Info level (requests.ml lines 342-350, 372-378) but requires manual log level configuration. Adding debug mode would: (1) simplify troubleshooting during development, (2) provide curl-like output for request debugging, (3) help diagnose API integration issues, and (4) enable easier support for users with API problems." 187 + }, 188 + { 189 + "source_repo": "third_party/go/req", 190 + "source_language": "Go", 191 + "criticality": "low", 192 + "change_type": "feature", 193 + "title": "Add Support for BaseURL Configuration", 194 + "description": "Add a base URL configuration at the session level (similar to Go's BaseURL field) that is prepended to all relative request URLs. This simplifies API clients by defining the base URL once (e.g., 'https://api.github.com') and using relative paths for individual requests (e.g., '/users/repos').", 195 + "affected_files": [ 196 + "lib/requests.ml" 197 + ], 198 + "rationale": "The Go library's BaseURL field allows defining the API base URL once at client creation. The OCaml library requires full URLs for every request. Adding BaseURL would: (1) reduce duplication in API clients (define 'https://api.example.com' once), (2) simplify environment-based configuration (dev/staging/prod base URLs), (3) make request URLs more readable (relative paths vs full URLs), and (4) align with common HTTP client patterns. This is especially useful for API SDK builders." 199 + } 200 + ] 201 + }
+235
third_party/go/requests.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/go/requests", 5 + "source_language": "Go", 6 + "criticality": "medium", 7 + "change_type": "feature", 8 + "title": "Add Response.SaveFile convenience method", 9 + "description": "The Go library provides a convenient SaveFile method on Response objects that automatically reads the response body and writes it to a file. The OCaml library requires users to manually read the body and write to a file.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/response.mli" 13 + ], 14 + "rationale": "The Go library's `resp.SaveFile(filename)` method (lines 307-321 in requests.go) provides a simple API for downloading files. This is a common use case that would benefit from a convenience method. Implementation would read the body using `text t` and use Eio.Path operations to write to a file. This reduces boilerplate for users who want to download files." 15 + }, 16 + { 17 + "source_repo": "third_party/go/requests", 18 + "source_language": "Go", 19 + "criticality": "medium", 20 + "change_type": "feature", 21 + "title": "Add proxy support", 22 + "description": "The Go library supports HTTP proxies through the Proxy() method. The OCaml library has proxy support noted in TODO but not implemented.", 23 + "affected_files": [ 24 + "lib/requests.ml", 25 + "lib/requests.mli", 26 + "lib/one.ml" 27 + ], 28 + "rationale": "Go library has proxy support via Proxy(proxyurl) (lines 240-253). While it has a security issue (InsecureSkipVerify=true), the proxy functionality itself is valuable for testing, corporate environments, and debugging. OCaml implementation should support proxy configuration with proper TLS verification, unlike the Go version. This would involve adding proxy parameters to connection pool configuration." 29 + }, 30 + { 31 + "source_repo": "third_party/go/requests", 32 + "source_language": "Go", 33 + "criticality": "low", 34 + "change_type": "enhancement", 35 + "title": "Add debug mode for request/response logging", 36 + "description": "The Go library has a Debug field that when set to 1 dumps full request and response details including headers and cookies. The OCaml library uses structured logging but doesn't have an equivalent simple debug toggle.", 37 + "affected_files": [ 38 + "lib/requests.ml", 39 + "lib/cmd.ml" 40 + ], 41 + "rationale": "Go library's Debug field (lines 186-206, 256-271) provides easy request/response inspection during development. While OCaml library has sophisticated Logs integration, a simple debug flag that auto-enables verbose logging for all HTTP operations would improve developer experience. Could be implemented as a session parameter that sets log levels automatically." 42 + }, 43 + { 44 + "source_repo": "third_party/go/requests", 45 + "source_language": "Go", 46 + "criticality": "medium", 47 + "change_type": "enhancement", 48 + "title": "Implement Response.Retry-After header parsing", 49 + "description": "The OCaml retry module has parse_retry_after function (lines 73-93 in retry.ml) but it's not integrated into the retry logic. The respect_retry_after config option exists but isn't used.", 50 + "affected_files": [ 51 + "lib/retry.ml", 52 + "lib/requests.ml" 53 + ], 54 + "rationale": "While the Go library doesn't have built-in retry support, the OCaml library has a parse_retry_after function that's defined but never called. The retry config has respect_retry_after=true by default (line 25), but this functionality isn't implemented in the actual retry logic (lines 95-123). Implementing this would properly honor server-sent Retry-After headers during retries, preventing thundering herd problems." 55 + }, 56 + { 57 + "source_repo": "third_party/go/requests", 58 + "source_language": "Go", 59 + "criticality": "low", 60 + "change_type": "enhancement", 61 + "title": "Add response body caching for multiple reads", 62 + "description": "The Go library caches the response body after first read (line 277-279 in requests.go), allowing multiple calls to Content() or Text() without re-reading. The OCaml library consumes the body stream on first read.", 63 + "affected_files": [ 64 + "lib/response.ml" 65 + ], 66 + "rationale": "Go's Response.Content() checks if content is already cached before reading (line 277: if len(resp.content) > 0). This allows calling Text() or Json() multiple times on the same response. OCaml's streaming approach is more memory-efficient, but for common use cases where responses are small, offering a cached response option or a to_string method that can be called multiple times would improve ergonomics." 67 + }, 68 + { 69 + "source_repo": "third_party/go/requests", 70 + "source_language": "Go", 71 + "criticality": "medium", 72 + "change_type": "feature", 73 + "title": "Add SetCookie method for manual cookie injection", 74 + "description": "The Go library allows manually setting cookies before requests via SetCookie (lines 211-213). The OCaml library only supports automatic cookie management from responses.", 75 + "affected_files": [ 76 + "lib/requests.ml", 77 + "lib/requests.mli" 78 + ], 79 + "rationale": "Go's SetCookie method (lines 211-217) allows programmatic cookie injection for testing or special scenarios. OCaml library only extracts cookies from Set-Cookie headers (lines 270-283 in requests.ml). Adding a method to manually add cookies to the jar would enable testing scenarios and integration with external authentication systems. Implementation would use Cookeio_jar.add_cookie." 80 + }, 81 + { 82 + "source_repo": "third_party/go/requests", 83 + "source_language": "Go", 84 + "criticality": "low", 85 + "change_type": "enhancement", 86 + "title": "Expand MIME type guessing for file bodies", 87 + "description": "The OCaml library's MIME type guessing for files is limited to 4 extensions (.json, .html, .xml, .txt) as noted in TODO. More comprehensive MIME detection would improve file upload functionality.", 88 + "affected_files": [ 89 + "lib/body.ml", 90 + "lib/mime.ml" 91 + ], 92 + "rationale": "Body.of_file has minimal MIME guessing (lines 36-50 in body.ml) with only 4 types, falling back to application/octet-stream. TODO.md line 2 notes this should be expanded. Adding common file types (images, documents, audio, video) would improve multipart form uploads. Could use a small embedded MIME database or integrate with system mime.types." 93 + }, 94 + { 95 + "source_repo": "third_party/go/requests", 96 + "source_language": "Go", 97 + "criticality": "high", 98 + "change_type": "bug", 99 + "title": "Improve error messages for file operations in multipart uploads", 100 + "description": "The Go library panics on file operations during multipart upload (lines 539, 544), which can crash applications. While OCaml doesn't have this specific issue, multipart file operations should have clear error handling.", 101 + "affected_files": [ 102 + "lib/body.ml" 103 + ], 104 + "rationale": "Go's openFile function panics on errors (line 579), and buildFilesAndForms panics on upload failures (lines 539, 544). This is poor error handling that crashes the entire application. OCaml's multipart implementation (lines 222-270 in body.ml) uses Eio.Path.open_in which can raise exceptions. These should be caught and converted to meaningful error messages indicating which file failed and why, rather than propagating raw exceptions." 105 + }, 106 + { 107 + "source_repo": "third_party/go/requests", 108 + "source_language": "Go", 109 + "criticality": "medium", 110 + "change_type": "feature", 111 + "title": "Add Close() method to explicitly close connections", 112 + "description": "The Go library has a Close() method (lines 236-238) to explicitly set Connection: close for one-off requests. The OCaml library relies on connection pool lifecycle management.", 113 + "affected_files": [ 114 + "lib/requests.ml", 115 + "lib/one.ml" 116 + ], 117 + "rationale": "Go's Close() sets httpreq.Close = true to force connection closure (line 237). This is useful for ensuring connections don't linger in the pool for long-running processes making occasional requests. While OCaml's connection pool has idle timeouts, adding an explicit close option or a one-shot request mode that doesn't use pooling would give users more control over connection lifecycle." 118 + }, 119 + { 120 + "source_repo": "third_party/go/requests", 121 + "source_language": "Go", 122 + "criticality": "low", 123 + "change_type": "enhancement", 124 + "title": "Add version string constant", 125 + "description": "The Go library exposes a VERSION constant (line 35) for library identification. This is useful for debugging and User-Agent headers.", 126 + "affected_files": [ 127 + "lib/requests.ml", 128 + "lib/requests.mli" 129 + ], 130 + "rationale": "Go library defines VERSION = '0.8' (line 35) and includes it in default User-Agent (line 72). Having a version constant is useful for debugging, logging, and automated tools. OCaml library should expose a version string, likely extracted from dune-project or defined as a constant, and optionally use it in default User-Agent header if not explicitly set." 131 + }, 132 + { 133 + "source_repo": "third_party/go/requests", 134 + "source_language": "Go", 135 + "criticality": "medium", 136 + "change_type": "enhancement", 137 + "title": "Add statistics tracking for connection pool efficiency", 138 + "description": "The OCaml library tracks basic statistics (requests_made, total_time, retries_count) but doesn't expose connection pool statistics like reuse rate or wait times.", 139 + "affected_files": [ 140 + "lib/requests.ml", 141 + "lib/requests.mli" 142 + ], 143 + "rationale": "While the Go library doesn't have this feature, the OCaml library's connection pooling approach would benefit from exposing statistics about pool efficiency. The library tracks requests_made (line 55) but not connection reuses, pool hits/misses, or average wait time. Adding methods to query pool statistics from Conpool would help users understand performance characteristics and tune pool parameters." 144 + }, 145 + { 146 + "source_repo": "third_party/go/requests", 147 + "source_language": "Go", 148 + "criticality": "medium", 149 + "change_type": "feature", 150 + "title": "Support variadic params in GET requests", 151 + "description": "The Go library allows passing multiple Params maps that get merged (lines 117-118). The OCaml library only accepts a single params list.", 152 + "affected_files": [ 153 + "lib/requests.ml" 154 + ], 155 + "rationale": "Go's Get method accepts multiple Params arguments using variadic parameters and merges them (lines 101-123). This allows composing query parameters from different sources. OCaml's get method (lines 562-570) accepts a single params list. Supporting multiple param lists or a more compositional approach to building query strings would improve flexibility, especially when combining default params with request-specific ones." 156 + }, 157 + { 158 + "source_repo": "third_party/go/requests", 159 + "source_language": "Go", 160 + "criticality": "low", 161 + "change_type": "enhancement", 162 + "title": "Improve error context in timeout scenarios", 163 + "description": "The OCaml library raises Error.Timeout with no context about which operation timed out or the configured timeout value. More context would aid debugging.", 164 + "affected_files": [ 165 + "lib/error.ml", 166 + "lib/requests.ml" 167 + ], 168 + "rationale": "When Eio.Time.with_timeout_exn raises (line 368 in requests.ml), it's caught by retry logic but the timeout exception (error.ml line 13) carries no context. Adding the URL, timeout value, and operation stage (connect vs read vs total) to the timeout error would significantly aid debugging. Go library sets timeouts on the entire client (line 232) making it clear what the limit was." 169 + }, 170 + { 171 + "source_repo": "third_party/go/requests", 172 + "source_language": "Go", 173 + "criticality": "high", 174 + "change_type": "security", 175 + "title": "Document security implications of verify_tls=false", 176 + "description": "The Go library disables TLS verification for proxies (line 250: InsecureSkipVerify=true) which is a security risk. The OCaml library has verify_tls parameter but should clearly document the security implications.", 177 + "affected_files": [ 178 + "lib/requests.mli", 179 + "README.md" 180 + ], 181 + "rationale": "Go's Proxy method sets TLSClientConfig with InsecureSkipVerify=true (line 250), disabling certificate validation. This is a critical security vulnerability that enables MITM attacks. While OCaml's verify_tls parameter exists (line 44), the documentation should prominently warn users that disabling it is insecure and should only be used in controlled testing environments. Add warnings in interface documentation and README." 182 + }, 183 + { 184 + "source_repo": "third_party/go/requests", 185 + "source_language": "Go", 186 + "criticality": "medium", 187 + "change_type": "enhancement", 188 + "title": "Add content-encoding validation before decompression", 189 + "description": "The Go library checks Accept-Encoding before decompressing gzip (line 282). The OCaml library always decompresses if Content-Encoding is present when auto_decompress is enabled.", 190 + "affected_files": [ 191 + "lib/http_client.ml" 192 + ], 193 + "rationale": "Go checks 'resp.req.Header.Get(\"Accept-Encoding\") != \"\"' before decompressing (line 282), ensuring client requested compression. OCaml's decompress_body (lines 97-117 in http_client.ml) decompresses based solely on Content-Encoding header when auto_decompress=true. Adding validation that Accept-Encoding was sent prevents issues if a server incorrectly sends compressed content when not requested. This is a defense-in-depth measure." 194 + }, 195 + { 196 + "source_repo": "third_party/go/requests", 197 + "source_language": "Go", 198 + "criticality": "low", 199 + "change_type": "enhancement", 200 + "title": "Add convenience method for cookies extraction from response", 201 + "description": "The Go library has a Cookies() method on Response (lines 330-337) to extract cookies from the jar for that URL. The OCaml library requires direct interaction with the cookie jar.", 202 + "affected_files": [ 203 + "lib/response.ml", 204 + "lib/response.mli" 205 + ], 206 + "rationale": "Go's resp.Cookies() method (lines 330-337) provides convenient access to cookies set by the response without directly accessing the cookie jar. OCaml requires users to access the cookie jar directly via the session (line 189). Adding Response.cookies() method that queries the jar for cookies matching the response URL would improve API ergonomics and encapsulation." 207 + }, 208 + { 209 + "source_repo": "third_party/go/requests", 210 + "source_language": "Go", 211 + "criticality": "low", 212 + "change_type": "enhancement", 213 + "title": "Add HTTP method constants or helpers", 214 + "description": "While the OCaml library has a Method module with types, it could benefit from more comprehensive method validation or helpers for custom methods.", 215 + "affected_files": [ 216 + "lib/method.ml", 217 + "lib/method.mli" 218 + ], 219 + "rationale": "The Method module provides standard HTTP methods as polymorphic variants but limited helpers for custom methods. Adding validation for method names (checking they contain only valid characters per RFC 7230) and helper functions for checking method safety/idempotency would improve robustness. This helps prevent issues with malformed custom methods." 220 + }, 221 + { 222 + "source_repo": "third_party/go/requests", 223 + "source_language": "Go", 224 + "criticality": "medium", 225 + "change_type": "enhancement", 226 + "title": "Implement form data builder with better type safety", 227 + "description": "The Go library has separate Datas and Files types for form data. The OCaml library uses generic string lists which is less type-safe for multipart forms.", 228 + "affected_files": [ 229 + "lib/body.ml", 230 + "lib/body.mli" 231 + ], 232 + "rationale": "Go separates Datas (string key-values) and Files (name to filepath mapping) as distinct types (lines 54-55). This provides clarity about what goes in each. OCaml's form function (lines 106-113) takes a list of string pairs, and multipart takes parts with explicit types, which is good. However, adding builder pattern or combinators for constructing multipart forms (adding text fields vs file fields) would improve type safety and reduce errors in form construction." 233 + } 234 + ] 235 + }
+193
third_party/go/resty.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/go/resty", 5 + "source_language": "Go", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add response body size limits to prevent memory exhaustion", 9 + "description": "Resty implements configurable response body size limits (ResponseBodyLimit) to prevent reading unbounded data into memory. The OCaml library currently reads entire response bodies without limits, which could lead to memory exhaustion attacks or unintentional resource exhaustion when downloading large files.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/http_client.ml" 13 + ], 14 + "rationale": "Without response body limits, malicious or misconfigured servers can cause the client to consume excessive memory. Resty provides both client-level and request-level configuration (SetResponseBodyLimit) with proper error handling (ErrResponseBodyTooLarge). This is a critical security feature for production systems." 15 + }, 16 + { 17 + "source_repo": "third_party/go/resty", 18 + "source_language": "Go", 19 + "criticality": "high", 20 + "change_type": "security", 21 + "title": "Add proper Retry-After header parsing for rate limiting compliance", 22 + "description": "Resty implements RFC 7231-compliant Retry-After header parsing, supporting both HTTP-date and delay-seconds formats. The OCaml library has stub code for parsing Retry-After (lines 73-93 in retry.ml) but doesn't use it in the retry logic. This can lead to violating server rate limits and getting blocked.", 23 + "affected_files": [ 24 + "lib/retry.ml", 25 + "lib/requests.ml" 26 + ], 27 + "rationale": "Respecting Retry-After headers is essential for being a good HTTP client citizen. Servers use this header to communicate rate limits and maintenance windows. Ignoring it can lead to request storms that harm both client and server, and may result in IP blocking or service degradation. Resty's implementation properly handles edge cases like negative delays and date parsing." 28 + }, 29 + { 30 + "source_repo": "third_party/go/resty", 31 + "source_language": "Go", 32 + "criticality": "medium", 33 + "change_type": "feature", 34 + "title": "Implement circuit breaker pattern for resilient error handling", 35 + "description": "Resty provides a CircuitBreaker feature that prevents cascading failures by temporarily stopping requests to failing services. It implements a state machine (Closed/Open/Half-Open) with configurable thresholds and timeout-based recovery. The OCaml library lacks this resilience pattern.", 36 + "affected_files": [ 37 + "lib/requests.ml", 38 + "lib/error.ml" 39 + ], 40 + "rationale": "Circuit breakers are a critical resilience pattern for distributed systems. They prevent resource exhaustion when downstream services fail by 'failing fast' instead of overwhelming failing services with retry attempts. Resty's implementation includes configurable policies (CircuitBreaker5xxPolicy), success/failure thresholds, and automatic recovery after timeout periods. This significantly improves system stability under partial failures." 41 + }, 42 + { 43 + "source_repo": "third_party/go/resty", 44 + "source_language": "Go", 45 + "criticality": "medium", 46 + "change_type": "feature", 47 + "title": "Add middleware/hook system for request/response interception", 48 + "description": "Resty implements a comprehensive middleware system with RequestMiddleware, ResponseMiddleware, and various hooks (OnError, OnSuccess, OnInvalid, OnPanic). This allows users to add custom logging, metrics, authentication, and error handling. The OCaml library lacks a systematic extension mechanism.", 49 + "affected_files": [ 50 + "lib/requests.ml", 51 + "lib/http_client.ml" 52 + ], 53 + "rationale": "A middleware/hook system is essential for production use cases like distributed tracing, metrics collection, custom authentication flows, and request/response transformation. Resty's design allows both client-level and request-level middleware with proper execution ordering. The OnPanic hook is particularly valuable for recovering from unexpected errors. This architectural pattern enables users to extend functionality without modifying library code." 54 + }, 55 + { 56 + "source_repo": "third_party/go/resty", 57 + "source_language": "Go", 58 + "criticality": "medium", 59 + "change_type": "enhancement", 60 + "title": "Enhance Digest authentication to support auth-int QoP and session algorithms", 61 + "description": "Resty's Digest authentication implementation supports multiple hash algorithms (MD5, SHA-256, SHA-512, SHA-512-256), session algorithms, auth-int QoP (quality of protection with body integrity), and userhash. The OCaml implementation (auth.ml) only supports basic MD5 with auth QoP.", 62 + "affected_files": [ 63 + "lib/auth.ml" 64 + ], 65 + "rationale": "Modern servers increasingly require stronger digest authentication. SHA-256 and SHA-512 provide better security than MD5. The auth-int QoP provides request body integrity protection. Session algorithms improve security for long-lived connections. Supporting these features ensures compatibility with security-conscious servers and follows RFC 7616 recommendations." 66 + }, 67 + { 68 + "source_repo": "third_party/go/resty", 69 + "source_language": "Go", 70 + "criticality": "medium", 71 + "change_type": "enhancement", 72 + "title": "Add request/response tracing with detailed timing breakdowns", 73 + "description": "Resty provides detailed HTTP request tracing via httptrace.ClientTrace, capturing DNS lookup time, TCP connection time, TLS handshake time, server processing time, and response time separately. The OCaml library only tracks total elapsed time (line 432-433 in requests.ml).", 74 + "affected_files": [ 75 + "lib/requests.ml", 76 + "lib/response.ml" 77 + ], 78 + "rationale": "Detailed timing breakdowns are essential for performance debugging and monitoring. They help identify bottlenecks (DNS, connection establishment, TLS handshake, or server processing). Resty's TraceInfo includes connection reuse status, idle time, and remote address information. This diagnostic capability is valuable for production troubleshooting and performance optimization." 79 + }, 80 + { 81 + "source_repo": "third_party/go/resty", 82 + "source_language": "Go", 83 + "criticality": "medium", 84 + "change_type": "enhancement", 85 + "title": "Implement flexible redirect policy system beyond same-origin checks", 86 + "description": "Resty provides a RedirectPolicy system with multiple built-in policies (FlexibleRedirectPolicy with max count, DomainCheckRedirectPolicy for allowed domains) and support for custom policies. The OCaml library only implements same-origin redirect security (lines 198-208 in requests.ml) without policy configurability.", 87 + "affected_files": [ 88 + "lib/requests.ml" 89 + ], 90 + "rationale": "Different applications need different redirect behaviors. Some need to follow redirects only within specific domains, others need to limit redirect counts differently, and some need custom logic. Resty's policy-based design allows composing multiple policies (e.g., max redirects + domain restrictions). This provides security and flexibility for diverse use cases like crawlers, API clients, and webhooks." 91 + }, 92 + { 93 + "source_repo": "third_party/go/resty", 94 + "source_language": "Go", 95 + "criticality": "medium", 96 + "change_type": "enhancement", 97 + "title": "Add support for request/response body unlimited reads via buffering", 98 + "description": "Resty provides SetResponseBodyUnlimitedReads to buffer response bodies in memory for multiple reads, useful for debugging and retry scenarios. It uses a copyReadCloser wrapper to transparently buffer content. The OCaml library consumes response bodies once.", 99 + "affected_files": [ 100 + "lib/response.ml", 101 + "lib/body.ml" 102 + ], 103 + "rationale": "Multiple response body reads are needed for retry with body inspection, detailed logging with full bodies, and debugging scenarios. Resty's implementation is opt-in to avoid unnecessary memory usage and works seamlessly with other features. The automatic body buffering in debug mode is particularly useful. This improves debuggability without sacrificing performance for normal operations." 104 + }, 105 + { 106 + "source_repo": "third_party/go/resty", 107 + "source_language": "Go", 108 + "criticality": "medium", 109 + "change_type": "feature", 110 + "title": "Implement weighted round-robin load balancing with health tracking", 111 + "description": "Resty provides sophisticated load balancing with WeightedRoundRobin that tracks host health, weights, failure counts, and automatic recovery. Hosts are temporarily removed after MaxFailures and automatically re-added after recovery duration. The OCaml library only uses connection pooling without load balancing.", 112 + "affected_files": [ 113 + "lib/requests.ml" 114 + ], 115 + "rationale": "Load balancing across multiple backend servers improves availability and performance. Weighted round-robin allows prioritizing certain hosts. Health tracking prevents sending requests to failing hosts. Automatic recovery enables graceful handling of transient failures. Resty's HostStateChangeFunc callback allows monitoring state transitions. This is essential for high-availability applications." 116 + }, 117 + { 118 + "source_repo": "third_party/go/resty", 119 + "source_language": "Go", 120 + "criticality": "low", 121 + "change_type": "enhancement", 122 + "title": "Add custom Content-Type encoder/decoder registration", 123 + "description": "Resty allows registering custom ContentTypeEncoder and ContentTypeDecoder functions for automatic body marshaling/unmarshaling based on Content-Type headers. The OCaml library handles JSON/form data but lacks an extensible encoding system.", 124 + "affected_files": [ 125 + "lib/body.ml", 126 + "lib/response.ml", 127 + "lib/mime.ml" 128 + ], 129 + "rationale": "Applications often need custom serialization formats (MessagePack, Protocol Buffers, custom XML variants, YAML). Resty's AddContentTypeEncoder/AddContentTypeDecoder pattern allows registering handlers at client or request level without modifying library code. This enables seamless integration with custom formats while maintaining type safety and automatic content negotiation." 130 + }, 131 + { 132 + "source_repo": "third_party/go/resty", 133 + "source_language": "Go", 134 + "criticality": "low", 135 + "change_type": "enhancement", 136 + "title": "Add path parameter templating for cleaner URL construction", 137 + "description": "Resty supports path parameter templating (e.g., /users/{userId}/posts/{postId}) with SetPathParam/SetPathParams. Parameters are automatically URL-escaped. The OCaml library requires manual URL construction.", 138 + "affected_files": [ 139 + "lib/requests.ml" 140 + ], 141 + "rationale": "Path parameter templating improves code readability and reduces URL construction errors. Automatic escaping prevents URL injection vulnerabilities. Resty provides both escaped (SetPathParam) and raw (SetRawPathParam) variants for different use cases. This feature reduces boilerplate and makes API client code more maintainable, especially for REST APIs with many parameterized routes." 142 + }, 143 + { 144 + "source_repo": "third_party/go/resty", 145 + "source_language": "Go", 146 + "criticality": "low", 147 + "change_type": "enhancement", 148 + "title": "Add automatic curl command generation for debugging", 149 + "description": "Resty can generate equivalent curl commands for debugging (EnableGenerateCurlCmd, SetDebugLogCurlCmd). This helps developers reproduce issues outside the application and share reproducible test cases. The OCaml library lacks this debugging aid.", 150 + "affected_files": [ 151 + "lib/requests.ml" 152 + ], 153 + "rationale": "Curl command generation significantly improves debugging workflow. Developers can copy generated commands to terminal for quick testing, share with colleagues or support teams, and verify library behavior. Resty implements proper escaping, header formatting, and body handling. The opt-in design prevents accidental logging of sensitive data. This is a valuable developer experience enhancement." 154 + }, 155 + { 156 + "source_repo": "third_party/go/resty", 157 + "source_language": "Go", 158 + "criticality": "low", 159 + "change_type": "feature", 160 + "title": "Add support for saving responses directly to files with automatic naming", 161 + "description": "Resty provides SetOutputFileName and SetSaveResponse to save HTTP responses directly to files without loading into memory. It determines filenames from Content-Disposition headers, URL paths, or user specification. The OCaml library only provides in-memory responses.", 162 + "affected_files": [ 163 + "lib/response.ml", 164 + "lib/requests.ml" 165 + ], 166 + "rationale": "Streaming responses to disk is essential for downloading large files without memory exhaustion. Resty's automatic filename detection from Content-Disposition headers improves user experience. The OutputDirectory setting allows consistent file organization. This feature is crucial for file download clients, web scrapers, and backup tools." 167 + }, 168 + { 169 + "source_repo": "third_party/go/resty", 170 + "source_language": "Go", 171 + "criticality": "low", 172 + "change_type": "enhancement", 173 + "title": "Add multipart progress tracking with callbacks", 174 + "description": "Resty supports progress callbacks for multipart uploads via MultipartField.ProgressCallback, providing real-time upload progress in bytes. The OCaml library lacks upload progress visibility.", 175 + "affected_files": [ 176 + "lib/body.ml" 177 + ], 178 + "rationale": "Upload progress feedback is essential for user experience in applications that upload large files. It enables progress bars, bandwidth monitoring, and timeout adjustments. Resty's callback-based design allows flexible progress handling without coupling to specific UI frameworks. This is particularly valuable for file upload tools and backup applications." 179 + }, 180 + { 181 + "source_repo": "third_party/go/resty", 182 + "source_language": "Go", 183 + "criticality": "low", 184 + "change_type": "enhancement", 185 + "title": "Add configurable debug body size limits for logging", 186 + "description": "Resty provides SetDebugBodyLimit to limit request/response body size in debug logs, preventing log overflow from large payloads. The OCaml library logs full bodies without limits.", 187 + "affected_files": [ 188 + "lib/requests.ml" 189 + ], 190 + "rationale": "Debug logging of large request/response bodies can overwhelm logs and impact performance. Resty's configurable limit (default unlimited with truncation messages) balances debuggability with log manageability. Large bodies show size instead of content ('***** REQUEST TOO LARGE (size - N) *****'). This prevents log storage exhaustion and improves log readability while maintaining diagnostic value." 191 + } 192 + ] 193 + }
+205
third_party/go/sling.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "go/sling", 5 + "source_language": "Go", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add support for custom response decoders beyond JSON", 9 + "description": "Sling supports pluggable ResponseDecoder interface that allows decoding responses into XML, protobuf, or custom formats. The OCaml library currently only provides JSON parsing via Response.json. Add a customizable decoder mechanism similar to Sling's ResponseDecoder interface to support XML, MessagePack, CBOR, and other formats.", 10 + "affected_files": [ 11 + "lib/response.mli", 12 + "lib/response.ml" 13 + ], 14 + "rationale": "Sling's ResponseDecoder interface (response.go:8-12) provides extensibility for different response formats. This is demonstrated in sling_test.go:43-48 with xmlResponseDecoder. The OCaml library should provide similar flexibility for modern APIs that use formats beyond JSON, improving interoperability with diverse APIs." 15 + }, 16 + { 17 + "source_repo": "go/sling", 18 + "source_language": "Go", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Implement builder pattern with method chaining for request construction", 22 + "description": "Sling uses a fluent builder pattern where each setter returns the modified Sling instance, enabling clean method chaining (e.g., sling.New().Get(url).QueryStruct(params).BodyJSON(data).Receive(success, failure)). The OCaml library uses optional parameters which can become unwieldy. Implement a builder-style API that returns a modified request configuration, allowing users to compose requests incrementally and reuse base configurations.", 23 + "affected_files": [ 24 + "lib/requests.mli", 25 + "lib/requests.ml" 26 + ], 27 + "rationale": "Sling's builder pattern (sling.go:66-81, examples/github.go:75-76) enables clear separation of base configuration from specific requests. The New() method creates independent copies to prevent mutation of parent Slings. This pattern improves code organization and reusability compared to long parameter lists. In OCaml, this could be implemented using a configuration record type that is copied and updated." 28 + }, 29 + { 30 + "source_repo": "go/sling", 31 + "source_language": "Go", 32 + "criticality": "high", 33 + "change_type": "enhancement", 34 + "title": "Add structured error response decoding with success/failure variants", 35 + "description": "Sling's Receive() method (sling.go:359-372) accepts both successV and failureV parameters, automatically decoding 2XX responses into successV and non-2XX into failureV. This provides typed error handling for API error responses. Implement a similar mechanism in the OCaml library that allows users to specify both success and failure decoders, returning a result type with properly parsed error structures.", 36 + "affected_files": [ 37 + "lib/response.mli", 38 + "lib/response.ml", 39 + "lib/requests.mli", 40 + "lib/requests.ml" 41 + ], 42 + "rationale": "Sling's dual-decoder approach (sling.go:406-422, examples/github.go:82-86) enables clean handling of typed API errors like GitHub's error response format. The OCaml library currently requires manual status checking and separate error parsing. Adding structured error decoding would improve ergonomics and type safety when working with REST APIs that return JSON error details." 43 + }, 44 + { 45 + "source_repo": "go/sling", 46 + "source_language": "Go", 47 + "criticality": "medium", 48 + "change_type": "feature", 49 + "title": "Support query parameter encoding from structured types", 50 + "description": "Sling provides QueryStruct() method that encodes Go structs with url tags into query parameters using go-querystring library. This avoids manual URL construction and ensures proper encoding. Add similar functionality to encode OCaml records or association lists into properly-encoded query strings, potentially using the existing params parameter but with automatic URL encoding and nested structure support.", 51 + "affected_files": [ 52 + "lib/requests.mli", 53 + "lib/requests.ml", 54 + "lib/one.mli", 55 + "lib/one.ml" 56 + ], 57 + "rationale": "Sling's QueryStruct (sling.go:212-222, examples/github.go:92-93) handles complex query parameters including arrays, nested structures, and proper URL encoding. The OCaml library's params parameter in get() only supports simple (string * string) list. Supporting structured query parameter encoding would improve usability for complex API queries and prevent URL encoding bugs." 58 + }, 59 + { 60 + "source_repo": "go/sling", 61 + "source_language": "Go", 62 + "criticality": "low", 63 + "change_type": "enhancement", 64 + "title": "Add BodyProvider abstraction for lazy body construction", 65 + "description": "Sling uses a BodyProvider interface (body.go:12-18) that defers body construction until the request is sent. This allows the same body configuration to be reused for multiple requests without re-encoding. Consider implementing a similar lazy evaluation pattern for Body.t in the OCaml library to improve efficiency when reusing request configurations.", 66 + "affected_files": [ 67 + "lib/body.mli", 68 + "lib/body.ml" 69 + ], 70 + "rationale": "Sling's BodyProvider pattern (body.go:33-50) separates body specification from actual encoding, enabling efficient reuse. The OCaml library's Body.t appears to eagerly construct content. Lazy construction could reduce memory usage and CPU time when the same body template is used multiple times, particularly for large JSON or form payloads." 71 + }, 72 + { 73 + "source_repo": "go/sling", 74 + "source_language": "Go", 75 + "criticality": "high", 76 + "change_type": "bug", 77 + "title": "Ensure response body is fully drained for connection reuse", 78 + "description": "Sling explicitly drains the response body using io.Copy(io.Discard, resp.Body) (sling.go:392) even after decoding to ensure HTTP keep-alive connections can be reused. Review the OCaml library's response handling to ensure response bodies are fully consumed or explicitly documented requirements for connection pool reuse.", 79 + "affected_files": [ 80 + "lib/response.ml", 81 + "lib/http_client.ml", 82 + "lib/requests.ml" 83 + ], 84 + "rationale": "Sling's explicit draining (sling.go:388-392) prevents connection pool exhaustion by ensuring the TCP connection can be reused. The comment references Go's net/http documentation about this requirement. The OCaml library uses Eio flows which should be fully read or closed to enable connection reuse in the pool. Verify this is properly documented and implemented." 85 + }, 86 + { 87 + "source_repo": "go/sling", 88 + "source_language": "Go", 89 + "criticality": "medium", 90 + "change_type": "enhancement", 91 + "title": "Skip response decoding for 204 No Content and zero Content-Length", 92 + "description": "Sling skips JSON decoding when the response status is 204 (No Content) or Content-Length is 0 (sling.go:394-397). This prevents decoder errors on empty responses. Implement similar logic in the OCaml library's Response.json and any future decoder methods to gracefully handle empty responses.", 93 + "affected_files": [ 94 + "lib/response.mli", 95 + "lib/response.ml" 96 + ], 97 + "rationale": "Sling's check (sling.go:394-397) prevents attempting to decode empty response bodies which would cause parsing errors. This is particularly important for DELETE requests and other operations that return 204 status. The OCaml library should implement similar guards in Response.json and Response.text to return appropriate empty values or special results for empty responses." 98 + }, 99 + { 100 + "source_repo": "go/sling", 101 + "source_language": "Go", 102 + "criticality": "low", 103 + "change_type": "enhancement", 104 + "title": "Add Path() method for incremental URL construction", 105 + "description": "Sling provides a Path() method (sling.go:202-210) that resolves paths relative to the current URL, enabling incremental URL building (e.g., base.Path('foo/').Path('bar')). Add similar functionality to allow building URLs incrementally rather than requiring complete URLs for each request.", 106 + "affected_files": [ 107 + "lib/requests.mli", 108 + "lib/requests.ml" 109 + ], 110 + "rationale": "Sling's Path method (sling.go:202-210, README.md:46-53) uses URL resolution to build paths incrementally, which is cleaner than string concatenation and handles trailing slashes correctly. This would improve API client ergonomics in the OCaml library by allowing users to define base URLs and extend them per-request." 111 + }, 112 + { 113 + "source_repo": "go/sling", 114 + "source_language": "Go", 115 + "criticality": "medium", 116 + "change_type": "feature", 117 + "title": "Add BodyForm() for automatic URL-encoded form submission", 118 + "description": "Sling provides BodyForm() (sling.go:267-272) that automatically encodes structs as application/x-www-form-urlencoded and sets the appropriate Content-Type. The OCaml library has Body.form but ensure it's prominently featured and handles encoding edge cases correctly (e.g., arrays, special characters, nested data).", 119 + "affected_files": [ 120 + "lib/body.mli", 121 + "lib/body.ml" 122 + ], 123 + "rationale": "Sling's BodyForm (body.go:52-68) uses the same query string encoding library for consistency and proper handling of complex data structures. The OCaml library's Body.form should be reviewed to ensure it handles all URL encoding edge cases and supports rich form data structures, not just simple key-value pairs." 124 + }, 125 + { 126 + "source_repo": "go/sling", 127 + "source_language": "Go", 128 + "criticality": "low", 129 + "change_type": "enhancement", 130 + "title": "Support service-oriented API client architecture pattern", 131 + "description": "Sling's documentation and examples (examples/github.go:67-112) demonstrate organizing API clients into services (e.g., IssueService) that wrap a shared Sling instance. Add documentation and examples showing how to structure OCaml API clients using this service pattern with shared session configuration.", 132 + "affected_files": [ 133 + "lib/requests.mli", 134 + "examples/session_example.ml" 135 + ], 136 + "rationale": "Sling's service pattern (examples/github.go:67-112, README.md:247-272) provides a clean architectural pattern for organizing API endpoints. The pattern uses a shared base Sling with common configuration (auth, base URL) and service-specific methods. Adding similar examples to the OCaml library would help users structure larger API clients effectively." 137 + }, 138 + { 139 + "source_repo": "go/sling", 140 + "source_language": "Go", 141 + "criticality": "high", 142 + "change_type": "security", 143 + "title": "Document connection reuse test requirements for security", 144 + "description": "Sling includes explicit tests for TCP connection reuse (sling_test.go:927-964) to ensure the connection pool works correctly. Add similar integration tests to verify that the OCaml library's connection pool properly reuses connections and doesn't leak resources or create new connections unnecessarily.", 145 + "affected_files": [ 146 + "test/test_simple.ml", 147 + "test/test_localhost.ml" 148 + ], 149 + "rationale": "Sling's connection reuse test (sling_test.go:927-964) uses atomic counters to verify only 1 connection is created for 10 sequential requests. This is crucial for preventing resource exhaustion and ensuring connection pool efficiency. The OCaml library uses Conpool but should have explicit tests verifying connection reuse behavior under various scenarios." 150 + }, 151 + { 152 + "source_repo": "go/sling", 153 + "source_language": "Go", 154 + "criticality": "medium", 155 + "change_type": "enhancement", 156 + "title": "Add comprehensive test coverage for header merging and inheritance", 157 + "description": "Sling has extensive tests for header behavior including canonicalization, Add vs Set semantics, and inheritance from parent Slings (sling_test.go:220-261). Review and expand the OCaml library's tests to ensure header merging, default headers, and per-request headers work correctly in all combinations.", 158 + "affected_files": [ 159 + "lib/headers.ml", 160 + "test/test_simple.ml" 161 + ], 162 + "rationale": "Sling's header tests (sling_test.go:220-261) cover edge cases like: header canonicalization, appending vs replacing values, inheritance through New(), and interaction between default and request-specific headers. The OCaml library should have similar comprehensive tests to prevent subtle bugs in header handling." 163 + }, 164 + { 165 + "source_repo": "go/sling", 166 + "source_language": "Go", 167 + "criticality": "medium", 168 + "change_type": "enhancement", 169 + "title": "Add SetBasicAuth convenience method", 170 + "description": "Sling provides SetBasicAuth(username, password) (sling.go:180-182) as a convenience wrapper that constructs the Authorization header. While the OCaml library has Auth.basic, consider adding a convenience method directly on the request builder that applies auth without requiring separate Auth module interaction.", 171 + "affected_files": [ 172 + "lib/requests.mli", 173 + "lib/requests.ml" 174 + ], 175 + "rationale": "Sling's SetBasicAuth (sling.go:180-189) provides a convenient way to set basic auth without manually constructing headers. While the OCaml library has Auth.basic and set_auth, adding method-specific convenience functions (with_basic_auth, with_bearer_token) would improve discoverability and reduce boilerplate." 176 + }, 177 + { 178 + "source_repo": "go/sling", 179 + "source_language": "Go", 180 + "criticality": "low", 181 + "change_type": "refactor", 182 + "title": "Consider separating request building from execution", 183 + "description": "Sling separates Request() (building) from Do() (execution), allowing users to inspect or modify the raw http.Request before sending (sling.go:279-303, 374-404). Consider providing a similar separation in the OCaml library where users can build a request configuration, inspect it, and then execute it separately.", 184 + "affected_files": [ 185 + "lib/requests.mli", 186 + "lib/requests.ml" 187 + ], 188 + "rationale": "Sling's separation (sling.go:279-303 for building, 374-404 for execution) enables advanced use cases like adding request tracing, inspecting URLs before sending, or integrating with middleware. This flexibility could benefit the OCaml library for debugging and testing scenarios where users need to inspect the constructed request." 189 + }, 190 + { 191 + "source_repo": "go/sling", 192 + "source_language": "Go", 193 + "criticality": "medium", 194 + "change_type": "enhancement", 195 + "title": "Add Doer interface abstraction for middleware support", 196 + "description": "Sling defines a Doer interface (sling.go:18-23) that enables wrapping the HTTP client with middleware layers. This pattern allows users to add logging, metrics, circuit breakers, etc. Consider adding a similar abstraction in the OCaml library to support client-side middleware without modifying library code.", 197 + "affected_files": [ 198 + "lib/requests.mli", 199 + "lib/requests.ml", 200 + "lib/http_client.mli" 201 + ], 202 + "rationale": "Sling's Doer interface (sling.go:18-23) enables composable middleware by wrapping http.Client. This is a powerful extensibility pattern mentioned in the documentation for adding custom behavior. The OCaml library could benefit from a similar pattern, perhaps using module functors or first-class modules to wrap the underlying HTTP client with custom logic." 203 + } 204 + ] 205 + }
+339
third_party/haskell/http-client.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "haskell/http-client", 5 + "source_language": "Haskell", 6 + "criticality": "high", 7 + "change_type": "bug", 8 + "title": "Add response body size validation", 9 + "description": "The Haskell library validates response body size matches Content-Length (ResponseBodyTooShort exception). The OCaml library reads bodies without validation, which can lead to silent truncation of responses when connections close prematurely.", 10 + "affected_files": [ 11 + "lib/http_client.ml", 12 + "lib/error.ml" 13 + ], 14 + "rationale": "The Haskell library throws ResponseBodyTooShort with expected vs actual sizes when a fixed-length response terminates early (Body.hs:133). This catches network issues that would otherwise silently corrupt data. The OCaml implementation in read_fixed_body (http_client.ml:196-208) reads until length is reached but doesn't detect premature EOF, potentially returning incomplete data without error." 15 + }, 16 + { 17 + "source_repo": "haskell/http-client", 18 + "source_language": "Haskell", 19 + "criticality": "high", 20 + "change_type": "security", 21 + "title": "Implement header validation to prevent request smuggling", 22 + "description": "The Haskell library validates request headers don't contain newlines (InvalidRequestHeader exception). The OCaml library lacks this validation, making it vulnerable to HTTP request smuggling attacks where attackers inject newlines to split requests.", 23 + "affected_files": [ 24 + "lib/http_client.ml", 25 + "lib/headers.ml", 26 + "lib/error.ml" 27 + ], 28 + "rationale": "The Haskell library has validateHeaders function (Headers.hs:141-149) that checks for newlines in header values and throws InvalidRequestHeader. This prevents HTTP request smuggling where malicious header values containing CRLF can inject additional headers or requests. The OCaml library builds headers in http_client.ml:164-168 without validation, allowing unsafe headers to be sent." 29 + }, 30 + { 31 + "source_repo": "haskell/http-client", 32 + "source_language": "Haskell", 33 + "criticality": "high", 34 + "change_type": "security", 35 + "title": "Add configurable limits for header size and count", 36 + "description": "The Haskell library enforces MaxHeaderLength (default 4096 bytes per field) and MaxNumberHeaders (default 100 fields) to prevent DoS attacks via malicious headers. The OCaml library has no such limits and could be exploited by servers sending oversized headers to consume memory.", 37 + "affected_files": [ 38 + "lib/http_client.ml", 39 + "lib/requests.ml", 40 + "lib/one.ml", 41 + "lib/error.ml" 42 + ], 43 + "rationale": "The Haskell library includes OverlongHeaders and TooManyHeaderFields exceptions (Types.hs:150-156) with configurable limits in ManagerSettings (Manager.hs:94-95). Headers.hs:94-97 enforces these limits during parsing. The OCaml library's parse_headers (http_client.ml:181-194) has no limits, making it vulnerable to memory exhaustion attacks where malicious servers send massive headers." 44 + }, 45 + { 46 + "source_repo": "haskell/http-client", 47 + "source_language": "Haskell", 48 + "criticality": "medium", 49 + "change_type": "bug", 50 + "title": "Distinguish connection vs response timeouts", 51 + "description": "The Haskell library separates ConnectionTimeout and ResponseTimeout as distinct error types. The OCaml library has a single Timeout exception, making it impossible to distinguish whether the timeout occurred during connection establishment or response receipt, which affects retry decisions.", 52 + "affected_files": [ 53 + "lib/error.ml", 54 + "lib/timeout.ml" 55 + ], 56 + "rationale": "The Haskell library has separate ConnectionTimeout and ResponseTimeout exceptions (Types.hs:165-168). This distinction is critical because connection timeouts are always retryable, while response timeouts may indicate the request is processing. The OCaml library has only Error.Timeout, losing this important context that affects retry logic and debugging." 57 + }, 58 + { 59 + "source_repo": "haskell/http-client", 60 + "source_language": "Haskell", 61 + "criticality": "medium", 62 + "change_type": "enhancement", 63 + "title": "Add NoResponseDataReceived error for improved retry logic", 64 + "description": "The Haskell library has a specific NoResponseDataReceived exception for when a connection closes before any response data arrives. This is critical for detecting stale pooled connections and automatically retrying. The OCaml library treats this as a generic connection error.", 65 + "affected_files": [ 66 + "lib/error.ml", 67 + "lib/http_client.ml" 68 + ], 69 + "rationale": "The Haskell library marks NoResponseDataReceived as retryable (Manager.hs:80) because it indicates a stale pooled connection that was closed by the server. The OCaml library checks for empty response in http_client.ml but raises a generic error, missing the opportunity to distinguish this specific retryable scenario from other connection failures." 70 + }, 71 + { 72 + "source_repo": "haskell/http-client", 73 + "source_language": "Haskell", 74 + "criticality": "medium", 75 + "change_type": "enhancement", 76 + "title": "Add WrongRequestBodyStreamSize validation", 77 + "description": "The Haskell library validates that streaming request bodies match their declared size (WrongRequestBodyStreamSize exception). The OCaml library doesn't validate streaming body sizes, which can cause issues with servers that expect Content-Length to match actual bytes sent.", 78 + "affected_files": [ 79 + "lib/body.ml", 80 + "lib/error.ml" 81 + ], 82 + "rationale": "The Haskell library throws WrongRequestBodyStreamSize with expected and actual sizes (Types.hs:212-217) when RequestBodyStream provides different bytes than declared. This catches application bugs early. The OCaml Body module has streaming support but doesn't validate sizes, which can cause subtle HTTP protocol violations." 83 + }, 84 + { 85 + "source_repo": "haskell/http-client", 86 + "source_language": "Haskell", 87 + "criticality": "medium", 88 + "change_type": "feature", 89 + "title": "Add HTTP 103 Early Hints support", 90 + "description": "The Haskell library supports HTTP 103 Early Hints responses, allowing applications to receive link preload hints before the final response. This enables performance optimizations like early resource fetching. The OCaml library doesn't handle 103 responses.", 91 + "affected_files": [ 92 + "lib/http_client.ml", 93 + "lib/response.ml" 94 + ], 95 + "rationale": "The Haskell library has earlyHintHeadersReceived callback and special handling for status 103 (Headers.hs:54-60) to collect early hint headers before continuing to read the final response. This is valuable for web performance optimization. The OCaml library's status line parser treats all 1xx responses the same way without special early hints support." 96 + }, 97 + { 98 + "source_repo": "haskell/http-client", 99 + "source_language": "Haskell", 100 + "criticality": "medium", 101 + "change_type": "feature", 102 + "title": "Support HTTP 100 Continue for request body optimization", 103 + "description": "The Haskell library supports Expect: 100-continue workflow, allowing servers to reject requests before the client sends a large body. The OCaml library doesn't implement this optimization, causing unnecessary bandwidth usage for rejected requests.", 104 + "affected_files": [ 105 + "lib/http_client.ml", 106 + "lib/requests.ml" 107 + ], 108 + "rationale": "The Haskell library has special logic for status 100 Continue (Headers.hs:53) with getStatusExpectContinue that waits for 100 before sending the body. This is important for large uploads where the server might reject based on headers alone. The OCaml library doesn't support this RFC 7231 optimization." 109 + }, 110 + { 111 + "source_repo": "haskell/http-client", 112 + "source_language": "Haskell", 113 + "criticality": "medium", 114 + "change_type": "enhancement", 115 + "title": "Add IncompleteHeaders exception for truncated responses", 116 + "description": "The Haskell library detects when response headers are incomplete/truncated (IncompleteHeaders exception) and marks this as retryable. The OCaml library may fail generically on truncated headers without distinguishing this retryable case.", 117 + "affected_files": [ 118 + "lib/error.ml", 119 + "lib/http_client.ml" 120 + ], 121 + "rationale": "The Haskell library has IncompleteHeaders exception (Types.hs:227-230) marked as retryable (Manager.hs:81), indicating headers were cut off mid-stream, usually due to connection issues. The OCaml library's parse_headers will fail on truncated headers but doesn't categorize this as a specific retryable error type." 122 + }, 123 + { 124 + "source_repo": "haskell/http-client", 125 + "source_language": "Haskell", 126 + "criticality": "medium", 127 + "change_type": "enhancement", 128 + "title": "Add chunked encoding error detection", 129 + "description": "The Haskell library has InvalidChunkHeaders exception to detect malformed chunked transfer encoding. The OCaml library parses chunked encoding but doesn't have specific error types for chunk format violations, making debugging harder.", 130 + "affected_files": [ 131 + "lib/error.ml", 132 + "lib/http_client.ml" 133 + ], 134 + "rationale": "The Haskell library throws InvalidChunkHeaders (Types.hs:223-226) when chunk size parsing or format is invalid. The OCaml library's read_chunked_body (http_client.ml:210-236) uses int_of_string which will raise generic exceptions on invalid chunks, losing the context that this is a chunked encoding issue." 135 + }, 136 + { 137 + "source_repo": "haskell/http-client", 138 + "source_language": "Haskell", 139 + "criticality": "medium", 140 + "change_type": "enhancement", 141 + "title": "Implement response modification hooks", 142 + "description": "The Haskell library provides managerModifyResponse hook allowing middleware to intercept and modify responses. The OCaml library lacks this extensibility point, limiting ability to implement cross-cutting concerns like logging, caching, or response transformation.", 143 + "affected_files": [ 144 + "lib/requests.ml" 145 + ], 146 + "rationale": "The Haskell library's ManagerSettings includes managerModifyResponse (Manager.hs:91) allowing users to transform responses before they're returned. This enables middleware patterns for logging, metrics, caching, etc. The OCaml library only has request-level configuration without response interception capabilities." 147 + }, 148 + { 149 + "source_repo": "haskell/http-client", 150 + "source_language": "Haskell", 151 + "criticality": "medium", 152 + "change_type": "enhancement", 153 + "title": "Add request modification hooks for middleware", 154 + "description": "The Haskell library provides managerModifyRequest hook for request interception. The OCaml library lacks this, making it harder to implement cross-cutting request concerns like request ID injection, logging, or dynamic header addition.", 155 + "affected_files": [ 156 + "lib/requests.ml" 157 + ], 158 + "rationale": "The Haskell library's managerModifyRequest (Manager.hs:90) allows IO-based request modification before sending, enabling middleware for request logging, adding correlation IDs, dynamic auth tokens, etc. The OCaml library has auth and default headers but no general request interception mechanism." 159 + }, 160 + { 161 + "source_repo": "haskell/http-client", 162 + "source_language": "Haskell", 163 + "criticality": "medium", 164 + "change_type": "enhancement", 165 + "title": "Implement exception wrapping for better context", 166 + "description": "The Haskell library has managerWrapException to enrich exceptions with request context. The OCaml library doesn't systematically attach request context to exceptions, making debugging harder when errors occur.", 167 + "affected_files": [ 168 + "lib/error.ml", 169 + "lib/requests.ml" 170 + ], 171 + "rationale": "The Haskell library's managerWrapException (Manager.hs:83-88) wraps IOExceptions with InternalException including the request context. This makes debugging much easier by showing which request failed. The OCaml library raises exceptions but doesn't consistently include URL or request details except in HTTPError." 172 + }, 173 + { 174 + "source_repo": "haskell/http-client", 175 + "source_language": "Haskell", 176 + "criticality": "low", 177 + "change_type": "enhancement", 178 + "title": "Support custom decompression predicates", 179 + "description": "The Haskell library allows custom predicates (browserDecompress, alwaysDecompress) to control which content types should be decompressed. The OCaml library always decompresses based on Content-Encoding header without content-type awareness.", 180 + "affected_files": [ 181 + "lib/http_client.ml", 182 + "lib/requests.ml" 183 + ], 184 + "rationale": "The Haskell library has decompress predicates that check MIME types to decide whether to decompress (Request.hs:20-21). Some content (e.g., pre-compressed files, binary formats) shouldn't be decompressed even with gzip encoding. The OCaml library's auto_decompress is boolean without content-type consideration." 185 + }, 186 + { 187 + "source_repo": "haskell/http-client", 188 + "source_language": "Haskell", 189 + "criticality": "low", 190 + "change_type": "enhancement", 191 + "title": "Add response status line validation", 192 + "description": "The Haskell library has InvalidStatusLine exception for unparseable status lines. The OCaml library uses failwith, which doesn't fit the error handling model and loses error categorization.", 193 + "affected_files": [ 194 + "lib/error.ml", 195 + "lib/http_client.ml" 196 + ], 197 + "rationale": "The Haskell library throws InvalidStatusLine with the raw bytes (Types.hs:174-177) when status parsing fails. The OCaml library's parse_status_line (http_client.ml:173-178) uses failwith for invalid status, which doesn't integrate with the Error module's exception hierarchy." 198 + }, 199 + { 200 + "source_repo": "haskell/http-client", 201 + "source_language": "Haskell", 202 + "criticality": "low", 203 + "change_type": "enhancement", 204 + "title": "Add InvalidHeader exception for malformed headers", 205 + "description": "The Haskell library has InvalidHeader exception for response headers that can't be parsed. The OCaml library silently skips unparseable headers, which could hide protocol violations or attacks.", 206 + "affected_files": [ 207 + "lib/error.ml", 208 + "lib/http_client.ml" 209 + ], 210 + "rationale": "The Haskell library throws InvalidHeader with the raw header line (Types.hs:178-181). The OCaml parse_headers (http_client.ml:186) silently skips headers without colons, continuing parsing. While robust, this could hide server bugs or malicious responses." 211 + }, 212 + { 213 + "source_repo": "haskell/http-client", 214 + "source_language": "Haskell", 215 + "criticality": "low", 216 + "change_type": "enhancement", 217 + "title": "Implement proxy CONNECT error handling", 218 + "description": "The Haskell library has ProxyConnectException with detailed proxy connection failure information (host, port, status). The OCaml library has generic ProxyError without structured details.", 219 + "affected_files": [ 220 + "lib/error.ml" 221 + ], 222 + "rationale": "The Haskell library's ProxyConnectException (Types.hs:192-195) includes the proxy host, port, and HTTP status code, making proxy issues debuggable. The OCaml Error.ProxyError is just a string, losing structured information about proxy failures." 223 + }, 224 + { 225 + "source_repo": "haskell/http-client", 226 + "source_language": "Haskell", 227 + "criticality": "low", 228 + "change_type": "enhancement", 229 + "title": "Add InvalidDestinationHost validation", 230 + "description": "The Haskell library validates destination hosts aren't empty or invalid (InvalidDestinationHost exception). The OCaml library may fail with generic errors on invalid hosts.", 231 + "affected_files": [ 232 + "lib/error.ml", 233 + "lib/requests.ml" 234 + ], 235 + "rationale": "The Haskell library has InvalidDestinationHost exception (Types.hs:231-233) to catch invalid hosts early with clear error messages. The OCaml library relies on Uri.host returning None, which leads to failwith in http_client.ml:132, not using the proper error hierarchy." 236 + }, 237 + { 238 + "source_repo": "haskell/http-client", 239 + "source_language": "Haskell", 240 + "criticality": "low", 241 + "change_type": "feature", 242 + "title": "Add TlsNotSupported exception for better error messages", 243 + "description": "The Haskell library throws TlsNotSupported when HTTPS is attempted without TLS configuration. The OCaml library may fail with cryptic TLS errors instead of user-friendly messages.", 244 + "affected_files": [ 245 + "lib/error.ml", 246 + "lib/requests.ml" 247 + ], 248 + "rationale": "The Haskell library throws TlsNotSupported (Types.hs:205-211) with helpful message to use tlsManagerSettings. The OCaml library creates pools with optional TLS, but doesn't have a clear error for misconfiguration, potentially leading to confusing failures." 249 + }, 250 + { 251 + "source_repo": "haskell/http-client", 252 + "source_language": "Haskell", 253 + "criticality": "medium", 254 + "change_type": "enhancement", 255 + "title": "Add retry predicate customization at session level", 256 + "description": "The Haskell library allows managerRetryableException predicate to customize which exceptions are retryable at the manager level. The OCaml library has fixed retry logic in Retry module without easy per-session customization.", 257 + "affected_files": [ 258 + "lib/retry.ml", 259 + "lib/requests.ml" 260 + ], 261 + "rationale": "The Haskell library's managerRetryableException (Manager.hs:70-82) allows custom retry logic per manager. This is valuable for applications with specific retry needs. The OCaml Retry.should_retry only checks method and status, without exception-based retry or easy per-session customization." 262 + }, 263 + { 264 + "source_repo": "haskell/http-client", 265 + "source_language": "Haskell", 266 + "criticality": "low", 267 + "change_type": "enhancement", 268 + "title": "Support cookie public suffix list for security", 269 + "description": "The Haskell library uses a public suffix list to prevent cookies from being set on TLDs like .com or .co.uk. The OCaml library (via cookeio) may not have this security feature, allowing overly broad cookie domains.", 270 + "affected_files": [ 271 + "lib/requests.ml" 272 + ], 273 + "rationale": "The Haskell library imports Network.PublicSuffixList.Lookup (Cookies.hs:29) to validate cookie domains against public suffixes, preventing cookies on .com, .org, etc. This is important for security. The OCaml library uses cookeio_jar but should verify it implements public suffix checking." 274 + }, 275 + { 276 + "source_repo": "haskell/http-client", 277 + "source_language": "Haskell", 278 + "criticality": "medium", 279 + "change_type": "refactor", 280 + "title": "Implement bracket pattern for response cleanup", 281 + "description": "The Haskell library uses explicit bracket pattern (responseOpen/responseClose) to ensure response resources are cleaned up even on exceptions. The OCaml library relies on Eio switch but doesn't expose explicit close for manual resource management.", 282 + "affected_files": [ 283 + "lib/response.ml", 284 + "lib/requests.ml" 285 + ], 286 + "rationale": "The Haskell library has ResponseClose type and responseClose function for explicit cleanup, with withResponse using bracket pattern. While the OCaml library uses Eio.Switch (response.ml:23-32), exposing an explicit close function would help users who need fine-grained resource control or want to consume responses outside the original switch scope." 287 + }, 288 + { 289 + "source_repo": "haskell/http-client", 290 + "source_language": "Haskell", 291 + "criticality": "low", 292 + "change_type": "feature", 293 + "title": "Add streamFile with progress callbacks", 294 + "description": "The Haskell library has observedStreamFile allowing progress tracking for file uploads via callbacks. The OCaml library doesn't have built-in upload progress reporting.", 295 + "affected_files": [ 296 + "lib/body.ml" 297 + ], 298 + "rationale": "The Haskell library's observedStreamFile (Request.hs:36) provides StreamFileStatus callbacks for upload progress. This is valuable for UI feedback on large uploads. The OCaml Body module supports streaming but doesn't have progress hooks." 299 + }, 300 + { 301 + "source_repo": "haskell/http-client", 302 + "source_language": "Haskell", 303 + "criticality": "low", 304 + "change_type": "enhancement", 305 + "title": "Support multiple algorithms in digest auth", 306 + "description": "The OCaml library implements MD5, SHA-256, and SHA-512-256 for digest auth. Verify all algorithms are correctly implemented and add test coverage for algorithm negotiation.", 307 + "affected_files": [ 308 + "lib/auth.ml", 309 + "test/" 310 + ], 311 + "rationale": "The OCaml auth.ml:123-132 implements multiple hash algorithms. The Haskell library also supports multiple algorithms in digest auth. Ensure test coverage exists for all algorithm variants and algorithm selection logic matches RFC 7616." 312 + }, 313 + { 314 + "source_repo": "haskell/http-client", 315 + "source_language": "Haskell", 316 + "criticality": "medium", 317 + "change_type": "enhancement", 318 + "title": "Add deflate format fallback for ambiguous Content-Encoding", 319 + "description": "The OCaml library already tries zlib then raw deflate for 'deflate' encoding. Ensure this matches Haskell behavior and add tests for both formats since servers inconsistently use zlib-wrapped vs raw deflate.", 320 + "affected_files": [ 321 + "lib/http_client.ml", 322 + "test/" 323 + ], 324 + "rationale": "The OCaml library correctly handles deflate ambiguity (http_client.ml:104-113) by trying zlib first, then raw deflate. This matches real-world server behavior. Ensure comprehensive test coverage exists for both deflate variants." 325 + }, 326 + { 327 + "source_repo": "haskell/http-client", 328 + "source_language": "Haskell", 329 + "criticality": "low", 330 + "change_type": "feature", 331 + "title": "Add connection reuse statistics and monitoring", 332 + "description": "The Haskell library tracks connection pool statistics. The OCaml library has requests_made counter but could expose more connection pool metrics for monitoring and debugging.", 333 + "affected_files": [ 334 + "lib/requests.ml" 335 + ], 336 + "rationale": "The Haskell library provides visibility into connection pool behavior. The OCaml library tracks basic stats (requests.ml:54-56) but could expose connection pool metrics like connections created, reused, idle, etc. This helps with performance tuning and debugging." 337 + } 338 + ] 339 + }
+207
third_party/haskell/http-streams.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/haskell/http-streams", 5 + "source_language": "Haskell", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add optional HTTP status code exception raising for error responses", 9 + "description": "http-streams provides two handler patterns: `simpleHandler` (ignores status codes) and `simpleHandler'` (raises HttpClientError for status >= 300). The OCaml library currently requires users to manually check response status codes. Add a configurable option to automatically raise HTTPError exceptions for 4xx/5xx status codes, similar to the `raise_for_status` behavior but applied automatically during response handling.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/one.ml", 13 + "lib/response.ml", 14 + "lib/error.ml" 15 + ], 16 + "rationale": "The Haskell library's `simpleHandler'` provides a convenient pattern where HTTP errors are raised as exceptions automatically, reducing boilerplate. Currently, OCaml users must explicitly call `Response.raise_for_status` or check status codes manually. Adding an optional `~raise_for_status:bool` parameter (default false for backwards compatibility) to request functions would improve ergonomics while maintaining current behavior." 17 + }, 18 + { 19 + "source_repo": "third_party/haskell/http-streams", 20 + "source_language": "Haskell", 21 + "criticality": "low", 22 + "change_type": "enhancement", 23 + "title": "Add convenience functions for streaming response body to output", 24 + "description": "http-streams provides patterns like `Streams.connect i stdout` to easily pipe response bodies to output streams. Add helper functions like `Response.to_flow`, `Response.to_file`, and `Response.copy_to` that simplify streaming responses to various destinations without requiring manual Buf_read usage.", 25 + "affected_files": [ 26 + "lib/response.ml", 27 + "lib/response.mli" 28 + ], 29 + "rationale": "The Haskell library's handlers often use simple streaming patterns (e.g., `\\p i -> Streams.connect i stdout`) that make it easy to pipe responses. The OCaml library has `Response.body` returning a flow, but lacks convenience functions to stream that body to common destinations. Adding helpers like `to_file : t -> _ Eio.Path.t -> unit` would improve ergonomics for common streaming use cases." 30 + }, 31 + { 32 + "source_repo": "third_party/haskell/http-streams", 33 + "source_language": "Haskell", 34 + "criticality": "high", 35 + "change_type": "security", 36 + "title": "Add Expect: 100-continue support for large request bodies", 37 + "description": "http-streams implements Expect: 100-continue protocol handling (Connection.hs:331-347) which sends headers first, waits for 100 Continue response from server, then sends body. This prevents wasting bandwidth sending large bodies to servers that will reject the request based on headers alone. Add support for automatic or opt-in Expect: 100-continue handling for requests with large bodies or when explicitly requested.", 38 + "affected_files": [ 39 + "lib/http_client.ml", 40 + "lib/requests.ml", 41 + "lib/one.ml", 42 + "lib/body.ml" 43 + ], 44 + "rationale": "The Expect: 100-continue mechanism (RFC 7231 §5.1.1) is a critical optimization for uploads and large POST/PUT requests. If the server responds with 401, 403, or other error codes before the body is sent, it saves bandwidth and time. This is especially important for file uploads, multipart forms, and authenticated requests. The Haskell implementation shows this requires: 1) Setting Expect header, 2) Sending headers + flush, 3) Reading response, 4) Only sending body if 100 received." 45 + }, 46 + { 47 + "source_repo": "third_party/haskell/http-streams", 48 + "source_language": "Haskell", 49 + "criticality": "medium", 50 + "change_type": "bug", 51 + "title": "Ensure response bodies are fully consumed even when handler doesn't read all data", 52 + "description": "http-streams explicitly drains response bodies after handler completion (Connection.hs:458-467, comment at 449-457) using `Streams.skipToEof` to maintain HTTP protocol invariants for connection reuse and pipelining. Verify that the OCaml implementation properly drains unconsumed response bodies when using connection pooling to prevent protocol desynchronization.", 53 + "affected_files": [ 54 + "lib/http_client.ml", 55 + "lib/requests.ml", 56 + "lib/response.ml" 57 + ], 58 + "rationale": "The Haskell library has a critical comment: 'The response body coming from the server MUST be fully read, even if (especially if) the user's handler doesn't consume it all. This is necessary to maintain the HTTP protocol invariants; otherwise pipelining would not work.' With connection pooling, if a response body isn't fully consumed, the next request on that connection will read leftover bytes as its response, causing protocol errors. The OCaml library should ensure bodies are drained when responses are closed or connections returned to pool." 59 + }, 60 + { 61 + "source_repo": "third_party/haskell/http-streams", 62 + "source_language": "Haskell", 63 + "criticality": "medium", 64 + "change_type": "enhancement", 65 + "title": "Add support for parsing and respecting Retry-After header with HTTP date format", 66 + "description": "The OCaml retry module parses Retry-After as integer seconds or RFC3339 dates, but http-streams demonstrates handling of full HTTP-date format (RFC 7231 §7.1.1.1) which is the standard format. The current implementation attempts RFC3339 parsing which may fail for proper HTTP-date headers. Enhance the parser to handle IMF-fixdate, obsolete RFC 850, and ANSI C asctime formats as specified in HTTP standards.", 67 + "affected_files": [ 68 + "lib/retry.ml" 69 + ], 70 + "rationale": "HTTP-date format (used in Retry-After, Date, Expires headers) differs from RFC3339. While the OCaml code attempts Ptime.of_rfc3339, HTTP servers send dates like 'Wed, 21 Oct 2015 07:28:00 GMT' (IMF-fixdate). The current parser may fail to parse valid Retry-After headers, causing the retry mechanism to ignore server-specified backoff delays. Proper HTTP-date parsing ensures compliance with RFC 7231 and respects server rate limiting." 71 + }, 72 + { 73 + "source_repo": "third_party/haskell/http-streams", 74 + "source_language": "Haskell", 75 + "criticality": "low", 76 + "change_type": "feature", 77 + "title": "Add specialized handlers for common response processing patterns", 78 + "description": "http-streams provides several built-in handlers: `debugHandler` (prints to stdout), `simpleHandler` (returns ByteString), `simpleHandler'` (returns or throws), and `jsonHandler` (parses JSON). The OCaml library has methods on Response but lacks pre-built handler functions. Add convenience functions like `Handlers.debug`, `Handlers.to_string`, `Handlers.to_json`, `Handlers.ignore` that can be passed to request functions for common use cases.", 79 + "affected_files": [ 80 + "lib/requests.ml", 81 + "lib/response.ml" 82 + ], 83 + "rationale": "The handler pattern in http-streams makes common operations very concise: `get url concatHandler`, `post url jsonHandler`. While OCaml's Response type has methods like `text` and `json`, having reusable handler functions could improve API ergonomics, especially for quick scripts or REPL usage. These handlers would encapsulate common patterns and reduce boilerplate in user code." 84 + }, 85 + { 86 + "source_repo": "third_party/haskell/http-streams", 87 + "source_language": "Haskell", 88 + "criticality": "high", 89 + "change_type": "bug", 90 + "title": "Add proper handling for responses with no content (204, 304, 1xx)", 91 + "description": "http-streams explicitly handles special status codes that never have response bodies: 204 No Content, 304 Not Modified, and 100 Continue, setting Content-Length to 0 (ResponseParser.hs:90-96). Ensure the OCaml implementation correctly handles these cases to avoid hanging when reading non-existent response bodies.", 92 + "affected_files": [ 93 + "lib/http_client.ml", 94 + "lib/response.ml" 95 + ], 96 + "rationale": "Per RFC 7230 §3.3.3, responses to HEAD requests, and responses with status codes 1xx, 204, and 304 MUST NOT include a message body, regardless of headers. If the HTTP client attempts to read a body for these responses, it may hang waiting for data that will never arrive, or misinterpret the next response as body data. The Haskell library demonstrates explicit checks for these status codes. The OCaml implementation should validate similar handling exists." 97 + }, 98 + { 99 + "source_repo": "third_party/haskell/http-streams", 100 + "source_language": "Haskell", 101 + "criticality": "medium", 102 + "change_type": "enhancement", 103 + "title": "Add Unix domain socket support for local service communication", 104 + "description": "http-streams provides `openConnectionUnix` (Connection.hs:282-300) for connecting to Unix domain sockets, useful for Docker API, systemd, and local services. Add support for 'unix://' URL scheme or a dedicated API to connect via Unix sockets, enabling communication with local services without TCP overhead.", 105 + "affected_files": [ 106 + "lib/http_client.ml", 107 + "lib/requests.ml", 108 + "lib/one.ml" 109 + ], 110 + "rationale": "Unix domain sockets are commonly used for local IPC with services like Docker daemon (unix:///var/run/docker.sock), systemd, and other system services. The Haskell library demonstrates this is straightforward to implement using AF_UNIX sockets with SockAddrUnix. Adding this would enable the OCaml library to interact with these services, which is a common use case for HTTP clients in systems programming contexts." 111 + }, 112 + { 113 + "source_repo": "third_party/haskell/http-streams", 114 + "source_language": "Haskell", 115 + "criticality": "low", 116 + "change_type": "enhancement", 117 + "title": "Add streaming JSON parser support for large JSON arrays/documents", 118 + "description": "http-streams' jsonHandler documentation (Inconvenience.hs:712-724) warns that it loads entire responses into memory and suggests using streaming parsers (Streams.parserToInputStream with Aeson combinators) for large JSON arrays. Document this pattern or provide built-in support for streaming JSON parsing to handle large API responses in constant space.", 119 + "affected_files": [ 120 + "lib/response.ml", 121 + "lib/response.mli", 122 + "examples/" 123 + ], 124 + "rationale": "The current `Response.json` implementation buffers the entire response body via `text t` before parsing. For large JSON arrays (e.g., paginated API responses, bulk data exports), this can cause memory issues. The Haskell library acknowledges this limitation and points users toward streaming solutions. OCaml with Jsonm or similar streaming JSON parsers could provide a `Response.json_stream : t -> Jsont.json Seq.t` or document the pattern for users who need it." 125 + }, 126 + { 127 + "source_repo": "third_party/haskell/http-streams", 128 + "source_language": "Haskell", 129 + "criticality": "medium", 130 + "change_type": "enhancement", 131 + "title": "Add configurable redirect following with custom status code handling", 132 + "description": "http-streams implements redirect following (Inconvenience.hs:360-407) that handles 301, 302, 303, and 307 status codes with a maximum redirect depth. The implementation demonstrates relative vs absolute URL handling via `splitURI`. Enhance the OCaml redirect implementation to expose which status codes trigger redirects and allow users to customize redirect behavior (e.g., method changes for 303).", 133 + "affected_files": [ 134 + "lib/requests.ml", 135 + "lib/one.ml" 136 + ], 137 + "rationale": "Different redirect status codes have different semantics: 301/302 may or may not change POST to GET, 303 MUST change to GET, 307/308 preserve method. The Haskell implementation treats 301/302/303/307 identically. The OCaml library should document its redirect behavior and potentially allow configuration of: which status codes to follow, whether to change methods, and custom redirect handlers. This is important for API clients with specific redirect requirements." 138 + }, 139 + { 140 + "source_repo": "third_party/haskell/http-streams", 141 + "source_language": "Haskell", 142 + "criticality": "low", 143 + "change_type": "enhancement", 144 + "title": "Implement URL encoding utilities for query parameters and form bodies", 145 + "description": "http-streams provides `urlEncode` and `urlEncodeBuilder` functions (Inconvenience.hs:111-158) that properly encode strings per RFC 2396, including special handling for space as '+' in form data. Add public URL encoding utilities to help users safely construct URLs with query parameters and properly encode form data.", 146 + "affected_files": [ 147 + "lib/requests.ml", 148 + "lib/body.ml" 149 + ], 150 + "rationale": "While the Uri library handles URL parsing, users often need to construct URLs with query parameters or encode form data. The Haskell library demonstrates that proper URL encoding requires careful handling: alphanumerics and specific characters ($-_.!~*'(),) pass through, spaces become '+', others become %XX. The OCaml library's `Body.form` likely handles this, but exposing utility functions like `encode_query_param` and `encode_form_value` would help users build URLs safely." 151 + }, 152 + { 153 + "source_repo": "third_party/haskell/http-streams", 154 + "source_language": "Haskell", 155 + "criticality": "high", 156 + "change_type": "security", 157 + "title": "Add deflate decompression support for Content-Encoding", 158 + "description": "http-streams throws UnexpectedCompression exception for deflate encoding (ResponseParser.hs:136), supporting only gzip. The OCaml library uses the decompress library which supports deflate, gzip, and zlib. Ensure all three compression formats are properly supported since deflate is a valid HTTP Content-Encoding per RFC 7231.", 159 + "affected_files": [ 160 + "lib/http_client.ml", 161 + "lib/requests.ml" 162 + ], 163 + "rationale": "RFC 7231 §3.1.2.2 defines both 'gzip' and 'deflate' as standard Content-Encoding values. While gzip is more common, some servers use deflate. The Haskell library explicitly rejects deflate, but the OCaml library has access to the decompress library which supports all three formats (gzip, deflate, zlib). Verify that auto_decompress handles deflate correctly, and if not, add support to avoid rejecting valid compressed responses." 164 + }, 165 + { 166 + "source_repo": "third_party/haskell/http-streams", 167 + "source_language": "Haskell", 168 + "criticality": "medium", 169 + "change_type": "feature", 170 + "title": "Add testing utilities for creating mock connections with pre-recorded responses", 171 + "description": "http-streams provides `makeConnection` (Connection.hs:111-123) and demonstrates creating fake connections with pre-recorded responses for testing (e.g., `fakeConnection` pattern). Expose utilities in the OCaml library to create mock HTTP connections for testing user code without network I/O, using in-memory flows with pre-recorded HTTP responses.", 172 + "affected_files": [ 173 + "lib/http_client.ml", 174 + "lib/requests.ml", 175 + "test/" 176 + ], 177 + "rationale": "The Haskell library's documentation shows creating connections from in-memory streams: `o <- Streams.nullOutput; i <- Streams.fromByteString response; makeConnection host noop o i`. This enables unit testing of HTTP client code without actual network calls. The OCaml library could provide similar testing utilities using Eio.Flow.string_source and Eio.Flow.buffer_sink, making it easier for users to test their HTTP client code with predictable responses." 178 + }, 179 + { 180 + "source_repo": "third_party/haskell/http-streams", 181 + "source_language": "Haskell", 182 + "criticality": "low", 183 + "change_type": "refactor", 184 + "title": "Add builder pattern for multipart form construction", 185 + "description": "http-streams provides builder functions for multipart parts: `simplePart`, `filePart`, `inputStreamPart` (Inconvenience.hs:566-604) that compose into a parts list. The OCaml library has `Body.multipart` taking a list of parts. Consider adding builder functions like `Part.string`, `Part.file`, `Part.stream` to make multipart form construction more discoverable and type-safe.", 186 + "affected_files": [ 187 + "lib/body.ml", 188 + "lib/body.mli" 189 + ], 190 + "rationale": "The Haskell library's multipart API is very clear: `parts = [simplePart name ct value, filePart name ct path]`. The OCaml equivalent uses a single `part` record type with variant content. Adding named constructors like `Part.of_string`, `Part.of_file` would improve discoverability and provide better type-directed programming. This is a minor ergonomic improvement but makes the API more self-documenting." 191 + }, 192 + { 193 + "source_repo": "third_party/haskell/http-streams", 194 + "source_language": "Haskell", 195 + "criticality": "medium", 196 + "change_type": "enhancement", 197 + "title": "Add HTTP pipelining support documentation and safety warnings", 198 + "description": "http-streams explicitly documents HTTP pipelining support (Connection.hs:165-172) but warns users about matching request/response counts and notes that not all servers support it. Document the OCaml library's approach to pipelining with connection pooling, including any safety mechanisms or limitations users should be aware of.", 199 + "affected_files": [ 200 + "README.md", 201 + "lib/http_client.ml", 202 + "lib/requests.ml" 203 + ], 204 + "rationale": "The Haskell library's documentation warns: 'you can reuse the connection to a web server, but it's up to you to ensure you match the number of requests sent to the number of responses read, and to process those responses in order'. With connection pooling, pipelining interactions become complex. The OCaml library should document: 1) Whether pipelining is supported, 2) If connection pool reuse allows pipelining, 3) Safety mechanisms to prevent protocol desynchronization, 4) Performance implications." 205 + } 206 + ] 207 + }
+271
third_party/haskell/req.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "haskell/req", 5 + "source_language": "Haskell", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add response body preview in error messages", 9 + "description": "When HTTP errors occur (4xx, 5xx status codes), include a preview of the response body (first 1024 bytes) in the HTTPError exception. This helps with debugging by showing error messages from the server without requiring users to manually inspect the response body.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/http_client.ml", 13 + "lib/requests.ml" 14 + ], 15 + "rationale": "The Haskell req library captures the first 1024 bytes of response body in exceptions via httpConfigBodyPreviewLength. This is invaluable for debugging as server error responses often contain detailed error messages. The OCaml library currently has an optional body field in HTTPError but it's not automatically populated with a preview. Adding this would improve the debugging experience significantly." 16 + }, 17 + { 18 + "source_repo": "haskell/req", 19 + "source_language": "Haskell", 20 + "criticality": "low", 21 + "change_type": "enhancement", 22 + "title": "Add OAuth 1.0 authentication support", 23 + "description": "Implement OAuth 1.0 authentication mechanism with request signing. This requires generating signatures using HMAC-SHA1, handling nonce generation, timestamp management, and proper parameter encoding according to RFC 5849.", 24 + "affected_files": [ 25 + "lib/auth.ml", 26 + "lib/auth.mli" 27 + ], 28 + "rationale": "The req library supports OAuth 1.0 via the oAuth1 function using the authenticate-oauth package. While OAuth 2.0 (Bearer tokens) is more common, OAuth 1.0 is still required for certain APIs like Twitter's legacy API. The OCaml library currently supports Basic, Bearer, and Digest auth, but lacks OAuth 1.0. This would provide comprehensive authentication coverage." 29 + }, 30 + { 31 + "source_repo": "haskell/req", 32 + "source_language": "Haskell", 33 + "criticality": "medium", 34 + "change_type": "enhancement", 35 + "title": "Implement configurable response validation callback", 36 + "description": "Add a configurable callback function that validates responses before the body is consumed. This should allow users to customize which status codes trigger exceptions and enable early rejection of invalid responses. The callback should receive the request, response headers, status code, and body preview.", 37 + "affected_files": [ 38 + "lib/requests.ml", 39 + "lib/requests.mli", 40 + "lib/one.ml" 41 + ], 42 + "rationale": "The req library has httpConfigCheckResponse that validates responses before body consumption, preventing parsing of malicious payloads. This is a security feature and usability improvement. The OCaml library currently requires users to call raise_for_status explicitly or check status codes manually. A configurable validation hook would provide better defaults and security." 43 + }, 44 + { 45 + "source_repo": "haskell/req", 46 + "source_language": "Haskell", 47 + "criticality": "low", 48 + "change_type": "enhancement", 49 + "title": "Add redacted header logging support", 50 + "description": "Implement a mechanism to mark headers as redacted for logging purposes. When logging requests, these headers should show '[REDACTED]' instead of their actual values to prevent leaking sensitive information like Authorization tokens in logs.", 51 + "affected_files": [ 52 + "lib/headers.ml", 53 + "lib/headers.mli" 54 + ], 55 + "rationale": "The req library has headerRedacted which allows marking headers for redacted logging. This is a security best practice when logging HTTP requests, as sensitive headers (Authorization, API keys, cookies) should not appear in logs. The OCaml library currently logs all headers as-is, which could leak credentials." 56 + }, 57 + { 58 + "source_repo": "haskell/req", 59 + "source_language": "Haskell", 60 + "criticality": "high", 61 + "change_type": "security", 62 + "title": "Enforce HTTPS for sensitive authentication methods", 63 + "description": "Add runtime validation that Basic authentication and Bearer tokens are only used with HTTPS URLs. When these authentication methods are applied to HTTP URLs, raise an error or log a strong warning. Consider adding a configuration flag to make this enforcement strict or lenient.", 64 + "affected_files": [ 65 + "lib/auth.ml", 66 + "lib/requests.ml", 67 + "lib/one.ml" 68 + ], 69 + "rationale": "The req library uses type-level enforcement to require HTTPS for basicAuth and oAuth2Bearer (via Url 'Https type). While OCaml cannot enforce this at the type level the same way, runtime validation is critical for security. Sending credentials over unencrypted HTTP is a serious security vulnerability. The current OCaml implementation allows this without any warning." 70 + }, 71 + { 72 + "source_repo": "haskell/req", 73 + "source_language": "Haskell", 74 + "criticality": "medium", 75 + "change_type": "enhancement", 76 + "title": "Add automatic URL path segment encoding", 77 + "description": "Ensure all path segments added to URLs are automatically percent-encoded to prevent injection attacks and handle special characters correctly. Add helper functions for safe URL construction that automatically encode segments.", 78 + "affected_files": [ 79 + "lib/requests.ml", 80 + "lib/one.ml" 81 + ], 82 + "rationale": "The req library's URL construction (/:) automatically percent-encodes all path segments, making URLs 'correct by construction' and preventing path traversal/injection vulnerabilities. The OCaml library uses Uri which handles encoding, but explicit guidance and helper functions would ensure users don't accidentally create unsafe URLs by manual string concatenation." 83 + }, 84 + { 85 + "source_repo": "haskell/req", 86 + "source_language": "Haskell", 87 + "criticality": "low", 88 + "change_type": "feature", 89 + "title": "Add compile-time URL validation using PPX", 90 + "description": "Create a PPX extension (similar to Haskell's QuasiQuoter urlQ) that validates URL strings at compile-time. This would catch malformed URLs during development rather than at runtime.", 91 + "affected_files": [ 92 + "lib/ppx_url.ml (new file)" 93 + ], 94 + "rationale": "The req library provides urlQ QuasiQuoter for compile-time URL validation. While this is a Haskell-specific feature, OCaml can achieve similar functionality with PPX extensions. This catches typos and malformed URLs during compilation, improving developer experience and reducing runtime errors." 95 + }, 96 + { 97 + "source_repo": "haskell/req", 98 + "source_language": "Haskell", 99 + "criticality": "low", 100 + "change_type": "enhancement", 101 + "title": "Add query flag support for valueless parameters", 102 + "description": "Add a dedicated function for query parameters without values (flags), which are common in some APIs (e.g., ?debug or ?verbose). Currently users must use empty string values.", 103 + "affected_files": [ 104 + "lib/requests.ml", 105 + "lib/requests.mli", 106 + "lib/one.ml", 107 + "lib/one.mli" 108 + ], 109 + "rationale": "The req library has queryFlag for parameters without values, which properly encodes them as ?flag instead of ?flag=. The OCaml library likely requires using empty strings or custom encoding. A dedicated API makes intent clearer and handles edge cases correctly." 110 + }, 111 + { 112 + "source_repo": "haskell/req", 113 + "source_language": "Haskell", 114 + "criticality": "medium", 115 + "change_type": "enhancement", 116 + "title": "Improve retry exception handling with explicit exception classification", 117 + "description": "Extend retry logic to include more granular exception handling. Specifically, add retry on ResponseTimeout and ConnectionTimeout exceptions by default, and provide a configurable callback for users to determine if custom exceptions should trigger retries.", 118 + "affected_files": [ 119 + "lib/retry.ml", 120 + "lib/retry.mli", 121 + "lib/requests.ml" 122 + ], 123 + "rationale": "The req library added exception-based retry in version 3.8.0, retrying on ResponseTimeout and ConnectionTimeout exceptions in addition to status codes. The OCaml library has retry logic but the exception handling could be more explicit and configurable. The current should_retry_exn is defined at call site but should be part of the retry configuration." 124 + }, 125 + { 126 + "source_repo": "haskell/req", 127 + "source_language": "Haskell", 128 + "criticality": "high", 129 + "change_type": "bug", 130 + "title": "Fix potential race condition in retry with Retry-After header", 131 + "description": "The retry logic parses Retry-After headers but should be integrated into the retry configuration callback. Ensure that when a 429 or 503 response includes Retry-After, the backoff calculation respects this header even if it's longer than backoff_max.", 132 + "affected_files": [ 133 + "lib/retry.ml", 134 + "lib/requests.ml" 135 + ], 136 + "rationale": "The req library's retry system properly integrates Retry-After header handling into the retry policy. The OCaml library has parse_retry_after function and respect_retry_after config, but inspection shows it's not clearly integrated into the actual retry logic in with_retry. This could lead to not respecting server-specified backoff times, potentially causing rate limit issues." 137 + }, 138 + { 139 + "source_repo": "haskell/req", 140 + "source_language": "Haskell", 141 + "criticality": "medium", 142 + "change_type": "enhancement", 143 + "title": "Add custom HTTP method support validation", 144 + "description": "For custom HTTP methods (Method.Other), add validation that ensures the method name contains only valid HTTP token characters (alphanumeric and !#$%&'*+-.^_`|~) per RFC 7230. Reject invalid method names early rather than sending malformed requests.", 145 + "affected_files": [ 146 + "lib/method.ml", 147 + "lib/method.mli" 148 + ], 149 + "rationale": "The req library's HttpMethod typeclass provides extension points for custom methods with validation. The OCaml library supports custom methods via polymorphic variant `Other of string but doesn't validate the method name. Invalid method names could cause protocol violations or security issues." 150 + }, 151 + { 152 + "source_repo": "haskell/req", 153 + "source_language": "Haskell", 154 + "criticality": "low", 155 + "change_type": "enhancement", 156 + "title": "Add proxy authentication support", 157 + "description": "Implement proxy authentication (Basic auth for proxies) separate from regular authentication. Add configuration for proxy credentials that are applied to CONNECT requests and proxy connections.", 158 + "affected_files": [ 159 + "lib/auth.ml", 160 + "lib/requests.ml", 161 + "lib/one.ml" 162 + ], 163 + "rationale": "The req library has basicProxyAuth for proxy authentication, which is separate from regular authentication. The OCaml library defines ProxyError but doesn't implement proxy authentication. This is needed for corporate environments where HTTP proxies require authentication." 164 + }, 165 + { 166 + "source_repo": "haskell/req", 167 + "source_language": "Haskell", 168 + "criticality": "low", 169 + "change_type": "refactor", 170 + "title": "Add HttpMethod and HttpBody abstraction traits", 171 + "description": "Create abstract interfaces (modules with module types) for HTTP methods and body types that allow users to define custom methods and body types without modifying library code. This would enable extension without editing core library files.", 172 + "affected_files": [ 173 + "lib/method.ml", 174 + "lib/body.ml" 175 + ], 176 + "rationale": "The req library has HttpMethod and HttpBody typeclasses that make it expandable - users can define custom methods and body types. While the OCaml library uses polymorphic variants which are somewhat extensible, formal abstraction interfaces would provide better documentation and type safety for extensions." 177 + }, 178 + { 179 + "source_repo": "haskell/req", 180 + "source_language": "Haskell", 181 + "criticality": "medium", 182 + "change_type": "enhancement", 183 + "title": "Add HTTP version configuration option", 184 + "description": "Allow users to specify which HTTP version to use (HTTP/1.0, HTTP/1.1, HTTP/2). Add configuration option for HTTP version preference and fallback behavior.", 185 + "affected_files": [ 186 + "lib/requests.ml", 187 + "lib/requests.mli", 188 + "lib/http_client.ml" 189 + ], 190 + "rationale": "The req library has httpVersion option to configure HTTP protocol version. The OCaml library appears to hardcode HTTP/1.1. Some APIs or debugging scenarios require HTTP/1.0, and HTTP/2 support would improve performance. This should be configurable." 191 + }, 192 + { 193 + "source_repo": "haskell/req", 194 + "source_language": "Haskell", 195 + "criticality": "medium", 196 + "change_type": "enhancement", 197 + "title": "Add response decompression configuration", 198 + "description": "Make automatic decompression configurable with a decompress option that allows users to disable automatic decompression for specific requests. This is useful when users want to handle decompression manually or when downloading pre-compressed files.", 199 + "affected_files": [ 200 + "lib/requests.ml", 201 + "lib/one.ml" 202 + ], 203 + "rationale": "The req library has a decompress option to control automatic response decompression. The OCaml library has auto_decompress flag in session config but it should also be controllable per-request. Some use cases require raw compressed data (downloading .gz files, custom decompression, debugging)." 204 + }, 205 + { 206 + "source_repo": "haskell/req", 207 + "source_language": "Haskell", 208 + "criticality": "low", 209 + "change_type": "enhancement", 210 + "title": "Improve test coverage with property-based testing", 211 + "description": "Add property-based tests using QCheck (OCaml's QuickCheck equivalent) to test URL encoding, header manipulation, authentication header generation, and retry backoff calculations. Generate random inputs to verify invariants.", 212 + "affected_files": [ 213 + "test/test_properties.ml (new file)" 214 + ], 215 + "rationale": "The req library has extensive QuickCheck property tests in pure-tests/Network/HTTP/ReqSpec.hs that test URL construction, encoding, and other pure functions with random inputs. The OCaml library has good integration tests but would benefit from property-based testing to catch edge cases in URL encoding, header handling, and retry logic." 216 + }, 217 + { 218 + "source_repo": "haskell/req", 219 + "source_language": "Haskell", 220 + "criticality": "low", 221 + "change_type": "enhancement", 222 + "title": "Add cookie jar configuration and manipulation API", 223 + "description": "Expose more cookie jar operations: get cookies for specific domain/path, manually add cookies, remove specific cookies, export/import cookie jar. Currently the library only supports clearing all cookies.", 224 + "affected_files": [ 225 + "lib/requests.ml", 226 + "lib/requests.mli" 227 + ], 228 + "rationale": "The req library has cookieJar option that allows users to manipulate and inject cookie jars. The OCaml library uses Cookeio_jar but only exposes cookies and clear_cookies functions. More granular cookie manipulation would be useful for testing, session management, and working with multiple user sessions." 229 + }, 230 + { 231 + "source_repo": "haskell/req", 232 + "source_language": "Haskell", 233 + "criticality": "medium", 234 + "change_type": "enhancement", 235 + "title": "Add streaming request body support with backpressure", 236 + "description": "Implement streaming request body support that can stream data from a source with backpressure handling. This should integrate with Eio's streaming primitives to allow uploading large files or generated data without loading everything into memory.", 237 + "affected_files": [ 238 + "lib/body.ml", 239 + "lib/body.mli", 240 + "lib/http_client.ml" 241 + ], 242 + "rationale": "The req library has a companion package req-conduit for streaming support. While the OCaml library has Body.of_stream, the streaming implementation should ensure proper backpressure handling and efficient chunk transfer. This is critical for uploading large files or streaming generated content." 243 + }, 244 + { 245 + "source_repo": "haskell/req", 246 + "source_language": "Haskell", 247 + "criticality": "low", 248 + "change_type": "feature", 249 + "title": "Add connection manager configuration options", 250 + "description": "Expose more connection pool configuration: max total connections (not just per-host), connection timeout for pool acquisition, validation query for stale connections. Currently the library uses Conpool with basic configuration.", 251 + "affected_files": [ 252 + "lib/requests.ml", 253 + "lib/requests.mli" 254 + ], 255 + "rationale": "The req library allows configuring the connection manager via withReqManager and alternate manager configuration. The OCaml library uses Conpool but could expose more configuration options for advanced use cases like connection validation, acquisition timeouts, and global connection limits across all hosts." 256 + }, 257 + { 258 + "source_repo": "haskell/req", 259 + "source_language": "Haskell", 260 + "criticality": "medium", 261 + "change_type": "enhancement", 262 + "title": "Add isStatusCodeException helper for error classification", 263 + "description": "Add utility functions to extract and classify HTTP exceptions: is_status_code_exception to check if error is HTTPError, get_status_code to extract status from HTTPError, is_client_error_status, is_server_error_status. This simplifies error handling code.", 264 + "affected_files": [ 265 + "lib/error.ml", 266 + "lib/error.mli" 267 + ], 268 + "rationale": "The req library provides isStatusCodeException helper for extracting StatusCodeException from HttpException. The OCaml library has error classification functions (is_client_error, is_server_error) but they could be enhanced with more specific helpers for common error handling patterns like extracting status codes and checking specific error types." 269 + } 270 + ] 271 + }
+265
third_party/java/http-request.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/java/http-request", 5 + "source_language": "Java", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add convenience status code checking methods", 9 + "description": "The Java library provides rich boolean methods like ok(), created(), noContent(), badRequest(), serverError(), notFound(), notModified() for checking response status codes. The OCaml library only has Response.ok and requires manual status code checking for other cases.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/response.mli" 13 + ], 14 + "rationale": "The Java library has 15+ status checking convenience methods (ok(), created(), noContent(), accepted(), badRequest(), unauthorized(), forbidden(), notFound(), notModified(), serverError(), etc.) that make code more readable and less error-prone. Currently, OCaml users must manually check status codes with pattern matching or comparisons. Adding convenience methods like Response.created, Response.no_content, Response.bad_request, Response.not_found would improve ergonomics and match common usage patterns. This is especially valuable since the Status module already has comprehensive status code definitions." 15 + }, 16 + { 17 + "source_repo": "third_party/java/http-request", 18 + "source_language": "Java", 19 + "criticality": "medium", 20 + "change_type": "feature", 21 + "title": "Add conditional request helpers (ETag and Last-Modified support)", 22 + "description": "The Java library provides built-in support for conditional requests with ifModifiedSince(), ifNoneMatch(), eTag(), lastModified(), date(), and expires() methods. The OCaml library lacks dedicated support for HTTP caching headers.", 23 + "affected_files": [ 24 + "lib/requests.ml", 25 + "lib/one.ml", 26 + "lib/response.ml", 27 + "lib/headers.ml" 28 + ], 29 + "rationale": "The Java library has comprehensive caching support: ifModifiedSince(long) sets If-Modified-Since header, ifNoneMatch(String) sets If-None-Match, eTag() retrieves ETag from response, lastModified()/date()/expires() parse date headers. The OCaml library requires manual header manipulation for conditional requests. Adding dedicated methods would enable efficient caching patterns: let etag = Response.etag response in Requests.get session ~headers:(Headers.if_none_match etag) url. This is a common pattern in production HTTP clients for reducing bandwidth and server load." 30 + }, 31 + { 32 + "source_repo": "third_party/java/http-request", 33 + "source_language": "Java", 34 + "criticality": "low", 35 + "change_type": "enhancement", 36 + "title": "Add compression control methods", 37 + "description": "The Java library provides explicit acceptGzipEncoding() and uncompress(bool) methods for fine-grained compression control. The OCaml library has auto_decompress as a session-level flag but lacks per-request compression negotiation.", 38 + "affected_files": [ 39 + "lib/requests.ml", 40 + "lib/one.ml", 41 + "lib/http_client.ml" 42 + ], 43 + "rationale": "The Java library allows per-request compression control with acceptGzipEncoding() to request compression and uncompress(true/false) to control decompression. The OCaml library only has auto_decompress at session creation (line 78 in requests.ml) and automatically adds Accept-Encoding: gzip, deflate if enabled (lines 251-256). Adding per-request compression control would allow users to optimize specific requests - for example, requesting compression for large text responses but not for already-compressed binary data, or handling responses where server-side decompression is preferred." 44 + }, 45 + { 46 + "source_repo": "third_party/java/http-request", 47 + "source_language": "Java", 48 + "criticality": "low", 49 + "change_type": "enhancement", 50 + "title": "Add receive() methods for streaming responses to files/outputs", 51 + "description": "The Java library provides receive(File), receive(OutputStream), receive(Writer) methods to stream response bodies directly to outputs without loading into memory. The OCaml library's Response.text always loads the full body into memory.", 52 + "affected_files": [ 53 + "lib/response.ml", 54 + "lib/response.mli" 55 + ], 56 + "rationale": "The Java library has receive(File), receive(OutputStream), receive(Writer), receive(Appendable) for streaming responses. The OCaml Response.body returns a flow source (line 63-67 in response.ml), and Response.text loads the entire body into memory with Eio.Buf_read.take_all (line 73). While the flow source enables streaming, there's no convenience method to stream directly to a file. Adding Response.save_to_file response path and Response.stream_to response flow would make common streaming patterns more ergonomic, especially for large file downloads where memory constraints matter." 57 + }, 58 + { 59 + "source_repo": "third_party/java/http-request", 60 + "source_language": "Java", 61 + "criticality": "high", 62 + "change_type": "bug", 63 + "title": "Add request body support for PATCH method", 64 + "description": "The Java library's patch() method supports request bodies, but the OCaml library's Requests.patch function accepts ?body parameter. Need to verify that PATCH with body is properly tested and documented.", 65 + "affected_files": [ 66 + "lib/requests.ml", 67 + "test/test_simple.ml", 68 + "test/test_localhost.ml" 69 + ], 70 + "rationale": "The Java library's patch() follows the same pattern as post() and put() with full body support (around line 1100-1150). The OCaml library has PATCH support in requests.ml:578-579 with optional ?body parameter, which is correct. However, reviewing the test files shows no explicit PATCH tests with body content. PATCH is commonly used for partial updates in REST APIs and must support request bodies. Adding comprehensive PATCH tests with JSON/form bodies would ensure correctness, especially since PATCH is in the retry allowed_methods list (retry.ml:24) which assumes idempotency that should be verified with proper testing." 71 + }, 72 + { 73 + "source_repo": "third_party/java/http-request", 74 + "source_language": "Java", 75 + "criticality": "medium", 76 + "change_type": "enhancement", 77 + "title": "Add buffer size configuration", 78 + "description": "The Java library provides bufferSize(int) method to configure buffer sizes for streaming operations (default 8192 bytes). The OCaml library uses hardcoded buffer sizes in multiple locations.", 79 + "affected_files": [ 80 + "lib/http_client.ml", 81 + "lib/body.ml", 82 + "lib/requests.ml" 83 + ], 84 + "rationale": "The Java library has bufferSize(int) method (around line 1655) with a default of 8192 bytes, configurable per request. The OCaml library uses hardcoded buffer sizes: De.io_buffer_size for decompression (http_client.ml:16, 17), 8192 for fixed body reads (http_client.ml:201), 4096 for chunked reads (http_client.ml:212). While these are reasonable defaults, allowing configuration would help with performance tuning - larger buffers for high-throughput scenarios, smaller buffers for memory-constrained environments. Adding a buffer_size field to the session configuration and passing it through to read operations would provide this flexibility." 85 + }, 86 + { 87 + "source_repo": "third_party/java/http-request", 88 + "source_language": "Java", 89 + "criticality": "low", 90 + "change_type": "enhancement", 91 + "title": "Add array parameter encoding support", 92 + "description": "The Java library automatically handles array parameters by encoding them with bracket notation (e.g., ?id[]=1&id[]=2&id[]=3). The OCaml library requires manual list handling for array parameters.", 93 + "affected_files": [ 94 + "lib/requests.ml", 95 + "lib/one.ml" 96 + ], 97 + "rationale": "The Java library's encode method handles arrays specially: get(url, true, \"id\", new int[]{1,2,3}) becomes ?id[]=1&id[]=2&id[]=3 (documented in README around line 150). The OCaml library's params parameter in Requests.get (line 562-568) takes a (string * string) list, requiring users to manually create multiple tuples for array values. Many web frameworks expect array parameters with brackets or repeated keys. Adding an extended params type that accepts (string * [string | string list]) would enable: Requests.get session ~params:[(\"id\", `List [\"1\"; \"2\"; \"3\"])] url. This matches common API patterns in frameworks like Rails, Django, and PHP." 98 + }, 99 + { 100 + "source_repo": "third_party/java/http-request", 101 + "source_language": "Java", 102 + "criticality": "medium", 103 + "change_type": "enhancement", 104 + "title": "Add ignoreCloseExceptions configuration option", 105 + "description": "The Java library provides ignoreCloseExceptions(bool) to control whether exceptions during resource cleanup are suppressed or propagated. This is important for production robustness.", 106 + "affected_files": [ 107 + "lib/response.ml", 108 + "lib/http_client.ml", 109 + "lib/requests.ml" 110 + ], 111 + "rationale": "The Java library's ignoreCloseExceptions(true) (around line 2395) suppresses exceptions during stream/connection closure to prevent cleanup errors from masking the original error. This is a production hardening feature - if a request fails and then closing the connection also fails, you want the original error, not the close error. The OCaml library doesn't have explicit close exception handling configuration. Eio's structured concurrency handles cleanup via switches (response.ml:23-34), but adding an ignore_close_exceptions flag to session config would allow users to control whether cleanup errors are logged-and-ignored vs. propagated, especially important when debugging connection pool issues." 112 + }, 113 + { 114 + "source_repo": "third_party/java/http-request", 115 + "source_language": "Java", 116 + "criticality": "medium", 117 + "change_type": "feature", 118 + "title": "Add upload progress callback support", 119 + "description": "The Java library provides an UploadProgress interface for monitoring large uploads. The OCaml library has no built-in progress tracking mechanism.", 120 + "affected_files": [ 121 + "lib/body.ml", 122 + "lib/http_client.ml" 123 + ], 124 + "rationale": "The Java library has an UploadProgress interface (around line 730) that receives callbacks during upload: onUpload(long uploaded, long total). This is essential for UX in applications uploading large files - users need progress feedback. The OCaml library streams bodies via Eio.Flow but has no progress hooks. Adding an optional progress callback to Body.t and invoking it during stream copying in http_client.ml:244 (Eio.Flow.copy_string) would enable: let body = Body.of_file ~progress:(fun uploaded total -> ...) file. This is particularly valuable for multipart uploads and large file transfers where progress indication is expected UX." 125 + }, 126 + { 127 + "source_repo": "third_party/java/http-request", 128 + "source_language": "Java", 129 + "criticality": "low", 130 + "change_type": "enhancement", 131 + "title": "Add user agent shortcuts and configuration", 132 + "description": "The Java library provides userAgent(String) method as a shortcut for setting User-Agent header. The OCaml library requires manual header setting or session configuration.", 133 + "affected_files": [ 134 + "lib/requests.ml", 135 + "lib/one.ml" 136 + ], 137 + "rationale": "The Java library has a userAgent(String) convenience method (around line 2600) for this common header. The OCaml library supports user agent via Cmd module (requests.ml:683-687) and default headers (line 629-632), but there's no per-request user_agent parameter. While users can use ~headers:(Headers.set \"User-Agent\" ...), a dedicated parameter would be more discoverable: Requests.get session ~user_agent:\"MyBot/1.0\" url. Many APIs require specific user agents for rate limiting, analytics, or access control, making this a frequently-set header that deserves first-class support." 138 + }, 139 + { 140 + "source_repo": "third_party/java/http-request", 141 + "source_language": "Java", 142 + "criticality": "high", 143 + "change_type": "security", 144 + "title": "Add Proxy-Authorization header stripping on cross-origin redirects", 145 + "description": "The OCaml library strips Authorization headers on cross-origin redirects (line 213 in requests.ml) but doesn't strip Proxy-Authorization. The Java library has dedicated proxy auth methods that should inform credential handling.", 146 + "affected_files": [ 147 + "lib/requests.ml" 148 + ], 149 + "rationale": "The Java library has separate proxyBasic() and proxyAuthorization() methods (lines 2495-2497) for proxy authentication, distinct from server authentication. The OCaml library's strip_sensitive_headers function (requests.ml:211-213) only removes Authorization but not Proxy-Authorization. While proxy credentials are less commonly used, they should also be stripped on cross-origin redirects to prevent credential leakage. If a proxy-authenticated request redirects to a different origin, the proxy credentials shouldn't follow. Updating strip_sensitive_headers to also remove Proxy-Authorization would close this potential security gap." 150 + }, 151 + { 152 + "source_repo": "third_party/java/http-request", 153 + "source_language": "Java", 154 + "criticality": "medium", 155 + "change_type": "enhancement", 156 + "title": "Add HEAD request optimization to skip body reading", 157 + "description": "HEAD requests should not read response bodies per HTTP spec, but the OCaml library may unnecessarily read body data based on Content-Length header.", 158 + "affected_files": [ 159 + "lib/http_client.ml" 160 + ], 161 + "rationale": "The Java library and HTTP spec (RFC 7231 Section 4.3.2) state that HEAD responses MUST NOT include a message body, even if Content-Length is present. The OCaml http_client.ml:258-274 reads body based on transfer-encoding and content-length headers without checking the request method. For HEAD requests, the library should skip body reading entirely even if Content-Length is set, as servers may include Content-Length to indicate what a GET would return. This is both a correctness issue (violates HTTP spec) and a performance optimization (avoids unnecessary I/O). The make_request function should accept the HTTP method and skip body reading for HEAD and possibly other methods like CONNECT." 162 + }, 163 + { 164 + "source_repo": "third_party/java/http-request", 165 + "source_language": "Java", 166 + "criticality": "low", 167 + "change_type": "enhancement", 168 + "title": "Add charset parameter to form encoding", 169 + "description": "The Java library's form() method accepts an optional charset parameter for international form data. The OCaml library's Body.form uses hardcoded UTF-8 encoding.", 170 + "affected_files": [ 171 + "lib/body.ml" 172 + ], 173 + "rationale": "The Java library has form(Map, String charset) overload (around line 1900) to support different character encodings for form data, though UTF-8 is recommended. The OCaml Body.form function (body.ml:106-113) uses Uri.pct_encode which encodes to UTF-8. While UTF-8 is the modern standard and recommended for web forms (HTML5 default), some legacy systems expect different encodings (ISO-8859-1, Windows-1252). Adding an optional ?charset parameter to Body.form would support these edge cases: Body.form ~charset:\"ISO-8859-1\" params. However, this is low priority as UTF-8 handles 99%+ of use cases and the complexity of charset conversion may not justify the benefit." 174 + }, 175 + { 176 + "source_repo": "third_party/java/http-request", 177 + "source_language": "Java", 178 + "criticality": "medium", 179 + "change_type": "enhancement", 180 + "title": "Add connection lifecycle management methods", 181 + "description": "The Java library provides disconnect() to explicitly close connections and useCaches(bool) to control URL caching. The OCaml library relies entirely on automatic connection pool lifecycle.", 182 + "affected_files": [ 183 + "lib/requests.ml" 184 + ], 185 + "rationale": "The Java library has disconnect() (line 1670) to force-close connections and useCaches(bool) (line 2348) to control caching behavior. The OCaml library uses Conpool for automatic connection management with idle timeouts (connection_idle_timeout=60.0, connection_lifetime=300.0 in requests.ml:73-74). While automatic management is generally better, providing an explicit connection flush/close method could be useful for testing or forcing connection rotation before the timeout expires. Adding Requests.close_idle_connections session would invoke the underlying pool's cleanup. This is more about API completeness than critical functionality, as the timeout-based approach handles most cases well." 186 + }, 187 + { 188 + "source_repo": "third_party/java/http-request", 189 + "source_language": "Java", 190 + "criticality": "low", 191 + "change_type": "feature", 192 + "title": "Add custom ConnectionFactory support", 193 + "description": "The Java library allows injecting custom ConnectionFactory to use alternative HTTP implementations (e.g., OkHttp). The OCaml library is tightly coupled to its Eio-based implementation.", 194 + "affected_files": [ 195 + "lib/requests.ml", 196 + "lib/http_client.ml" 197 + ], 198 + "rationale": "The Java library has a ConnectionFactory interface (around line 710) allowing users to provide custom connection implementations, enabling integration with libraries like OkHttp while keeping the high-level API. The OCaml library is hardcoded to use Eio flows and Conpool. While the current implementation is appropriate for Eio-based applications, providing a connection factory abstraction would allow: (1) testing with mock connections, (2) integration with other async runtimes if OCaml gains more runtime options, (3) custom protocol handling. However, given OCaml's ecosystem convergence on Eio and the complexity of defining a connection abstraction, this is low priority unless testing needs demand it." 199 + }, 200 + { 201 + "source_repo": "third_party/java/http-request", 202 + "source_language": "Java", 203 + "criticality": "medium", 204 + "change_type": "enhancement", 205 + "title": "Improve retry-after header handling in retry logic", 206 + "description": "The OCaml library has parse_retry_after function in retry.ml but it's not integrated into the main retry flow in requests.ml. The Java library doesn't have built-in retry, but the OCaml implementation should leverage its own retry-after parsing.", 207 + "affected_files": [ 208 + "lib/requests.ml", 209 + "lib/retry.ml" 210 + ], 211 + "rationale": "The retry.ml module has a parse_retry_after function (lines 73-93) that handles both integer seconds and HTTP date formats, and the config has respect_retry_after flag (line 15). However, the retry implementation in requests.ml (lines 526-559) doesn't actually use the response headers to check for Retry-After. It only uses calculate_backoff for exponential backoff. To properly respect Retry-After headers (especially for 429 Too Many Requests and 503 Service Unavailable), the retry logic should: (1) check response headers for Retry-After, (2) use that delay if present and config.respect_retry_after is true, (3) fall back to exponential backoff otherwise. This would make the library more compliant with HTTP specs and API rate limiting best practices." 212 + }, 213 + { 214 + "source_repo": "third_party/java/http-request", 215 + "source_language": "Java", 216 + "criticality": "high", 217 + "change_type": "bug", 218 + "title": "Fix potential cookie security issue with cross-origin redirects", 219 + "description": "The OCaml library strips Authorization header on cross-origin redirects but doesn't strip Cookie header, potentially leaking session cookies to different origins.", 220 + "affected_files": [ 221 + "lib/requests.ml" 222 + ], 223 + "rationale": "The Java library's design keeps cookies and authorization separate. The OCaml library's strip_sensitive_headers function (requests.ml:211-213) only removes Authorization header but not Cookie header. When a redirect crosses origins (different host), cookies should also be stripped to prevent session hijacking. For example, if example.com redirects to attacker.com, the user's example.com cookies shouldn't be sent to attacker.com. The same_origin check (lines 198-208) considers scheme upgrades (http→https) safe, which is correct for cookies on the same domain. However, the stripping logic should remove Cookie header when origins don't match: Lines 418-419 should invoke a more comprehensive strip function that removes both Authorization and Cookie headers. This is a security issue that could lead to credential/session leakage." 224 + }, 225 + { 226 + "source_repo": "third_party/java/http-request", 227 + "source_language": "Java", 228 + "criticality": "medium", 229 + "change_type": "refactor", 230 + "title": "Simplify multipart boundary generation", 231 + "description": "The OCaml library uses crypto-RNG for multipart boundaries which may be overkill. The Java library uses simpler timestamp-based boundaries which are sufficient for form encoding.", 232 + "affected_files": [ 233 + "lib/body.ml" 234 + ], 235 + "rationale": "The OCaml generate_boundary function (body.ml:115-119) uses Mirage_crypto_rng.generate 16 for cryptographically random boundaries: \"----WebKitFormBoundary\" + 32 hex chars. The Java library uses simpler boundaries (timestamp + random) which are sufficient since boundary uniqueness only needs to avoid collisions within a single request body, not provide security. While the current approach works, it has dependency implications - it requires Mirage_crypto_rng to be initialized (requests.ml:24-27 notes this requirement). A simpler approach using Unix.gettimeofday() + Random.bits() would reduce crypto dependencies for this non-security-critical use case. However, given that the library already requires crypto for TLS and Digest auth, this is more of a cleanup than critical change." 236 + }, 237 + { 238 + "source_repo": "third_party/java/http-request", 239 + "source_language": "Java", 240 + "criticality": "low", 241 + "change_type": "enhancement", 242 + "title": "Add detailed error context to connection failures", 243 + "description": "The Java library wraps IOExceptions in HttpRequestException with preserved cause. The OCaml library could provide more structured error context including the URL, method, and stage of failure.", 244 + "affected_files": [ 245 + "lib/error.ml", 246 + "lib/requests.ml", 247 + "lib/http_client.ml" 248 + ], 249 + "rationale": "The Java HttpRequestException (lines 660-681) preserves the original IOException as cause and wraps it in a runtime exception. The OCaml Error module (error.ml) has comprehensive error types but ConnectionError just takes a string message (line 15). When a connection fails, knowing which URL, method, and stage (DNS resolution, TCP connect, TLS handshake, send, receive) would significantly aid debugging. Enhancing ConnectionError to include structured context: type connection_error = {url: string; method_: Method.t; stage: [`DNS | `Connect | `TLS | `Send | `Receive]; underlying: exn} would make errors more actionable. This follows the HTTPError pattern (lines 16-22) which already includes structured context." 250 + }, 251 + { 252 + "source_repo": "third_party/java/http-request", 253 + "source_language": "Java", 254 + "criticality": "medium", 255 + "change_type": "enhancement", 256 + "title": "Add response body to HTTPError exception for better debugging", 257 + "description": "The OCaml HTTPError includes an optional body field, but it's always set to None in practice. The Java library can include response bodies in error messages.", 258 + "affected_files": [ 259 + "lib/response.ml", 260 + "lib/requests.ml" 261 + ], 262 + "rationale": "The OCaml Error.HTTPError type has a body: string option field (error.ml:20), and raise_for_status in response.ml:81-89 raises HTTPError but sets body to None. Including the actual response body in error exceptions would significantly improve debugging - many APIs return detailed error messages in JSON format (e.g., {\"error\": \"Invalid API key\"}). The Java library can include body content in errors. Changing response.ml:88 to body = Some (try text t with _ -> None) would capture error responses. For large responses, truncating to first 1024 bytes would prevent memory issues. This is especially valuable for 4xx client errors where the server often provides actionable error details." 263 + } 264 + ] 265 + }
+222
third_party/java/okhttp.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/java/okhttp", 5 + "source_language": "Kotlin", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add Interceptor Chain Pattern for Request/Response Middleware", 9 + "description": "Implement a composable interceptor pattern that allows users to observe, modify, or short-circuit requests and responses. OkHttp provides two levels: application interceptors (for full call span including retries/redirects) and network interceptors (for individual network exchanges). This enables powerful middleware capabilities like custom logging, request signing, response transformation, and circuit breaking.", 10 + "affected_files": [ 11 + "lib/requests.mli", 12 + "lib/requests.ml", 13 + "lib/one.mli", 14 + "lib/one.ml" 15 + ], 16 + "rationale": "OkHttp's interceptor pattern is one of its most powerful features, enabling extensibility without modifying core library code. The OCaml library currently lacks this capability - users cannot easily add custom request/response processing logic. Adding interceptors would enable: (1) custom authentication schemes beyond the built-in ones, (2) request/response logging at various levels, (3) response caching strategies, (4) automatic request retries with custom logic, (5) request signing for APIs, (6) metrics collection, and (7) third-party integrations. The pattern fits naturally with OCaml's functional style using functions of type `request -> (response, error) result` chained together." 17 + }, 18 + { 19 + "source_repo": "third_party/java/okhttp", 20 + "source_language": "Kotlin", 21 + "criticality": "high", 22 + "change_type": "feature", 23 + "title": "Implement EventListener for Request/Response Observability", 24 + "description": "Add an EventListener interface similar to OkHttp's that provides lifecycle callbacks for HTTP operations. Events should include: callStart/callEnd/callFailed, dnsStart/dnsEnd, connectStart/connectEnd/connectFailed, secureConnectStart/secureConnectEnd, requestHeadersStart/requestHeadersEnd, responseHeadersStart/responseHeadersEnd, requestBodyStart/requestBodyEnd, responseBodyStart/responseBodyEnd, connectionAcquired/connectionReleased. This enables comprehensive monitoring, metrics collection, and debugging without invasive code changes.", 25 + "affected_files": [ 26 + "lib/requests.mli", 27 + "lib/requests.ml", 28 + "lib/one.mli", 29 + "lib/one.ml", 30 + "lib/http_client.ml" 31 + ], 32 + "rationale": "OkHttp's EventListener provides granular visibility into the HTTP request lifecycle, which is essential for production monitoring, performance analysis, and debugging. The OCaml library currently only has basic logging via the Logs library, but lacks structured events that applications can programmatically consume. An EventListener would enable: (1) application-level metrics (connection pool stats, DNS lookup times, TLS handshake duration), (2) distributed tracing integration (OpenTelemetry), (3) per-request performance profiling, (4) custom retry logic based on connection events, (5) alerting on connection failures, and (6) debugging without enabling verbose logging. The callback-based design is idiomatic in OCaml and can be implemented efficiently." 33 + }, 34 + { 35 + "source_repo": "third_party/java/okhttp", 36 + "source_language": "Kotlin", 37 + "criticality": "high", 38 + "change_type": "security", 39 + "title": "Add Certificate Pinning Support", 40 + "description": "Implement certificate pinning to constrain which TLS certificates are trusted, protecting against CA compromise and MITM attacks. Support pinning Subject Public Key Info (SPKI) SHA-256 hashes per RFC 7469 (HPKP). Include pattern matching for domains: exact match (example.com), single wildcard (*.example.com for one subdomain), and double wildcard (**.example.com for any number of subdomains). Provide helpful error messages showing actual vs. expected certificate pins when validation fails.", 41 + "affected_files": [ 42 + "lib/requests.mli", 43 + "lib/requests.ml", 44 + "lib/one.mli", 45 + "lib/one.ml" 46 + ], 47 + "rationale": "Certificate pinning is a critical security feature for applications communicating with known servers, especially mobile apps and internal services. OkHttp has robust certificate pinning that has been battle-tested in production. The OCaml library currently only supports basic TLS certificate verification via the CA bundle, which is vulnerable to CA compromise or MITM attacks with rogue CAs. Certificate pinning would provide defense-in-depth for: (1) high-security applications (banking, healthcare, government), (2) preventing MITM attacks in hostile networks, (3) detecting unexpected certificate changes, and (4) meeting compliance requirements (PCI-DSS, HIPAA). The implementation can leverage the existing tls-eio library's certificate validation hooks." 48 + }, 49 + { 50 + "source_repo": "third_party/java/okhttp", 51 + "source_language": "Kotlin", 52 + "criticality": "medium", 53 + "change_type": "enhancement", 54 + "title": "Add HTTP/2 Protocol Support", 55 + "description": "Implement HTTP/2 protocol support with ALPN negotiation, enabling multiplexed streams over a single connection, header compression (HPACK), server push, and flow control. This provides significant performance improvements for applications making multiple requests to the same host, especially over high-latency connections.", 56 + "affected_files": [ 57 + "lib/http_client.ml", 58 + "lib/requests.ml", 59 + "lib/one.ml" 60 + ], 61 + "rationale": "OkHttp has comprehensive HTTP/2 support that is automatically negotiated via ALPN when both client and server support it. The OCaml library currently only implements HTTP/1.1, which requires multiple TCP connections for concurrent requests and has higher overhead due to uncompressed headers. HTTP/2 benefits include: (1) reduced latency through request multiplexing (no head-of-line blocking), (2) lower bandwidth usage via HPACK header compression, (3) single TCP connection reduces connection establishment overhead, (4) better resource utilization with stream prioritization, and (5) future-proofing as HTTP/2 becomes the default. Modern web APIs and CDNs heavily optimize for HTTP/2. The h2 OCaml library provides HTTP/2 framing that could be integrated with the existing connection pooling." 62 + }, 63 + { 64 + "source_repo": "third_party/java/okhttp", 65 + "source_language": "Kotlin", 66 + "criticality": "medium", 67 + "change_type": "feature", 68 + "title": "Implement Response Caching with RFC 7234 Compliance", 69 + "description": "Add disk-based HTTP response caching following RFC 7234 (HTTP Caching) semantics. Implement cache storage with LRU eviction, respect Cache-Control headers (max-age, public/private, no-cache, no-store, must-revalidate), support conditional requests (If-None-Match with ETags, If-Modified-Since), and handle 304 Not Modified responses. Provide cache statistics (hit count, network count, cache size).", 70 + "affected_files": [ 71 + "lib/requests.mli", 72 + "lib/requests.ml" 73 + ], 74 + "rationale": "OkHttp includes production-ready HTTP caching that significantly reduces network traffic and improves application performance. The OCaml library previously had caching (CACHEIO.md mentions it was removed for simplicity), but this is a critical feature for production applications. HTTP caching provides: (1) reduced latency for repeated requests, (2) bandwidth savings (especially important for mobile apps), (3) improved offline capability, (4) reduced server load, and (5) better user experience with instant responses for cached content. The comment in requests.mli acknowledges caching was disabled, indicating this is a known gap. Modern APIs increasingly use aggressive caching with proper Cache-Control headers to improve performance." 75 + }, 76 + { 77 + "source_repo": "third_party/java/okhttp", 78 + "source_language": "Kotlin", 79 + "criticality": "medium", 80 + "change_type": "enhancement", 81 + "title": "Enhance Retry Strategy with Happy Eyeballs (RFC 6555) for Multi-Homed Hosts", 82 + "description": "Implement concurrent connection attempts to multiple IP addresses returned by DNS, returning the first successful connection (Happy Eyeballs / RFC 6555). When DNS returns multiple A/AAAA records, attempt connections in parallel with small delays (e.g., 250ms) between attempts. Track failed routes in a RouteDatabase to avoid immediate retry. This provides faster connection establishment and automatic failover.", 83 + "affected_files": [ 84 + "lib/retry.ml", 85 + "lib/retry.mli", 86 + "lib/http_client.ml" 87 + ], 88 + "rationale": "OkHttp implements Happy Eyeballs by default, providing resilient connection establishment when servers are multi-homed or have both IPv4 and IPv6 addresses. The OCaml library's retry logic currently only retries after complete failure, not during connection establishment. Happy Eyeballs provides: (1) faster connection to dual-stack (IPv4/IPv6) hosts by racing both protocols, (2) automatic failover when one IP address is unreachable, (3) improved reliability for multi-homed services, (4) better user experience with reduced connection latency, and (5) graceful handling of network transitions. This is especially important for mobile applications and services deployed with multiple replicas. The Eio.Fiber.first primitive can be used to implement the racing behavior efficiently." 89 + }, 90 + { 91 + "source_repo": "third_party/java/okhttp", 92 + "source_language": "Kotlin", 93 + "criticality": "medium", 94 + "change_type": "feature", 95 + "title": "Add Preemptive Proxy Authentication", 96 + "description": "Implement preemptive authentication for HTTP proxies to avoid the challenge-response round trip. When proxy credentials are configured, send the Proxy-Authorization header on the initial CONNECT request for HTTPS tunnels. This is distinct from origin server authentication and should support both Basic and Digest schemes for proxies.", 97 + "affected_files": [ 98 + "lib/auth.ml", 99 + "lib/auth.mli", 100 + "lib/requests.ml" 101 + ], 102 + "rationale": "OkHttp has sophisticated proxy authentication including preemptive authentication to establish TLS tunnels through authenticated proxies efficiently. The OCaml library currently lacks proxy support entirely (though it's mentioned in the Cmd module documentation as 'when proxy support is added'). Preemptive proxy authentication is important for: (1) enterprise environments with authenticated HTTP proxies, (2) reducing latency by avoiding challenge-response round trips, (3) proper TLS tunnel establishment (CONNECT method), (4) compatibility with common proxy servers (Squid, corporate proxies), and (5) mobile apps routing through debugging proxies. Adding proxy support should be considered a prerequisite, with preemptive authentication as an optimization." 103 + }, 104 + { 105 + "source_repo": "third_party/java/okhttp", 106 + "source_language": "Kotlin", 107 + "criticality": "medium", 108 + "change_type": "enhancement", 109 + "title": "Add Configurable Dispatcher with Request Queueing and Concurrency Limits", 110 + "description": "Implement a request dispatcher that manages concurrent request execution with configurable limits. Support maxRequests (global concurrent limit, default: 64) and maxRequestsPerHost (per-host limit, default: 5) to prevent overwhelming servers or clients. Queue requests when limits are reached and execute them when resources become available. Add EventListener callbacks for dispatcherQueueStart and dispatcherQueueEnd.", 111 + "affected_files": [ 112 + "lib/requests.ml", 113 + "lib/requests.mli" 114 + ], 115 + "rationale": "OkHttp's Dispatcher provides essential backpressure and resource management for applications making many concurrent requests. The OCaml library relies on users to manually manage concurrency with Eio.Fiber primitives, which can easily lead to resource exhaustion when making hundreds of concurrent requests. A dispatcher would provide: (1) automatic backpressure to prevent connection pool exhaustion, (2) protection against overwhelming target servers (rate limiting), (3) fair resource allocation across multiple hosts, (4) improved observability of queued vs. executing requests, and (5) prevention of file descriptor exhaustion. This is particularly important for batch processing, web scrapers, and applications with bursty request patterns. The implementation can use Eio.Semaphore for concurrency limiting." 116 + }, 117 + { 118 + "source_repo": "third_party/java/okhttp", 119 + "source_language": "Kotlin", 120 + "criticality": "medium", 121 + "change_type": "enhancement", 122 + "title": "Enhance Timeout Configuration with Per-Operation Granularity", 123 + "description": "Extend timeout configuration to include separate timeouts for connect (TCP handshake), read (socket read operations), write (socket write operations), and total call duration. Currently the library only supports connect, read, and total timeouts. Add the ability for interceptors to modify timeout values per-request using withConnectTimeout, withReadTimeout, withWriteTimeout functions on the chain.", 124 + "affected_files": [ 125 + "lib/timeout.ml", 126 + "lib/timeout.mli", 127 + "lib/requests.ml", 128 + "lib/one.ml" 129 + ], 130 + "rationale": "OkHttp provides fine-grained timeout control with separate connect, read, write, and call timeouts, plus the ability for interceptors to adjust timeouts dynamically. The OCaml library has connect, read, and total timeouts but lacks write timeout and dynamic adjustment. Enhanced timeouts provide: (1) protection against slow writes when uploading large files, (2) ability to adjust timeouts based on request characteristics (e.g., longer timeout for large downloads), (3) better control over resource lifetime, (4) more precise error attribution (connect vs. read timeout), and (5) compatibility with diverse network conditions. Write timeouts are especially important for upload-heavy applications and when dealing with slow or stalled connections." 131 + }, 132 + { 133 + "source_repo": "third_party/java/okhttp", 134 + "source_language": "Kotlin", 135 + "criticality": "low", 136 + "change_type": "enhancement", 137 + "title": "Add Request/Response Tagging for Metadata Attachment", 138 + "description": "Allow attaching arbitrary metadata (tags) to Request and Response objects that can be retrieved later by interceptors or application code. Support type-safe tagging using OCaml's type system (e.g., heterogeneous maps keyed by type witnesses). This enables passing context through the request pipeline without polluting headers.", 139 + "affected_files": [ 140 + "lib/requests.mli", 141 + "lib/response.mli", 142 + "lib/response.ml" 143 + ], 144 + "rationale": "OkHttp's tagging system allows attaching arbitrary objects to requests/responses, which is useful for passing metadata through interceptor chains without using headers. The OCaml library has no equivalent mechanism. Request tagging enables: (1) passing request-specific configuration to interceptors (e.g., custom retry policy), (2) attaching tracing context (trace IDs, span IDs) without headers, (3) storing request metadata for logging (request origin, user ID), (4) associating application-level objects with requests (database connections, user sessions), and (5) cleaner separation of application concerns from HTTP headers. In OCaml, this could be implemented using Universal type or heterogeneous maps for type-safe tagging." 145 + }, 146 + { 147 + "source_repo": "third_party/java/okhttp", 148 + "source_language": "Kotlin", 149 + "criticality": "low", 150 + "change_type": "enhancement", 151 + "title": "Add DNS-over-HTTPS (DoH) Support for Secure DNS Resolution", 152 + "description": "Implement DNS-over-HTTPS as an alternative to traditional DNS lookups, improving privacy and security. Allow configuration of DoH providers (Google, Cloudflare, custom) and fallback to system DNS on failure. This prevents DNS hijacking and ensures encrypted DNS queries.", 153 + "affected_files": [ 154 + "lib/requests.ml", 155 + "lib/requests.mli", 156 + "lib/one.ml" 157 + ], 158 + "rationale": "OkHttp provides DNS-over-HTTPS support as a separate module (okhttp-dnsoverhttps), recognizing the growing importance of secure DNS. The OCaml library relies on system DNS resolution, which is vulnerable to DNS hijacking and exposes DNS queries to network observers. DoH provides: (1) encrypted DNS queries protecting user privacy, (2) resistance to DNS hijacking and MITM attacks, (3) bypassing DNS-based censorship, (4) compliance with privacy regulations, and (5) consistency across networks (using trusted DoH providers). This is particularly valuable for privacy-focused applications, VPNs, and applications operating in hostile network environments. The implementation can reuse the existing HTTP client to query DoH endpoints." 159 + }, 160 + { 161 + "source_repo": "third_party/java/okhttp", 162 + "source_language": "Kotlin", 163 + "criticality": "low", 164 + "change_type": "enhancement", 165 + "title": "Add Brotli Compression Support", 166 + "description": "Extend automatic decompression to support Brotli (br) content encoding in addition to the existing gzip and deflate support. Brotli provides better compression ratios than gzip, especially for text content, reducing bandwidth usage by 15-25% compared to gzip.", 167 + "affected_files": [ 168 + "lib/http_client.ml", 169 + "lib/one.ml" 170 + ], 171 + "rationale": "OkHttp supports Brotli compression via a separate module (okhttp-brotli), as Brotli is increasingly adopted by CDNs and web servers for its superior compression. The OCaml library supports gzip and deflate but not Brotli. Adding Brotli support provides: (1) reduced bandwidth consumption (15-25% better than gzip for text), (2) faster page loads and API responses, (3) compatibility with modern web infrastructure (many CDNs prefer Brotli), (4) improved mobile app performance, and (5) cost savings for metered connections. Major web services (Google, Facebook, Cloudflare) serve Brotli-compressed content by default. The decompress OCaml library includes Brotli support that can be integrated." 172 + }, 173 + { 174 + "source_repo": "third_party/java/okhttp", 175 + "source_language": "Kotlin", 176 + "criticality": "low", 177 + "change_type": "feature", 178 + "title": "Add Server-Sent Events (SSE) Client Support", 179 + "description": "Implement a client for Server-Sent Events (SSE/EventSource) protocol, enabling efficient server-to-client streaming with automatic reconnection. Parse SSE message format (data, event, id, retry fields), handle connection lifecycle, and provide a stream of events to the application. Support Last-Event-ID for resuming interrupted streams.", 180 + "affected_files": [ 181 + "lib/requests.mli", 182 + "lib/requests.ml" 183 + ], 184 + "rationale": "OkHttp provides SSE support as a separate module (okhttp-sse), recognizing SSE as a lightweight alternative to WebSockets for server-push scenarios. The OCaml library has no SSE support. SSE is widely used for: (1) real-time notifications and updates, (2) streaming APIs (chat applications, live feeds, monitoring dashboards), (3) progressive data loading, (4) lower overhead than polling, and (5) automatic reconnection handling. SSE is simpler than WebSockets for unidirectional server-to-client communication and works over HTTP/1.1 and HTTP/2. The implementation can leverage the existing streaming response body support with a parser for the SSE message format." 185 + }, 186 + { 187 + "source_repo": "third_party/java/okhttp", 188 + "source_language": "Kotlin", 189 + "criticality": "low", 190 + "change_type": "feature", 191 + "title": "Implement Mock Server for Testing (Similar to MockWebServer)", 192 + "description": "Create a lightweight HTTP server for testing that allows queueing mock responses, recording requests, configurable delays, connection simulation (stalls, drops), and support for HTTP, HTTPS, and HTTP/2. Provide an API for asserting on captured requests and flexible request matching/dispatching.", 193 + "affected_files": [], 194 + "rationale": "OkHttp's MockWebServer is essential testing infrastructure used extensively in OkHttp's own test suite and by thousands of applications. The OCaml library has minimal test infrastructure (basic echo servers in test/). A mock server would enable: (1) reliable, fast, offline unit tests without external dependencies, (2) testing error conditions (timeouts, connection failures, malformed responses), (3) testing retry logic and redirect handling, (4) verifying request construction (headers, body, authentication), (5) simulating slow or unreliable networks, and (6) integration testing without real servers. This significantly improves test reliability and development velocity. The implementation can use Eio's networking primitives and build on the existing HTTP parsing logic." 195 + }, 196 + { 197 + "source_repo": "third_party/java/okhttp", 198 + "source_language": "Kotlin", 199 + "criticality": "medium", 200 + "change_type": "enhancement", 201 + "title": "Add Connection Event Listener Hooks for Pool Monitoring", 202 + "description": "Extend EventListener with connection pool-specific events: connectionPoolConnectionAcquired, connectionPoolConnectionReleased, connectionPoolConnectionCreated, connectionPoolConnectionClosed, connectionPoolIdleConnectionEvicted. This enables monitoring connection pool health, detecting connection leaks, and optimizing pool configuration.", 203 + "affected_files": [ 204 + "lib/requests.ml" 205 + ], 206 + "rationale": "OkHttp's EventListener includes detailed connection pool events that are critical for production monitoring and performance tuning. The OCaml library uses Conpool for connection pooling but provides no visibility into pool behavior beyond basic statistics. Connection pool monitoring enables: (1) detecting connection leaks (acquired but never released), (2) optimizing pool size based on actual usage patterns, (3) identifying connection churn (frequent create/close cycles), (4) monitoring idle connection eviction, (5) alerting on pool exhaustion, and (6) correlating connection issues with request failures. This is essential for production applications to maintain optimal performance and diagnose connection-related issues." 207 + }, 208 + { 209 + "source_repo": "third_party/java/okhttp", 210 + "source_language": "Kotlin", 211 + "criticality": "low", 212 + "change_type": "enhancement", 213 + "title": "Add Helper Method to Convert Requests to cURL Commands for Debugging", 214 + "description": "Provide a utility function that converts an HTTP request to an equivalent cURL command line, including all headers, authentication, body, and method. This aids in debugging by allowing developers to reproduce requests outside the application and share them with others.", 215 + "affected_files": [ 216 + "lib/requests.mli", 217 + "lib/requests.ml" 218 + ], 219 + "rationale": "OkHttp's Request.toCurl() method is invaluable for debugging HTTP requests by generating equivalent cURL commands. The OCaml library has no such utility. A cURL converter provides: (1) easy reproduction of requests in terminal/scripts, (2) sharing requests with teammates who don't have access to the application, (3) debugging with standard tools (curl, HTTPie), (4) documentation and examples from actual requests, and (5) testing API endpoints independently. This is particularly useful when troubleshooting authentication issues, debugging request headers, or when working with third-party APIs. The implementation is straightforward - format the request components into cURL's command-line syntax." 220 + } 221 + ] 222 + }
+281
third_party/javascript/axios.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/javascript/axios", 5 + "source_language": "JavaScript", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add request/response interceptor system", 9 + "description": "Implement a flexible interceptor mechanism that allows users to register handlers for transforming or inspecting requests before they are sent and responses before they are returned. Interceptors should support both synchronous and asynchronous execution, conditional execution (runWhen predicate), and proper cleanup (eject by ID). This enables cross-cutting concerns like logging, authentication token refresh, request metrics, and error normalization.", 10 + "affected_files": [ 11 + "lib/requests.mli", 12 + "lib/requests.ml", 13 + "lib/one.mli", 14 + "lib/one.ml" 15 + ], 16 + "rationale": "Axios provides a powerful InterceptorManager that allows users to inject middleware into the request/response pipeline. This pattern enables separation of concerns and composability. The OCaml library currently requires users to manually wrap request functions to add cross-cutting functionality. Interceptors would allow: (1) automatic token refresh on 401 responses, (2) centralized logging and metrics, (3) request/response transformation, (4) error normalization, (5) retry logic composition. The implementation can use an effect-based approach or callback lists stored in the session type." 17 + }, 18 + { 19 + "source_repo": "third_party/javascript/axios", 20 + "source_language": "JavaScript", 21 + "criticality": "medium", 22 + "change_type": "feature", 23 + "title": "Add request cancellation with token-based system", 24 + "description": "Implement a cancellation token mechanism that allows requests to be cancelled programmatically. Provide both a CancelToken pattern (with source() factory) and integration with modern patterns (support for custom cancellation predicates). The cancellation system should support: (1) creating cancel tokens with associated cancel functions, (2) subscribing to cancellation events, (3) checking cancellation status before/during request execution, (4) throwing CanceledError to distinguish from network errors.", 25 + "affected_files": [ 26 + "lib/requests.mli", 27 + "lib/requests.ml", 28 + "lib/one.mli", 29 + "lib/one.ml", 30 + "lib/error.mli", 31 + "lib/error.ml" 32 + ], 33 + "rationale": "Axios supports both CancelToken (legacy) and AbortSignal/AbortController (modern) for request cancellation. The OCaml library currently relies on Eio's structured concurrency and switch cancellation, but this doesn't provide fine-grained per-request cancellation or cancellation callbacks. Adding explicit cancellation tokens would enable: (1) cancelling individual requests in a fiber group, (2) implementing request racing with first-success patterns, (3) cancelling long-running uploads/downloads, (4) triggering cleanup callbacks on cancellation. The implementation should integrate with Eio's cancellation context but provide explicit control." 34 + }, 35 + { 36 + "source_repo": "third_party/javascript/axios", 37 + "source_language": "JavaScript", 38 + "criticality": "medium", 39 + "change_type": "feature", 40 + "title": "Add progress event support for uploads and downloads", 41 + "description": "Implement progress tracking for request bodies (uploads) and response bodies (downloads) with throttled event callbacks. Support progress events that report: bytes transferred (loaded), total bytes (if known), progress percentage, transfer rate (bytes/sec), and estimated time remaining. Include configurable throttling to limit event frequency (default: 3 events/sec) and rate calculation using a sliding window speedometer.", 42 + "affected_files": [ 43 + "lib/one.mli", 44 + "lib/one.ml", 45 + "lib/body.mli", 46 + "lib/body.ml", 47 + "lib/response.mli", 48 + "lib/response.ml" 49 + ], 50 + "rationale": "Axios provides sophisticated progress tracking with throttling and rate calculation via progressEventReducer and speedometer helpers. The OCaml library has basic on_progress callbacks for upload/download in the One module, but lacks: (1) throttling to prevent excessive callback invocations, (2) rate calculation for showing transfer speed, (3) estimated time remaining, (4) progress events for the main Requests API (only One module has it). Enhanced progress tracking enables better UX for CLI tools and applications handling large files." 51 + }, 52 + { 53 + "source_repo": "third_party/javascript/axios", 54 + "source_language": "JavaScript", 55 + "criticality": "high", 56 + "change_type": "security", 57 + "title": "Add XSRF/CSRF token protection for same-origin requests", 58 + "description": "Implement automatic XSRF protection that reads tokens from cookies and injects them into request headers for same-origin requests. Support: (1) configurable cookie name (default: XSRF-TOKEN), (2) configurable header name (default: X-XSRF-TOKEN), (3) same-origin checking (protocol + host + port comparison), (4) conditional injection via boolean flag or predicate function, (5) automatic cookie reading from browser-like storage or custom cookie jar.", 59 + "affected_files": [ 60 + "lib/requests.mli", 61 + "lib/requests.ml", 62 + "lib/headers.mli", 63 + "lib/headers.ml" 64 + ], 65 + "rationale": "Axios provides built-in XSRF protection for browser environments by automatically reading XSRF tokens from cookies and injecting them into request headers for same-origin requests. This is a critical security feature for web applications using cookie-based authentication. The OCaml library currently has no XSRF protection, requiring users to manually implement this security measure. While OCaml is primarily server-side, many applications (especially those using cookie-based sessions) would benefit from automated XSRF protection. Implementation should: (1) check if request is same-origin, (2) read token from cookie jar, (3) inject into configured header, (4) be opt-in via configuration flag." 66 + }, 67 + { 68 + "source_repo": "third_party/javascript/axios", 69 + "source_language": "JavaScript", 70 + "criticality": "medium", 71 + "change_type": "enhancement", 72 + "title": "Add request/response data transformation pipeline", 73 + "description": "Implement a transformation system that applies an array of transform functions to request data (before sending) and response data (after receiving). Each transformer receives the data, headers, and config context. Provide default transformers for: (1) JSON serialization/parsing with error handling, (2) form data encoding, (3) automatic content-type detection, (4) string/buffer conversions. Allow users to override or extend transformers.", 74 + "affected_files": [ 75 + "lib/requests.mli", 76 + "lib/requests.ml", 77 + "lib/body.mli", 78 + "lib/body.ml", 79 + "lib/response.mli", 80 + "lib/response.ml" 81 + ], 82 + "rationale": "Axios uses a transform pipeline (transformRequest/transformResponse) that handles data conversion, JSON parsing, and error handling. The OCaml library has basic JSON parsing via Response.json and Body.json, but lacks: (1) customizable transformation pipelines, (2) error recovery options (silent parsing failures), (3) forced content-type parsing (parse as JSON even without Content-Type header), (4) automatic charset conversion. Transformers would enable: (1) custom serialization formats, (2) data validation before sending, (3) response normalization, (4) automatic error extraction from response bodies." 83 + }, 84 + { 85 + "source_repo": "third_party/javascript/axios", 86 + "source_language": "JavaScript", 87 + "criticality": "medium", 88 + "change_type": "enhancement", 89 + "title": "Add sophisticated configuration merging with merge strategies", 90 + "description": "Enhance the configuration merging system with property-specific merge strategies. Implement merge functions for: (1) 'valueFromConfig2' - request-specific values override instance defaults (url, method, data), (2) 'defaultToConfig2' - instance defaults used unless explicitly overridden (timeout, headers), (3) 'mergeDirectKeys' - only merge if explicitly provided in request config (validateStatus), (4) 'mergeDeepProperties' - deep merge for nested objects like headers with case-insensitive handling.", 91 + "affected_files": [ 92 + "lib/requests.mli", 93 + "lib/requests.ml", 94 + "lib/headers.mli", 95 + "lib/headers.ml" 96 + ], 97 + "rationale": "Axios has sophisticated config merging via mergeConfig.js with property-specific merge strategies that handle different semantics for different config properties. The OCaml library uses basic header merging (Headers.merge) but lacks nuanced merging for other configuration. Current limitations: (1) all config is either instance-level or request-level with simple override semantics, (2) no differentiation between 'not provided' and 'explicitly set to None', (3) headers are merged but other nested config is not. Enhanced merging would enable: (1) better config composition, (2) proper defaults inheritance, (3) explicit override detection." 98 + }, 99 + { 100 + "source_repo": "third_party/javascript/axios", 101 + "source_language": "JavaScript", 102 + "criticality": "low", 103 + "change_type": "enhancement", 104 + "title": "Add comprehensive request/response validation system", 105 + "description": "Implement validation utilities that check configuration and data for correctness. Include: (1) type validators for config properties (object, boolean, number, function, string), (2) transitional validators that warn about deprecated options with migration guidance, (3) spelling validators that detect common typos in config keys (e.g., 'baseUrl' vs 'baseURL', 'withXsrfToken' vs 'withXSRFToken'), (4) value range validators for numeric config.", 106 + "affected_files": [ 107 + "lib/requests.mli", 108 + "lib/requests.ml", 109 + "lib/error.mli", 110 + "lib/error.ml" 111 + ], 112 + "rationale": "Axios includes a validator.js helper that provides type checking and spelling validation to catch configuration errors early with helpful messages. The OCaml library relies on type system for correctness but could benefit from: (1) runtime validation for edge cases not caught by types (e.g., negative timeouts), (2) deprecation warnings for old API usage, (3) helpful error messages for common mistakes, (4) validation of URLs and header values. While OCaml's type system prevents many errors, runtime validation can improve the developer experience by catching semantic errors." 113 + }, 114 + { 115 + "source_repo": "third_party/javascript/axios", 116 + "source_language": "JavaScript", 117 + "criticality": "medium", 118 + "change_type": "enhancement", 119 + "title": "Add validateStatus configuration option with custom predicates", 120 + "description": "Add a validateStatus configuration option that allows users to customize which HTTP status codes are considered successful. Default behavior should treat 200-299 as success, but users should be able to provide custom predicates like 'status -> status < 500' to change error semantics. This should integrate with retry logic and error handling.", 121 + "affected_files": [ 122 + "lib/requests.mli", 123 + "lib/requests.ml", 124 + "lib/response.mli", 125 + "lib/response.ml", 126 + "lib/retry.mli", 127 + "lib/retry.ml" 128 + ], 129 + "rationale": "Axios allows customization of what constitutes a successful response via validateStatus function (default: status >= 200 && status < 300). The OCaml library uses Response.ok for 2xx checking and has retry status_forcelist, but lacks: (1) customizable success criteria per request, (2) automatic error raising based on status, (3) integration between validation and retry logic. Current workaround requires manual status checking after every request. Adding validateStatus would enable: (1) treating 404 as success for existence checks, (2) treating 3xx as errors when redirects are disabled, (3) custom status semantics per-endpoint." 130 + }, 131 + { 132 + "source_repo": "third_party/javascript/axios", 133 + "source_language": "JavaScript", 134 + "criticality": "high", 135 + "change_type": "enhancement", 136 + "title": "Enhance error context with request/response details", 137 + "description": "Expand error types to include full context: config used for request, request object details, response object (if received), and response status. Modify HTTPError exception to include response body for debugging. Add factory methods like 'from_exn' for converting between error representations. Ensure all errors include actionable debugging information.", 138 + "affected_files": [ 139 + "lib/error.mli", 140 + "lib/error.ml", 141 + "lib/response.mli", 142 + "lib/response.ml" 143 + ], 144 + "rationale": "Axios AxiosError includes comprehensive context: message, code, config, request, response, and status. This enables detailed error logging and debugging. The OCaml library has good error types but HTTPError includes: url, status, reason, body (option), headers. Improvements needed: (1) include request details (method, headers sent), (2) always capture response body for errors (currently optional), (3) add request/response timing information, (4) include retry attempt count in errors. Richer error context enables: (1) better debugging of production issues, (2) error logging and monitoring, (3) error recovery decisions based on full context." 145 + }, 146 + { 147 + "source_repo": "third_party/javascript/axios", 148 + "source_language": "JavaScript", 149 + "criticality": "medium", 150 + "change_type": "enhancement", 151 + "title": "Add configurable timeout error clarification", 152 + "description": "Differentiate between connection timeout (ETIMEDOUT - couldn't establish connection within timeout) and read timeout (ECONNABORTED - connection established but response took too long). Add a clarifyTimeoutError configuration option (default: false for backward compatibility) that provides more specific timeout error types. Include timeout type information in error messages.", 153 + "affected_files": [ 154 + "lib/error.mli", 155 + "lib/error.ml", 156 + "lib/timeout.mli", 157 + "lib/timeout.ml" 158 + ], 159 + "rationale": "Axios provides clarifyTimeoutError transitional option that distinguishes ETIMEDOUT (connection timeout) from ECONNABORTED (read timeout). The OCaml library has a single Timeout exception without distinguishing: (1) connection timeout (couldn't connect to server), (2) read timeout (connected but response too slow), (3) total request timeout (entire request exceeded limit). More specific timeout errors enable: (1) different retry strategies (retry connection timeouts more aggressively), (2) better diagnostics (connection vs server slowness), (3) appropriate error messages to users. Implementation should track which timeout fired and include that in the error." 160 + }, 161 + { 162 + "source_repo": "third_party/javascript/axios", 163 + "source_language": "JavaScript", 164 + "criticality": "low", 165 + "change_type": "enhancement", 166 + "title": "Add JSON parsing error recovery with silent/forced options", 167 + "description": "Enhance JSON parsing in Response.json with error recovery options: (1) silentJSONParsing - return raw body text instead of failing on parse errors, (2) forcedJSONParsing - attempt JSON parsing even when Content-Type is not application/json. Add configuration options to control this behavior globally or per-request. Preserve parse errors in Result type for debugging.", 168 + "affected_files": [ 169 + "lib/response.mli", 170 + "lib/response.ml", 171 + "lib/requests.mli", 172 + "lib/requests.ml" 173 + ], 174 + "rationale": "Axios supports transitional options for JSON parsing: silentJSONParsing (don't throw on parse errors) and forcedJSONParsing (parse without Content-Type check). The OCaml library Response.json returns Result type which is good, but lacks: (1) configuration for automatic fallback to raw text on parse errors, (2) ability to force parsing when Content-Type is missing, (3) logging of parse errors, (4) partial parse recovery. Enhanced JSON handling enables: (1) resilience to malformed responses, (2) working with APIs that send JSON without proper Content-Type, (3) debugging parse failures with better error messages." 175 + }, 176 + { 177 + "source_repo": "third_party/javascript/axios", 178 + "source_language": "JavaScript", 179 + "criticality": "low", 180 + "change_type": "enhancement", 181 + "title": "Add form data helpers with automatic Content-Type handling", 182 + "description": "Extend the Body module with convenience methods for form submissions: postForm, putForm, patchForm that automatically handle multipart/form-data encoding from key-value pairs or objects. Automatically set Content-Type and handle boundary generation. Support both simple form data and file uploads with a unified API.", 183 + "affected_files": [ 184 + "lib/body.mli", 185 + "lib/body.ml", 186 + "lib/requests.mli", 187 + "lib/requests.ml" 188 + ], 189 + "rationale": "Axios provides postForm/putForm/patchForm convenience methods that automatically convert objects to multipart/form-data or application/x-www-form-urlencoded based on content. The OCaml library has Body.form for URL-encoded and Body.multipart for multipart, but lacks: (1) automatic selection between encodings, (2) convenience methods on the request API, (3) automatic handling of file detection. Current usage requires explicit multipart construction. Form helpers would simplify: (1) simple file uploads, (2) mixed form+file submissions, (3) API consistency with common patterns." 190 + }, 191 + { 192 + "source_repo": "third_party/javascript/axios", 193 + "source_language": "JavaScript", 194 + "criticality": "high", 195 + "change_type": "enhancement", 196 + "title": "Add beforeRedirect hook for custom redirect handling", 197 + "description": "Implement a beforeRedirect callback option that is invoked before following each redirect. The callback receives the redirect response details (status, headers, location) and can: (1) modify the next request (headers, auth), (2) cancel the redirect by raising an exception, (3) log redirect chains, (4) implement custom redirect logic. This integrates with the existing redirect following mechanism.", 198 + "affected_files": [ 199 + "lib/requests.mli", 200 + "lib/requests.ml", 201 + "lib/one.mli", 202 + "lib/one.ml" 203 + ], 204 + "rationale": "Axios HTTP adapter supports a beforeRedirect hook for custom redirect handling logic. The OCaml library follows redirects automatically with basic credential stripping for cross-origin redirects, but lacks: (1) visibility into redirect chains, (2) ability to modify requests before redirect, (3) custom logic for specific status codes (301 vs 302 vs 307), (4) redirect logging. Current implementation strips Authorization header on cross-origin but has TODO for .netrc support. A beforeRedirect hook enables: (1) re-acquiring credentials for new hosts, (2) logging redirect chains for debugging, (3) implementing custom redirect policies, (4) canceling suspicious redirect chains." 205 + }, 206 + { 207 + "source_repo": "third_party/javascript/axios", 208 + "source_language": "JavaScript", 209 + "criticality": "medium", 210 + "change_type": "feature", 211 + "title": "Add maxContentLength and maxBodyLength limits", 212 + "description": "Implement configuration options to limit response body size (maxContentLength) and request body size (maxBodyLength). When limits are exceeded, fail fast with a descriptive error before transferring all data. Support both limits as separate concerns (request upload vs response download). Default to unlimited (-1) for backward compatibility.", 213 + "affected_files": [ 214 + "lib/requests.mli", 215 + "lib/requests.ml", 216 + "lib/response.mli", 217 + "lib/response.ml", 218 + "lib/body.mli", 219 + "lib/body.ml" 220 + ], 221 + "rationale": "Axios supports maxContentLength (response size limit) and maxBodyLength (request size limit) to prevent memory exhaustion and DoS attacks. The OCaml library has no size limits, which could lead to: (1) OOM when downloading huge responses, (2) slow uploads of oversized requests, (3) vulnerability to malicious servers sending infinite responses, (4) inability to enforce API size constraints. Size limits enable: (1) fail-fast on oversized payloads, (2) protection against malicious/buggy servers, (3) enforcement of API contracts, (4) better resource management. Implementation should check Content-Length header and stop transfer when limit exceeded." 222 + }, 223 + { 224 + "source_repo": "third_party/javascript/axios", 225 + "source_language": "JavaScript", 226 + "criticality": "low", 227 + "change_type": "enhancement", 228 + "title": "Add HTTP method-specific header defaults", 229 + "description": "Implement default headers that are automatically added based on HTTP method. For example, PATCH/PUT/POST automatically get 'Content-Type: application/json' if not specified. Allow users to configure method-specific defaults at the instance level. Merge method defaults with instance defaults and request-specific headers.", 230 + "affected_files": [ 231 + "lib/requests.mli", 232 + "lib/requests.ml", 233 + "lib/headers.mli", 234 + "lib/headers.ml" 235 + ], 236 + "rationale": "Axios defines default headers per HTTP method in defaults/index.js (e.g., POST/PUT/PATCH get specific defaults). The OCaml library has instance-level default_headers that apply to all requests uniformly. Method-specific defaults would: (1) reduce boilerplate for common patterns (JSON POST), (2) enforce conventions per HTTP method, (3) allow better customization of instance behavior. Current workaround requires setting headers on every request or using a single default that may not fit all methods. Implementation should layer: common defaults < method defaults < instance defaults < request defaults." 237 + }, 238 + { 239 + "source_repo": "third_party/javascript/axios", 240 + "source_language": "JavaScript", 241 + "criticality": "medium", 242 + "change_type": "enhancement", 243 + "title": "Add comprehensive error codes for better error categorization", 244 + "description": "Expand the Error module with specific error codes similar to axios: ERR_BAD_OPTION_VALUE, ERR_BAD_OPTION, ECONNABORTED, ETIMEDOUT, ERR_NETWORK, ERR_FR_TOO_MANY_REDIRECTS, ERR_DEPRECATED, ERR_BAD_RESPONSE, ERR_BAD_REQUEST, ERR_CANCELED, ERR_NOT_SUPPORT, ERR_INVALID_URL. Each error variant should include a code field for programmatic error handling.", 245 + "affected_files": [ 246 + "lib/error.mli", 247 + "lib/error.ml" 248 + ], 249 + "rationale": "Axios uses standardized error codes as static constants on AxiosError for precise error categorization. The OCaml library has exception types (Timeout, ConnectionError, HTTPError, etc.) but lacks: (1) structured error codes for subcategories (network vs timeout vs abort), (2) machine-readable error classification, (3) standardized codes for cross-language interop. Error codes enable: (1) switch/match on specific error types, (2) error code documentation, (3) consistent error handling patterns, (4) integration with monitoring systems. Implementation should add a code variant to the error type `t` and preserve it in exceptions." 250 + }, 251 + { 252 + "source_repo": "third_party/javascript/axios", 253 + "source_language": "JavaScript", 254 + "criticality": "low", 255 + "change_type": "refactor", 256 + "title": "Extract adapter selection logic into pluggable adapter system", 257 + "description": "Refactor the HTTP client implementation to use an adapter pattern with multiple backend implementations. Create adapters for: (1) HTTP/1.1 pooled connections (current), (2) HTTP/2 (future), (3) mock adapter for testing. Allow users to specify custom adapters or adapter selection logic. Adapters should have a common interface for making requests.", 258 + "affected_files": [ 259 + "lib/http_client.ml", 260 + "lib/one.ml", 261 + "lib/requests.ml" 262 + ], 263 + "rationale": "Axios uses an adapter system (adapters.js) that selects between xhr (browser), http (Node.js), and fetch (modern) based on environment. The OCaml library has a single HTTP/1.1 implementation in http_client.ml. While not immediately necessary, an adapter pattern would: (1) enable HTTP/2 support without breaking existing code, (2) allow testing with mock adapters, (3) support different backends (curl, h2, httpaf), (4) enable environment-specific optimizations. This is lower priority but provides architectural flexibility for future enhancements." 264 + }, 265 + { 266 + "source_repo": "third_party/javascript/axios", 267 + "source_language": "JavaScript", 268 + "criticality": "low", 269 + "change_type": "enhancement", 270 + "title": "Add response timing metadata and performance metrics", 271 + "description": "Extend Response type with detailed timing information: (1) DNS lookup time, (2) TCP connection time, (3) TLS handshake time, (4) time to first byte, (5) total transfer time, (6) redirect time. Expose this timing data via Response accessors. Add request statistics to the session object: total requests, total time, average latency, retry count.", 272 + "affected_files": [ 273 + "lib/response.mli", 274 + "lib/response.ml", 275 + "lib/requests.mli", 276 + "lib/requests.ml" 277 + ], 278 + "rationale": "Axios tracks timing via response.config and custom timing code. The OCaml library has Response.elapsed (total time) and basic statistics (requests_made, total_time, retries_count) but lacks detailed timing breakdown. Enhanced metrics enable: (1) performance debugging (identify slow DNS, slow TLS, slow servers), (2) monitoring and alerting, (3) optimization identification, (4) SLA compliance checking. The library already tracks elapsed time at requests.ml:217, so adding detailed breakpoints would be straightforward. Implementation can use Eio.Time.now at key points in the request lifecycle." 279 + } 280 + ] 281 + }
+285
third_party/javascript/got.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/javascript/got", 5 + "source_language": "TypeScript", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add granular timeout controls for different request phases", 9 + "description": "The got library provides 7 distinct timeout types (lookup, connect, secureConnect, socket, send, response, request) allowing fine-grained control over each phase of the HTTP request lifecycle. The OCaml library currently only has 3 timeout types (connect, read, total), which is less granular. Adding phase-specific timeouts would help users diagnose which stage of the request is slow and set appropriate limits for each phase.", 10 + "affected_files": [ 11 + "lib/timeout.ml", 12 + "lib/timeout.mli", 13 + "lib/http_client.ml", 14 + "lib/one.ml" 15 + ], 16 + "rationale": "Got's timeout system distinguishes between DNS lookup, TCP connection, TLS handshake, socket idle, request upload, response headers, and total request time. This granularity is valuable for debugging performance issues and setting precise timeout policies. For example, users might want a short DNS timeout (2s) but a longer upload timeout (60s) for large files. The OCaml library's current approach lumps multiple phases together, making it harder to identify bottlenecks." 17 + }, 18 + { 19 + "source_repo": "third_party/javascript/got", 20 + "source_language": "TypeScript", 21 + "criticality": "medium", 22 + "change_type": "feature", 23 + "title": "Implement upload and download progress callbacks", 24 + "description": "Got provides real-time progress events for both uploads and downloads with percent completion, bytes transferred, and total size. The OCaml library does not currently expose progress tracking, which is essential for user-facing applications with large file transfers. Progress callbacks should emit structured data including percentage, transferred bytes, and total bytes.", 25 + "affected_files": [ 26 + "lib/response.ml", 27 + "lib/response.mli", 28 + "lib/http_client.ml", 29 + "lib/requests.ml", 30 + "lib/one.ml" 31 + ], 32 + "rationale": "Progress tracking is critical for CLI tools and user-facing applications that download/upload large files. The ocurl CLI tool already has progress bars, suggesting this feature would be useful. Got's implementation shows progress should be calculated during streaming, emit events during transfer, and handle cases where Content-Length is unknown. This would significantly improve UX for applications built on this library." 33 + }, 34 + { 35 + "source_repo": "third_party/javascript/got", 36 + "source_language": "TypeScript", 37 + "criticality": "high", 38 + "change_type": "security", 39 + "title": "Add Content-Length validation to prevent truncation attacks", 40 + "description": "Got includes a strictContentLength option that validates the actual bytes received against the Content-Length header. This prevents silent truncation attacks where a MITM attacker or faulty proxy truncates responses. The OCaml library does not validate Content-Length, which could allow incomplete responses to be treated as complete. When enabled, requests should fail with a specific error if received bytes don't match the declared Content-Length.", 41 + "affected_files": [ 42 + "lib/http_client.ml", 43 + "lib/response.ml", 44 + "lib/error.ml", 45 + "lib/error.mli" 46 + ], 47 + "rationale": "Content-Length mismatches can indicate MITM attacks, network issues, or buggy proxies. Got validates both compressed and uncompressed byte counts depending on context. The OCaml library reads Content-Length but doesn't validate it, risking silent data corruption. This is especially important for security-sensitive applications or when downloading executable code/configuration files. Adding validation with an optional flag (default: true for safety) would prevent these attack vectors." 48 + }, 49 + { 50 + "source_repo": "third_party/javascript/got", 51 + "source_language": "TypeScript", 52 + "criticality": "medium", 53 + "change_type": "feature", 54 + "title": "Add request/response hook system for extensibility", 55 + "description": "Got provides 6 hook types (init, beforeRequest, beforeRedirect, beforeRetry, beforeError, afterResponse) that allow users to modify requests, transform errors, implement custom authentication, logging, or caching. The OCaml library has no equivalent hook system. Hooks enable powerful patterns like request signing, response transformation, custom retry logic, and instrumentation without modifying core library code.", 56 + "affected_files": [ 57 + "lib/requests.ml", 58 + "lib/requests.mli", 59 + "lib/one.ml", 60 + "lib/one.mli" 61 + ], 62 + "rationale": "Hooks provide a standardized extension point for cross-cutting concerns. Got's hook system enables use cases like: AWS signature authentication via beforeRequest, custom error classes via beforeError, response caching via afterResponse, and audit logging. The OCaml library currently requires users to wrap every request call for these patterns, leading to verbose code. A hook system using first-class functions would fit OCaml's functional style while providing similar extensibility." 63 + }, 64 + { 65 + "source_repo": "third_party/javascript/got", 66 + "source_language": "TypeScript", 67 + "criticality": "low", 68 + "change_type": "feature", 69 + "title": "Add AbortController/cancellation support for in-flight requests", 70 + "description": "Got supports AbortController to cancel in-flight requests, which is essential for user-initiated cancellations (e.g., clicking a cancel button) or implementing request timeouts at the application level. The OCaml library doesn't expose explicit cancellation, though Eio's switch cancellation provides some capability. Explicit cancellation with a standard API would improve usability.", 71 + "affected_files": [ 72 + "lib/requests.ml", 73 + "lib/requests.mli", 74 + "lib/one.ml", 75 + "lib/http_client.ml" 76 + ], 77 + "rationale": "While Eio's switch cancellation can terminate requests, it's not granular enough for per-request cancellation in complex applications. Users may want to cancel specific requests while keeping others running. Got's approach using AbortSignal provides a standard pattern. The OCaml library could expose cancellation via Eio.Promise or a custom cancellation token, enabling use cases like request racing (first response wins) or user-initiated cancellation in interactive applications." 78 + }, 79 + { 80 + "source_repo": "third_party/javascript/got", 81 + "source_language": "TypeScript", 82 + "criticality": "high", 83 + "change_type": "bug", 84 + "title": "Add specialized error types for more granular error handling", 85 + "description": "Got defines 10+ specialized error types (RequestError, HTTPError, MaxRedirectsError, TimeoutError, ReadError, UploadError, CacheError, ParseError, RetryError, AbortError) each with relevant metadata. The OCaml library has 10 error exceptions but lacks specific types for UploadError, ReadError, ParseError, and RetryError. These distinctions help users handle different failure modes appropriately and debug issues faster.", 86 + "affected_files": [ 87 + "lib/error.ml", 88 + "lib/error.mli", 89 + "lib/response.ml", 90 + "lib/http_client.ml" 91 + ], 92 + "rationale": "Granular error types enable precise error handling. Got distinguishes between errors during upload (UploadError), download (ReadError), and parsing (ParseError), each with different recovery strategies. The OCaml library conflates these under generic errors. For instance, an UploadError might indicate the request body stream failed, suggesting local disk issues, while a ReadError indicates network/server issues. Adding these error types with relevant context (timings, partial data, phase information) would significantly improve debuggability." 93 + }, 94 + { 95 + "source_repo": "third_party/javascript/got", 96 + "source_language": "TypeScript", 97 + "criticality": "medium", 98 + "change_type": "enhancement", 99 + "title": "Add detailed timing information for performance profiling", 100 + "description": "Got provides comprehensive timing data for all request phases: start, socket, lookup, connect, secureConnect, upload, response, end, with calculated phase durations (wait, dns, tcp, tls, request, firstByte, download, total). The OCaml library only tracks total elapsed time. Detailed timings are essential for diagnosing performance issues and implementing smart retry strategies.", 101 + "affected_files": [ 102 + "lib/response.ml", 103 + "lib/response.mli", 104 + "lib/http_client.ml", 105 + "lib/requests.ml" 106 + ], 107 + "rationale": "Performance profiling requires granular timing data. Got's timing structure helps identify bottlenecks: slow DNS (lookup phase), network latency (tcp phase), TLS negotiation (tls phase), server processing (firstByte), or bandwidth issues (download phase). The OCaml library only provides total elapsed time, making it impossible to identify which phase is slow. Adding phase-specific timestamps using Eio's clock would enable performance analysis and smarter timeout/retry policies based on historical timings." 108 + }, 109 + { 110 + "source_repo": "third_party/javascript/got", 111 + "source_language": "TypeScript", 112 + "criticality": "medium", 113 + "change_type": "enhancement", 114 + "title": "Improve retry strategy with enforceRetryRules option", 115 + "description": "Got's retry configuration includes an enforceRetryRules flag that determines whether custom calculateDelay functions can override built-in retry rules (methods, status codes, error codes, limits). When true, the library enforces these rules before calling custom logic. The OCaml library doesn't provide this level of control, potentially allowing custom retry logic to violate safety constraints.", 116 + "affected_files": [ 117 + "lib/retry.ml", 118 + "lib/retry.mli" 119 + ], 120 + "rationale": "The enforceRetryRules pattern provides a safety mechanism ensuring custom retry logic respects fundamental constraints. Without this, a custom retry calculator might retry non-idempotent POST requests or exceed the maximum retry count, leading to data corruption or infinite loops. The OCaml library's retry system currently evaluates all conditions inline. Separating rule enforcement from custom delay calculation would make the retry system both safer and more flexible." 121 + }, 122 + { 123 + "source_repo": "third_party/javascript/got", 124 + "source_language": "TypeScript", 125 + "criticality": "low", 126 + "change_type": "enhancement", 127 + "title": "Add support for Unix domain sockets", 128 + "description": "Got supports Unix domain sockets via the socketPath option, enabling communication with local services (Docker daemon, systemd, local databases) without TCP overhead. The OCaml library doesn't expose Unix socket support, though the underlying Eio capabilities exist. Adding this feature would enable zero-copy local IPC and communication with containerized services.", 129 + "affected_files": [ 130 + "lib/requests.ml", 131 + "lib/one.ml", 132 + "lib/http_client.ml" 133 + ], 134 + "rationale": "Unix domain sockets are widely used for local service communication (Docker API, containerd, local databases, systemd). Got validates Unix socket URLs and handles them specially to prevent security issues (e.g., redirect from HTTP to Unix socket). The OCaml library could leverage Eio's Unix socket support to enable these use cases. This is especially valuable for system tools, container management, and local service discovery." 135 + }, 136 + { 137 + "source_repo": "third_party/javascript/got", 138 + "source_language": "TypeScript", 139 + "criticality": "low", 140 + "change_type": "feature", 141 + "title": "Add HTTP/2 support with automatic protocol negotiation", 142 + "description": "Got supports HTTP/2 via the http2 option with automatic ALPN negotiation, connection reuse, and multiplexing. The OCaml library only implements HTTP/1.1. HTTP/2 provides significant performance improvements through multiplexing, header compression, and server push. Modern APIs increasingly require or benefit from HTTP/2.", 143 + "affected_files": [ 144 + "lib/http_client.ml", 145 + "lib/requests.ml", 146 + "lib/one.ml" 147 + ], 148 + "rationale": "HTTP/2 reduces latency through request multiplexing (multiple requests over one connection), header compression (HPACK), and server push. Got automatically negotiates HTTP/2 via ALPN when available. The OCaml library's HTTP/1.1 implementation forces sequential requests or connection overhead for concurrent requests. Adding HTTP/2 support (potentially via an OCaml HTTP/2 library like h2) would improve performance for API clients making many concurrent requests and align with modern web standards." 149 + }, 150 + { 151 + "source_repo": "third_party/javascript/got", 152 + "source_language": "TypeScript", 153 + "criticality": "medium", 154 + "change_type": "enhancement", 155 + "title": "Add pagination API for handling paginated responses", 156 + "description": "Got provides a dedicated pagination API that automatically follows Link headers (RFC 8288) and yields pages lazily. This is a common pattern for REST APIs (GitHub, GitLab, pagination standards). The OCaml library requires users to manually implement pagination logic. A built-in pagination API would simplify working with paginated endpoints.", 157 + "affected_files": [ 158 + "lib/requests.ml", 159 + "lib/requests.mli", 160 + "lib/response.ml" 161 + ], 162 + "rationale": "Many REST APIs use Link headers for pagination (GitHub, GitLab, etc.). Got's pagination API parses Link headers, follows next/prev/first/last relations, and yields pages as an async iterator. The OCaml library requires users to manually parse Link headers and make follow-up requests. Adding a pagination helper using Eio's Seq or Stream abstraction would reduce boilerplate for API clients and standardize pagination handling across applications." 163 + }, 164 + { 165 + "source_repo": "third_party/javascript/got", 166 + "source_language": "TypeScript", 167 + "criticality": "medium", 168 + "change_type": "enhancement", 169 + "title": "Add DNS caching to reduce lookup latency", 170 + "description": "Got includes automatic DNS caching via cacheable-lookup with configurable TTL to reduce DNS lookup overhead for repeated requests to the same host. The OCaml library doesn't cache DNS results, causing repeated lookups for each request. DNS caching can significantly reduce latency for applications making many requests to the same domain.", 171 + "affected_files": [ 172 + "lib/http_client.ml", 173 + "lib/requests.ml", 174 + "lib/one.ml" 175 + ], 176 + "rationale": "DNS lookups add 20-200ms latency per request. Got caches DNS results with configurable TTL, eliminating this overhead for subsequent requests. The OCaml library performs fresh DNS lookups for each connection, even when making thousands of requests to the same API endpoint. Implementing DNS caching (respecting TTL from DNS records) would improve performance for high-throughput API clients. Eio's network API could be extended or wrapped to add this functionality." 177 + }, 178 + { 179 + "source_repo": "third_party/javascript/got", 180 + "source_language": "TypeScript", 181 + "criticality": "low", 182 + "change_type": "enhancement", 183 + "title": "Add methodRewriting option for automatic redirect method handling", 184 + "description": "Got provides a methodRewriting option that automatically changes POST/PUT/PATCH to GET on 301/302 redirects while preserving methods on 307/308. The OCaml library doesn't expose this control. Some servers use non-standard redirect behavior, and the ability to customize method rewriting improves compatibility.", 185 + "affected_files": [ 186 + "lib/requests.ml", 187 + "lib/http_client.ml" 188 + ], 189 + "rationale": "HTTP redirect semantics are complex: 303 always uses GET, 307/308 preserve the method, but 301/302 behavior varies by browser/client. Got's methodRewriting option allows users to control this behavior. The OCaml library likely has hardcoded behavior. Exposing this as a configuration option would improve compatibility with servers that use non-standard redirect patterns and give users fine-grained control over redirect handling." 190 + }, 191 + { 192 + "source_repo": "third_party/javascript/got", 193 + "source_language": "TypeScript", 194 + "criticality": "high", 195 + "change_type": "security", 196 + "title": "Add checkServerIdentity option for custom TLS certificate validation", 197 + "description": "Got exposes the checkServerIdentity callback allowing custom certificate validation logic (e.g., certificate pinning, custom root CAs, SNI validation). The OCaml library doesn't expose this level of TLS control. Custom certificate validation is essential for high-security environments, certificate pinning, and working with internal CAs.", 198 + "affected_files": [ 199 + "lib/http_client.ml", 200 + "lib/one.ml", 201 + "lib/requests.ml" 202 + ], 203 + "rationale": "Advanced security scenarios require custom certificate validation: pinning specific certificates/keys, validating against private CAs, implementing CT log verification, or checking certificate transparency. Got exposes Node's checkServerIdentity for this purpose. The OCaml library uses tls-eio but doesn't expose custom validation hooks. Adding configuration for custom certificate validation (via tls-eio's authenticator mechanism) would enable enterprise security requirements and certificate pinning strategies." 204 + }, 205 + { 206 + "source_repo": "third_party/javascript/got", 207 + "source_language": "TypeScript", 208 + "criticality": "medium", 209 + "change_type": "enhancement", 210 + "title": "Add ignoreInvalidCookies option for lenient cookie parsing", 211 + "description": "Got provides an ignoreInvalidCookies option that silently ignores malformed Set-Cookie headers instead of failing the request. Some servers send invalid cookies, and the ability to ignore them improves compatibility. The OCaml library's cookie handling behavior in these cases should be configurable.", 212 + "affected_files": [ 213 + "lib/requests.ml", 214 + "lib/http_client.ml" 215 + ], 216 + "rationale": "Real-world servers often send malformed cookies (invalid dates, bad domains, encoding issues). Got's ignoreInvalidCookies option allows graceful handling by logging warnings but not failing requests. The OCaml library uses cookeio for cookie parsing, which may be strict. Adding a configuration option to ignore invalid cookies (while logging them) would improve compatibility with poorly-implemented servers without sacrificing correctness for well-behaved ones." 217 + }, 218 + { 219 + "source_repo": "third_party/javascript/got", 220 + "source_language": "TypeScript", 221 + "criticality": "low", 222 + "change_type": "enhancement", 223 + "title": "Add allowGetBody option for GET requests with bodies", 224 + "description": "Got includes an allowGetBody option that permits request bodies on GET requests, which while non-standard, is required by some APIs (Elasticsearch). The OCaml library likely prohibits this. Supporting GET with body (as an opt-in) improves compatibility with non-standard APIs.", 225 + "affected_files": [ 226 + "lib/http_client.ml", 227 + "lib/requests.ml", 228 + "lib/one.ml" 229 + ], 230 + "rationale": "While RFC 7231 discourages GET requests with bodies, some APIs require them (Elasticsearch search API). Got provides allowGetBody to enable this non-standard behavior when needed. The OCaml library likely prevents bodies on GET requests. Adding this as an opt-in option would improve compatibility with these APIs while maintaining correct default behavior. This is a pragmatic compromise between standards compliance and real-world API compatibility." 231 + }, 232 + { 233 + "source_repo": "third_party/javascript/got", 234 + "source_language": "TypeScript", 235 + "criticality": "medium", 236 + "change_type": "feature", 237 + "title": "Add beforeCache hooks for customizing cache behavior", 238 + "description": "Got provides beforeCache hooks that can modify responses before caching or prevent caching entirely by returning false. This enables cache policies based on custom logic (e.g., don't cache sensitive data, modify cache TTL). The OCaml library has disabled HTTP caching. When/if caching is re-enabled, this hook would be valuable.", 239 + "affected_files": [ 240 + "lib/requests.ml", 241 + "lib/http_client.ml" 242 + ], 243 + "rationale": "HTTP caching requires policy decisions: which responses to cache, for how long, whether to cache sensitive data. Got's beforeCache hooks allow intercepting responses before they're cached, enabling use cases like: excluding responses with auth tokens, adjusting cache TTL based on content, adding cache metadata, or preventing caching of error responses. While the OCaml library has disabled caching (per code comments), implementing hooks in preparation for re-enabling caching would follow Got's extensible architecture." 244 + }, 245 + { 246 + "source_repo": "third_party/javascript/got", 247 + "source_language": "TypeScript", 248 + "criticality": "low", 249 + "change_type": "enhancement", 250 + "title": "Add support for brotli and zstd compression algorithms", 251 + "description": "Got supports gzip, deflate, brotli, and zstd compression algorithms. The OCaml library only supports gzip and deflate. Brotli typically provides 20% better compression than gzip, and zstd offers excellent speed/ratio tradeoffs. Supporting modern compression algorithms would reduce bandwidth usage.", 252 + "affected_files": [ 253 + "lib/http_client.ml" 254 + ], 255 + "rationale": "Modern compression algorithms like brotli and zstd provide better compression ratios and/or speed than gzip. Got automatically requests and decompresses brotli/zstd when available. The OCaml library only supports gzip/deflate via the decompress library. Adding brotli support (via existing OCaml libraries) would reduce bandwidth for APIs that support it (Google, Cloudflare CDNs). Zstd support would benefit real-time APIs where compression speed matters." 256 + }, 257 + { 258 + "source_repo": "third_party/javascript/got", 259 + "source_language": "TypeScript", 260 + "criticality": "medium", 261 + "change_type": "enhancement", 262 + "title": "Add maxRetryAfter option to cap Retry-After delays", 263 + "description": "Got provides maxRetryAfter to cap the maximum delay from Retry-After headers, preventing servers from imposing arbitrarily long delays. The OCaml library respects Retry-After but doesn't cap it. A malicious or misconfigured server could send 'Retry-After: 999999999' causing indefinite waits.", 264 + "affected_files": [ 265 + "lib/retry.ml", 266 + "lib/retry.mli" 267 + ], 268 + "rationale": "Retry-After headers can be maliciously large or misconfigured. Got caps these values with maxRetryAfter (defaulting to the request timeout). The OCaml library's parse_retry_after function doesn't validate or cap the delay, potentially causing extremely long waits. Adding a maximum cap (configured via retry config, defaulting to backoff_max) would prevent denial-of-service via Retry-After headers while still respecting legitimate rate limiting." 269 + }, 270 + { 271 + "source_repo": "third_party/javascript/got", 272 + "source_language": "TypeScript", 273 + "criticality": "medium", 274 + "change_type": "feature", 275 + "title": "Add diagnostics channel for observability and monitoring", 276 + "description": "Got implements diagnostics_channel for emitting lifecycle events (request created, started, response received, errors, retries, redirects) enabling external monitoring, tracing, and debugging without modifying application code. The OCaml library doesn't have equivalent instrumentation hooks. Adding structured event emission would enable observability.", 277 + "affected_files": [ 278 + "lib/requests.ml", 279 + "lib/http_client.ml", 280 + "lib/retry.ml" 281 + ], 282 + "rationale": "Modern applications require observability: request tracing, performance monitoring, error tracking, and debugging. Got's diagnostics_channel emits structured events at key lifecycle points with request IDs, timings, URLs, and error details. External tools can subscribe without code changes. The OCaml library logs via the Logs library but doesn't provide structured event hooks. Adding an event emission system (potentially via Effects or a simple callback registry) would enable OpenTelemetry integration, custom metrics, and request tracing." 283 + } 284 + ] 285 + }
+275
third_party/javascript/needle.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "needle", 5 + "source_language": "JavaScript", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add hierarchical timeout support (open/response/read)", 9 + "description": "Needle implements three distinct timeout types: open_timeout (connection establishment, default 10s), response_timeout (time to first response headers, default 0/disabled), and read_timeout (data transfer after headers, default 0/disabled). The OCaml library only supports connect, read, and total timeouts. The missing 'response_timeout' is critical for detecting hung servers that accept connections but never send headers.", 10 + "affected_files": [ 11 + "lib/timeout.ml", 12 + "lib/requests.ml", 13 + "lib/one.ml", 14 + "lib/http_client.ml" 15 + ], 16 + "rationale": "Response timeout is distinct from connection timeout and read timeout. A server may accept connections (passing connect_timeout) and eventually send data (passing read_timeout if measured from connection start), but take minutes to send response headers. This scenario is currently not detectable. Needle's three-phase timeout model (open → response → read) provides finer-grained control over the request lifecycle and can detect stalled servers earlier." 17 + }, 18 + { 19 + "source_repo": "needle", 20 + "source_language": "JavaScript", 21 + "criticality": "medium", 22 + "change_type": "feature", 23 + "title": "Add AbortSignal/cancellation mechanism for request termination", 24 + "description": "Needle supports AbortSignal for request cancellation, allowing external cancellation of in-flight requests. This is particularly useful for: (1) user-initiated cancellation (e.g., UI cancel button), (2) coordinated shutdown of multiple requests, (3) timeout implementation at application level, and (4) cleanup on component unmount/fiber cancellation. The OCaml library currently has no programmatic way to cancel an in-flight request.", 25 + "affected_files": [ 26 + "lib/requests.ml", 27 + "lib/one.ml", 28 + "lib/http_client.ml" 29 + ], 30 + "rationale": "While Eio provides fiber cancellation via switches, there's no explicit API for users to cancel individual requests. Needle's abort_handler pattern could be adapted using Eio.Cancel.protect and exposing a cancellation token. This would enable use cases like race conditions (first response wins, cancel others), user-driven cancellations, and better integration with React-style component lifecycles in OCaml web frameworks." 31 + }, 32 + { 33 + "source_repo": "needle", 34 + "source_language": "JavaScript", 35 + "criticality": "medium", 36 + "change_type": "enhancement", 37 + "title": "Add stream length detection for automatic Content-Length headers", 38 + "description": "Needle provides stream_length option and get_stream_length() utility that automatically determines the content length of file streams using fs.stat(). When stream_length=0 and a file path is provided, it automatically sets Content-Length headers without requiring users to manually compute file sizes. The OCaml library requires users to manually specify content length for streams.", 39 + "affected_files": [ 40 + "lib/body.ml", 41 + "lib/requests.ml", 42 + "lib/one.ml" 43 + ], 44 + "rationale": "Many HTTP servers and some APIs reject or perform poorly with chunked transfer encoding, requiring Content-Length headers. When uploading files, users currently must manually stat the file to get its size. Needle's automatic stream length detection using Eio.Path.load and Eio.File.stat would improve ergonomics for file uploads and enable better compatibility with servers that require Content-Length (some S3-compatible APIs, older HTTP/1.0 servers)." 45 + }, 46 + { 47 + "source_repo": "needle", 48 + "source_language": "JavaScript", 49 + "criticality": "high", 50 + "change_type": "bug", 51 + "title": "Fix decompression error handling to prevent request failures", 52 + "description": "Needle handles decompression errors gracefully by catching errors in the decompression pipeline and continuing the request, emitting warnings but not failing. The OCaml library (http_client.ml:101-113) falls back to raw body on decompression errors, which is good, but doesn't log warnings or provide visibility into decompression failures. However, there's a risk that decompression errors in streaming contexts could cause request failures.", 53 + "affected_files": [ 54 + "lib/http_client.ml", 55 + "lib/requests.ml", 56 + "lib/response.ml" 57 + ], 58 + "rationale": "Malformed compressed responses (partial gzip, corrupted deflate) should not cause complete request failures. The current fallback in http_client.ml works for buffered responses, but streaming responses via Eio.Flow.source_ty may not have the same protection. Needle's pattern of catching decompressor errors and emitting warnings (while continuing with raw data) is more robust. Additionally, the library should log when decompression fails so users can debug server-side compression issues." 59 + }, 60 + { 61 + "source_repo": "needle", 62 + "source_language": "JavaScript", 63 + "criticality": "medium", 64 + "change_type": "enhancement", 65 + "title": "Implement Retry-After header support in retry logic", 66 + "description": "Needle's retry mechanism respects the Retry-After header from HTTP responses (configurable via respect_retry_after option). The OCaml library has parse_retry_after in retry.ml:73-93 but this function is never called or used in the actual retry implementation (retry.ml:95-123). The with_retry function doesn't check response headers for Retry-After.", 67 + "affected_files": [ 68 + "lib/retry.ml", 69 + "lib/requests.ml" 70 + ], 71 + "rationale": "Retry-After is a standard HTTP header (RFC 7231) used by servers to indicate when clients should retry requests, especially for 429 (Too Many Requests) and 503 (Service Unavailable) responses. Respecting this header prevents thundering herd problems and follows server guidance. The parse_retry_after function exists but is dead code. Integrating it into the retry logic (when respect_retry_after is true) would make retries more server-friendly and reduce wasted retry attempts." 72 + }, 73 + { 74 + "source_repo": "needle", 75 + "source_language": "JavaScript", 76 + "criticality": "low", 77 + "change_type": "enhancement", 78 + "title": "Add direct-to-disk output option for downloads", 79 + "description": "Needle supports an 'output' option that writes response bodies directly to disk, bypassing memory buffering entirely. This is useful for large file downloads (videos, datasets, ISOs) where holding the entire response in memory is impractical. The OCaml library requires users to manually implement streaming to files using Eio.Flow.copy.", 80 + "affected_files": [ 81 + "lib/requests.ml", 82 + "lib/one.ml", 83 + "lib/response.ml" 84 + ], 85 + "rationale": "While the OCaml library supports streaming via Response.body (Eio.Flow.source_ty), users must manually write the code to pipe this to a file using Eio.Flow.copy. Needle's output option provides a convenience API that handles this automatically, including error handling during write. Adding a ?output:Eio.Path.t parameter to request functions would improve ergonomics for download use cases and reduce boilerplate code." 86 + }, 87 + { 88 + "source_repo": "needle", 89 + "source_language": "JavaScript", 90 + "criticality": "medium", 91 + "change_type": "security", 92 + "title": "Add NO_PROXY environment variable support for proxy exclusions", 93 + "description": "Needle implements NO_PROXY environment variable support (with regex pattern matching) to exclude certain hosts from proxying. This is a standard Unix convention used by curl, wget, and most HTTP clients. The OCaml library currently has no proxy support at all, but when added, NO_PROXY exclusions should be included.", 94 + "affected_files": [ 95 + "lib/requests.ml", 96 + "lib/one.ml" 97 + ], 98 + "rationale": "In corporate and development environments, HTTP_PROXY is often set globally, but certain hosts (localhost, 127.0.0.1, internal domains) should bypass the proxy. NO_PROXY (and no_proxy) environment variables are the standard mechanism for this. Without this support, users cannot easily exclude hosts from proxying without modifying code. Needle's should_proxy_to() pattern with regex matching for NO_PROXY provides a robust implementation model." 99 + }, 100 + { 101 + "source_repo": "needle", 102 + "source_language": "JavaScript", 103 + "criticality": "medium", 104 + "change_type": "enhancement", 105 + "title": "Add configuration aliasing for backward compatibility", 106 + "description": "Needle provides option aliases (timeout → open_timeout, follow → follow_max, decode → decode_response, parse → parse_response) to maintain backward compatibility while allowing clearer naming. The OCaml library has no aliasing mechanism, making API evolution more breaking.", 107 + "affected_files": [ 108 + "lib/requests.ml", 109 + "lib/timeout.ml", 110 + "lib/retry.ml" 111 + ], 112 + "rationale": "As the library evolves, parameter names may need refinement for clarity (e.g., 'timeout' is ambiguous - connection timeout? total timeout?). Needle's aliasing system (aliased.options and aliased.inverted maps) allows old names to continue working while encouraging new names. This reduces breaking changes for users. The OCaml library could implement this via optional parameters with deprecation warnings, improving API evolution without breaking existing code." 113 + }, 114 + { 115 + "source_repo": "needle", 116 + "source_language": "JavaScript", 117 + "criticality": "low", 118 + "change_type": "enhancement", 119 + "title": "Add response events (header, headers, redirect) for streaming scenarios", 120 + "description": "Needle emits events during the request lifecycle: 'response' (when response starts), 'header'/'headers' (when headers received), 'redirect' (when following redirects), 'timeout' (when timeout occurs), and 'done' (when complete). The OCaml library provides only a completed Response object with no intermediate notifications.", 121 + "affected_files": [ 122 + "lib/requests.ml", 123 + "lib/one.ml", 124 + "lib/response.ml" 125 + ], 126 + "rationale": "For streaming requests, users may want to make decisions based on response headers before reading the body (e.g., check Content-Length, validate Content-Type, inspect custom headers). Needle's event emission allows users to inspect headers and decide whether to proceed with body consumption. In OCaml, this could be implemented as callback parameters or by returning a response record with headers before body streaming. This enables early rejection of large responses and header-based routing." 127 + }, 128 + { 129 + "source_repo": "needle", 130 + "source_language": "JavaScript", 131 + "criticality": "medium", 132 + "change_type": "enhancement", 133 + "title": "Improve redirect handling with method preservation and referer options", 134 + "description": "Needle provides fine-grained redirect control: follow_keep_method (preserve POST/PUT on redirect), follow_set_referer (add Referer header), follow_if_same_host (only follow same-host redirects), follow_if_same_protocol (only follow http→http or https→https), and follow_if_same_location (prevent redirect loops). The OCaml library only has follow_redirects (bool) and max_redirects (int), providing coarse control.", 135 + "affected_files": [ 136 + "lib/requests.ml", 137 + "lib/one.ml" 138 + ], 139 + "rationale": "RFC 7231 semantics for redirects can be complex (301/302 should change POST to GET, but 307/308 preserve method). Some security policies require preventing redirects to external hosts or protocol downgrade (https→http). Needle's granular options allow users to implement precise redirect policies. Adding follow_keep_method, follow_if_same_host, and follow_if_same_protocol would improve security (prevent open redirect exploits) and RFC compliance." 140 + }, 141 + { 142 + "source_repo": "needle", 143 + "source_language": "JavaScript", 144 + "criticality": "low", 145 + "change_type": "enhancement", 146 + "title": "Add charset decoding support using iconv", 147 + "description": "Needle implements automatic charset detection and decoding via the decoder.js module using iconv-lite. It parses Content-Type headers for charset parameters and decodes non-UTF8 encodings (latin1, windows-1252, shift-jis, etc.) to UTF-8. The OCaml library assumes UTF-8 and has no charset handling.", 148 + "affected_files": [ 149 + "lib/http_client.ml", 150 + "lib/response.ml", 151 + "lib/mime.ml" 152 + ], 153 + "rationale": "Many legacy websites and APIs use non-UTF8 encodings (especially Latin-1/ISO-8859-1, Windows-1252 for European languages, or GB2312/Shift-JIS for Asian languages). Without charset decoding, response text will be mojibake. Needle's StreamDecoder using iconv-lite handles this automatically. OCaml equivalent would use the uutf or camomile libraries. Adding optional charset detection (when decode_response=true) would improve international compatibility." 154 + }, 155 + { 156 + "source_repo": "needle", 157 + "source_language": "JavaScript", 158 + "criticality": "low", 159 + "change_type": "refactor", 160 + "title": "Add comprehensive error code classification", 161 + "description": "Needle's error handling tests check for specific error codes (ENOTFOUND, EADDRINFO, EAI_AGAIN for DNS failures, ECONNRESET for connection issues) and ensures errors don't throw synchronously. The OCaml library has generic ConnectionError exceptions without structured error codes.", 162 + "affected_files": [ 163 + "lib/error.ml", 164 + "lib/requests.ml", 165 + "lib/one.ml" 166 + ], 167 + "rationale": "Different connection errors require different handling: DNS failures (ENOTFOUND) may indicate configuration issues, ECONNREFUSED may indicate service down, ETIMEDOUT indicates network issues. Needle's tests validate error codes are preserved and surfaced correctly. The OCaml library should preserve underlying Eio error details and classify them in Error.t, allowing users to implement different retry strategies based on error type (retry ETIMEDOUT, don't retry ECONNREFUSED)." 168 + }, 169 + { 170 + "source_repo": "needle", 171 + "source_language": "JavaScript", 172 + "criticality": "high", 173 + "change_type": "security", 174 + "title": "Implement secure TLS defaults and prevent protocol downgrade", 175 + "description": "Needle allows TLS configuration (rejectUnauthorized, secureProtocol, ciphers, etc.) but defaults to rejectUnauthorized=false for backward compatibility, which is insecure. The OCaml library defaults to verify_tls=true, which is more secure. However, neither library prevents HTTPS→HTTP protocol downgrade during redirects.", 176 + "affected_files": [ 177 + "lib/requests.ml", 178 + "lib/one.ml" 179 + ], 180 + "rationale": "The OCaml library's default of verify_tls=true is correct. However, the library should also prevent protocol downgrade attacks during redirects (HTTPS→HTTP). When implementing follow_if_same_protocol, it should default to true for HTTPS requests to prevent attackers from using redirects to downgrade to unencrypted HTTP. Needle doesn't do this by default either, so this is an opportunity for the OCaml library to be more secure than the reference implementation." 181 + }, 182 + { 183 + "source_repo": "needle", 184 + "source_language": "JavaScript", 185 + "criticality": "medium", 186 + "change_type": "feature", 187 + "title": "Add brotli decompression support", 188 + "description": "Needle supports brotli compression (Content-Encoding: br) in addition to gzip and deflate, with automatic detection and fallback for older Node versions. The OCaml library only supports gzip, deflate, and zlib decompression.", 189 + "affected_files": [ 190 + "lib/http_client.ml", 191 + "lib/requests.ml" 192 + ], 193 + "rationale": "Brotli provides better compression ratios than gzip (typically 15-20% smaller) and is widely supported by modern browsers and CDNs. Many API providers (Google, Cloudflare, Fastly) serve brotli-compressed responses when Accept-Encoding: br is sent. The OCaml decompress library doesn't include brotli, but the decompress.br package or ocaml-brotli bindings could be added as an optional dependency. Supporting brotli would reduce bandwidth usage and improve performance." 194 + }, 195 + { 196 + "source_repo": "needle", 197 + "source_language": "JavaScript", 198 + "criticality": "medium", 199 + "change_type": "enhancement", 200 + "title": "Add request/response statistics and byte counting", 201 + "description": "Needle tracks response.bytes (total bytes received) in responses. The OCaml library tracks requests_made, total_time, and retries_count at the session level but doesn't track bytes transferred per request or total.", 202 + "affected_files": [ 203 + "lib/response.ml", 204 + "lib/requests.ml" 205 + ], 206 + "rationale": "Byte counting is useful for: (1) monitoring bandwidth usage, (2) implementing rate limiting, (3) cost tracking for metered APIs, (4) progress reporting for large transfers, and (5) debugging (detecting unexpected response sizes). Adding bytes_received and bytes_sent fields to Response.t and cumulative counters to the session statistics would enable bandwidth monitoring and progress tracking without requiring users to wrap streams." 207 + }, 208 + { 209 + "source_repo": "needle", 210 + "source_language": "JavaScript", 211 + "criticality": "low", 212 + "change_type": "enhancement", 213 + "title": "Add URI transformation/modifier hook", 214 + "description": "Needle supports a 'uri_modifier' option that allows users to transform the final URI before sending the request. This is useful for adding signatures, signing requests (AWS Signature v4), adding dynamic query parameters, or implementing custom URL transformations.", 215 + "affected_files": [ 216 + "lib/requests.ml", 217 + "lib/one.ml" 218 + ], 219 + "rationale": "Some authentication schemes require signing the final URL (AWS SigV4, Azure Shared Key). Some proxies or gateways require URL transformation. Rather than forcing users to compute and pass the complete URL, a uri_modifier callback (Uri.t -> Uri.t) would allow late-stage URL manipulation. This is particularly useful when the library constructs URLs from base + path + query parameters, and users need to add computed signatures." 220 + }, 221 + { 222 + "source_repo": "needle", 223 + "source_language": "JavaScript", 224 + "criticality": "low", 225 + "change_type": "enhancement", 226 + "title": "Add custom DNS lookup function support", 227 + "description": "Needle allows passing a custom 'lookup' function to override DNS resolution. This enables custom DNS resolution strategies (DNS-over-HTTPS, local overrides, round-robin, latency-based selection).", 228 + "affected_files": [ 229 + "lib/requests.ml", 230 + "lib/one.ml" 231 + ], 232 + "rationale": "Custom DNS resolution is useful for: (1) testing (override production domains to point to test servers), (2) local development (override DNS for debugging), (3) DNS-over-HTTPS for privacy, (4) implementing custom load balancing, and (5) working around DNS caching issues. Eio's net interface may not directly support this, but exposing a way to provide custom hostname→IP resolution would enable these use cases." 233 + }, 234 + { 235 + "source_repo": "needle", 236 + "source_language": "JavaScript", 237 + "criticality": "medium", 238 + "change_type": "feature", 239 + "title": "Add automatic XML parsing support", 240 + "description": "Needle automatically parses XML responses (when Content-Type matches XML) using the sax parser, similar to how it parses JSON. The OCaml library only has automatic JSON parsing via Response.json.", 241 + "affected_files": [ 242 + "lib/response.ml", 243 + "lib/requests.ml" 244 + ], 245 + "rationale": "Many APIs (SOAP services, AWS, Azure, older REST APIs) return XML. While users can manually parse, automatic XML parsing (using markup.ml or xmlm) when Content-Type is application/xml would match the convenience of automatic JSON parsing. This could be implemented as Response.xml returning an XML document AST. The feature should be optional (controlled by parse_response config) to avoid overhead when XML parsing isn't needed." 246 + }, 247 + { 248 + "source_repo": "needle", 249 + "source_language": "JavaScript", 250 + "criticality": "low", 251 + "change_type": "enhancement", 252 + "title": "Add default User-Agent with library version and platform info", 253 + "description": "Needle automatically sets a User-Agent header with library version, Node.js version, platform, and architecture (e.g., 'Needle/3.2.0 (Node.js v18.0.0; linux x64)'). The OCaml library has no default User-Agent.", 254 + "affected_files": [ 255 + "lib/requests.ml", 256 + "lib/headers.ml" 257 + ], 258 + "rationale": "Many HTTP servers log User-Agent for analytics and debugging. Some servers reject requests without User-Agent headers. A default User-Agent identifying the library and OCaml version helps with: (1) server-side debugging (identifying HTTP client issues), (2) API provider analytics, and (3) compliance with HTTP best practices. It should be easily overridable but present by default. Format: 'OCaml-Requests/<version> (OCaml <version>; <platform>)'." 259 + }, 260 + { 261 + "source_repo": "needle", 262 + "source_language": "JavaScript", 263 + "criticality": "medium", 264 + "change_type": "enhancement", 265 + "title": "Add test infrastructure with mock servers and error injection", 266 + "description": "Needle's test suite uses helpers.js to create mock HTTP/HTTPS servers with configurable responses, delays, and SSL certificates. The OCaml test suite relies on external httpbin.org service and simple echo servers.", 267 + "affected_files": [ 268 + "test/test_simple.ml", 269 + "test/test_localhost.ml", 270 + "test/httpbin.t" 271 + ], 272 + "rationale": "External test dependencies (httpbin.org) can cause flaky tests due to network issues, service downtime, or rate limiting. Needle's approach of spinning up local HTTP/HTTPS servers with controllable behavior enables testing edge cases (slow responses, partial content, connection drops, SSL errors) reliably. Adding a test helper module that creates Eio-based mock servers would improve test reliability and coverage. This would enable testing timeout edge cases, retry logic, and error handling without external dependencies." 273 + } 274 + ] 275 + }
+256
third_party/javascript/node-fetch.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/javascript/node-fetch", 5 + "source_language": "JavaScript", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add response body size limiting to prevent resource exhaustion", 9 + "description": "Node-fetch implements a 'size' option that limits response body size during streaming consumption, throwing a FetchError with type 'max-size' when exceeded. The OCaml library currently reads entire response bodies without any size limits, which could lead to memory exhaustion attacks or accidental resource consumption.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/one.ml", 13 + "lib/http_client.ml" 14 + ], 15 + "rationale": "The text() method in response.ml uses max_int as the max_size parameter, effectively having no limit. Node-fetch validates size per-chunk during streaming and throws early. This is a critical security feature to prevent denial-of-service through large response bodies. Should add configurable max_response_size option (default: 0 = unlimited) and check during body consumption." 16 + }, 17 + { 18 + "source_repo": "third_party/javascript/node-fetch", 19 + "source_language": "JavaScript", 20 + "criticality": "medium", 21 + "change_type": "enhancement", 22 + "title": "Implement comprehensive referrer policy support", 23 + "description": "Node-fetch implements 9 referrer policy levels (no-referrer, no-referrer-when-downgrade, same-origin, origin, strict-origin, origin-when-cross-origin, strict-origin-when-cross-origin, unsafe-url) following W3C standards. The OCaml library has basic same-origin checking for header stripping but lacks configurable referrer policy.", 24 + "affected_files": [ 25 + "lib/one.ml", 26 + "lib/requests.ml" 27 + ], 28 + "rationale": "Referrer policies are important for privacy and security, controlling what referrer information is sent across origins. Node-fetch has a sophisticated implementation with origin trustworthiness checking (HTTPS, localhost, file schemes) and automatic credential stripping from referrer. The OCaml library only strips Authorization headers on cross-origin redirects but doesn't have a general referrer policy mechanism. This would enhance privacy controls and spec compliance." 29 + }, 30 + { 31 + "source_repo": "third_party/javascript/node-fetch", 32 + "source_language": "JavaScript", 33 + "criticality": "high", 34 + "change_type": "feature", 35 + "title": "Add abort signal support for request cancellation", 36 + "description": "Node-fetch uses AbortSignal for standardized request cancellation and timeout handling, replacing the deprecated built-in timeout option. The OCaml library uses Eio timeouts but lacks a unified cancellation mechanism that can be triggered externally or shared across multiple requests.", 37 + "affected_files": [ 38 + "lib/one.ml", 39 + "lib/requests.ml", 40 + "lib/timeout.ml" 41 + ], 42 + "rationale": "AbortSignal provides a standard way to cancel operations, handle timeouts, and coordinate cancellation across multiple concurrent requests. Node-fetch removed built-in timeout in v3.x in favor of AbortSignal for better composability. The OCaml library could leverage Eio's cancellation via promises/switches more explicitly, allowing users to cancel requests programmatically. This would improve API ergonomics and enable use cases like request racing or user-initiated cancellation." 43 + }, 44 + { 45 + "source_repo": "third_party/javascript/node-fetch", 46 + "source_language": "JavaScript", 47 + "criticality": "medium", 48 + "change_type": "enhancement", 49 + "title": "Add error type classification for operational vs programmer errors", 50 + "description": "Node-fetch uses a custom error hierarchy with a 'type' field that classifies errors (system, max-redirect, max-size, invalid-redirect, aborted) and preserves system error details (code, errno). The OCaml library has comprehensive error types but lacks this classification granularity.", 51 + "affected_files": [ 52 + "lib/error.ml" 53 + ], 54 + "rationale": "Node-fetch's error.type field allows applications to handle different error categories appropriately. For example, 'system' errors include ECONNREFUSED, ENOTFOUND with preserved errno; 'max-redirect' indicates redirect limit exceeded; 'max-size' indicates body too large. The OCaml library has exceptions like ConnectionError but doesn't preserve underlying system error details or provide sub-classification. Adding an error_type field and preserving system error codes would improve error handling precision." 55 + }, 56 + { 57 + "source_repo": "third_party/javascript/node-fetch", 58 + "source_language": "JavaScript", 59 + "criticality": "medium", 60 + "change_type": "enhancement", 61 + "title": "Implement automatic method conversion on 303 redirects", 62 + "description": "Node-fetch automatically converts POST/PUT/PATCH to GET when receiving a 303 redirect status, following HTTP semantics. The OCaml library follows redirects but doesn't implement method conversion rules.", 63 + "affected_files": [ 64 + "lib/one.ml" 65 + ], 66 + "rationale": "HTTP spec (RFC 7231) requires that 303 responses cause the subsequent request to use GET regardless of the original method. Node-fetch also converts 301/302 POST to GET for legacy browser compatibility. The OCaml library's redirect logic in one.ml:169-196 follows Location headers but doesn't change the method. This could lead to unexpected behavior where POST requests are retried as POST after 303, which violates HTTP semantics. Should add method conversion: 303 -> always GET, 301/302 POST -> GET, others preserve method." 67 + }, 68 + { 69 + "source_repo": "third_party/javascript/node-fetch", 70 + "source_language": "JavaScript", 71 + "criticality": "low", 72 + "change_type": "enhancement", 73 + "title": "Add data: URI scheme support", 74 + "description": "Node-fetch added support for data: URI scheme (RFC 2397) in v3.x, allowing inline data to be fetched. The OCaml library only supports http/https schemes.", 75 + "affected_files": [ 76 + "lib/one.ml", 77 + "lib/requests.ml" 78 + ], 79 + "rationale": "Data URIs are useful for testing, embedding small resources, and certain application patterns. Node-fetch parses data: URLs to extract MIME type and decode content (base64 or URL-encoded). While not critical, this feature improves compatibility with web standards and enables additional use cases. Implementation would require parsing data: URLs and returning synthetic responses without network calls." 80 + }, 81 + { 82 + "source_repo": "third_party/javascript/node-fetch", 83 + "source_language": "JavaScript", 84 + "criticality": "medium", 85 + "change_type": "enhancement", 86 + "title": "Enhance redirect security with better cross-origin detection", 87 + "description": "Node-fetch implements comprehensive cross-origin redirect detection considering domain/subdomain relationships and protocol downgrades (HTTPS->HTTP). The OCaml library's same_origin check only allows same-host and HTTP->HTTPS upgrades.", 88 + "affected_files": [ 89 + "lib/one.ml" 90 + ], 91 + "rationale": "The same_origin function at one.ml:14-24 correctly strips Authorization on cross-origin redirects but could be more sophisticated. Node-fetch's implementation also considers: (1) subdomain relationships, (2) HTTPS->HTTP downgrades should always strip headers even on same host, (3) port changes. The current OCaml implementation allows HTTP->HTTPS upgrades but doesn't handle the reverse. Should enhance to detect protocol downgrades and strip sensitive headers more aggressively for improved security." 92 + }, 93 + { 94 + "source_repo": "third_party/javascript/node-fetch", 95 + "source_language": "JavaScript", 96 + "criticality": "medium", 97 + "change_type": "enhancement", 98 + "title": "Add cookie stripping on cross-origin redirects", 99 + "description": "Node-fetch strips Cookie and Cookie2 headers on cross-domain redirects alongside Authorization headers. The OCaml library only strips Authorization headers.", 100 + "affected_files": [ 101 + "lib/one.ml" 102 + ], 103 + "rationale": "The strip_sensitive_headers function at one.ml:27-29 only removes Authorization but should also remove Cookie headers to prevent credential leakage across origins. While the library has automatic cookie management via Cookeio, when cookies are sent manually via headers or in one-shot requests, they should be stripped on cross-origin redirects. Node-fetch also strips WWW-Authenticate. Adding Cookie/Cookie2 to the strip list improves security posture." 104 + }, 105 + { 106 + "source_repo": "third_party/javascript/node-fetch", 107 + "source_language": "JavaScript", 108 + "criticality": "low", 109 + "change_type": "feature", 110 + "title": "Add response cloning capability", 111 + "description": "Node-fetch supports cloning Response objects to enable parallel consumption of the same response body through stream teeing. The OCaml library's response bodies can only be consumed once.", 112 + "affected_files": [ 113 + "lib/response.ml" 114 + ], 115 + "rationale": "Node-fetch allows response.clone() which creates an independent copy of the response with a teed body stream, enabling multiple consumers to read the same response. The OCaml response.ml marks bodies as closed after consumption and has a one-time read constraint. While this is memory-efficient, some use cases (logging + processing, retries with body inspection) benefit from cloning. Could implement using Eio stream teeing if needed, though the single-consumption model is reasonable for most use cases." 116 + }, 117 + { 118 + "source_repo": "third_party/javascript/node-fetch", 119 + "source_language": "JavaScript", 120 + "criticality": "medium", 121 + "change_type": "enhancement", 122 + "title": "Add redirect mode options (follow, error, manual)", 123 + "description": "Node-fetch supports three redirect modes: 'follow' (default, up to 20 redirects), 'error' (throw on any redirect), 'manual' (return 3xx response without following). The OCaml library has follow_redirects boolean and max_redirects but lacks 'error' and 'manual' modes.", 124 + "affected_files": [ 125 + "lib/one.ml", 126 + "lib/requests.ml" 127 + ], 128 + "rationale": "Different applications need different redirect handling strategies. Node-fetch's redirect modes provide: (1) 'error' mode for APIs that should never redirect, (2) 'manual' mode for applications that want to handle redirects themselves (useful for authentication flows, custom logic). The OCaml library's follow_redirects=false still follows redirects internally but returns final response. Adding an explicit redirect_mode type ('Follow | Error | Manual) would improve API clarity and enable strict no-redirect enforcement." 129 + }, 130 + { 131 + "source_repo": "third_party/javascript/node-fetch", 132 + "source_language": "JavaScript", 133 + "criticality": "low", 134 + "change_type": "enhancement", 135 + "title": "Add response.redirected boolean flag", 136 + "description": "Node-fetch provides a response.redirected boolean property that indicates whether the response is the result of following redirects. The OCaml library doesn't expose this information.", 137 + "affected_files": [ 138 + "lib/response.ml" 139 + ], 140 + "rationale": "The redirected flag helps applications understand if they received the originally requested resource or were redirected. Node-fetch sets this based on redirect counter > 0. The OCaml library tracks redirects internally in one.ml but doesn't expose this in the Response type. Adding a redirected field and redirect_count would improve transparency and help with debugging redirect chains." 141 + }, 142 + { 143 + "source_repo": "third_party/javascript/node-fetch", 144 + "source_language": "JavaScript", 145 + "criticality": "medium", 146 + "change_type": "enhancement", 147 + "title": "Improve chunked encoding termination detection", 148 + "description": "Node-fetch implements special detection for premature connection close vs proper chunked encoding termination (0\\r\\n\\r\\n), handling cases where the final chunk is split across packets. The OCaml library relies on standard HTTP parsing.", 149 + "affected_files": [ 150 + "lib/http_client.ml" 151 + ], 152 + "rationale": "Node-fetch has sophisticated logic to detect whether a chunked response ended properly or the connection was closed prematurely. This is important for distinguishing network errors from complete responses. The OCaml http_client.ml parses responses but may not have special handling for split final chunks. While Eio's HTTP parsing may handle this, explicit validation of chunked encoding termination would improve error detection and reporting." 153 + }, 154 + { 155 + "source_repo": "third_party/javascript/node-fetch", 156 + "source_language": "JavaScript", 157 + "criticality": "low", 158 + "change_type": "enhancement", 159 + "title": "Add support for Retry-After header in retry logic", 160 + "description": "Node-fetch documents that applications should respect Retry-After headers for 429/503 responses. The OCaml library has retry logic with respect_retry_after config option and parse_retry_after function but integration could be enhanced.", 161 + "affected_files": [ 162 + "lib/retry.ml", 163 + "lib/requests.ml" 164 + ], 165 + "rationale": "The retry.ml module has parse_retry_after that handles both integer seconds and HTTP dates (retry.ml:73-93) and respect_retry_after config option, which is excellent. However, the actual retry implementation in with_retry doesn't appear to use the Retry-After header from responses. Node-fetch applications manually check Retry-After and incorporate it into their retry timing. The OCaml library should enhance the retry mechanism to actually extract and use Retry-After from 429/503 responses when respect_retry_after=true." 166 + }, 167 + { 168 + "source_repo": "third_party/javascript/node-fetch", 169 + "source_language": "JavaScript", 170 + "criticality": "high", 171 + "change_type": "enhancement", 172 + "title": "Add configurable highWaterMark for stream buffer control", 173 + "description": "Node-fetch allows configuring stream buffer size via highWaterMark option (default 16KB). The OCaml library uses Eio's default flow settings without exposed buffer size configuration.", 174 + "affected_files": [ 175 + "lib/response.ml", 176 + "lib/body.ml" 177 + ], 178 + "rationale": "Node-fetch defaults to 16KB buffer (vs browser ~1MB) for server-side efficiency but allows customization. Buffer size affects memory usage vs throughput tradeoffs, especially for large responses or many concurrent requests. The OCaml library uses Eio flows which have internal buffering but doesn't expose this as a configuration option. Adding configurable buffer_size for response bodies would allow users to optimize for their use case (low memory vs high throughput)." 179 + }, 180 + { 181 + "source_repo": "third_party/javascript/node-fetch", 182 + "source_language": "JavaScript", 183 + "criticality": "medium", 184 + "change_type": "enhancement", 185 + "title": "Enhance decompression error handling with fallback to raw body", 186 + "description": "Node-fetch uses Z_SYNC_FLUSH for lenient decompression and properly handles empty bodies with compression headers (204, 304 responses). The OCaml library has decompression but could improve edge case handling.", 187 + "affected_files": [ 188 + "lib/http_client.ml" 189 + ], 190 + "rationale": "The http_client.ml decompress_body function (http_client.ml:96-116) correctly falls back to raw body on decompression errors, which matches node-fetch behavior. However, node-fetch also handles special cases: (1) empty responses with Content-Encoding shouldn't fail decompression, (2) deflate has ambiguity (raw vs zlib-wrapped) requiring dual attempts. The OCaml library already tries zlib then deflate (http_client.ml:107-112), which is good. Could add special handling for empty bodies with compression headers to avoid unnecessary decompression attempts." 191 + }, 192 + { 193 + "source_repo": "third_party/javascript/node-fetch", 194 + "source_language": "JavaScript", 195 + "criticality": "low", 196 + "change_type": "enhancement", 197 + "title": "Add brotli decompression support", 198 + "description": "Node-fetch supports gzip, deflate, and brotli decompression automatically. The OCaml library supports gzip and deflate but not brotli.", 199 + "affected_files": [ 200 + "lib/http_client.ml" 201 + ], 202 + "rationale": "Brotli (RFC 7932) offers better compression than gzip and is widely supported by modern servers. Node-fetch automatically decompresses br-encoded responses. The OCaml library's decompress_body function handles gzip/deflate/zlib but not brotli. While not critical, adding brotli support would improve compatibility with modern web servers and reduce bandwidth usage. Would require adding decompress-brotli library dependency." 203 + }, 204 + { 205 + "source_repo": "third_party/javascript/node-fetch", 206 + "source_language": "JavaScript", 207 + "criticality": "medium", 208 + "change_type": "enhancement", 209 + "title": "Add comprehensive testing for edge cases", 210 + "description": "Node-fetch has 2340 lines of tests covering compression errors, redirect chains, premature close detection, abort scenarios, empty responses with headers, and various body types. The OCaml library has basic tests but could expand coverage.", 211 + "affected_files": [ 212 + "test/test_simple.ml", 213 + "test/test_localhost.ml" 214 + ], 215 + "rationale": "Node-fetch's test suite covers critical edge cases: (1) premature stream close vs complete response, (2) invalid compression with graceful fallback, (3) redirect chains with header stripping, (4) abort during various operation phases, (5) slow redirects with timeout, (6) multiple concurrent aborts, (7) body consumption errors. The OCaml test files test_simple.ml and test_localhost.ml have basic connection pool and echo server tests. Expanding test coverage to include error conditions, edge cases, compression failures, redirect scenarios, and timeout handling would improve library robustness." 216 + }, 217 + { 218 + "source_repo": "third_party/javascript/node-fetch", 219 + "source_language": "JavaScript", 220 + "criticality": "low", 221 + "change_type": "enhancement", 222 + "title": "Add support for custom agents for advanced connection control", 223 + "description": "Node-fetch accepts an agent option (http.Agent/https.Agent or function) for custom connection handling, enabling keep-alive tuning, custom DNS, IPv4/IPv6 selection, and certificate control. The OCaml library has tls_config but lacks general agent pattern.", 224 + "affected_files": [ 225 + "lib/one.ml", 226 + "lib/requests.ml" 227 + ], 228 + "rationale": "Node-fetch's agent option enables: (1) custom keep-alive settings, (2) custom DNS resolution, (3) IPv4/IPv6 preference, (4) self-signed certificate handling, (5) proxy configuration. The OCaml library supports custom TLS config via tls_config parameter and has verify_tls flag. However, there's no general 'agent' or 'connector' abstraction for customizing connection establishment. The connection pool architecture provides some of this, but one-shot requests in one.ml don't have extension points beyond TLS. Adding a connection_options or agent-like parameter could enable advanced use cases." 229 + }, 230 + { 231 + "source_repo": "third_party/javascript/node-fetch", 232 + "source_language": "JavaScript", 233 + "criticality": "medium", 234 + "change_type": "feature", 235 + "title": "Add multipart/form-data boundary detection and parsing", 236 + "description": "Node-fetch implements a state machine-based parser for multipart/form-data responses, extracting individual parts with headers and data. The OCaml library can send multipart but doesn't parse multipart responses.", 237 + "affected_files": [ 238 + "lib/response.ml", 239 + "lib/body.ml" 240 + ], 241 + "rationale": "While the OCaml library excellently handles multipart request bodies via Body.multipart (body.ml:115-123 with boundary generation), it doesn't parse multipart responses. Node-fetch has a sophisticated multipart parser for handling FormData responses. This is less common for HTTP clients (multipart is typically for uploads), but some APIs return multipart responses. Adding multipart response parsing would improve spec compliance and enable consuming APIs that return multipart data." 242 + }, 243 + { 244 + "source_repo": "third_party/javascript/node-fetch", 245 + "source_language": "JavaScript", 246 + "criticality": "low", 247 + "change_type": "enhancement", 248 + "title": "Add Blob and File support for request bodies", 249 + "description": "Node-fetch supports Blob and File objects as request bodies with automatic MIME type detection. The OCaml library has file bodies but doesn't have a general Blob abstraction.", 250 + "affected_files": [ 251 + "lib/body.ml" 252 + ], 253 + "rationale": "Node-fetch treats Blob/File as first-class body types with automatic Content-Type inference from blob.type. The OCaml library has Body.File which loads files (body.ml:31-54) with MIME type guessing from extension. This is similar functionality but less general. The existing implementation is appropriate for OCaml's type system - a Blob-like abstraction would be redundant. The current approach with explicit file paths and MIME types is clearer than JS's Blob API." 254 + } 255 + ] 256 + }
+299
third_party/javascript/superagent.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/javascript/superagent", 5 + "source_language": "JavaScript", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add maxResponseSize protection against zip bombs", 9 + "description": "Superagent implements protection against zip bombs and large responses with maxResponseSize (default 200MB). The OCaml library currently has no such protection, making it vulnerable to memory exhaustion attacks from malicious servers sending extremely large or compressed payloads.", 10 + "affected_files": [ 11 + "lib/http_client.ml", 12 + "lib/http_client.mli", 13 + "lib/response.ml", 14 + "lib/response.mli", 15 + "lib/one.ml", 16 + "lib/one.mli" 17 + ], 18 + "rationale": "In superagent's request-base.js:550-557 and node/index.js:1143-1160, there's a maxResponseSize feature that tracks uncompressed response size and aborts if exceeded. This prevents DoS via zip bombs or excessively large responses. The OCaml library performs decompression (http_client.ml:14-94) but has no size limits, creating a security vulnerability." 19 + }, 20 + { 21 + "source_repo": "third_party/javascript/superagent", 22 + "source_language": "JavaScript", 23 + "criticality": "medium", 24 + "change_type": "enhancement", 25 + "title": "Add custom retry callback for user-defined retry logic", 26 + "description": "Superagent allows users to provide a custom retry callback function to override default retry logic. The OCaml library only supports predefined retry configurations without custom decision logic.", 27 + "affected_files": [ 28 + "lib/retry.ml", 29 + "lib/retry.mli" 30 + ], 31 + "rationale": "In superagent's request-base.js:142-150 and 189-223, the retry() method accepts an optional callback function that can return true/false to override default retry decisions. This provides flexibility for application-specific retry policies (e.g., retry based on response body content, custom headers, or business logic). The OCaml library (retry.ml:9-17) only supports static configuration." 32 + }, 33 + { 34 + "source_repo": "third_party/javascript/superagent", 35 + "source_language": "JavaScript", 36 + "criticality": "medium", 37 + "change_type": "feature", 38 + "title": "Add upload timeout in addition to response timeout", 39 + "description": "Superagent supports separate upload and response timeouts, while the OCaml library only has connect, read, and total timeouts. An upload timeout is useful for large file uploads over slow connections.", 40 + "affected_files": [ 41 + "lib/timeout.ml", 42 + "lib/timeout.mli", 43 + "lib/http_client.ml" 44 + ], 45 + "rationale": "In superagent's request-base.js:89-129, the timeout configuration supports three distinct types: deadline (total), response (time to first byte), and upload (time since last data sent/received). The OCaml library (timeout.mli:17-18) only supports connect, read, and total timeouts. Upload timeout is critical for tracking progress on large uploads and preventing indefinite hangs." 46 + }, 47 + { 48 + "source_repo": "third_party/javascript/superagent", 49 + "source_language": "JavaScript", 50 + "criticality": "medium", 51 + "change_type": "feature", 52 + "title": "Add progress event callbacks for uploads and downloads", 53 + "description": "Superagent emits 'progress' events during uploads and downloads with information about bytes transferred. The OCaml library has no mechanism for tracking transfer progress.", 54 + "affected_files": [ 55 + "lib/requests.ml", 56 + "lib/requests.mli", 57 + "lib/one.ml", 58 + "lib/one.mli", 59 + "lib/response.ml" 60 + ], 61 + "rationale": "In superagent's node/index.js:1222-1240, progress events are emitted with direction, lengthComputable, loaded, and total fields. This enables UI progress bars, bandwidth monitoring, and timeout adjustments. The OCaml library has no equivalent feature, limiting user experience for large transfers." 62 + }, 63 + { 64 + "source_repo": "third_party/javascript/superagent", 65 + "source_language": "JavaScript", 66 + "criticality": "low", 67 + "change_type": "enhancement", 68 + "title": "Add .ok() method for custom success validation", 69 + "description": "Superagent provides an .ok() method that accepts a callback to define custom success criteria beyond status codes. The OCaml library only checks status codes for determining success.", 70 + "affected_files": [ 71 + "lib/response.ml", 72 + "lib/response.mli", 73 + "lib/requests.ml" 74 + ], 75 + "rationale": "In superagent's request-base.js:306-322, the .ok() method allows users to define custom success validation (e.g., checking response body, specific headers, or business logic). This is more flexible than the OCaml library's Response.ok which only checks if status is 2xx (response.mli:58-60)." 76 + }, 77 + { 78 + "source_repo": "third_party/javascript/superagent", 79 + "source_language": "JavaScript", 80 + "criticality": "medium", 81 + "change_type": "feature", 82 + "title": "Add .unset() method to remove individual headers", 83 + "description": "Superagent provides a .unset() method to remove specific headers. The OCaml library can only remove headers from the Headers.t type, not from request configuration.", 84 + "affected_files": [ 85 + "lib/requests.ml", 86 + "lib/requests.mli" 87 + ], 88 + "rationale": "In superagent's request-base.js:398-402, the .unset() method removes headers by name. The OCaml library has Headers.remove (headers.mli:61-62) but no way to remove default headers from a requests instance after they've been set, limiting flexibility when reusing clients." 89 + }, 90 + { 91 + "source_repo": "third_party/javascript/superagent", 92 + "source_language": "JavaScript", 93 + "criticality": "low", 94 + "change_type": "enhancement", 95 + "title": "Add .sortQuery() for deterministic query string ordering", 96 + "description": "Superagent provides a .sortQuery() method to ensure deterministic query string ordering for caching and testing. The OCaml library doesn't provide query string sorting.", 97 + "affected_files": [ 98 + "lib/requests.ml", 99 + "lib/one.ml" 100 + ], 101 + "rationale": "In superagent's request-base.js:698-730, sortQuery() enables alphabetical or custom sorting of query parameters. This is useful for cache key consistency, API signature generation, and reproducible testing. The OCaml library handles query params (requests.mli:376) but doesn't offer sorting." 102 + }, 103 + { 104 + "source_repo": "third_party/javascript/superagent", 105 + "source_language": "JavaScript", 106 + "criticality": "medium", 107 + "change_type": "feature", 108 + "title": "Add .connect() method for DNS override and host IP mapping", 109 + "description": "Superagent provides a .connect() method to override DNS resolution and map hostnames to specific IP addresses. The OCaml library has no such feature for testing or working with hosts not in DNS.", 110 + "affected_files": [ 111 + "lib/http_client.ml", 112 + "lib/one.ml", 113 + "lib/requests.ml" 114 + ], 115 + "rationale": "In superagent's node/index.js:1314-1324 and 719-751, the .connect() method allows mapping hostnames to IPs (useful for testing, development, or bypassing DNS). This is implemented in the request() method. The OCaml library doesn't support this, making it harder to test against local servers with production hostnames." 116 + }, 117 + { 118 + "source_repo": "third_party/javascript/superagent", 119 + "source_language": "JavaScript", 120 + "criticality": "low", 121 + "change_type": "enhancement", 122 + "title": "Add .trustLocalhost() to disable TLS verification for localhost", 123 + "description": "Superagent provides a .trustLocalhost() method to automatically disable TLS verification for localhost and 127.0.0.1. The OCaml library requires explicit TLS configuration changes.", 124 + "affected_files": [ 125 + "lib/requests.ml", 126 + "lib/requests.mli", 127 + "lib/one.ml" 128 + ], 129 + "rationale": "In superagent's node/index.js:1326-1329 and 776-780, trustLocalhost() provides a convenient way to test local HTTPS servers without certificate errors. The OCaml library requires setting verify_tls:false globally (requests.mli:223), which is less secure for production code that also accesses external hosts." 130 + }, 131 + { 132 + "source_repo": "third_party/javascript/superagent", 133 + "source_language": "JavaScript", 134 + "criticality": "high", 135 + "change_type": "security", 136 + "title": "Add support for client certificates (cert, key, pfx) for mTLS", 137 + "description": "Superagent supports client certificate authentication (mTLS) via .cert(), .key(), .ca(), and .pfx() methods. The OCaml library only supports TLS server verification, not client certificates.", 138 + "affected_files": [ 139 + "lib/requests.ml", 140 + "lib/requests.mli", 141 + "lib/http_client.ml", 142 + "lib/one.ml" 143 + ], 144 + "rationale": "In superagent's node/index.js:607-655, methods exist for setting client certificates (.cert(), .key(), .ca(), .pfx() with passphrase). These are used in request():758-762 to configure TLS. The OCaml library only has tls_config:Tls.Config.client parameter but doesn't expose convenient methods for client cert authentication, limiting use in enterprise/mTLS environments." 145 + }, 146 + { 147 + "source_repo": "third_party/javascript/superagent", 148 + "source_language": "JavaScript", 149 + "criticality": "medium", 150 + "change_type": "enhancement", 151 + "title": "Add abort event and expose abort() method on requests", 152 + "description": "Superagent emits an 'abort' event when requests are cancelled and provides an abort() method. The OCaml library uses switch cancellation but doesn't provide explicit abort methods or events.", 153 + "affected_files": [ 154 + "lib/requests.ml", 155 + "lib/requests.mli", 156 + "lib/one.ml", 157 + "lib/response.ml" 158 + ], 159 + "rationale": "In superagent's request-base.js:474-488 and then():266-282, abort() cancels the request and emits an 'abort' event. This allows fine-grained control and cleanup. The OCaml library relies on Eio.Switch cancellation, which is less explicit and doesn't provide per-request abort callbacks." 160 + }, 161 + { 162 + "source_repo": "third_party/javascript/superagent", 163 + "source_language": "JavaScript", 164 + "criticality": "low", 165 + "change_type": "enhancement", 166 + "title": "Add serializer customization for request bodies", 167 + "description": "Superagent allows custom serializers via .serialize() method to control how request bodies are encoded. The OCaml library only supports predefined body types.", 168 + "affected_files": [ 169 + "lib/body.ml", 170 + "lib/body.mli", 171 + "lib/requests.ml" 172 + ], 173 + "rationale": "In superagent's request-base.js:80-86 and node/index.js:100-106, 996-1007, custom serializers can be set per-request or globally. This enables XML, MessagePack, Protobuf, or custom encodings. The OCaml library (body.mli) only supports string, json, form, file, and multipart without extensibility." 174 + }, 175 + { 176 + "source_repo": "third_party/javascript/superagent", 177 + "source_language": "JavaScript", 178 + "criticality": "low", 179 + "change_type": "enhancement", 180 + "title": "Add parser customization for response bodies", 181 + "description": "Superagent allows custom parsers via .parse() method to control how response bodies are decoded. The OCaml library only supports text and json parsing.", 182 + "affected_files": [ 183 + "lib/response.ml", 184 + "lib/response.mli" 185 + ], 186 + "rationale": "In superagent's request-base.js:46-49 and node/index.js:117, 1063-1134, custom parsers can be set per-request or per-MIME-type. This enables XML, YAML, MessagePack, or custom decodings. The OCaml library (response.mli:109-127) only has .text() and .json() methods without extensibility." 187 + }, 188 + { 189 + "source_repo": "third_party/javascript/superagent", 190 + "source_language": "JavaScript", 191 + "criticality": "medium", 192 + "change_type": "feature", 193 + "title": "Add redirect event emission for tracking redirect chains", 194 + "description": "Superagent emits a 'redirect' event for each redirect encountered, allowing tracking and custom redirect handling. The OCaml library silently follows redirects.", 195 + "affected_files": [ 196 + "lib/requests.ml", 197 + "lib/one.ml", 198 + "lib/http_client.ml" 199 + ], 200 + "rationale": "In superagent's node/index.js:958-962, a 'redirect' event is emitted before following each redirect, providing the intermediate response. This enables logging redirect chains, detecting redirect loops, and custom handling. The OCaml library follows redirects (requests.mli:221-222) but provides no visibility into the redirect process." 201 + }, 202 + { 203 + "source_repo": "third_party/javascript/superagent", 204 + "source_language": "JavaScript", 205 + "criticality": "medium", 206 + "change_type": "enhancement", 207 + "title": "Preserve redirect history in response object", 208 + "description": "Superagent stores the full redirect chain in response.redirects. The OCaml library doesn't track redirect history.", 209 + "affected_files": [ 210 + "lib/response.ml", 211 + "lib/response.mli" 212 + ], 213 + "rationale": "In superagent's node/index.js:166, 934, 960, the _redirectList array tracks all URLs in the redirect chain and is exposed in the response object. This is useful for security audits, debugging, and understanding the redirect path. The OCaml library only returns the final URL (response.mli:85-87)." 214 + }, 215 + { 216 + "source_repo": "third_party/javascript/superagent", 217 + "source_language": "JavaScript", 218 + "criticality": "high", 219 + "change_type": "security", 220 + "title": "Strip sensitive headers when redirecting across origins", 221 + "description": "Superagent strips Content-Type, Content-Length, and Authorization headers when redirecting to a different origin. The OCaml library may leak sensitive headers across origins.", 222 + "affected_files": [ 223 + "lib/http_client.ml", 224 + "lib/requests.ml", 225 + "lib/one.ml" 226 + ], 227 + "rationale": "In superagent's node/index.js:514-520, 533, utils.cleanHeader() removes sensitive headers during cross-origin redirects. This prevents authorization tokens from being sent to unintended hosts. The OCaml library needs to implement similar origin-aware header filtering to prevent security leaks." 228 + }, 229 + { 230 + "source_repo": "third_party/javascript/superagent", 231 + "source_language": "JavaScript", 232 + "criticality": "medium", 233 + "change_type": "feature", 234 + "title": "Add HTTP/2 support with opt-in configuration", 235 + "description": "Superagent supports HTTP/2 via .http2() method. The OCaml library only supports HTTP/1.1.", 236 + "affected_files": [ 237 + "lib/http_client.ml", 238 + "lib/http_client.mli", 239 + "lib/one.ml", 240 + "lib/requests.ml" 241 + ], 242 + "rationale": "In superagent's node/index.js:209-218, 783-785, HTTP/2 can be enabled per-request or globally. Modern servers prefer HTTP/2 for better performance (multiplexing, header compression). The OCaml library should add HTTP/2 support using h2 library." 243 + }, 244 + { 245 + "source_repo": "third_party/javascript/superagent", 246 + "source_language": "JavaScript", 247 + "criticality": "low", 248 + "change_type": "enhancement", 249 + "title": "Add .toJSON() method for request inspection and debugging", 250 + "description": "Superagent provides .toJSON() to serialize request details for debugging and logging. The OCaml library has no equivalent.", 251 + "affected_files": [ 252 + "lib/requests.ml", 253 + "lib/requests.mli" 254 + ], 255 + "rationale": "In superagent's request-base.js:568-575, toJSON() returns a plain object with method, url, data, and headers. This is useful for logging, debugging, and creating request snapshots. The OCaml library should provide a similar inspection capability." 256 + }, 257 + { 258 + "source_repo": "third_party/javascript/superagent", 259 + "source_language": "JavaScript", 260 + "criticality": "medium", 261 + "change_type": "enhancement", 262 + "title": "Add Agent pattern for sharing configuration across requests", 263 + "description": "Superagent's Agent class allows creating request factories with default settings applied to all requests. The OCaml library's Requests.t is similar but the Agent pattern is more explicit.", 264 + "affected_files": [ 265 + "lib/requests.ml", 266 + "lib/requests.mli" 267 + ], 268 + "rationale": "In superagent's agent-base.js:26-47, the Agent class stores default settings and applies them to each request. While OCaml's Requests.t serves a similar purpose (requests.mli:206-209), the explicit Agent pattern with _setDefaults makes the configuration inheritance clearer. Consider documenting this pattern more explicitly." 269 + }, 270 + { 271 + "source_repo": "third_party/javascript/superagent", 272 + "source_language": "JavaScript", 273 + "criticality": "low", 274 + "change_type": "enhancement", 275 + "title": "Add .buffer() method to control response buffering", 276 + "description": "Superagent allows disabling response buffering via .buffer(false) for streaming. The OCaml library streams by default but could benefit from explicit buffering control.", 277 + "affected_files": [ 278 + "lib/response.ml", 279 + "lib/response.mli", 280 + "lib/one.ml" 281 + ], 282 + "rationale": "In superagent's request-base.js and node/index.js:484-487, 1057-1068, .buffer() controls whether responses are buffered or streamed. The OCaml library uses Flow.source for streaming (response.mli:95-107) but lacks explicit buffering hints that could optimize memory usage." 283 + }, 284 + { 285 + "source_repo": "third_party/javascript/superagent", 286 + "source_language": "JavaScript", 287 + "criticality": "medium", 288 + "change_type": "bug", 289 + "title": "Add double-callback prevention for .end()", 290 + "description": "Superagent prevents double-callback bugs by checking if callback was already called. The OCaml library should ensure similar guarantees.", 291 + "affected_files": [ 292 + "lib/requests.ml", 293 + "lib/http_client.ml", 294 + "lib/one.ml" 295 + ], 296 + "rationale": "In superagent's node/index.js:869, there's a check for double callbacks with a warning. In OCaml's functional style with Eio, this is less likely but should still be verified, especially around retry and timeout logic to prevent duplicate responses or race conditions." 297 + } 298 + ] 299 + }
+266
third_party/php/buzz.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/php/buzz", 5 + "source_language": "PHP", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add auth-int support to Digest authentication", 9 + "description": "The Buzz library implements quality of protection (qop) with auth-int mode for digest authentication, which provides integrity protection by hashing the request body. The OCaml implementation currently only supports qop=auth. Extend the digest auth implementation to support qop=auth-int when the server requires it, computing HA2 as hash(method:uri:hash(entity-body)) instead of just hash(method:uri).", 10 + "affected_files": [ 11 + "lib/auth.ml", 12 + "lib/auth.mli" 13 + ], 14 + "rationale": "Auth-int provides stronger security guarantees by ensuring integrity of the request body. While not commonly used, supporting it ensures RFC 7616 compliance and prevents authentication failures with servers that require it. The Buzz library shows this can be implemented cleanly with conditional logic based on qop value." 15 + }, 16 + { 17 + "source_repo": "third_party/php/buzz", 18 + "source_language": "PHP", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Add MD5-sess algorithm support to Digest authentication", 22 + "description": "Buzz implements MD5-sess algorithm for digest authentication (lines 262-269 in DigestAuthMiddleware.php), which computes HA1 as hash(hash(username:realm:password):nonce:cnonce) instead of just hash(username:realm:password). The OCaml library currently only supports single-hash algorithms. Add MD5-sess and SHA-256-sess support.", 23 + "affected_files": [ 24 + "lib/auth.ml", 25 + "lib/auth.mli" 26 + ], 27 + "rationale": "MD5-sess provides session-specific hashing that changes with each nonce, offering better protection against replay attacks. While the base algorithms are considered sufficient for most use cases, supporting -sess variants ensures full RFC 7616 compliance and compatibility with servers that require it." 28 + }, 29 + { 30 + "source_repo": "third_party/php/buzz", 31 + "source_language": "PHP", 32 + "criticality": "low", 33 + "change_type": "enhancement", 34 + "title": "Implement nonce count tracking for Digest authentication", 35 + "description": "Buzz tracks nonce count (nc) across multiple requests with the same nonce (lines 207-217 in DigestAuthMiddleware.php), incrementing it for each use. The OCaml implementation hardcodes nc='00000001'. Implement proper nonce count tracking in the session state to support multiple requests with the same server nonce.", 36 + "affected_files": [ 37 + "lib/auth.ml", 38 + "lib/requests.ml" 39 + ], 40 + "rationale": "Proper nonce count tracking allows clients to reuse server nonces across multiple requests, reducing authentication overhead. While the current implementation works by treating each request independently, tracking nc is required by RFC 7616 for proper digest auth implementation and enables connection efficiency improvements." 41 + }, 42 + { 43 + "source_repo": "third_party/php/buzz", 44 + "source_language": "PHP", 45 + "criticality": "medium", 46 + "change_type": "security", 47 + "title": "Add option to prevent downgrade from Digest to Basic auth", 48 + "description": "Buzz provides OPTION_IGNORE_DOWNGRADE_REQUEST flag (line 54) to prevent servers from downgrading from Digest to Basic authentication. The OCaml library doesn't have explicit downgrade protection. Add a configuration option to reject Basic auth challenges when Digest auth is configured, preventing downgrade attacks where an attacker could force plaintext credential transmission.", 49 + "affected_files": [ 50 + "lib/auth.ml", 51 + "lib/requests.ml" 52 + ], 53 + "rationale": "Downgrade attacks can compromise security by forcing the use of weaker authentication schemes. While Basic over HTTPS is reasonably secure, preventing downgrades when Digest is expected provides defense-in-depth. This is particularly important for security-conscious applications that explicitly choose Digest auth for its cryptographic properties." 54 + }, 55 + { 56 + "source_repo": "third_party/php/buzz", 57 + "source_language": "PHP", 58 + "criticality": "low", 59 + "change_type": "feature", 60 + "title": "Add request/response history tracking", 61 + "description": "Buzz implements HistoryMiddleware (HistoryMiddleware.php) with Journal and Entry classes to record all requests, responses, and timing information. This is useful for debugging, testing, and monitoring. Implement a similar opt-in history tracking mechanism that records request/response pairs with timing data.", 62 + "affected_files": [ 63 + "lib/requests.ml", 64 + "lib/requests.mli" 65 + ], 66 + "rationale": "History tracking is invaluable for debugging HTTP interactions, writing tests that need to verify all requests made, and monitoring API usage patterns. The Buzz implementation shows this can be cleanly implemented as an optional feature without impacting performance when disabled. This complements the existing logging infrastructure." 67 + }, 68 + { 69 + "source_repo": "third_party/php/buzz", 70 + "source_language": "PHP", 71 + "criticality": "low", 72 + "change_type": "enhancement", 73 + "title": "Add automatic Content-Length header calculation", 74 + "description": "Buzz's ContentLengthMiddleware (lines 12-20) automatically adds Content-Length headers for request bodies when not already present. The OCaml library has a content_length function on Body.t but doesn't automatically apply it to requests. Add automatic Content-Length header setting for bodies with known sizes.", 75 + "affected_files": [ 76 + "lib/requests.ml", 77 + "lib/http_client.ml" 78 + ], 79 + "rationale": "Many servers require or strongly prefer Content-Length headers for request bodies. While the current implementation works, automatically adding this header when the size is known improves compatibility and can enable server-side optimizations. The body module already calculates lengths, so this is a simple enhancement." 80 + }, 81 + { 82 + "source_repo": "third_party/php/buzz", 83 + "source_language": "PHP", 84 + "criticality": "high", 85 + "change_type": "security", 86 + "title": "Add protocol restriction to prevent SSRF attacks", 87 + "description": "Buzz restricts allowed protocols to HTTP and HTTPS only (lines 86-88 in AbstractCurl.php) using CURLOPT_PROTOCOLS to prevent SSRF attacks via file://, ftp://, gopher://, etc. The OCaml library should validate URI schemes before making requests and reject non-HTTP(S) protocols.", 88 + "affected_files": [ 89 + "lib/requests.ml", 90 + "lib/one.ml", 91 + "lib/http_client.ml" 92 + ], 93 + "rationale": "SSRF (Server-Side Request Forgery) vulnerabilities can allow attackers to access internal resources by providing malicious URLs. Restricting protocols to http:// and https:// is a critical security control. This is especially important for applications that accept user-provided URLs, preventing access to local files, internal network services, or other protocol handlers." 94 + }, 95 + { 96 + "source_repo": "third_party/php/buzz", 97 + "source_language": "PHP", 98 + "criticality": "medium", 99 + "change_type": "enhancement", 100 + "title": "Implement granular error classification for network errors", 101 + "description": "Buzz's parseError method (lines 213-230 in AbstractCurl.php) distinguishes between different types of network failures: DNS resolution, connection failures, timeouts, and SSL errors. The OCaml library uses a generic ConnectionError. Implement more granular error types for different network failure modes to enable better error handling and retry logic.", 102 + "affected_files": [ 103 + "lib/error.ml", 104 + "lib/http_client.ml" 105 + ], 106 + "rationale": "Different network errors require different handling strategies. DNS failures might be transient and worth retrying, while SSL errors likely indicate misconfiguration and shouldn't be retried. Connection refused might indicate the service is down, while timeout could mean network congestion. Granular errors enable smarter retry policies and better diagnostics." 107 + }, 108 + { 109 + "source_repo": "third_party/php/buzz", 110 + "source_language": "PHP", 111 + "criticality": "low", 112 + "change_type": "enhancement", 113 + "title": "Add per-request timing measurements", 114 + "description": "Buzz's LoggerMiddleware and HistoryMiddleware (lines 20-42 in LoggerMiddleware.php) track request start time and calculate duration in milliseconds. The OCaml Response.t has elapsed time, but timing could be exposed more granularly. Add timing breakdowns for connection time, TLS handshake time, time to first byte, and total time.", 115 + "affected_files": [ 116 + "lib/response.ml", 117 + "lib/http_client.ml" 118 + ], 119 + "rationale": "Detailed timing metrics are essential for performance debugging and monitoring. Knowing whether slowness is due to connection establishment, TLS negotiation, server processing, or data transfer helps identify bottlenecks. The response already tracks total elapsed time, so adding these breakdowns provides valuable observability." 120 + }, 121 + { 122 + "source_repo": "third_party/php/buzz", 123 + "source_language": "PHP", 124 + "criticality": "medium", 125 + "change_type": "enhancement", 126 + "title": "Add immutable configuration pattern with validation", 127 + "description": "Buzz uses an immutable ParameterBag with OptionsResolver for type-safe configuration validation (ParameterBag.php and AbstractClient.php lines 26-34). The OCaml library uses record updates but doesn't validate configuration invariants. Implement configuration validation for timeout values, redirect limits, retry counts, etc., raising clear errors for invalid configurations.", 128 + "affected_files": [ 129 + "lib/timeout.ml", 130 + "lib/retry.ml", 131 + "lib/requests.ml" 132 + ], 133 + "rationale": "Configuration errors should be caught early with clear error messages rather than causing runtime failures or undefined behavior. Validating that timeouts are positive, max_redirects is reasonable, backoff_factor is non-negative, etc., prevents subtle bugs and provides better developer experience. The immutable pattern already exists; adding validation completes it." 134 + }, 135 + { 136 + "source_repo": "third_party/php/buzz", 137 + "source_language": "PHP", 138 + "criticality": "low", 139 + "change_type": "feature", 140 + "title": "Add WSSE authentication support", 141 + "description": "Buzz implements WSSE (Web Services Security) authentication (WsseAuthMiddleware.php) for SOAP and WS-Security APIs, adding X-WSSE headers with username token, nonce, and digest. Add WSSE authentication support to the Auth module for interoperability with SOAP services and older web services.", 142 + "affected_files": [ 143 + "lib/auth.ml", 144 + "lib/auth.mli" 145 + ], 146 + "rationale": "While WSSE is less common in modern REST APIs, it's still widely used in enterprise SOAP services and legacy systems. Supporting WSSE as an authentication option improves library completeness and enables interoperability with these systems. The implementation is straightforward: generate nonce, compute SHA-1 digest, format X-WSSE header." 147 + }, 148 + { 149 + "source_repo": "third_party/php/buzz", 150 + "source_language": "PHP", 151 + "criticality": "medium", 152 + "change_type": "enhancement", 153 + "title": "Add automatic Content-Type detection for request bodies", 154 + "description": "Buzz's ContentTypeMiddleware (lines 14-30) automatically detects JSON and XML content types by examining request bodies and sets appropriate Content-Type headers. The OCaml library requires explicit MIME type specification. Add optional auto-detection that inspects body content to infer Content-Type when not explicitly set.", 155 + "affected_files": [ 156 + "lib/body.ml", 157 + "lib/requests.ml" 158 + ], 159 + "rationale": "Automatic Content-Type detection improves ergonomics for common cases while still allowing explicit specification when needed. Detecting JSON by looking for {/[ at the start and XML by looking for < helps prevent common mistakes where developers forget to set Content-Type. The Buzz implementation limits detection to small bodies to avoid performance issues." 160 + }, 161 + { 162 + "source_repo": "third_party/php/buzz", 163 + "source_language": "PHP", 164 + "criticality": "high", 165 + "change_type": "bug", 166 + "title": "Handle large request bodies with streaming to avoid memory exhaustion", 167 + "description": "Buzz implements smart body handling (lines 168-180 in AbstractCurl.php): bodies larger than 1MB use streaming (CURLOPT_UPLOAD with READFUNCTION) to avoid loading the entire body into memory, while small bodies use POSTFIELDS for efficiency. The OCaml library's http_client.ml should verify it properly streams large bodies without buffering.", 168 + "affected_files": [ 169 + "lib/http_client.ml", 170 + "lib/body.ml" 171 + ], 172 + "rationale": "Loading large request bodies (file uploads, large JSON payloads) into memory can cause memory exhaustion and poor performance. The threshold-based approach (1MB in Buzz) provides good performance for small requests while protecting against memory issues for large ones. Verify the OCaml implementation properly uses the Stream and File body variants without buffering." 173 + }, 174 + { 175 + "source_repo": "third_party/php/buzz", 176 + "source_language": "PHP", 177 + "criticality": "low", 178 + "change_type": "enhancement", 179 + "title": "Add cURL handle pooling pattern", 180 + "description": "Buzz implements cURL handle pooling (lines 22-77 in AbstractCurl.php) with releaseHandle() and createHandle() to reuse handles and avoid recreation overhead. The OCaml library uses connection pooling at the TCP level. Consider adding similar pooling at the protocol client level to reuse parser state and buffers.", 181 + "affected_files": [ 182 + "lib/http_client.ml" 183 + ], 184 + "rationale": "While the OCaml library already has TCP connection pooling via conpool, reusing HTTP client state (buffers, parsers) can provide additional performance benefits. The Buzz implementation shows careful cleanup of callbacks and state reset between uses. This is a performance optimization rather than functional requirement, but could improve throughput for high-request-rate scenarios." 185 + }, 186 + { 187 + "source_repo": "third_party/php/buzz", 188 + "source_language": "PHP", 189 + "criticality": "medium", 190 + "change_type": "enhancement", 191 + "title": "Add proxy authentication support", 192 + "description": "Buzz supports proxy configuration via the 'proxy' option in ParameterBag (line 192 in AbstractCurl.php). The OCaml library doesn't appear to have proxy support. Add configuration options for HTTP/HTTPS proxies, including proxy authentication if needed.", 193 + "affected_files": [ 194 + "lib/requests.ml", 195 + "lib/one.ml", 196 + "lib/http_client.ml" 197 + ], 198 + "rationale": "Proxy support is essential for enterprise environments where direct internet access is restricted. Many corporate networks require HTTP proxies for outbound connections. Adding proxy configuration (host:port, optional authentication) enables the library to work in these environments. This is a common requirement for production deployments." 199 + }, 200 + { 201 + "source_repo": "third_party/php/buzz", 202 + "source_language": "PHP", 203 + "criticality": "low", 204 + "change_type": "enhancement", 205 + "title": "Add response body size limits to prevent DoS", 206 + "description": "Buzz uses max_size parameter in various contexts to limit response body sizes and prevent memory exhaustion. The OCaml library's Response.text uses max_int which could allow unbounded memory allocation. Add configurable response body size limits with clear errors when exceeded.", 207 + "affected_files": [ 208 + "lib/response.ml", 209 + "lib/requests.ml" 210 + ], 211 + "rationale": "Unbounded response body reading can lead to denial of service through memory exhaustion if a malicious or misconfigured server sends extremely large responses. Adding a configurable limit (e.g., 100MB default) with a clear error message protects applications from this attack vector while allowing opt-in for legitimate large downloads." 212 + }, 213 + { 214 + "source_repo": "third_party/php/buzz", 215 + "source_language": "PHP", 216 + "criticality": "low", 217 + "change_type": "refactor", 218 + "title": "Implement middleware/interceptor pattern for extensibility", 219 + "description": "Buzz's middleware system (MiddlewareInterface with handleRequest/handleResponse) provides clean extensibility for cross-cutting concerns like logging, authentication, metrics, and caching. Consider implementing a similar pattern in the OCaml library to allow users to inject custom logic at request/response boundaries.", 220 + "affected_files": [ 221 + "lib/requests.ml", 222 + "lib/requests.mli" 223 + ], 224 + "rationale": "The middleware pattern enables powerful extensibility without modifying library code. Users can implement custom authentication schemes, add metrics collection, implement caching strategies, or inject debugging logic. While the OCaml library uses a functional approach with Auth.custom, a more general middleware system would enable richer integrations. This is valuable for framework integration and enterprise use cases." 225 + }, 226 + { 227 + "source_repo": "third_party/php/buzz", 228 + "source_language": "PHP", 229 + "criticality": "medium", 230 + "change_type": "enhancement", 231 + "title": "Add HTTP/2 support detection and configuration", 232 + "description": "Buzz detects and uses HTTP/2 when available (lines 239-244 in AbstractCurl.php, checking for CURL_HTTP_VERSION_2_0 support) and implements HTTP/2 server push in MultiCurl. The OCaml library appears to be HTTP/1.1 only. Investigate adding HTTP/2 support using h2 library, with graceful fallback to HTTP/1.1.", 233 + "affected_files": [ 234 + "lib/http_client.ml", 235 + "lib/requests.ml" 236 + ], 237 + "rationale": "HTTP/2 provides significant performance improvements through multiplexing, header compression, and server push. Many modern servers support HTTP/2, and clients should take advantage of these features. While HTTP/1.1 is sufficient for compatibility, HTTP/2 support would improve performance for API-heavy applications. The h2 OCaml library provides HTTP/2 implementation." 238 + }, 239 + { 240 + "source_repo": "third_party/php/buzz", 241 + "source_language": "PHP", 242 + "criticality": "low", 243 + "change_type": "enhancement", 244 + "title": "Add batch request support for concurrent operations", 245 + "description": "Buzz implements BatchClientInterface with sendAsyncRequest() for concurrent request processing (MultiCurl.php). While the OCaml library uses Eio.Fiber for concurrency, adding a higher-level batch API that handles common patterns (execute multiple requests, wait for all, collect results) would improve ergonomics.", 246 + "affected_files": [ 247 + "lib/requests.ml", 248 + "lib/requests.mli" 249 + ], 250 + "rationale": "Batch operations are common in API clients (e.g., fetching multiple resources concurrently). While Eio.Fiber provides the concurrency primitives, a batch API would make this pattern more accessible and provide consistent error handling. Functions like batch_get, batch_post that return results or errors for each request would improve developer experience." 251 + }, 252 + { 253 + "source_repo": "third_party/php/buzz", 254 + "source_language": "PHP", 255 + "criticality": "low", 256 + "change_type": "enhancement", 257 + "title": "Add form submission helper with file upload support", 258 + "description": "Buzz provides submitForm() method (lines 86-95 in Browser.php) that simplifies form submission with automatic Content-Type handling. The OCaml library has Body.form and Body.multipart but no high-level form submission helper. Add convenience functions for common form submission patterns.", 259 + "affected_files": [ 260 + "lib/requests.ml", 261 + "lib/requests.mli" 262 + ], 263 + "rationale": "Form submission is a common operation, and providing helpers that automatically handle URL encoding, multipart encoding with file uploads, and Content-Type headers reduces boilerplate. While the building blocks exist, a submit_form function that takes fields and optional files would improve ergonomics for web scraping and form automation use cases." 264 + } 265 + ] 266 + }
+266
third_party/php/guzzle.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/php/guzzle", 5 + "source_language": "PHP", 6 + "criticality": "medium", 7 + "change_type": "feature", 8 + "title": "Add request/response lifecycle hooks (on_headers, on_redirect callbacks)", 9 + "description": "Guzzle provides lifecycle hooks like 'on_headers' (called when headers are received but before body download) and 'on_redirect' callbacks. These enable use cases like early header validation, conditional body downloads, progress tracking, and custom redirect handling. The OCaml library currently lacks this extensibility.", 10 + "affected_files": [ 11 + "lib/requests.mli", 12 + "lib/requests.ml", 13 + "lib/one.mli", 14 + "lib/one.ml", 15 + "lib/http_client.ml", 16 + "lib/response.mli" 17 + ], 18 + "rationale": "Guzzle's RequestOptions::ON_HEADERS callback allows users to inspect headers before downloading the body, enabling early termination for large files or conditional processing. The on_redirect callback (in RedirectMiddleware) provides control over redirect handling. In OCaml, this could be implemented via optional callback parameters: '~on_headers:(Headers.t -> unit)' and '~on_redirect:(Uri.t -> Uri.t -> int -> unit)'. This is particularly useful for large file downloads where the user wants to check content-type or content-length before proceeding, or for custom redirect logging/validation." 19 + }, 20 + { 21 + "source_repo": "third_party/php/guzzle", 22 + "source_language": "PHP", 23 + "criticality": "low", 24 + "change_type": "enhancement", 25 + "title": "Add configurable base_uri for relative URL resolution", 26 + "description": "Guzzle supports a 'base_uri' configuration option that automatically merges relative URIs with a base URL. This simplifies API client code by allowing requests like 'get(\"/users/123\")' instead of repeating the full URL. The OCaml library currently requires full URLs for all requests.", 27 + "affected_files": [ 28 + "lib/requests.mli", 29 + "lib/requests.ml" 30 + ], 31 + "rationale": "Guzzle's Client constructor accepts 'base_uri' which is automatically prepended to relative URIs via the buildUri() method (Client.php:161). This is especially useful for API clients where all requests target the same domain. In OCaml, this could be added to the Requests.t session state with a '~base_uri:Uri.t option' parameter in create(), and automatic URI merging in each request method. This reduces code duplication and makes API client code more maintainable." 32 + }, 33 + { 34 + "source_repo": "third_party/php/guzzle", 35 + "source_language": "PHP", 36 + "criticality": "medium", 37 + "change_type": "feature", 38 + "title": "Add middleware/interceptor system for request/response transformation", 39 + "description": "Guzzle provides a composable middleware system (HandlerStack) that allows users to inject custom logic at various points in the request/response lifecycle. This enables features like custom logging, request/response transformation, custom retry logic, metrics collection, and debugging without modifying core library code. The OCaml library currently has a fixed pipeline.", 40 + "affected_files": [ 41 + "lib/requests.mli", 42 + "lib/requests.ml", 43 + "lib/one.mli", 44 + "lib/one.ml" 45 + ], 46 + "rationale": "Guzzle's HandlerStack (HandlerStack.php) composes middlewares in an onion pattern, where each middleware wraps the next handler. Built-in middlewares include httpErrors, redirect, cookies, retry, log, history, and prepareBody. Users can add custom middlewares via push/unshift/before/after methods. In OCaml, this could be implemented as a list of functions with type '(Request.t -> Response.t) -> (Request.t -> Response.t)', allowing users to inject behavior like custom authentication schemes, request signing, response caching, or metrics. This pattern is well-established in web frameworks and provides excellent extensibility." 47 + }, 48 + { 49 + "source_repo": "third_party/php/guzzle", 50 + "source_language": "PHP", 51 + "criticality": "low", 52 + "change_type": "enhancement", 53 + "title": "Add response body summarization in error messages", 54 + "description": "Guzzle includes a BodySummarizer that truncates response bodies in error messages to prevent log pollution from large responses. Error messages show a snippet like 'resulted in a 404 Not Found response: <html>... (truncated)'. The OCaml library includes full body in HTTPError which could be very large.", 55 + "affected_files": [ 56 + "lib/error.mli", 57 + "lib/error.ml", 58 + "lib/response.ml" 59 + ], 60 + "rationale": "Guzzle's BodySummarizer (BodySummarizer.php) and RequestException::create (RequestException.php:105) automatically summarize response bodies to prevent massive error messages. The default truncation is configurable. In the OCaml library, Error.HTTPError includes 'body: string option' which could contain megabytes of HTML. Adding automatic truncation (e.g., first 500 bytes + '... (truncated N bytes)') would improve log readability and prevent performance issues when logging errors. This should be configurable via an optional parameter." 61 + }, 62 + { 63 + "source_repo": "third_party/php/guzzle", 64 + "source_language": "PHP", 65 + "criticality": "high", 66 + "change_type": "security", 67 + "title": "Add user info redaction in URIs for error messages and logs", 68 + "description": "Guzzle automatically redacts username:password from URIs when creating error messages using Utils::redactUserInfo(). This prevents credential leakage in logs. The OCaml library currently includes full URIs in error messages and logs, which could expose credentials if users include them in URLs.", 69 + "affected_files": [ 70 + "lib/error.ml", 71 + "lib/response.ml", 72 + "lib/http_client.ml" 73 + ], 74 + "rationale": "Guzzle's RequestException::create (RequestException.php:92) calls GuzzleHttp\\Psr7\\Utils::redactUserInfo() to remove 'user:pass@' from URIs before including them in exception messages. This prevents accidental credential exposure in logs, monitoring systems, or error reports. The OCaml library should implement similar redaction. For example, 'https://user:pass@api.example.com/data' should appear as 'https://***:***@api.example.com/data' in error messages. This is a security best practice to prevent credential leakage." 75 + }, 76 + { 77 + "source_repo": "third_party/php/guzzle", 78 + "source_language": "PHP", 79 + "criticality": "low", 80 + "change_type": "feature", 81 + "title": "Add request history tracking middleware for debugging", 82 + "description": "Guzzle provides a 'history' middleware that records all requests and responses (including errors) to an array for inspection and debugging. This is invaluable for testing, debugging, and understanding complex request flows. The OCaml library currently only tracks statistics.", 83 + "affected_files": [ 84 + "lib/requests.mli", 85 + "lib/requests.ml" 86 + ], 87 + "rationale": "Guzzle's Middleware::history (Middleware.php:88-120) pushes request/response/error tuples to a container for later inspection. This is extremely useful for debugging multi-request flows, understanding redirect chains, and writing tests. In OCaml, this could be implemented as an optional '~history:(Request.t * Response.t option * exn option) list ref' parameter that accumulates all requests. Combined with the existing statistics, this would provide comprehensive observability. The history should be opt-in to avoid memory issues with long-running sessions." 88 + }, 89 + { 90 + "source_repo": "third_party/php/guzzle", 91 + "source_language": "PHP", 92 + "criticality": "medium", 93 + "change_type": "enhancement", 94 + "title": "Add handler context information to exceptions for low-level debugging", 95 + "description": "Guzzle's RequestException includes a 'handlerContext' array with low-level transport details (SSL info, timing, connection data) via getHandlerContext(). This helps debug network-level issues. The OCaml library's errors don't include low-level connection metadata.", 96 + "affected_files": [ 97 + "lib/error.mli", 98 + "lib/error.ml", 99 + "lib/http_client.ml" 100 + ], 101 + "rationale": "Guzzle's RequestException constructor (RequestException.php:31-44) accepts a handlerContext parameter that stores low-level transport information accessible via getHandlerContext(). This includes SSL/TLS details, timing information, and handler-specific metadata useful for debugging connection issues. In OCaml, errors could include optional metadata like TLS version, cipher suite, connection reuse info, DNS resolution time, etc. This would be particularly valuable for debugging production issues where high-level logs are insufficient." 102 + }, 103 + { 104 + "source_repo": "third_party/php/guzzle", 105 + "source_language": "PHP", 106 + "criticality": "medium", 107 + "change_type": "enhancement", 108 + "title": "Add delay option to pause before sending requests", 109 + "description": "Guzzle supports a 'delay' option (RequestOptions::DELAY) that waits a specified number of milliseconds before sending a request. This is useful for rate limiting, coordinated testing, and respecting API throttling. The OCaml library doesn't provide built-in request delays.", 110 + "affected_files": [ 111 + "lib/requests.mli", 112 + "lib/requests.ml", 113 + "lib/one.mli", 114 + "lib/one.ml" 115 + ], 116 + "rationale": "Guzzle's RequestOptions::DELAY (RequestOptions.php:102-104) allows users to delay request sending by N milliseconds. This is implemented in the transport layer. In OCaml, this could be added as an optional '~delay:float' parameter that calls 'Eio.Time.sleep clock delay' before initiating the connection. This is particularly useful for implementing custom rate limiting, spreading load during bulk operations, or respecting API rate limits when retry logic isn't sufficient. While users can call sleep themselves, having it built-in ensures proper integration with timeouts." 117 + }, 118 + { 119 + "source_repo": "third_party/php/guzzle", 120 + "source_language": "PHP", 121 + "criticality": "low", 122 + "change_type": "enhancement", 123 + "title": "Add Expect: 100-Continue header support for large uploads", 124 + "description": "Guzzle's PrepareBodyMiddleware automatically adds 'Expect: 100-Continue' for large request bodies (>1MB by default), allowing servers to reject requests before the body is uploaded. This saves bandwidth and time for large uploads. The OCaml library doesn't support this optimization.", 125 + "affected_files": [ 126 + "lib/http_client.ml", 127 + "lib/body.ml" 128 + ], 129 + "rationale": "Guzzle's PrepareBodyMiddleware and RequestOptions::EXPECT (RequestOptions.php:107-122) implement RFC 7231 Expect/100-Continue for large payloads. When enabled, the client sends headers first, waits for '100 Continue' from the server, then sends the body. This prevents wasting bandwidth on rejected requests. The OCaml library could implement this in http_client.ml by: 1) detecting body size >1MB, 2) adding Expect header, 3) waiting for 100 Continue response, 4) then sending body. This is particularly valuable for multipart file uploads where the server might reject based on authentication or quotas before accepting the full upload." 130 + }, 131 + { 132 + "source_repo": "third_party/php/guzzle", 133 + "source_language": "PHP", 134 + "criticality": "low", 135 + "change_type": "enhancement", 136 + "title": "Add strict redirect mode to preserve HTTP method on redirects", 137 + "description": "Guzzle's redirect middleware supports a 'strict' mode that preserves the HTTP method on redirects (e.g., POST -> POST) instead of the browser behavior of changing POST to GET. The OCaml library always uses browser-style redirects.", 138 + "affected_files": [ 139 + "lib/http_client.ml" 140 + ], 141 + "rationale": "Guzzle's RedirectMiddleware supports RequestOptions::ALLOW_REDIRECTS with a 'strict' boolean (RequestOptions.php:18-32). When strict=true, POST requests remain POST on redirect; when false (default), they become GET (RFC 7231 behavior for 301/302). The OCaml library in http_client.ml likely implements only the non-strict behavior. Adding '~strict_redirects:bool' parameter would allow API clients to maintain the request method through redirects, which some APIs require. This should default to false for compatibility with standard browser behavior." 142 + }, 143 + { 144 + "source_repo": "third_party/php/guzzle", 145 + "source_language": "PHP", 146 + "criticality": "low", 147 + "change_type": "feature", 148 + "title": "Add referer header support for redirect tracking", 149 + "description": "Guzzle's redirect middleware can automatically set the Referer header when following redirects to track the redirect chain. This helps with debugging and some APIs use it for security. The OCaml library doesn't set Referer headers.", 150 + "affected_files": [ 151 + "lib/http_client.ml" 152 + ], 153 + "rationale": "Guzzle's RequestOptions::ALLOW_REDIRECTS supports a 'referer' boolean option (RequestOptions.php:24-25) that automatically adds a Referer header pointing to the previous URL when following redirects. This is useful for debugging redirect chains and some APIs require it. In the OCaml library, this could be implemented as an optional '~set_referer:bool' parameter (default false) in http_client.ml's redirect handling logic. When enabled, each redirected request would include 'Referer: <previous_url>' header." 154 + }, 155 + { 156 + "source_repo": "third_party/php/guzzle", 157 + "source_language": "PHP", 158 + "criticality": "medium", 159 + "change_type": "feature", 160 + "title": "Add pooled concurrent request execution (Pool/batch API)", 161 + "description": "Guzzle provides a Pool class for sending multiple requests concurrently with configurable concurrency limits, fulfilled/rejected callbacks, and memory-efficient streaming. The OCaml library requires users to manually manage concurrency with Fiber.all/both.", 162 + "affected_files": [ 163 + "lib/requests.mli", 164 + "lib/requests.ml" 165 + ], 166 + "rationale": "Guzzle's Pool class (Pool.php) enables efficient concurrent request execution with configurable max concurrency (default 25), per-request callbacks for fulfilled/rejected cases, and automatic batching. Pool.batch() collects all results while Pool() allows streaming results. In OCaml, this could be implemented as 'Requests.pool ~sw req ~max_concurrency:int ~requests:(unit -> Request.t) list ~on_response:(Response.t -> unit) -> unit' using Eio.Fiber with a semaphore to limit concurrency. This abstracts the common pattern of 'make N concurrent requests but limit parallelism to M'. Currently users must manually implement this with Fiber.all and chunking logic." 167 + }, 168 + { 169 + "source_repo": "third_party/php/guzzle", 170 + "source_language": "PHP", 171 + "criticality": "low", 172 + "change_type": "enhancement", 173 + "title": "Add transfer statistics callback (on_stats) for performance monitoring", 174 + "description": "Guzzle's 'on_stats' callback provides detailed transfer statistics including total time, DNS lookup time, connection time, TLS handshake time, and size metrics. This enables detailed performance monitoring and debugging. The OCaml library only tracks elapsed time.", 175 + "affected_files": [ 176 + "lib/requests.mli", 177 + "lib/requests.ml", 178 + "lib/response.mli", 179 + "lib/http_client.ml" 180 + ], 181 + "rationale": "Guzzle's RequestOptions::ON_STATS (RequestOptions.php:180-188) provides comprehensive transfer statistics via a callback. This includes timing breakdowns (DNS, connect, TLS, transfer), byte counts (sent/received), and connection reuse info. In OCaml, this could be implemented by: 1) creating a 'type transfer_stats' record with timing/size fields, 2) adding optional '~on_stats:(transfer_stats -> unit)' callback parameter, 3) tracking metrics in http_client.ml, 4) calling the callback after completion. This would enable APM integration, performance debugging, and identifying slow operations (DNS vs TLS vs transfer)." 182 + }, 183 + { 184 + "source_repo": "third_party/php/guzzle", 185 + "source_language": "PHP", 186 + "criticality": "low", 187 + "change_type": "feature", 188 + "title": "Add MockHandler for comprehensive testing support", 189 + "description": "Guzzle provides a MockHandler that allows tests to inject pre-defined responses or exceptions without making real network calls. This enables deterministic, fast testing of HTTP client code. The OCaml library lacks built-in mocking support.", 190 + "affected_files": [ 191 + "lib/requests.mli", 192 + "lib/requests.ml", 193 + "test/mock_handler.ml" 194 + ], 195 + "rationale": "Guzzle's Handler/MockHandler.php allows tests to queue responses/exceptions that are returned instead of making real HTTP calls. This is crucial for testing error handling, timeouts, and various response scenarios without external dependencies. In OCaml, this could be implemented as a module 'Requests.Mock' with functions like 'create_handler : Response.t list -> t' that returns a handler satisfying the same interface as the real client. Tests could use 'Requests.create ~handler:(Mock.create_handler [...])' to inject test responses. This would make the test suite faster, more reliable, and enable testing error conditions that are hard to reproduce." 196 + }, 197 + { 198 + "source_repo": "third_party/php/guzzle", 199 + "source_language": "PHP", 200 + "criticality": "medium", 201 + "change_type": "enhancement", 202 + "title": "Improve retry middleware to accept response for backoff calculation", 203 + "description": "Guzzle's RetryMiddleware passes the response to the delay function, allowing custom backoff strategies based on response headers (like Retry-After value). The OCaml library's retry module calculates backoff independently of the response.", 204 + "affected_files": [ 205 + "lib/retry.mli", 206 + "lib/retry.ml" 207 + ], 208 + "rationale": "Guzzle's RetryMiddleware.php:115 calls 'delay(retries, response, request)' with the response available for custom backoff calculation. This allows delay functions to inspect Retry-After headers or other response data. The OCaml library's retry.ml has 'calculate_backoff' and 'parse_retry_after' as separate functions. Refactoring to pass the optional Response.t to a custom backoff function would allow more sophisticated retry strategies, like backing off longer for 503 vs 500, or respecting server-specific rate limit headers beyond just Retry-After. This could be an optional '~backoff_fn:(attempt:int -> response:Response.t option -> float)' parameter." 209 + }, 210 + { 211 + "source_repo": "third_party/php/guzzle", 212 + "source_language": "PHP", 213 + "criticality": "low", 214 + "change_type": "enhancement", 215 + "title": "Add protocol restriction for redirects (allowed redirect protocols)", 216 + "description": "Guzzle allows configuring which protocols are allowed for redirects (default: http, https only) to prevent redirects to file://, ftp://, or other protocols. The OCaml library doesn't validate redirect target protocols.", 217 + "affected_files": [ 218 + "lib/http_client.ml" 219 + ], 220 + "rationale": "Guzzle's RequestOptions::ALLOW_REDIRECTS includes a 'protocols' array (RequestOptions.php:26-27) that whitelists allowed redirect schemes (default ['http', 'https']). This prevents SSRF attacks where a malicious server redirects to file:///, ftp://, or internal resources. The OCaml library should validate redirect URIs in http_client.ml to ensure the scheme is in an allowed list. Add '~allowed_redirect_protocols:string list' parameter (default ['http'; 'https']) and check 'Uri.scheme redirect_uri' before following. This is a defense-in-depth security measure." 221 + }, 222 + { 223 + "source_repo": "third_party/php/guzzle", 224 + "source_language": "PHP", 225 + "criticality": "medium", 226 + "change_type": "enhancement", 227 + "title": "Add IDN (Internationalized Domain Names) support for Unicode domains", 228 + "description": "Guzzle automatically converts Unicode/IDN domain names to ASCII punycode for DNS resolution using idn_to_ascii(). The OCaml library may not handle Unicode domains correctly.", 229 + "affected_files": [ 230 + "lib/http_client.ml" 231 + ], 232 + "rationale": "Guzzle's RequestOptions::IDN_CONVERSION (RequestOptions.php:147-152) and related logic converts internationalized domain names (like münchen.de) to punycode (xn--mnchen-3ya.de) for DNS compatibility. The OCaml library should ensure proper IDN handling, likely through the 'domain-name' library (already a dependency for SNI support). If not already implemented, add IDN normalization in http_client.ml before DNS resolution. This ensures the library works correctly with Unicode domain names common in non-English regions." 233 + }, 234 + { 235 + "source_repo": "third_party/php/guzzle", 236 + "source_language": "PHP", 237 + "criticality": "low", 238 + "change_type": "enhancement", 239 + "title": "Add sink option for direct-to-file/stream response writing", 240 + "description": "Guzzle's 'sink' option allows writing response bodies directly to a file path or stream without buffering in memory. This is useful for large downloads. The OCaml library supports streaming but could be more ergonomic with a sink parameter.", 241 + "affected_files": [ 242 + "lib/requests.mli", 243 + "lib/requests.ml", 244 + "lib/one.mli", 245 + "lib/one.ml" 246 + ], 247 + "rationale": "Guzzle's RequestOptions::SINK (RequestOptions.php:215-219) accepts a file path or stream resource to write the response body directly, avoiding memory buffering. The OCaml library has 'One.download ~sink' but the main API doesn't have a similar ergonomic option. Adding optional '~sink:Eio.Flow.sink_ty Eio.Resource.t' parameter to get/post/etc methods would automatically stream response to the sink without users manually reading Response.body. This makes large file downloads more ergonomic: 'Requests.get req url ~sink:(Eio.Path.(fs / \"file.zip\" |> sink))' instead of manual streaming." 248 + }, 249 + { 250 + "source_repo": "third_party/php/guzzle", 251 + "source_language": "PHP", 252 + "criticality": "low", 253 + "change_type": "enhancement", 254 + "title": "Add force_ip_resolve option to control IPv4/IPv6 preference", 255 + "description": "Guzzle supports force_ip_resolve option to force IPv4 or IPv6 resolution, useful for testing and working around network issues. The OCaml library doesn't provide IP version control.", 256 + "affected_files": [ 257 + "lib/requests.mli", 258 + "lib/requests.ml", 259 + "lib/one.mli", 260 + "lib/one.ml", 261 + "lib/http_client.ml" 262 + ], 263 + "rationale": "Guzzle's RequestOptions::FORCE_IP_RESOLVE (RequestOptions.php:271-273) allows forcing IPv4-only or IPv6-only resolution. This is useful for debugging dual-stack issues, working around broken IPv6 connectivity, or testing IPv6 specifically. In OCaml, this would require Eio.Net API support for address family filtering. If Eio supports this, add optional '~ip_version:[`V4 | `V6 | `Any]' parameter that configures DNS resolution. This is a nice-to-have feature for advanced users dealing with dual-stack networking issues." 264 + } 265 + ] 266 + }
+206
third_party/php/http-client.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/php/http-client", 5 + "source_language": "PHP", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add URI userInfo Security Check", 9 + "description": "Implement security check to prevent username:password in URIs (RFC 7230 section 2.7.1). The PHP library has ForbidUriUserInfo interceptor enabled by default that throws InvalidRequestException when URI contains user info. This prevents password leakage in logs, headers, and during redirects. OCaml library currently accepts URIs with userInfo without warnings.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/one.ml", 13 + "lib/error.ml" 14 + ], 15 + "rationale": "URIs with embedded credentials (http://user:pass@example.com) are deprecated by RFC 7230 and pose security risks. When URIs are logged or converted to strings (e.g., in Referer headers), passwords can leak. The PHP library blocks this by default with an opt-out via allowDeprecatedUriUserInfo(). OCaml library should add similar validation, logging a warning or raising an error when Uri.userinfo returns Some value, recommending Authorization header instead." 16 + }, 17 + { 18 + "source_repo": "third_party/php/http-client", 19 + "source_language": "PHP", 20 + "criticality": "high", 21 + "change_type": "feature", 22 + "title": "Add Multiple Granular Timeout Types", 23 + "description": "Implement separate timeouts for TCP connect, TLS handshake, transfer, and inactivity phases. PHP library has 4 distinct timeout types (getTcpConnectTimeout, getTlsHandshakeTimeout, getTransferTimeout, getInactivityTimeout), all defaulting to 10s. OCaml library only has connect, read, and total timeouts without TLS-specific or inactivity timeouts.", 24 + "affected_files": [ 25 + "lib/timeout.ml", 26 + "lib/http_client.ml", 27 + "lib/requests.ml" 28 + ], 29 + "rationale": "Different phases of HTTP requests have different timeout characteristics. TLS handshake can be slow on first connection, while subsequent reads should be faster. Inactivity timeout (time since last data received) is different from total transfer timeout (entire request duration). Currently, OCaml library uses 'read' timeout which doesn't distinguish between TLS handshake delays and inactivity. Adding granular timeouts provides better control and more accurate timeout diagnostics." 30 + }, 31 + { 32 + "source_repo": "third_party/php/http-client", 33 + "source_language": "PHP", 34 + "criticality": "medium", 35 + "change_type": "security", 36 + "title": "Add Response Body Size Limit", 37 + "description": "Implement configurable response body size limit to prevent memory exhaustion attacks. PHP library has setBodySizeLimit (default 10 MiB) and setHeaderSizeLimit (default 16 KiB for HTTP/1.x) that enforce limits during streaming. OCaml library has no built-in protection against unbounded response bodies.", 38 + "affected_files": [ 39 + "lib/response.ml", 40 + "lib/http_client.ml", 41 + "lib/requests.ml", 42 + "lib/one.ml" 43 + ], 44 + "rationale": "Malicious or misconfigured servers can send arbitrarily large responses, causing memory exhaustion. PHP library enforces body_size_limit during streaming and throws exception when exceeded. OCaml library should add similar protection: add body_size_limit field to request config (default 10 MiB), wrap response body with size-limiting reader in http_client.ml, raise EncodingError when limit exceeded. This prevents DoS via large responses." 45 + }, 46 + { 47 + "source_repo": "third_party/php/http-client", 48 + "source_language": "PHP", 49 + "criticality": "medium", 50 + "change_type": "feature", 51 + "title": "Add Redirect Chain Access", 52 + "description": "Provide access to complete redirect chain via getPreviousResponse() on Response objects. PHP library stores previous responses when following redirects, allowing inspection of the full redirect path (response->getPreviousResponse()->getPreviousResponse()...). OCaml library discards intermediate redirect responses.", 53 + "affected_files": [ 54 + "lib/response.ml", 55 + "lib/requests.ml", 56 + "lib/one.ml" 57 + ], 58 + "rationale": "Applications often need to inspect the redirect chain for debugging, security analysis, or tracking redirect patterns. PHP's FollowRedirects interceptor calls setPreviousResponse on each redirect response, creating a linked list. OCaml library should add optional 'previous_response: t option' field to Response.t and populate it during redirect following in requests.ml:422. This enables debugging redirect loops, analyzing redirect patterns, and security auditing." 59 + }, 60 + { 61 + "source_repo": "third_party/php/http-client", 62 + "source_language": "PHP", 63 + "criticality": "medium", 64 + "change_type": "feature", 65 + "title": "Add Event Listener Infrastructure", 66 + "description": "Implement event listener system for fine-grained observability of request lifecycle. PHP library has EventListener interface with 17+ hooks (requestStart, requestEnd, requestFailed, connectionAcquired, requestHeaderStart/End, requestBodyProgress, responseHeaderStart/End, responseBodyProgress, etc.) allowing HAR logging, metrics collection, and debugging without modifying interceptors.", 67 + "affected_files": [ 68 + "lib/requests.ml", 69 + "lib/one.ml", 70 + "lib/response.ml" 71 + ], 72 + "rationale": "Production applications need detailed observability without invasive code changes. PHP's EventListener system enables HAR (HTTP Archive) logging, performance monitoring, progress tracking, and debugging. OCaml library currently only has basic Logs statements. Adding callback-based listeners would enable: progress bars for large uploads/downloads, connection pool statistics, retry metrics, TLS handshake timing, request/response tracing. Implement as optional callbacks in request config: on_request_start, on_headers_received, on_body_chunk, on_request_end, on_error." 73 + }, 74 + { 75 + "source_repo": "third_party/php/http-client", 76 + "source_language": "PHP", 77 + "criticality": "medium", 78 + "change_type": "enhancement", 79 + "title": "Add Request Attributes System", 80 + "description": "Implement request-local attribute storage for passing data between interceptors/middleware. PHP library has getAttribute/setAttribute/hasAttribute allowing namespaced key-value storage on Request objects. This enables loose coupling between interceptors without global state.", 81 + "affected_files": [ 82 + "lib/requests.ml", 83 + "lib/one.ml" 84 + ], 85 + "rationale": "As the library evolves and users add custom middleware/interceptors, they need to pass context without tight coupling. PHP's attribute system uses namespaced keys (e.g., 'MyCompany.MyPackage.Timing' -> stopwatch object) to avoid collisions. OCaml library could add 'attributes: (string * Obj.t) list' to request context, with get_attribute/set_attribute functions. This enables extensibility patterns like: timing interceptors storing timestamps, caching interceptors marking requests, custom auth storing tokens, testing interceptors injecting mocks." 86 + }, 87 + { 88 + "source_repo": "third_party/php/http-client", 89 + "source_language": "PHP", 90 + "criticality": "medium", 91 + "change_type": "feature", 92 + "title": "Add 1xx Informational Response Handlers", 93 + "description": "Implement callback support for 1xx informational responses (100 Continue, 103 Early Hints). PHP library has setInformationalResponseHandler for non-101 1xx responses and setUpgradeHandler for 101 Switching Protocols. OCaml library doesn't expose 1xx responses to users.", 94 + "affected_files": [ 95 + "lib/http_client.ml", 96 + "lib/response.ml", 97 + "lib/requests.ml" 98 + ], 99 + "rationale": "HTTP/1.1 informational responses (1xx) provide important intermediate feedback. 100 Continue indicates server is ready for request body, 103 Early Hints provides resource hints before main response. 101 Switching Protocols enables WebSocket upgrades. PHP library allows callbacks to handle these without blocking main request flow. OCaml library should add optional callbacks: on_informational_response: (int -> Headers.t -> unit) option for general 1xx responses, on_upgrade: (Eio.Flow.two_way -> unit) option for 101 upgrades. Currently http_client.ml likely discards 1xx responses." 100 + }, 101 + { 102 + "source_repo": "third_party/php/http-client", 103 + "source_language": "PHP", 104 + "criticality": "medium", 105 + "change_type": "enhancement", 106 + "title": "Improve Retry Logic with Unprocessed Request Detection", 107 + "description": "Enhance retry logic to check if request was unprocessed by server (like PHP's isUnprocessed()). PHP's RetryRequests interceptor retries if request.isUnprocessed() OR request.isIdempotent() on HttpException. This catches connection failures before server processing. OCaml library only checks method and status code.", 108 + "affected_files": [ 109 + "lib/retry.ml", 110 + "lib/requests.ml", 111 + "lib/error.ml" 112 + ], 113 + "rationale": "Connection can fail before server processes request (connection dropped during send, TLS handshake failure, etc.). These failures are safe to retry even for non-idempotent methods since server never saw the request. PHP tracks request phase (Unprocessed, Connected, HeadersReceived, etc.) and allows retry if unprocessed. OCaml library should track whether request headers/body were fully sent. Add 'sent_to_server: bool' tracking in http_client.ml, set to false on connection errors before writing headers. In retry.ml, allow retry if not sent_to_server regardless of HTTP method. This safely retries POST on connection failures before transmission." 114 + }, 115 + { 116 + "source_repo": "third_party/php/http-client", 117 + "source_language": "PHP", 118 + "criticality": "low", 119 + "change_type": "enhancement", 120 + "title": "Add Header Validation for Pseudo-headers", 121 + "description": "Validate that user-provided headers don't start with ':' (HTTP/2 pseudo-headers). PHP library's setHeader/addHeader throw Error if header name starts with ':' or is empty. This prevents HTTP/2 protocol violations.", 122 + "affected_files": [ 123 + "lib/headers.ml" 124 + ], 125 + "rationale": "HTTP/2 uses pseudo-headers (:method, :path, :authority, :scheme) that must not be set by users. PHP library validates header names in Request.setHeader/addHeader (line 159-162, 174-176). While OCaml library only supports HTTP/1.1 currently, adding validation now prevents future issues when HTTP/2 support is added. Add validation in Headers.set/Headers.add: if String.length name > 0 && name.[0] = ':' then invalid_arg. This provides better error messages and prevents protocol violations." 126 + }, 127 + { 128 + "source_repo": "third_party/php/http-client", 129 + "source_language": "PHP", 130 + "criticality": "low", 131 + "change_type": "feature", 132 + "title": "Add HTTP/2 Server Push Handler Callbacks", 133 + "description": "Add infrastructure for HTTP/2 server push even though HTTP/2 isn't implemented yet. PHP library has setPushHandler and interceptPush for handling pushed resources. This allows accepting or rejecting pushes with callbacks.", 134 + "affected_files": [ 135 + "lib/requests.ml", 136 + "lib/response.ml" 137 + ], 138 + "rationale": "While OCaml library currently only supports HTTP/1.1, planning for HTTP/2 server push in the API design prevents breaking changes later. PHP library allows push handlers at request level: setPushHandler receives (Request, Future<Response>) for each push. Applications can accept/reject or cache pushed resources. OCaml library should reserve space in API (even if unimplemented): add ~on_push:(Request.t -> Response.t Eio.Promise.t -> unit) option parameter. Document as 'reserved for future HTTP/2 support'. This ensures API compatibility when HTTP/2 is added." 139 + }, 140 + { 141 + "source_repo": "third_party/php/http-client", 142 + "source_language": "PHP", 143 + "criticality": "low", 144 + "change_type": "enhancement", 145 + "title": "Add Configurable Default Headers (Accept)", 146 + "description": "Make default Accept header configurable and optional. PHP library sets 'Accept: */*' by default via SetRequestHeaderIfUnset interceptor, with skipDefaultAcceptHeader() to disable. OCaml library doesn't set default Accept header.", 147 + "affected_files": [ 148 + "lib/requests.ml", 149 + "lib/one.ml" 150 + ], 151 + "rationale": "Many servers behave differently without an Accept header. HTTP/1.1 spec says absence of Accept implies 'Accept: */*' but some servers don't follow spec. PHP library adds this by default for compatibility while allowing opt-out. OCaml library should add ~default_accept:(string option) to session creation (default: Some \"*/*\"), allowing None to disable. Apply in requests.ml if not already set in user headers. This improves server compatibility while maintaining control for applications that want specific behavior." 152 + }, 153 + { 154 + "source_repo": "third_party/php/http-client", 155 + "source_language": "PHP", 156 + "criticality": "low", 157 + "change_type": "refactor", 158 + "title": "Add Redirect Path Resolution Algorithm", 159 + "description": "Implement RFC 3986 compliant path resolution for redirects with removeDotSegments and mergePaths. PHP's FollowRedirects has detailed implementation handling '..' and '.' in redirect paths. OCaml library uses Uri.resolve which may not handle all edge cases.", 160 + "affected_files": [ 161 + "lib/requests.ml", 162 + "lib/one.ml" 163 + ], 164 + "rationale": "RFC 3986 section 5.2 specifies how to resolve relative URIs including handling '..' and '.' segments. PHP library implements removeDotSegments (lines 58-86) and mergePaths (91-106) following RFC exactly. OCaml's Uri.resolve should handle this, but PHP's explicit implementation suggests edge cases exist. Review Uri.resolve behavior for redirects like 'Location: ../../../path' or 'Location: ./././path'. If Uri.resolve doesn't match RFC 3986, add custom resolution using similar algorithm. This ensures redirect behavior matches browser/spec for complex relative paths." 165 + }, 166 + { 167 + "source_repo": "third_party/php/http-client", 168 + "source_language": "PHP", 169 + "criticality": "medium", 170 + "change_type": "enhancement", 171 + "title": "Add Automatic Referer Header Management", 172 + "description": "Automatically set Referer header on redirects following RFC-compliant privacy rules. PHP's FollowRedirects sets Referer to previous URL on redirects unless going from HTTPS to HTTP (security rule from RFC 2616 sec 15.1.3). OCaml library doesn't automatically set Referer on redirects.", 173 + "affected_files": [ 174 + "lib/requests.ml", 175 + "lib/one.ml" 176 + ], 177 + "rationale": "Referer header helps servers understand redirect chains and is expected by many web applications. However, sending HTTPS URLs in Referer when redirecting to HTTP leaks secure URLs. PHP library implements this correctly: assignRedirectRefererHeader (lines 210-223) sets Referer unless referrer is HTTPS and destination is HTTP. OCaml library should add similar logic in redirect handling (around requests.ml:411): if redirect_is_https or not original_was_https, set Referer to original URL with userinfo and fragment removed (Uri.with_userinfo None). This balances functionality with security." 178 + }, 179 + { 180 + "source_repo": "third_party/php/http-client", 181 + "source_language": "PHP", 182 + "criticality": "low", 183 + "change_type": "enhancement", 184 + "title": "Preserve Request Method on 307/308 Redirects", 185 + "description": "Distinguish between 301/302 (change to GET) and 307/308 (preserve method) redirects. PHP's FollowRedirects only follows 307/308 for GET requests (line 235), preserving POST/PUT/DELETE semantics. OCaml library changes all redirects to GET.", 186 + "affected_files": [ 187 + "lib/requests.ml", 188 + "lib/one.ml" 189 + ], 190 + "rationale": "HTTP status codes 307 (Temporary Redirect) and 308 (Permanent Redirect) specifically require preserving the HTTP method, unlike 301/302 which allow changing POST to GET. PHP library implements this distinction: for 307/308, only follows if method is GET, otherwise returns the redirect response (lines 234-237). OCaml library currently has 'cloneRequest' equivalent that always sets method to GET (not visible in excerpt but implied). Should check redirect status: if status in [307; 308] and method not in [GET; HEAD], don't auto-follow or preserve original method. This matches browser behavior and RFC 7231." 191 + }, 192 + { 193 + "source_repo": "third_party/php/http-client", 194 + "source_language": "PHP", 195 + "criticality": "medium", 196 + "change_type": "enhancement", 197 + "title": "Add Retry-After Header Respect in Retry Logic", 198 + "description": "Enhance retry backoff to respect Retry-After header from server (429/503 responses). PHP library has respect_retry_after configuration. OCaml library parses Retry-After but doesn't appear to use it in actual retry implementation with_retry function.", 199 + "affected_files": [ 200 + "lib/retry.ml", 201 + "lib/requests.ml" 202 + ], 203 + "rationale": "Servers send Retry-After header (RFC 7231) to indicate when to retry, especially for 429 Too Many Requests and 503 Service Unavailable. Respecting this prevents thundering herd and follows server's guidance. OCaml library has parse_retry_after in retry.ml (lines 73-93) supporting both delay-seconds and HTTP-date formats, and config has respect_retry_after flag, but with_retry function (lines 95-123) doesn't use it. Should modify with_retry to: if config.respect_retry_after and response has Retry-After header, use max(parsed_delay, calculated_backoff) as delay. This requires passing response/headers to retry logic or extracting Retry-After before retry." 204 + } 205 + ] 206 + }
+200
third_party/php/httplug.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "php/httplug", 5 + "source_language": "PHP", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add factory method for HTTPError exception with normalized error messages", 9 + "description": "HTTPlug's HttpException provides a static factory method `create()` that generates normalized error messages in the format '[url] %s [http method] %s [status code] %s [reason phrase] %s'. This makes error messages consistent across the codebase and easier to parse/log. The OCaml library's HTTPError exception currently requires manual message construction.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/response.ml" 13 + ], 14 + "rationale": "HTTPlug's factory method ensures consistent error message formatting across all HTTP errors, making debugging and log parsing easier. Currently in response.ml:82-89, raise_for_status creates HTTPError with minimal context. Adding a similar factory function would provide better error messages with full context (URL, method, status, reason phrase) in a standardized format. This is especially valuable for logging and error tracking systems." 15 + }, 16 + { 17 + "source_repo": "php/httplug", 18 + "source_language": "PHP", 19 + "criticality": "high", 20 + "change_type": "enhancement", 21 + "title": "Separate NetworkException from RequestException in exception hierarchy", 22 + "description": "HTTPlug follows PSR-18 specification by ensuring NetworkException (network-level failures with no response) does NOT extend RequestException (request failed but response was received). This is a critical semantic distinction: NetworkException means no response was ever received (DNS failure, connection timeout, network error), while RequestException/HTTPError means a response was received but indicates an error. The OCaml library's ConnectionError exception is properly separate, but this distinction should be clearly documented and consistently enforced.", 23 + "affected_files": [ 24 + "lib/error.ml", 25 + "lib/error.mli" 26 + ], 27 + "rationale": "The PSR-18 specification explicitly requires that network exceptions (no response) be distinct from request exceptions (response received). This semantic distinction is crucial for error handling: network errors might be retryable with the same request, while HTTP errors (4xx/5xx) often require different handling. HTTPlug changed this in v2.1.0 to comply with PSR-18. The OCaml library already has this separation (ConnectionError vs HTTPError), but it should be clearly documented that ConnectionError represents network-level failures where no response was received, while HTTPError represents received HTTP error responses." 28 + }, 29 + { 30 + "source_repo": "php/httplug", 31 + "source_language": "PHP", 32 + "criticality": "medium", 33 + "change_type": "feature", 34 + "title": "Add RequestAware trait/module pattern for exceptions", 35 + "description": "HTTPlug uses a RequestAwareTrait that provides consistent access to the failed request across different exception types. This trait provides setRequest() and getRequest() methods, ensuring all request-related exceptions can expose the request that failed. The OCaml library embeds request context directly in exception variants, but could benefit from helper functions to extract request details consistently.", 36 + "affected_files": [ 37 + "lib/error.ml", 38 + "lib/error.mli" 39 + ], 40 + "rationale": "HTTPlug's RequestAwareTrait pattern ensures consistent access to request context across all request-related exceptions. While OCaml's variant types already carry the necessary context (url in HTTPError, TooManyRedirects), adding helper functions like `Error.get_url`, `Error.get_request_context` would provide a consistent API for extracting request details from any error type. This makes error handling and logging more uniform across the codebase." 41 + }, 42 + { 43 + "source_repo": "php/httplug", 44 + "source_language": "PHP", 45 + "criticality": "low", 46 + "change_type": "enhancement", 47 + "title": "Store HTTP status code as exception code in HTTPError", 48 + "description": "HTTPlug's HttpException stores the HTTP status code as the exception code ($this->code = $response->getStatusCode()). This allows catching and filtering exceptions by status code using standard exception handling mechanisms. The OCaml library's HTTPError carries the status as a field but doesn't expose it through a standard exception code mechanism.", 49 + "affected_files": [ 50 + "lib/error.ml" 51 + ], 52 + "rationale": "HTTPlug sets the exception code to the HTTP status code in HttpException constructor (line 34), making it easy to programmatically handle different error classes. While OCaml exceptions don't have a 'code' field like PHP, the status is already accessible in the HTTPError variant. This is already well-handled in the OCaml implementation through pattern matching, so this is a low-priority observation rather than a critical issue." 53 + }, 54 + { 55 + "source_repo": "php/httplug", 56 + "source_language": "PHP", 57 + "criticality": "medium", 58 + "change_type": "feature", 59 + "title": "Add promise-based async API with retry support", 60 + "description": "HTTPlug provides HttpAsyncClient interface with promise-based async operations. The key feature added in v2.3.0 is that HttpRejectedPromise's onRejected callback can return a Promise, enabling retry mechanisms through promise chaining. This allows implementing sophisticated retry logic where a failed request can be transformed into a new request attempt by returning a new promise from the rejection handler.", 61 + "affected_files": [ 62 + "lib/requests.ml", 63 + "lib/one.ml", 64 + "lib/retry.ml" 65 + ], 66 + "rationale": "HTTPlug's promise-based retry mechanism (added in v2.3.0, CHANGELOG:24-25) allows the onRejected callback of HttpRejectedPromise to return a promise for retry. This enables flexible, composable retry strategies through promise chaining. The OCaml library uses Eio's structured concurrency with retry logic in retry.ml:95-123, which is effective but tightly coupled to the request execution. Adding a promise/future-like abstraction for requests would enable more flexible composition of retry, timeout, and error handling logic, similar to how HTTPlug's promise chain works." 67 + }, 68 + { 69 + "source_repo": "php/httplug", 70 + "source_language": "PHP", 71 + "criticality": "low", 72 + "change_type": "enhancement", 73 + "title": "Add immutable promise states to prevent state mutation", 74 + "description": "HTTPlug's promise implementations (HttpFulfilledPromise and HttpRejectedPromise) are final classes with immutable state (Promise::FULFILLED or Promise::REJECTED). This prevents subclassing vulnerabilities and ensures promises cannot change state after creation, following the Promise/A+ specification.", 75 + "affected_files": [ 76 + "lib/requests.ml" 77 + ], 78 + "rationale": "HTTPlug's promises are final classes with immutable states, preventing state mutation after creation. This is a security and correctness feature that ensures promises behave predictably. The OCaml library uses Eio's structured concurrency which provides similar guarantees through the type system (fibers complete once and their results are immutable). This is already well-handled in the OCaml implementation, so this is mostly a confirmation that the current approach is sound." 79 + }, 80 + { 81 + "source_repo": "php/httplug", 82 + "source_language": "PHP", 83 + "criticality": "medium", 84 + "change_type": "enhancement", 85 + "title": "Add middleware/plugin architecture for request/response transformation", 86 + "description": "HTTPlug is designed as a thin abstraction layer where middleware/plugins can be implemented through the decorator pattern. The library enables wrapping HttpClient implementations with decorators that add behaviors like logging, metrics, authentication, retry, caching, etc. This is achieved through interface-based design where any decorator implements the same HttpClient or HttpAsyncClient interface.", 87 + "affected_files": [ 88 + "lib/requests.ml", 89 + "lib/requests.mli" 90 + ], 91 + "rationale": "HTTPlug's architecture explicitly supports middleware through the decorator pattern - any class implementing HttpClient can wrap another HttpClient to add behavior. This enables modular, composable request/response transformations. The OCaml library has some middleware-like features (auth headers, retry logic, auto-decompression) baked into the main client, but doesn't expose a formal middleware API. Adding a middleware type like `type middleware = t -> (request -> response) -> (request -> response)` would enable users to add custom behaviors (logging, metrics, caching, custom auth, request signing, etc.) without modifying the core library." 92 + }, 93 + { 94 + "source_repo": "php/httplug", 95 + "source_language": "PHP", 96 + "criticality": "high", 97 + "change_type": "security", 98 + "title": "Document security considerations for exception information leakage", 99 + "description": "HTTPlug's exceptions contain full request and response data for debugging, including URLs, headers, and body content. The library doesn't have built-in sanitization to prevent sensitive data (auth tokens, API keys, passwords) from appearing in exception messages and stack traces. This is a potential security risk if exceptions are logged in production without sanitization.", 100 + "affected_files": [ 101 + "lib/error.ml", 102 + "lib/error.mli", 103 + "README.md" 104 + ], 105 + "rationale": "HTTPlug's HttpException includes full request/response context in exceptions (URL, method, status, headers), which is valuable for debugging but can leak sensitive data in logs. The OCaml library's error.ml:144-149 includes body and headers in HTTPError pretty-printing, which could expose sensitive data. Documentation should warn users about this and provide guidance on sanitizing errors before logging in production. Consider adding a `pp_safe` variant that omits sensitive fields, or a configurable sanitization function." 106 + }, 107 + { 108 + "source_repo": "php/httplug", 109 + "source_language": "PHP", 110 + "criticality": "low", 111 + "change_type": "enhancement", 112 + "title": "Add comprehensive PHPSpec-style behavior-driven testing", 113 + "description": "HTTPlug uses PHPSpec for behavior-driven development testing. Tests are organized as specifications that mirror the source structure, with comprehensive coverage of promise chaining, exception handling, callback behavior, and edge cases. The test suite runs against multiple PHP versions (7.1-8.4) and both latest and lowest dependency versions to ensure compatibility.", 114 + "affected_files": [ 115 + "test/", 116 + "dune" 117 + ], 118 + "rationale": "HTTPlug has 6 spec files (162 lines) covering all core behavior: promise states, chaining, exception handling, factory methods, and callback exception propagation. The tests verify both normal flows and edge cases (e.g., non-HTTPlug exceptions in callbacks, retry through rejected promises). The OCaml library has integration tests (httpbin.t) but could benefit from more unit-level behavior tests for individual modules (Error, Retry, Auth, Headers) to verify edge cases and ensure correctness across different scenarios." 119 + }, 120 + { 121 + "source_repo": "php/httplug", 122 + "source_language": "PHP", 123 + "criticality": "medium", 124 + "change_type": "enhancement", 125 + "title": "Add multi-version compatibility testing in CI", 126 + "description": "HTTPlug's CI tests against multiple PHP versions (7.1 through 8.4) and both highest and lowest dependency versions. This ensures compatibility across a wide range of environments and catches dependency-related issues early. Tests also include code coverage reporting to Scrutinizer-CI with Xdebug.", 127 + "affected_files": [ 128 + ".github/workflows/", 129 + "dune-project" 130 + ], 131 + "rationale": "HTTPlug tests against 8 PHP versions and both latest/lowest dependencies, ensuring broad compatibility. The OCaml library should similarly test against multiple OCaml compiler versions (4.14, 5.0, 5.1, 5.2+) and different dependency versions to catch compatibility issues. This is especially important given Eio's requirement for OCaml 5.x and the library's use of domain-local storage and effects." 132 + }, 133 + { 134 + "source_repo": "php/httplug", 135 + "source_language": "PHP", 136 + "criticality": "medium", 137 + "change_type": "enhancement", 138 + "title": "Add response object to HTTPError exception for debugging", 139 + "description": "HTTPlug's HttpException provides access to both the request AND response objects through getRequest() and getResponse() methods. This allows exception handlers to inspect the full response (headers, body, status) when an HTTP error occurs, which is crucial for debugging and error recovery strategies. The exception code is set to the HTTP status code for easy categorization.", 140 + "affected_files": [ 141 + "lib/error.ml", 142 + "lib/response.ml" 143 + ], 144 + "rationale": "HTTPlug's HttpException (lines 17-45 in HttpException.php) stores both request and response objects, making them available to error handlers. The OCaml library's HTTPError exception carries url, status, reason, body (option), and headers, but the body is optional and may be None. In response.ml:81-89, raise_for_status creates HTTPError with body=None. Capturing the response body in HTTPError exceptions would provide more debugging context. Consider adding a configurable max_error_body_size to prevent large responses from bloating exceptions." 145 + }, 146 + { 147 + "source_repo": "php/httplug", 148 + "source_language": "PHP", 149 + "criticality": "low", 150 + "change_type": "enhancement", 151 + "title": "Add Retry-After header parsing for rate limiting", 152 + "description": "HTTPlug's design allows middleware to implement retry logic with Retry-After header parsing. The OCaml library has partial support in retry.ml:73-93 with parse_retry_after function that handles both integer seconds and RFC3339 dates. However, this parsed value is not currently used in the retry logic (with_retry function at line 95 doesn't reference Retry-After headers).", 153 + "affected_files": [ 154 + "lib/retry.ml", 155 + "lib/requests.ml" 156 + ], 157 + "rationale": "The OCaml library has a parse_retry_after function (retry.ml:73-93) that parses both integer and HTTP date formats, but this is never called in the actual retry implementation (with_retry at line 95). The retry config has respect_retry_after flag (default true) but it's not used. To properly support rate limiting, the retry logic should extract the Retry-After header from HTTP 429 or 503 responses and use that delay instead of the exponential backoff when present and respect_retry_after is true." 158 + }, 159 + { 160 + "source_repo": "php/httplug", 161 + "source_language": "PHP", 162 + "criticality": "low", 163 + "change_type": "refactor", 164 + "title": "Simplify library to focus on core abstraction and move complex features to plugins", 165 + "description": "HTTPlug is deliberately minimal (309 lines core, 162 lines tests) and focuses purely on providing interfaces for HTTP clients and async clients with basic promise and exception handling. Complex features like retry, authentication, middleware, caching, and logging are intentionally left to plugin implementations. This keeps the core library small, focused, and easy to maintain.", 166 + "affected_files": [ 167 + "lib/requests.ml", 168 + "lib/auth.ml", 169 + "lib/retry.ml" 170 + ], 171 + "rationale": "HTTPlug's philosophy is to be a minimal abstraction layer (total 309 LOC) that doesn't reinvent functionality - it provides interfaces and lets implementations handle specifics. The OCaml library has many features baked in (auth, retry, cookies, compression, redirects) which makes it more batteries-included but also more complex. Consider whether some features could be extracted into separate modules/packages that users opt into, keeping the core library simpler. This is a design philosophy question rather than a critical issue." 172 + }, 173 + { 174 + "source_repo": "php/httplug", 175 + "source_language": "PHP", 176 + "criticality": "medium", 177 + "change_type": "enhancement", 178 + "title": "Add streaming support with backpressure for large responses", 179 + "description": "HTTPlug's promise-based async API allows for streaming responses where the promise resolves with a response object that can have a streaming body. This enables processing large responses without loading them entirely into memory. The OCaml library has streaming support through Eio.Flow in response.ml:9-16, but could benefit from explicit backpressure mechanisms.", 180 + "affected_files": [ 181 + "lib/response.ml", 182 + "lib/body.ml" 183 + ], 184 + "rationale": "The OCaml library already uses Eio.Flow for streaming (response.ml:12 - body is Eio.Flow.source_ty), which is good. However, for truly large responses (multi-GB files, long-lived streaming APIs), explicit backpressure mechanisms would prevent memory buildup. Eio provides backpressure through its flow system, but the library could expose controls for chunk size, buffer limits, and flow control. This would make the library safer for processing very large responses or streaming APIs." 185 + }, 186 + { 187 + "source_repo": "php/httplug", 188 + "source_language": "PHP", 189 + "criticality": "high", 190 + "change_type": "bug", 191 + "title": "Fix incomplete Retry-After header implementation", 192 + "description": "The retry.ml module has a parse_retry_after function and respect_retry_after config flag, but the with_retry function never actually uses Retry-After headers from responses. This means the library claims to support Retry-After (config default is true) but doesn't actually implement it. This is misleading to users who expect rate-limiting to be respected.", 193 + "affected_files": [ 194 + "lib/retry.ml", 195 + "lib/requests.ml" 196 + ], 197 + "rationale": "The retry module has parse_retry_after (lines 73-93) and respect_retry_after config (default true in line 25), but with_retry (lines 95-123) only uses calculate_backoff for delays. To properly implement this feature: 1) Pass response headers to retry logic when available, 2) Extract Retry-After header for 429/503 responses, 3) Use parsed delay instead of backoff when respect_retry_after is true and header is present. This is a high-priority bug because the feature is advertised but not implemented." 198 + } 199 + ] 200 + }
+161
third_party/python/grequests.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/python/grequests", 5 + "source_language": "Python", 6 + "criticality": "high", 7 + "change_type": "enhancement", 8 + "title": "Add exception handler callback for concurrent requests", 9 + "description": "Implement an exception_handler callback mechanism for map/batch operations that allows users to customize error handling for individual failed requests. grequests supports exception_handler in map() and imap() functions that receives (request, exception) and can return replacement values or None. This enables graceful degradation where some failures don't abort the entire batch.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/requests.mli" 13 + ], 14 + "rationale": "The OCaml library uses Eio.Fiber.both/all for concurrent requests but lacks a standard pattern for handling partial failures. When using Fiber.all, if one request fails, the entire batch fails. Adding an exception_handler pattern (similar to grequests) would allow users to collect both successes and failures, enabling more robust batch processing. This is critical for real-world applications that need to handle partial failures gracefully (e.g., fetching data from multiple APIs where some might be down)." 15 + }, 16 + { 17 + "source_repo": "third_party/python/grequests", 18 + "source_language": "Python", 19 + "criticality": "medium", 20 + "change_type": "feature", 21 + "title": "Add batch/map convenience functions for concurrent requests", 22 + "description": "Add high-level batch processing functions similar to grequests.map() and grequests.imap() that accept a list of request descriptors and execute them concurrently, returning a list of responses. Include options for: (1) concurrency limit (size parameter), (2) stream mode, (3) exception handling callback, (4) timeout for entire batch (gtimeout).", 23 + "affected_files": [ 24 + "lib/requests.ml", 25 + "lib/requests.mli" 26 + ], 27 + "rationale": "Currently, users must manually use Eio.Fiber.both/all with complex patterns (refs, lists) to perform batch requests. grequests provides a simple map([requests]) API that handles concurrency automatically with a pool. Adding similar convenience functions would significantly improve API ergonomics for common use cases like: fetching multiple URLs, parallel API calls, batch data downloads. The OCaml version could leverage the existing connection pools and provide similar functionality with better type safety." 28 + }, 29 + { 30 + "source_repo": "third_party/python/grequests", 31 + "source_language": "Python", 32 + "criticality": "medium", 33 + "change_type": "feature", 34 + "title": "Add streaming/generator-based batch processing (imap equivalent)", 35 + "description": "Implement a streaming variant of batch operations that yields responses as they complete (similar to grequests.imap). This would return an iterator/sequence that produces responses in completion order rather than request order, enabling earlier processing of faster responses.", 36 + "affected_files": [ 37 + "lib/requests.ml", 38 + "lib/requests.mli" 39 + ], 40 + "rationale": "grequests.imap() uses a generator that yields results as they arrive, enabling streaming processing of large batches without waiting for all requests to complete. This is valuable for: (1) reducing memory usage in large batches, (2) starting processing earlier (faster time-to-first-result), (3) implementing progress monitoring. In OCaml, this could be implemented using Eio.Stream or a callback-based approach. This would be particularly useful for scenarios like crawling, batch data collection, or fan-out API calls." 41 + }, 42 + { 43 + "source_repo": "third_party/python/grequests", 44 + "source_language": "Python", 45 + "criticality": "medium", 46 + "change_type": "enhancement", 47 + "title": "Add index tracking for unordered concurrent responses", 48 + "description": "Implement indexed response tracking similar to grequests.imap_enumerated() that yields (index, response) tuples. This allows users to correlate responses back to original requests when processing results in completion order (which may differ from submission order).", 49 + "affected_files": [ 50 + "lib/requests.ml", 51 + "lib/requests.mli" 52 + ], 53 + "rationale": "When processing concurrent requests, responses arrive in arbitrary order based on network latency and server response time. grequests.imap_enumerated() addresses this by returning (index, response) pairs so users can map results back to inputs. This is critical for maintaining data integrity when: (1) processing related datasets in parallel, (2) need to match responses to input parameters, (3) handling partial failures while preserving order information. Without this, users must build their own tracking mechanisms." 54 + }, 55 + { 56 + "source_repo": "third_party/python/grequests", 57 + "source_language": "Python", 58 + "criticality": "low", 59 + "change_type": "enhancement", 60 + "title": "Add callback/hooks support for individual responses", 61 + "description": "Implement a callback parameter (similar to grequests callback kwarg and hooks) that gets invoked when each response is received. This would allow users to define response processing logic at request creation time rather than after collecting all responses.", 62 + "affected_files": [ 63 + "lib/requests.ml", 64 + "lib/requests.mli" 65 + ], 66 + "rationale": "grequests supports a callback parameter that simplifies response processing by allowing users to attach handlers at request time. This improves API ergonomics for: (1) side-effect operations (logging, metrics), (2) transforming responses inline, (3) early validation. While OCaml's functional style provides other patterns for this, a callback mechanism would be familiar to users coming from other HTTP libraries and could simplify common patterns." 67 + }, 68 + { 69 + "source_repo": "third_party/python/grequests", 70 + "source_language": "Python", 71 + "criticality": "medium", 72 + "change_type": "enhancement", 73 + "title": "Add concurrency pool size limiting for batch operations", 74 + "description": "Implement a concurrency limit parameter (similar to grequests size parameter) that restricts the maximum number of concurrent requests in flight. This prevents resource exhaustion when processing large batches and provides backpressure.", 75 + "affected_files": [ 76 + "lib/requests.ml", 77 + "lib/requests.mli" 78 + ], 79 + "rationale": "grequests uses a Pool(size) to limit concurrent greenlets, preventing resource exhaustion when processing hundreds or thousands of requests. The OCaml library has connection pools but lacks batch-level concurrency control. Without this, users doing Fiber.all on 1000 URLs would spawn 1000 concurrent fibers, potentially exhausting: (1) file descriptors, (2) memory, (3) remote server capacity. Adding a concurrency limiter (using Eio.Semaphore or similar) would enable safe batch processing of arbitrary-sized workloads." 80 + }, 81 + { 82 + "source_repo": "third_party/python/grequests", 83 + "source_language": "Python", 84 + "criticality": "low", 85 + "change_type": "enhancement", 86 + "title": "Document concurrent request patterns with Eio primitives", 87 + "description": "Add comprehensive documentation and examples showing how to perform concurrent requests using Eio.Fiber.both, Eio.Fiber.all, Eio.Promise, and Eio.Stream. Include patterns for: batch processing, partial failure handling, progress tracking, and concurrency limiting.", 88 + "affected_files": [ 89 + "lib/requests.mli", 90 + "README.md" 91 + ], 92 + "rationale": "The current documentation shows Eio.Fiber.both examples but doesn't comprehensively cover concurrent request patterns. grequests' primary value is making concurrency simple and obvious. While Eio provides powerful concurrency primitives, users need guidance on best practices for: (1) batch request patterns, (2) error handling in concurrent contexts, (3) progress monitoring, (4) resource management. Better documentation would reduce the learning curve and prevent common pitfalls." 93 + }, 94 + { 95 + "source_repo": "third_party/python/grequests", 96 + "source_language": "Python", 97 + "criticality": "medium", 98 + "change_type": "enhancement", 99 + "title": "Add session/client sharing for concurrent requests", 100 + "description": "Document and ensure proper session/client sharing across concurrent fibers. Verify that the same Requests.t instance can be safely used from multiple concurrent fibers for connection pool sharing and cookie/auth state consistency.", 101 + "affected_files": [ 102 + "lib/requests.ml", 103 + "lib/requests.mli" 104 + ], 105 + "rationale": "grequests supports passing a session parameter to requests for sharing state (cookies, auth, connection pooling). The OCaml library has session support (Requests.t) but needs to ensure thread-safety for concurrent fiber access. The cookie_mutex is present but documentation should clarify: (1) whether the same session can be used from concurrent fibers, (2) how connection pools are shared, (3) whether cookies/auth are properly synchronized. This is important for efficient concurrent operations that need shared state." 106 + }, 107 + { 108 + "source_repo": "third_party/python/grequests", 109 + "source_language": "Python", 110 + "criticality": "high", 111 + "change_type": "enhancement", 112 + "title": "Improve error handling to capture exception context in concurrent scenarios", 113 + "description": "Enhance error handling to preserve request context (URL, method, headers) when exceptions occur in concurrent operations. Store exception information with traceback/context similar to grequests' exception and traceback attributes on failed requests.", 114 + "affected_files": [ 115 + "lib/error.ml", 116 + "lib/error.mli", 117 + "lib/requests.ml" 118 + ], 119 + "rationale": "grequests captures exceptions with full traceback and stores them as attributes (exception, traceback) on the request object, making debugging concurrent failures much easier. When processing 100 concurrent requests and one fails, you can see exactly which request failed and why. The OCaml library's error types should include more context: (1) original request URL/method, (2) attempt number (for retries), (3) timestamp, (4) potentially the full request configuration. This is critical for debugging production issues in concurrent/batch operations." 120 + }, 121 + { 122 + "source_repo": "third_party/python/grequests", 123 + "source_language": "Python", 124 + "criticality": "low", 125 + "change_type": "enhancement", 126 + "title": "Add batch timeout parameter for overall operation", 127 + "description": "Implement a batch-level timeout (similar to grequests gtimeout parameter) that limits the total time for all requests in a batch operation, not just individual request timeouts.", 128 + "affected_files": [ 129 + "lib/requests.ml", 130 + "lib/requests.mli" 131 + ], 132 + "rationale": "grequests.map() accepts a gtimeout parameter that limits the total time for gevent.joinall(), allowing users to specify an overall deadline for batch operations. This is different from per-request timeouts and is useful for: (1) bounded-time batch operations, (2) preventing indefinite hangs when some requests are very slow, (3) implementing service-level SLAs. The OCaml version could use Eio.Time.with_timeout to wrap batch operations." 133 + }, 134 + { 135 + "source_repo": "third_party/python/grequests", 136 + "source_language": "Python", 137 + "criticality": "medium", 138 + "change_type": "enhancement", 139 + "title": "Add comprehensive test coverage for concurrent request patterns", 140 + "description": "Add test cases covering: (1) concurrent requests with mixed success/failure, (2) exception handling in batch operations, (3) timeout behavior in concurrent scenarios, (4) cookie/session sharing across concurrent requests, (5) connection pool behavior under concurrent load.", 141 + "affected_files": [ 142 + "test/test_localhost.ml", 143 + "test/test_simple.ml" 144 + ], 145 + "rationale": "grequests has comprehensive tests for concurrent scenarios (test_map, test_imap, test_concurrency_with_delayed_url, test_map_timeout_exception_handler, etc.). The OCaml test suite should similarly verify concurrent behavior. Current tests seem focused on individual requests. Adding tests for: (1) partial failures in batches, (2) exception handler behavior, (3) concurrent session usage, (4) pool exhaustion scenarios would improve reliability and serve as usage examples." 146 + }, 147 + { 148 + "source_repo": "third_party/python/grequests", 149 + "source_language": "Python", 150 + "criticality": "medium", 151 + "change_type": "enhancement", 152 + "title": "Add stream parameter support for batch operations", 153 + "description": "Implement a stream parameter (similar to grequests stream parameter in map/imap) that controls whether response bodies are downloaded immediately or kept as streams. This allows users to defer body downloads in batch operations.", 154 + "affected_files": [ 155 + "lib/requests.ml", 156 + "lib/requests.mli" 157 + ], 158 + "rationale": "grequests supports a stream=True parameter that prevents immediate body consumption, useful when: (1) fetching large files in batches, (2) only checking headers/status codes, (3) selective body downloading based on headers. The OCaml library already has streaming support (Response.body returns a flow), but batch operations should support a flag to control whether bodies are pre-fetched into strings or left as streams. This is important for memory efficiency in large batch operations." 159 + } 160 + ] 161 + }
+257
third_party/python/httplib2.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "httplib2", 5 + "source_language": "Python", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add URI sanitization to prevent CRLF injection attacks", 9 + "description": "httplib2 sanitizes URIs by replacing spaces with %20 and CRLF characters with their URL-encoded equivalents to prevent CWE-75 space injection and CWE-93 CRLF injection attacks. The OCaml library should implement similar sanitization before sending requests.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/one.ml", 13 + "lib/http_client.ml" 14 + ], 15 + "rationale": "httplib2 at line 1557-1559 performs: uri.replace(' ', '%20').replace('\\r', '%0D').replace('\\n', '%0A'). This prevents attackers from manipulating requests via malicious URIs containing newlines or carriage returns. The OCaml library currently lacks this protection, making it vulnerable to header injection attacks where an attacker could inject arbitrary headers or split the request." 16 + }, 17 + { 18 + "source_repo": "httplib2", 19 + "source_language": "Python", 20 + "criticality": "high", 21 + "change_type": "feature", 22 + "title": "Implement HTTP caching with Cache-Control and ETag support", 23 + "description": "httplib2 has comprehensive HTTP caching support including Cache-Control directives (no-cache, max-age, etc.), ETag validation, Last-Modified headers, and cache freshness calculations. This is a major missing feature in the OCaml library that would significantly improve performance for repeated requests.", 24 + "affected_files": [ 25 + "lib/requests.ml", 26 + "lib/response.ml", 27 + "lib/headers.ml" 28 + ], 29 + "rationale": "httplib2 implements RFC 7234 HTTP caching with FileCache storage, conditional requests (If-None-Match, If-Modified-Since), and cache freshness determination via _entry_disposition(). This reduces bandwidth and latency for cacheable resources. The OCaml library has no caching mechanism, requiring full downloads on every request even when content hasn't changed. Implementing caching would align with HTTP best practices and improve client efficiency." 30 + }, 31 + { 32 + "source_repo": "httplib2", 33 + "source_language": "Python", 34 + "criticality": "medium", 35 + "change_type": "enhancement", 36 + "title": "Add force_exception_to_status_code mode for exception-to-response conversion", 37 + "description": "httplib2 provides a force_exception_to_status_code flag that converts exceptions (timeouts, connection errors, etc.) into HTTP-like response objects with appropriate status codes (408 for timeout, 400 for other errors). This allows error handling through a uniform response interface.", 38 + "affected_files": [ 39 + "lib/error.ml", 40 + "lib/requests.ml", 41 + "lib/one.ml" 42 + ], 43 + "rationale": "httplib2 lines 1730-1752 show that when force_exception_to_status_code=True, socket.timeout becomes a 408 response, and other exceptions become 400/500 responses. This is useful for applications that want consistent error handling through the response type rather than exception catching. The OCaml library currently requires explicit exception handling and doesn't offer this alternative pattern. Adding an option to convert errors to Response objects with error status codes would improve API ergonomics for certain use cases." 44 + }, 45 + { 46 + "source_repo": "httplib2", 47 + "source_language": "Python", 48 + "criticality": "medium", 49 + "change_type": "enhancement", 50 + "title": "Add optimistic concurrency control with If-Match headers", 51 + "description": "httplib2 automatically adds If-Match headers for PUT/PATCH requests when cached ETags are available, implementing optimistic concurrency control. This prevents lost updates when multiple clients modify the same resource.", 52 + "affected_files": [ 53 + "lib/requests.ml", 54 + "lib/headers.ml" 55 + ], 56 + "rationale": "httplib2 lines 1295, 1620-1628 show automatic If-Match header addition for PUT/PATCH when ETags exist in cache. This implements the HTTP-based optimistic concurrency pattern described in RFC 7232. The OCaml library doesn't have this feature, requiring users to manually implement version checking. Adding support for optimistic concurrency would prevent lost updates and align with HTTP editing best practices." 57 + }, 58 + { 59 + "source_repo": "httplib2", 60 + "source_language": "Python", 61 + "criticality": "medium", 62 + "change_type": "security", 63 + "title": "Implement forward_authorization_headers flag for cross-origin redirects", 64 + "description": "httplib2 provides a forward_authorization_headers flag (default: False) that controls whether Authorization headers are preserved during redirects. By default, it strips auth headers on redirects to prevent credential leakage to untrusted domains.", 65 + "affected_files": [ 66 + "lib/requests.ml" 67 + ], 68 + "rationale": "httplib2 line 1310 and 1488-1489 show that Authorization headers are deleted during redirects unless forward_authorization_headers=True. The OCaml library at requests.ml:210-216 has same_origin logic but could be enhanced with explicit configuration. While the OCaml library has some redirect security logic, making this behavior configurable and well-documented would improve security transparency and flexibility for cases where forwarding auth is intentional." 69 + }, 70 + { 71 + "source_repo": "httplib2", 72 + "source_language": "Python", 73 + "criticality": "medium", 74 + "change_type": "feature", 75 + "title": "Add SOCKS proxy support (SOCKS4/SOCKS5)", 76 + "description": "httplib2 supports SOCKS proxies in addition to HTTP proxies, using the PySocks library. It can parse proxy URLs with schemes like socks4:// and socks5:// and route traffic through SOCKS proxies.", 77 + "affected_files": [ 78 + "lib/requests.ml" 79 + ], 80 + "rationale": "httplib2 lines 47-50, 851-982, and 1000-1066 show SOCKS proxy support through the socks library. The proxy_info_from_url function (line 951-982) parses socks4/socks5 schemes and ProxyInfo supports different proxy types. The OCaml library appears to lack SOCKS proxy support. Adding this would enable usage through Tor, corporate SOCKS proxies, and other SOCKS-based networks, which is valuable for privacy-conscious and enterprise applications." 81 + }, 82 + { 83 + "source_repo": "httplib2", 84 + "source_language": "Python", 85 + "criticality": "medium", 86 + "change_type": "enhancement", 87 + "title": "Support proxy bypass for specific hosts", 88 + "description": "httplib2's ProxyInfo supports bypass_hosts to exclude certain domains from proxying (e.g., localhost, internal networks). This includes wildcard support and recognizes the NO_PROXY environment variable.", 89 + "affected_files": [ 90 + "lib/requests.ml" 91 + ], 92 + "rationale": "httplib2 lines 854, 912-928, and 970-981 implement proxy bypass logic. The bypass_host method supports exact matches and suffix wildcards (*.example.com), and proxy_info_from_url reads the NO_PROXY environment variable. This is essential for environments where local/internal hosts should bypass the proxy while external requests use it. The OCaml library would benefit from similar proxy bypass configuration." 93 + }, 94 + { 95 + "source_repo": "httplib2", 96 + "source_language": "Python", 97 + "criticality": "low", 98 + "change_type": "enhancement", 99 + "title": "Add support for WSSE authentication", 100 + "description": "httplib2 implements WSSE (Web Services Security) UsernameToken authentication, which uses SHA-1 hashing with nonces and timestamps. While less common than Basic/Digest, it's used by some web services and blogs.", 101 + "affected_files": [ 102 + "lib/auth.ml", 103 + "lib/auth.mli" 104 + ], 105 + "rationale": "httplib2 lines 710-735 implement WsseAuthentication with timestamp and nonce-based password digests. While WSSE is less common than OAuth or modern bearer tokens, some legacy systems still use it. The OCaml library supports Basic, Bearer, and Digest auth but not WSSE. Adding WSSE would improve compatibility with legacy web services that require this authentication method." 106 + }, 107 + { 108 + "source_repo": "httplib2", 109 + "source_language": "Python", 110 + "criticality": "low", 111 + "change_type": "enhancement", 112 + "title": "Support authentication scope tracking by URI path depth", 113 + "description": "httplib2 tracks authentication scope using path prefixes and depth calculations, allowing the same credentials to be reused for URIs under the same path hierarchy. This reduces authentication overhead for APIs with path-based resource organization.", 114 + "affected_files": [ 115 + "lib/auth.ml", 116 + "lib/requests.ml" 117 + ], 118 + "rationale": "httplib2 lines 495-544 show the Authentication class with depth(), inscope(), and path-based authorization tracking. The library maintains a list of authorizations and selects the best match based on URI path depth (line 1442-1443). This allows efficient auth reuse within resource hierarchies. The OCaml library applies auth per-request but doesn't track scope hierarchies. Implementing this could reduce authentication attempts for multi-request workflows against the same API." 119 + }, 120 + { 121 + "source_repo": "httplib2", 122 + "source_language": "Python", 123 + "criticality": "high", 124 + "change_type": "enhancement", 125 + "title": "Implement automatic retry with BadStatusLine detection", 126 + "description": "httplib2 has sophisticated retry logic that detects stale connections via BadStatusLine and retries on the first attempt regardless of the RETRIES setting. It also handles HTTPException during connection establishment differently than during data transfer.", 127 + "affected_files": [ 128 + "lib/retry.ml", 129 + "lib/requests.ml", 130 + "lib/http_client.ml" 131 + ], 132 + "rationale": "httplib2 lines 1363-1434 show retry logic that: (1) always retries BadStatusLine on first attempt (connection went stale), (2) retries HTTPException with connection reset, (3) retries specific errno values (ENETUNREACH, EADDRNOTAVAIL) for transient errors. The seen_bad_status_line variable (line 1364) ensures stale connection retries don't count against the retry limit. The OCaml library has retry support but doesn't special-case stale connections. Implementing this would improve reliability when connection pools contain stale connections." 133 + }, 134 + { 135 + "source_repo": "httplib2", 136 + "source_language": "Python", 137 + "criticality": "medium", 138 + "change_type": "enhancement", 139 + "title": "Add support for permanent redirect caching (301, 308)", 140 + "description": "httplib2 caches permanent redirects (301 for GET, 308 for all methods) with a special -x-permanent-redirect-url header and automatically follows them from cache without hitting the original URL again.", 141 + "affected_files": [ 142 + "lib/requests.ml" 143 + ], 144 + "rationale": "httplib2 lines 1479-1483 and 1657-1670 show that 301/308 redirects are cached permanently and subsequent requests to the original URL are redirected from cache. This optimization eliminates network round-trips for resources that have permanently moved. The OCaml library follows redirects but doesn't cache permanent ones, requiring a network request every time. Implementing permanent redirect caching would improve performance for moved resources." 145 + }, 146 + { 147 + "source_repo": "httplib2", 148 + "source_language": "Python", 149 + "criticality": "low", 150 + "change_type": "enhancement", 151 + "title": "Support Cache-Control: only-if-cached directive", 152 + "description": "httplib2 implements the only-if-cached directive which returns cached content if available, otherwise returns a 504 Gateway Timeout response without making a network request. This is useful for offline-first applications.", 153 + "affected_files": [ 154 + "lib/requests.ml" 155 + ], 156 + "rationale": "httplib2 lines 1721-1725 show that requests with only-if-cached return a 504 response when no cached content exists, avoiding network requests. This Cache-Control directive (RFC 7234) enables offline-capable applications that can gracefully degrade when cached content is unavailable. The OCaml library has no caching support yet, so this would be part of a broader caching implementation." 157 + }, 158 + { 159 + "source_repo": "httplib2", 160 + "source_language": "Python", 161 + "criticality": "medium", 162 + "change_type": "refactor", 163 + "title": "Separate HOP_BY_HOP headers from end-to-end headers for caching", 164 + "description": "httplib2 maintains a list of hop-by-hop headers (Connection, Keep-Alive, Proxy-Authorization, etc.) and strips them before caching, ensuring only end-to-end headers are stored and forwarded.", 165 + "affected_files": [ 166 + "lib/headers.ml", 167 + "lib/requests.ml" 168 + ], 169 + "rationale": "httplib2 lines 104-113 and 190-193 define HOP_BY_HOP headers and _get_end2end_headers() function that filters them out. RFC 7230 requires hop-by-hop headers to be removed before caching or forwarding. The OCaml library doesn't currently distinguish these header types. When implementing caching, the library should filter hop-by-hop headers to comply with HTTP specifications and avoid caching connection-specific information." 170 + }, 171 + { 172 + "source_repo": "httplib2", 173 + "source_language": "Python", 174 + "criticality": "low", 175 + "change_type": "enhancement", 176 + "title": "Add certificate and key file authentication (mTLS client certificates)", 177 + "description": "httplib2 supports client certificate authentication via KeyCerts storage and loads cert_file/key_file/key_password when establishing HTTPS connections. This enables mutual TLS authentication.", 178 + "affected_files": [ 179 + "lib/requests.ml" 180 + ], 181 + "rationale": "httplib2 lines 834-844, 1082-1117, and 1569-1582 show client certificate support through KeyCerts class and cert_file/key_file parameters passed to HTTPSConnectionWithTimeout. The OCaml library uses Tls.Config.client but doesn't expose an API for users to configure client certificates easily. Adding support for client certificate authentication would enable mTLS scenarios required by many enterprise APIs and secure services." 182 + }, 183 + { 184 + "source_repo": "httplib2", 185 + "source_language": "Python", 186 + "criticality": "medium", 187 + "change_type": "enhancement", 188 + "title": "Implement Vary header support for cache keying", 189 + "description": "httplib2 respects the Vary response header and stores variant-specific cache entries based on request headers like Accept-Language or User-Agent. This ensures cached responses match request variations.", 190 + "affected_files": [ 191 + "lib/requests.ml" 192 + ], 193 + "rationale": "httplib2 lines 445-453 and 1638-1646 implement Vary header handling by storing -varied-{header} annotations in cached entries and checking if subsequent requests match the varied headers. RFC 7231 requires caches to respect Vary to avoid serving incorrect cached variants. The OCaml library has no caching yet, but when implementing it, Vary support is essential for correctness when servers use content negotiation." 194 + }, 195 + { 196 + "source_repo": "httplib2", 197 + "source_language": "Python", 198 + "criticality": "low", 199 + "change_type": "bug", 200 + "title": "Handle both zlib and raw deflate for Content-Encoding: deflate", 201 + "description": "When handling deflate-encoded content, httplib2 first tries the zlib wrapper (common in practice despite specs) and falls back to raw DEFLATE if that fails. The OCaml implementation should maintain this dual-mode fallback.", 202 + "affected_files": [ 203 + "lib/http_client.ml" 204 + ], 205 + "rationale": "httplib2 lines 395-399 show that deflate tries both zlib.decompress with MAX_WBITS and -MAX_WBITS (raw DEFLATE). The HTTP spec defines deflate as zlib-wrapped, but many servers incorrectly send raw DEFLATE. The OCaml library at http_client.ml:105-113 already implements the correct zlib-first, raw-deflate-fallback behavior, which is good. This is noted for confirmation that the current implementation matches httplib2's robust approach." 206 + }, 207 + { 208 + "source_repo": "httplib2", 209 + "source_language": "Python", 210 + "criticality": "low", 211 + "change_type": "enhancement", 212 + "title": "Add debuglevel support for connection debugging", 213 + "description": "httplib2 exposes a debuglevel parameter that can be set globally or per-Http instance to enable verbose logging of HTTP connection details, useful for troubleshooting.", 214 + "affected_files": [ 215 + "lib/requests.ml", 216 + "lib/http_client.ml" 217 + ], 218 + "rationale": "httplib2 lines 76-77 and 1597 show debuglevel support that's passed to connection objects and controls verbose output. While the OCaml library uses the Logs library for structured logging which is more sophisticated than debuglevel, adding a convenience function to set log levels for debugging would improve developer experience during troubleshooting." 219 + }, 220 + { 221 + "source_repo": "httplib2", 222 + "source_language": "Python", 223 + "criticality": "high", 224 + "change_type": "security", 225 + "title": "Add support for configurable redirect codes and safe methods", 226 + "description": "httplib2 allows customization of redirect_codes (which status codes trigger redirects) and safe_methods (which methods are safe to automatically redirect). This prevents unsafe redirects of POST/PUT requests that could have side effects.", 227 + "affected_files": [ 228 + "lib/requests.ml" 229 + ], 230 + "rationale": "httplib2 lines 115-119 and 1291-1297 define REDIRECT_CODES, SAFE_METHODS as configurable attributes. Line 1464 checks if method is in safe_methods before auto-following redirects. The OCaml library follows redirects but may not have sufficient controls to prevent dangerous auto-redirects of mutating operations. Making redirect behavior configurable and ensuring POST/PUT aren't blindly redirected would prevent unintended side effects and align with RFC 7231 safety requirements." 231 + }, 232 + { 233 + "source_repo": "httplib2", 234 + "source_language": "Python", 235 + "criticality": "medium", 236 + "change_type": "enhancement", 237 + "title": "Add environment variable support for proxy and CA cert configuration", 238 + "description": "httplib2 reads http_proxy, https_proxy, no_proxy environment variables for proxy configuration and CA_CERTS environment variable for certificate paths. This enables zero-config operation in containerized/CI environments.", 239 + "affected_files": [ 240 + "lib/requests.ml" 241 + ], 242 + "rationale": "httplib2 lines 938-948 implement proxy_info_from_environment() which reads http_proxy/HTTP_PROXY environment variables, and lines 970-981 handle NO_PROXY for bypass configuration. Environment-based configuration is a widely-adopted pattern that makes applications container-friendly and easier to configure without code changes. The OCaml library would benefit from similar environment variable support for proxies and CA certificates." 243 + }, 244 + { 245 + "source_repo": "httplib2", 246 + "source_language": "Python", 247 + "criticality": "medium", 248 + "change_type": "feature", 249 + "title": "Add relative URI redirect handling with urljoin", 250 + "description": "httplib2 handles relative Location headers (which violate RFC 2616 but are common) by using urljoin to resolve them against the request URL, ensuring redirects work even when servers send non-compliant responses.", 251 + "affected_files": [ 252 + "lib/requests.ml" 253 + ], 254 + "rationale": "httplib2 lines 1473-1478 show detection and fix-up of relative redirects using urllib.parse.urljoin. Line 1473 comments that relative redirects violate the MUST in RFC 2616 but are common enough to handle. The OCaml library should similarly handle relative Location headers robustly using Uri.resolve or equivalent to maintain compatibility with non-compliant but real-world servers." 255 + } 256 + ] 257 + }
+272
third_party/python/requests.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/python/requests", 5 + "source_language": "Python", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add separate ConnectTimeout and ReadTimeout exceptions", 9 + "description": "Python requests provides separate ConnectTimeout and ReadTimeout exceptions (both inheriting from base Timeout). ConnectTimeout also inherits from ConnectionError since connection timeouts are safe to retry. This granularity helps applications implement smarter retry logic - connection timeouts are always safe to retry, while read timeouts may indicate the request partially completed.", 10 + "affected_files": [ 11 + "lib/error.mli", 12 + "lib/error.ml", 13 + "lib/timeout.ml" 14 + ], 15 + "rationale": "The OCaml library currently has a single Timeout exception. Distinguishing between connect and read timeouts enables safer automatic retry logic and better debugging. Python requests marks ConnectTimeout as explicitly 'safe to retry' in its documentation, which is a valuable pattern for resilient HTTP clients." 16 + }, 17 + { 18 + "source_repo": "third_party/python/requests", 19 + "source_language": "Python", 20 + "criticality": "medium", 21 + "change_type": "enhancement", 22 + "title": "Include response body snippet in HTTPError for better debugging", 23 + "description": "Python requests' raise_for_status() includes the error message in the exception, and HTTPError exceptions carry both request and response objects. The OCaml implementation currently passes body as 'None' when creating HTTPError in raise_for_status (response.ml:81-89). Including a truncated body snippet (e.g., first 500 chars) would significantly improve debugging of API errors without memory overhead.", 24 + "affected_files": [ 25 + "lib/response.ml", 26 + "lib/error.ml" 27 + ], 28 + "rationale": "When API calls fail, the response body often contains critical error details (error codes, messages, validation failures). Currently, OCaml's raise_for_status discards this information. Python requests preserves the full response object in exceptions, making debugging much easier. Adding a truncated body preview strikes a balance between debuggability and memory usage." 29 + }, 30 + { 31 + "source_repo": "third_party/python/requests", 32 + "source_language": "Python", 33 + "criticality": "low", 34 + "change_type": "enhancement", 35 + "title": "Add ChunkedEncodingError and ContentDecodingError exceptions", 36 + "description": "Python requests has specific exceptions for chunked transfer encoding errors and content decoding failures (e.g., gzip decompression errors). These are currently mapped to generic errors in the OCaml library. Specific exception types allow applications to handle encoding/decoding failures differently from network or HTTP errors.", 37 + "affected_files": [ 38 + "lib/error.mli", 39 + "lib/error.ml" 40 + ], 41 + "rationale": "The OCaml library has EncodingError but it's generic. Separating ChunkedEncodingError (malformed chunked response) from ContentDecodingError (compression/decompression failure) matches Python requests' error taxonomy and enables more precise error handling, especially for applications dealing with unreliable servers or proxies that corrupt responses." 42 + }, 43 + { 44 + "source_repo": "third_party/python/requests", 45 + "source_language": "Python", 46 + "criticality": "medium", 47 + "change_type": "enhancement", 48 + "title": "Improve HTTPDigestAuth with thread-safe nonce tracking and MD5-SESS support", 49 + "description": "Python requests' HTTPDigestAuth uses thread-local storage to track nonce counts and previous challenges, enabling proper handling of repeated requests and challenge reuse. It also supports MD5-SESS algorithm. The OCaml implementation currently uses a fixed nonce count of 1 (auth.ml:196) and doesn't handle nonce reuse or MD5-SESS algorithm properly.", 50 + "affected_files": [ 51 + "lib/auth.ml", 52 + "lib/auth.mli" 53 + ], 54 + "rationale": "The OCaml Digest auth implementation is functional but incomplete. Python requests tracks nonce counts across requests to prevent replay attacks and reuses challenges when possible for efficiency. While OCaml doesn't need thread-local storage (Eio handles concurrency differently), maintaining nonce state per session would improve compliance with RFC 7616 and security. The fixed nc=00000001 works but isn't RFC-compliant for repeated requests." 55 + }, 56 + { 57 + "source_repo": "third_party/python/requests", 58 + "source_language": "Python", 59 + "criticality": "high", 60 + "change_type": "enhancement", 61 + "title": "Add StreamConsumedError to prevent double-reading response bodies", 62 + "description": "Python requests raises StreamConsumedError when attempting to read a response body that has already been consumed. This prevents subtle bugs where code tries to read response.text twice or mix streaming with full-body reads. The OCaml library currently uses a generic 'failwith' message (response.ml:71, 65) which isn't catchable as a specific exception type.", 63 + "affected_files": [ 64 + "lib/response.ml", 65 + "lib/error.mli", 66 + "lib/error.ml" 67 + ], 68 + "rationale": "Response body consumption is a common source of bugs in HTTP clients. The OCaml library tracks closed state but doesn't provide a catchable exception type. Converting the failwith calls to a proper StreamConsumedError exception (following Python requests' pattern) would enable applications to gracefully handle double-read attempts and provide better error messages. This is particularly important for streaming responses where the body is consumed incrementally." 69 + }, 70 + { 71 + "source_repo": "third_party/python/requests", 72 + "source_language": "Python", 73 + "criticality": "medium", 74 + "change_type": "enhancement", 75 + "title": "Add hook system for request/response interception", 76 + "description": "Python requests provides a hook system that allows registering callbacks for events like 'response'. This enables middleware-style functionality (logging, metrics, retries, auth refresh) without modifying core request code. The OCaml library currently doesn't have an equivalent extensibility mechanism.", 77 + "affected_files": [ 78 + "lib/requests.mli", 79 + "lib/requests.ml", 80 + "lib/one.mli", 81 + "lib/one.ml" 82 + ], 83 + "rationale": "Hooks provide clean extensibility without inheritance or code modification. Python requests uses them internally (e.g., HTTPDigestAuth registers response hooks to handle 401 challenges). Adding a simple hook system with events like `before_request` and `after_response` would enable logging, metrics collection, custom retry logic, and authentication refresh tokens - all common enterprise requirements." 84 + }, 85 + { 86 + "source_repo": "third_party/python/requests", 87 + "source_language": "Python", 88 + "criticality": "low", 89 + "change_type": "enhancement", 90 + "title": "Add Response.iter_content() and iter_lines() for chunk iteration", 91 + "description": "Python requests provides iter_content(chunk_size) and iter_lines() methods for iterating over response bodies in chunks or lines without loading the full response into memory. The OCaml library has streaming support via Flow.source but doesn't provide convenient iteration helpers.", 92 + "affected_files": [ 93 + "lib/response.mli", 94 + "lib/response.ml" 95 + ], 96 + "rationale": "While the OCaml library supports streaming via Eio.Flow, adding convenience functions for common patterns (chunked iteration, line iteration) would improve ergonomics. Python requests makes these patterns trivial with iter_content and iter_lines. OCaml equivalents could return sequences or use Eio's streaming primitives more directly." 97 + }, 98 + { 99 + "source_repo": "third_party/python/requests", 100 + "source_language": "Python", 101 + "criticality": "medium", 102 + "change_type": "enhancement", 103 + "title": "Implement retry-after header parsing with HTTP date support", 104 + "description": "Python requests' retry logic fully parses Retry-After headers supporting both integer seconds and HTTP date formats. The OCaml implementation has basic integer parsing and incomplete RFC3339 date parsing (retry.ml:74-93) but the error handling silently fails without proper fallback.", 105 + "affected_files": [ 106 + "lib/retry.ml" 107 + ], 108 + "rationale": "The OCaml library's parse_retry_after partially implements this feature but doesn't fully handle HTTP date formats. Python requests properly parses both formats according to RFC 7231. Improving this ensures compliance with rate-limiting APIs (GitHub, Twitter, etc.) that use HTTP dates in Retry-After headers. The current implementation logs a warning but could provide better user feedback." 109 + }, 110 + { 111 + "source_repo": "third_party/python/requests", 112 + "source_language": "Python", 113 + "criticality": "medium", 114 + "change_type": "feature", 115 + "title": "Add request/response history tracking for debugging redirect chains", 116 + "description": "Python requests maintains a history list on responses showing the full redirect chain. Each response in the chain includes the request that generated it. This is invaluable for debugging redirect issues, authentication flows, and understanding API behavior. The OCaml library doesn't track request/response history.", 117 + "affected_files": [ 118 + "lib/response.mli", 119 + "lib/response.ml", 120 + "lib/requests.ml" 121 + ], 122 + "rationale": "Redirect debugging is difficult without history tracking. Python requests stores the complete redirect chain in response.history, with each entry containing status, headers, and URL. This is particularly useful for OAuth flows, SSO redirects, and APIs with complex redirect logic. Adding this feature would significantly improve debuggability." 123 + }, 124 + { 125 + "source_repo": "third_party/python/requests", 126 + "source_language": "Python", 127 + "criticality": "low", 128 + "change_type": "enhancement", 129 + "title": "Add InvalidHeader exception for malformed header values", 130 + "description": "Python requests raises InvalidHeader when header values contain invalid characters (e.g., newlines which could enable header injection attacks). The OCaml library doesn't appear to validate header values for security issues.", 131 + "affected_files": [ 132 + "lib/headers.ml", 133 + "lib/error.mli", 134 + "lib/error.ml" 135 + ], 136 + "rationale": "Header injection is a security concern. Python requests validates headers via check_header_validity() and raises InvalidHeader for suspicious values. While OCaml's type system provides some protection, runtime validation of header values (checking for CRLF, null bytes) would prevent header injection vulnerabilities, especially when headers come from untrusted sources." 137 + }, 138 + { 139 + "source_repo": "third_party/python/requests", 140 + "source_language": "Python", 141 + "criticality": "medium", 142 + "change_type": "enhancement", 143 + "title": "Add URL validation with specific exceptions (MissingSchema, InvalidSchema, InvalidURL)", 144 + "description": "Python requests validates URLs early with specific exceptions: MissingSchema (no http/https), InvalidSchema (unsupported scheme), InvalidURL (malformed). The OCaml library has a generic InvalidURL exception but doesn't distinguish between error types or validate URLs comprehensively before making requests.", 145 + "affected_files": [ 146 + "lib/error.mli", 147 + "lib/error.ml", 148 + "lib/requests.ml", 149 + "lib/one.ml" 150 + ], 151 + "rationale": "Early URL validation with specific error types improves error messages and prevents wasted network calls. Python requests fails fast with clear errors like 'MissingSchema: Invalid URL \"example.com\": No scheme supplied.' The OCaml library could validate URLs using the Uri library more thoroughly and provide specific exceptions for common URL errors." 152 + }, 153 + { 154 + "source_repo": "third_party/python/requests", 155 + "source_language": "Python", 156 + "criticality": "high", 157 + "change_type": "security", 158 + "title": "Verify TLS certificate file existence and validity before making requests", 159 + "description": "Python requests (adapters.py:326-334) validates that certificate and key files exist before attempting to use them, raising OSError with clear messages. This prevents confusing TLS errors later in the connection process. The OCaml library should perform similar validation.", 160 + "affected_files": [ 161 + "lib/one.ml", 162 + "lib/requests.ml" 163 + ], 164 + "rationale": "Python requests checks if cert and key files exist before creating connections, providing clear error messages like 'Could not find the TLS certificate file, invalid path: /bad/path.pem'. This prevents cryptic TLS errors during connection. The OCaml library should validate certificate paths early when verify_tls=true or custom TLS configs are provided, improving user experience and security by catching configuration errors before network calls." 165 + }, 166 + { 167 + "source_repo": "third_party/python/requests", 168 + "source_language": "Python", 169 + "criticality": "medium", 170 + "change_type": "enhancement", 171 + "title": "Support environment variables for CA bundle configuration", 172 + "description": "Python requests checks REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE environment variables for custom CA certificate bundles as fallback when verify=True. This allows system-wide or containerized certificate configuration without code changes. The OCaml library currently only uses ca-certs library defaults.", 173 + "affected_files": [ 174 + "lib/one.ml", 175 + "lib/requests.ml" 176 + ], 177 + "rationale": "Environment variable support is standard for HTTP clients and essential for containerized deployments, corporate proxies, and custom PKI. Python requests checks REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE (for curl compatibility). Adding this to OCaml would improve Docker/Kubernetes deployments and enterprise environments where custom CA bundles are needed." 178 + }, 179 + { 180 + "source_repo": "third_party/python/requests", 181 + "source_language": "Python", 182 + "criticality": "low", 183 + "change_type": "enhancement", 184 + "title": "Add .netrc authentication support for automatic credential lookup", 185 + "description": "Python requests automatically reads credentials from ~/.netrc when trust_env=True and no explicit authentication is provided. This is a standard Unix convention for storing credentials. The OCaml library doesn't support .netrc files.", 186 + "affected_files": [ 187 + "lib/auth.ml", 188 + "lib/requests.ml" 189 + ], 190 + "rationale": "The .netrc file format is a Unix standard for storing credentials (used by curl, ftp, etc.). Python requests reads it automatically via get_netrc_auth(). While this feature is lower priority, it improves Unix integration and helps users migrate from curl-based scripts. The OCaml implementation could use a library like netrc-ocaml or implement basic parsing." 191 + }, 192 + { 193 + "source_repo": "third_party/python/requests", 194 + "source_language": "Python", 195 + "criticality": "medium", 196 + "change_type": "refactor", 197 + "title": "Add proxy authentication with separate Proxy-Authorization header handling", 198 + "description": "Python requests has explicit HTTPProxyAuth class and handles Proxy-Authorization headers separately from regular Authorization headers, including automatic stripping during redirects to prevent credential leakage. The OCaml library mentions proxy support but implementation is incomplete.", 199 + "affected_files": [ 200 + "lib/auth.ml", 201 + "lib/auth.mli", 202 + "lib/requests.ml" 203 + ], 204 + "rationale": "Proxy authentication requires different headers (Proxy-Authorization vs Authorization) and different security considerations. Python requests implements HTTPProxyAuth separately and has logic to rebuild proxy auth on redirects (sessions.py:302-331). The OCaml library should fully implement proxy authentication with proper header handling and security." 205 + }, 206 + { 207 + "source_repo": "third_party/python/requests", 208 + "source_language": "Python", 209 + "criticality": "medium", 210 + "change_type": "enhancement", 211 + "title": "Support tuple timeout format (connect_timeout, read_timeout) in addition to single float", 212 + "description": "Python requests accepts timeout as either a single float (applies to both connect and read) or a tuple (connect_timeout, read_timeout). The OCaml library has separate fields in the Timeout record but the API requires constructing the full record rather than accepting shorthand formats.", 213 + "affected_files": [ 214 + "lib/timeout.mli", 215 + "lib/timeout.ml" 216 + ], 217 + "rationale": "Python requests' tuple timeout format is convenient: timeout=5.0 applies to both, timeout=(3.0, 10.0) sets different values. The OCaml library could add a helper that accepts either float or (float * float) for ergonomics. This is a common pattern where connect timeout should be shorter than read timeout." 218 + }, 219 + { 220 + "source_repo": "third_party/python/requests", 221 + "source_language": "Python", 222 + "criticality": "low", 223 + "change_type": "enhancement", 224 + "title": "Add preferred_clock selection based on platform for accurate timing", 225 + "description": "Python requests (sessions.py:54-58) selects time.perf_counter on Windows and time.time on Unix for most accurate elapsed time measurements. This ensures consistent, high-resolution timing across platforms. The OCaml library uses Unix.gettimeofday which may not be monotonic.", 226 + "affected_files": [ 227 + "lib/response.ml", 228 + "lib/requests.ml" 229 + ], 230 + "rationale": "Elapsed time measurement should use monotonic clocks to avoid issues with clock adjustments. Python requests carefully selects the best clock per platform. OCaml's Eio.Time should provide monotonic time - the library should use Eio.Time.now for elapsed measurements instead of Unix.gettimeofday to ensure accuracy and consistency with Eio's concurrency model." 231 + }, 232 + { 233 + "source_repo": "third_party/python/requests", 234 + "source_language": "Python", 235 + "criticality": "low", 236 + "change_type": "feature", 237 + "title": "Add response.links parsing for HTTP Link headers", 238 + "description": "Python requests parses Link headers (RFC 5988) into a dictionary of relations. This is commonly used for pagination in REST APIs (GitHub, GitLab, etc.) with rel='next', rel='prev', etc. The OCaml library doesn't parse Link headers.", 239 + "affected_files": [ 240 + "lib/response.mli", 241 + "lib/response.ml" 242 + ], 243 + "rationale": "Link headers are standard for pagination in modern REST APIs. Python requests' response.links provides parsed link relations automatically. Adding this convenience method would make pagination easier. Implementation could use the existing Headers module and parse the Link header format per RFC 5988." 244 + }, 245 + { 246 + "source_repo": "third_party/python/requests", 247 + "source_language": "Python", 248 + "criticality": "medium", 249 + "change_type": "enhancement", 250 + "title": "Add response encoding detection and automatic charset handling", 251 + "description": "Python requests uses charset_normalizer/chardet to detect response encoding when not specified in Content-Type, and provides response.text that handles encoding automatically. The OCaml library's Response.text returns raw bytes as string without encoding handling.", 252 + "affected_files": [ 253 + "lib/response.mli", 254 + "lib/response.ml" 255 + ], 256 + "rationale": "Text encoding is a common source of bugs. Python requests automatically detects encoding via Content-Type charset parameter, or uses charset_normalizer to detect it. The OCaml library could leverage libraries like uutf or ocaml-encoding to handle charset detection and conversion, ensuring Response.text always returns properly decoded UTF-8 strings." 257 + }, 258 + { 259 + "source_repo": "third_party/python/requests", 260 + "source_language": "Python", 261 + "criticality": "low", 262 + "change_type": "enhancement", 263 + "title": "Add context manager support (or enhance Eio switch documentation) for resource cleanup", 264 + "description": "Python requests Session supports context managers (with Session() as s:) for automatic cleanup. The OCaml library uses Eio switches which provide similar functionality but this pattern should be prominently documented and potentially wrapped in a more intuitive API.", 265 + "affected_files": [ 266 + "lib/requests.mli", 267 + "README.md" 268 + ], 269 + "rationale": "Python requests' context manager pattern is very clear: 'with requests.Session() as s:' ensures cleanup. The OCaml library relies on Eio switches which work similarly but may not be obvious to new users. Adding documentation emphasizing the Switch.run pattern and potentially adding helper functions would improve API clarity. The current API is correct but could be more discoverable." 270 + } 271 + ] 272 + }
+275
third_party/python/uplink.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/python/uplink", 5 + "source_language": "Python", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add Request/Response Hook System for Middleware Support", 9 + "description": "Implement a comprehensive hook system that allows users to intercept and modify requests before sending and responses after receiving. Uplink provides TransactionHook with audit_request(), handle_response(), and handle_exception() methods that can be chained together. This enables logging, authentication refresh, metrics collection, request validation, and response transformation without modifying core library code.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/requests.mli", 13 + "lib/one.ml", 14 + "lib/one.mli" 15 + ], 16 + "rationale": "The OCaml library currently lacks a middleware/hook system for request/response interception. Users cannot easily add cross-cutting concerns like logging, metrics, or custom authentication flows. Uplink's hook system provides a clean, composable way to extend functionality. This would enable users to: (1) Implement custom logging without forking the library, (2) Add distributed tracing headers automatically, (3) Refresh expired tokens on 401 responses, (4) Transform responses (e.g., auto-parse JSON), (5) Add custom validation. Implementation would involve adding a new hooks.ml module with types for request_hook, response_hook, and exception_hook, then threading these through the request execution pipeline." 17 + }, 18 + { 19 + "source_repo": "third_party/python/uplink", 20 + "source_language": "Python", 21 + "criticality": "high", 22 + "change_type": "feature", 23 + "title": "Add Rate Limiting Support to Prevent Client-Side Abuse", 24 + "description": "Implement a rate limiting decorator/configuration that enforces client-side request rate limits. Uplink provides @ratelimit(calls=N, period=seconds) that tracks request counts per time window and automatically delays requests to stay within limits. This prevents accidental DoS of APIs and respects rate limit policies proactively.", 25 + "affected_files": [ 26 + "lib/ratelimit.ml", 27 + "lib/ratelimit.mli", 28 + "lib/requests.ml", 29 + "lib/requests.mli" 30 + ], 31 + "rationale": "The OCaml library has no client-side rate limiting mechanism. This means users can accidentally overwhelm APIs or exceed rate limits, leading to 429 responses and potential IP bans. Uplink's rate limiter uses a sliding window algorithm to enforce limits before requests are sent. Implementation would involve: (1) Creating a new ratelimit.ml module with a token bucket or sliding window implementation, (2) Adding rate limit configuration to Session.t, (3) Checking rate limits before executing requests in the request pipeline, (4) Using Eio.Time.sleep to delay requests when limits are reached. This is especially important for production applications that need predictable API usage patterns." 32 + }, 33 + { 34 + "source_repo": "third_party/python/uplink", 35 + "source_language": "Python", 36 + "criticality": "medium", 37 + "change_type": "enhancement", 38 + "title": "Enhance Retry Backoff with Full Jitter Strategy", 39 + "description": "Add full jitter backoff strategy to retry logic as recommended by AWS best practices. Uplink implements backoff.jittered() which uses random(0, min(cap, base * 2^attempt)) instead of the current implementation's random jitter added to exponential backoff. Full jitter reduces thundering herd problems when multiple clients retry simultaneously.", 40 + "affected_files": [ 41 + "lib/retry.ml", 42 + "lib/retry.mli" 43 + ], 44 + "rationale": "The OCaml library currently implements exponential backoff with additive jitter: base_delay = backoff_factor * 2^attempt, then adds random(0, base_delay). However, AWS research shows that full jitter (random between 0 and the exponential value) provides better performance under high contention. Uplink implements this as backoff.jittered() which generates random(0, 2^n) capped at maximum. This reduces retry collisions when many clients experience failures simultaneously. The change would be minimal in retry.ml - just change the jitter calculation from additive to full jitter: let delay = if jitter then Random.float (min backoff_max base_delay) else base_delay." 45 + }, 46 + { 47 + "source_repo": "third_party/python/uplink", 48 + "source_language": "Python", 49 + "criticality": "medium", 50 + "change_type": "enhancement", 51 + "title": "Add Predicate-Based Retry Conditions for Fine-Grained Control", 52 + "description": "Extend retry configuration to support custom predicates that determine whether to retry based on response content, headers, or exception details. Uplink provides retry.when.raises(ExceptionType) and retry.when.status(*codes) predicates that can be combined with | operator. Current OCaml implementation only supports status code lists.", 53 + "affected_files": [ 54 + "lib/retry.ml", 55 + "lib/retry.mli" 56 + ], 57 + "rationale": "The OCaml library's retry logic is limited to status_forcelist (specific status codes). Users cannot retry based on: (1) Specific exception types (e.g., only retry ConnectionError, not AuthenticationError), (2) Response content (e.g., retry if body contains 'rate limit exceeded'), (3) Response headers (e.g., retry if X-RateLimit-Remaining is 0), (4) Custom business logic. Uplink's predicate system is composable and extensible. Implementation would involve: (1) Adding a retry_predicate type: type retry_predicate = Request.t -> Response.t option -> Error.t option -> bool, (2) Adding combinators: val (||) : retry_predicate -> retry_predicate -> retry_predicate, (3) Providing built-in predicates: val on_status : int list -> retry_predicate, val on_exception : Error.t -> retry_predicate, (4) Using predicates in should_retry function instead of just checking status codes." 58 + }, 59 + { 60 + "source_repo": "third_party/python/uplink", 61 + "source_language": "Python", 62 + "criticality": "medium", 63 + "change_type": "feature", 64 + "title": "Add Proxy Authentication Support (Proxy-Authorization Header)", 65 + "description": "Implement ProxyAuth class similar to Uplink's uplink.auth.ProxyAuth that sets the Proxy-Authorization header for authenticated proxy connections. Currently the OCaml library has no explicit proxy authentication support.", 66 + "affected_files": [ 67 + "lib/auth.ml", 68 + "lib/auth.mli" 69 + ], 70 + "rationale": "The OCaml library supports HTTP proxies but lacks explicit proxy authentication. Corporate environments often require authenticated proxies. Uplink provides ProxyAuth(username, password) that sets the Proxy-Authorization header with Basic auth encoding. Implementation would be straightforward: (1) Add type proxy_auth = { username: string; password: string } to auth.ml, (2) Add function apply_proxy_auth : proxy_auth -> Headers.t -> Headers.t that adds 'Proxy-Authorization: Basic base64(user:pass)' header, (3) Add proxy_auth field to Session configuration, (4) Apply proxy auth headers in http_client.ml before sending requests through proxies. This is a high-value addition for enterprise users." 71 + }, 72 + { 73 + "source_repo": "third_party/python/uplink", 74 + "source_language": "Python", 75 + "criticality": "medium", 76 + "change_type": "feature", 77 + "title": "Add Multi-Auth Composition for Combining Authentication Methods", 78 + "description": "Implement a MultiAuth combinator that allows applying multiple authentication methods to a single request. Uplink provides MultiAuth(*auth_methods) that applies all auth methods sequentially, enabling scenarios like: (1) Basic auth + API key header, (2) Multiple API keys for different services, (3) Staged authentication workflows.", 79 + "affected_files": [ 80 + "lib/auth.ml", 81 + "lib/auth.mli" 82 + ], 83 + "rationale": "The OCaml library's auth system only supports a single auth method per request. Some APIs require multiple authentication tokens (e.g., API key in header + OAuth token + request signature). Uplink's MultiAuth provides list-like composition: MultiAuth(BasicAuth(u,p), ApiTokenHeader('X-Key', key)). Implementation would involve: (1) Adding type multi_auth = auth list to auth.ml, (2) Creating apply_multi : multi_auth -> Headers.t -> Headers.t that folds over auth methods, (3) Updating Session.t to accept Auth.t | Multi_auth.t. This enables complex auth scenarios without custom header manipulation code in user applications." 84 + }, 85 + { 86 + "source_repo": "third_party/python/uplink", 87 + "source_language": "Python", 88 + "criticality": "medium", 89 + "change_type": "feature", 90 + "title": "Add API Token Query Parameter Authentication", 91 + "description": "Implement query parameter-based authentication similar to Uplink's ApiTokenParam(param_name, token). Some APIs (especially webhooks and legacy systems) require authentication via query parameters instead of headers.", 92 + "affected_files": [ 93 + "lib/auth.ml", 94 + "lib/auth.mli" 95 + ], 96 + "rationale": "The OCaml library only supports header-based authentication (Basic, Bearer, Digest). Some APIs use query parameter authentication (e.g., ?api_key=xxx or ?access_token=yyy). Uplink provides ApiTokenParam('api_key', token) that adds the token to the query string. Implementation would involve: (1) Adding type query_param_auth = { param_name: string; token: string } to auth.ml, (2) Modifying the auth application logic to support both header and query param injection, (3) Adding Uri manipulation to append auth query parameters. While less secure than header-based auth (query params are logged), it's necessary for compatibility with certain APIs." 97 + }, 98 + { 99 + "source_repo": "third_party/python/uplink", 100 + "source_language": "Python", 101 + "criticality": "low", 102 + "change_type": "enhancement", 103 + "title": "Add Named Exception Variants for Better Error Handling", 104 + "description": "Expose exception types as a named module or record accessible from the session object, similar to Uplink's client.exceptions property. This allows users to catch specific exceptions without importing Error module: try session.get(...) with session.exceptions.timeout -> ...", 105 + "affected_files": [ 106 + "lib/requests.ml", 107 + "lib/requests.mli", 108 + "lib/error.ml", 109 + "lib/error.mli" 110 + ], 111 + "rationale": "The OCaml library requires users to import the Error module to catch specific exceptions: open Requests.Error; try ... with Timeout -> ... Uplink provides a more ergonomic approach via client.exceptions that exposes all exception types as properties. In OCaml, this could be implemented as a module within the Session: module Exceptions = struct exception Timeout = Error.Timeout exception ConnectionError = Error.ConnectionError ... end. This improves discoverability and reduces import boilerplate. Users could then write: try session.get url with session.Exceptions.Timeout -> .... Implementation would involve adding an Exceptions module to requests.mli that re-exports all Error exceptions." 112 + }, 113 + { 114 + "source_repo": "third_party/python/uplink", 115 + "source_language": "Python", 116 + "criticality": "medium", 117 + "change_type": "enhancement", 118 + "title": "Add Per-Request Timeout Override Support", 119 + "description": "Allow timeout overrides on a per-request basis, not just at session level. Uplink supports @timeout decorator and timeout: Timeout parameter for individual requests. Currently OCaml library requires creating new sessions or modifying session config for different timeouts.", 120 + "affected_files": [ 121 + "lib/requests.ml", 122 + "lib/requests.mli", 123 + "lib/one.ml", 124 + "lib/one.mli", 125 + "lib/http_client.ml" 126 + ], 127 + "rationale": "The OCaml library sets timeouts at session creation via ?timeout parameter, but doesn't support per-request timeout overrides. Different endpoints often have different performance characteristics - a file download might need 5 minutes while a health check needs 5 seconds. Uplink allows per-method timeout configuration. Implementation would involve: (1) Adding optional ?timeout parameter to all request methods (get, post, etc.), (2) Threading timeout through to http_client.ml's send_request function, (3) Using the per-request timeout if provided, falling back to session timeout otherwise. This is especially important for applications that interact with multiple endpoints with varying latencies." 128 + }, 129 + { 130 + "source_repo": "third_party/python/uplink", 131 + "source_language": "Python", 132 + "criticality": "low", 133 + "change_type": "enhancement", 134 + "title": "Add Response Content-Type Validation Helper", 135 + "description": "Add utility functions to validate response Content-Type headers before parsing, preventing MIME-type confusion attacks. Uplink commonly uses response handlers to validate content-type matches expected format (e.g., application/json before calling response.json()).", 136 + "affected_files": [ 137 + "lib/response.ml", 138 + "lib/response.mli" 139 + ], 140 + "rationale": "The OCaml library's Response.json function doesn't validate Content-Type header before parsing. This can lead to MIME-type confusion where an attacker returns text/html with JSON payload, potentially causing security issues or confusing error messages. Uplink's response handlers commonly check content-type. Implementation would involve: (1) Adding Response.validate_content_type : t -> string list -> (unit, string) result that checks if response Content-Type matches one of the expected types, (2) Optionally enabling strict mode that raises exception on mismatch, (3) Adding Response.json_strict that validates application/json content-type before parsing. This improves security and error handling clarity." 141 + }, 142 + { 143 + "source_repo": "third_party/python/uplink", 144 + "source_language": "Python", 145 + "criticality": "low", 146 + "change_type": "enhancement", 147 + "title": "Add Request Context Dictionary for Middleware Communication", 148 + "description": "Add a mutable context dictionary to requests that flows through the entire request lifecycle, allowing hooks/middleware to share state. Uplink provides session.context and Context annotation for passing arbitrary data through the request pipeline.", 149 + "affected_files": [ 150 + "lib/requests.ml", 151 + "lib/requests.mli" 152 + ], 153 + "rationale": "When implementing the hook system (recommendation #1), there needs to be a way for hooks to communicate with each other and pass metadata through the request lifecycle. Uplink's context dictionary enables: (1) Request ID generation in audit hook, used in response handler for logging, (2) Tracing spans that need to be closed after response, (3) Custom metadata for business logic. Implementation would involve: (1) Adding context: (string, string) Hashtbl.t field to Session.t, (2) Adding get_context, set_context methods, (3) Passing context reference through request execution. In OCaml, this could be typed more safely using a heterogeneous map or GADT-based key-value store." 154 + }, 155 + { 156 + "source_repo": "third_party/python/uplink", 157 + "source_language": "Python", 158 + "criticality": "low", 159 + "change_type": "enhancement", 160 + "title": "Add Connection Timeout Separate from Read Timeout", 161 + "description": "Split timeout configuration into separate connect_timeout and read_timeout settings as Uplink does. Currently OCaml library has ?connect and ?read in Timeout.create but may not be using both granularly in all HTTP clients.", 162 + "affected_files": [ 163 + "lib/timeout.ml", 164 + "lib/timeout.mli", 165 + "lib/http_client.ml" 166 + ], 167 + "rationale": "The OCaml library's Timeout module has connect and read fields, but it's important to verify they are applied separately throughout the HTTP client code. Uplink clearly separates these concerns because connection timeouts (DNS, TCP handshake, TLS handshake) have different characteristics than read timeouts (waiting for response data). Connection timeouts should be short (5-10s) while read timeouts for large downloads should be longer. Review http_client.ml to ensure: (1) Connect timeout only applies to Eio.Net.connect and TLS handshake, (2) Read timeout applies to subsequent read operations, (3) Both can be configured independently. If already implemented correctly, this is documentation enhancement; otherwise it's a bug fix." 168 + }, 169 + { 170 + "source_repo": "third_party/python/uplink", 171 + "source_language": "Python", 172 + "criticality": "high", 173 + "change_type": "security", 174 + "title": "Add Certificate Pinning Support for Enhanced Security", 175 + "description": "Add support for certificate pinning to prevent man-in-the-middle attacks even with compromised CAs. While neither library currently implements this, Uplink's architecture with custom client sessions makes it easy to add. This would allow users to specify expected certificate fingerprints or public keys.", 176 + "affected_files": [ 177 + "lib/requests.ml", 178 + "lib/requests.mli" 179 + ], 180 + "rationale": "The OCaml library relies on CA certificate validation via ca-certs and tls libraries, but doesn't support certificate pinning. For high-security applications, certificate pinning ensures only specific certificates are trusted, preventing attacks even if a CA is compromised. Implementation would involve: (1) Adding ?pin_certificates:(string list) option to Session configuration (SHA256 fingerprints or PEM public keys), (2) Adding validation callback in TLS config that checks peer certificate against pinned values, (3) Raising SSLError if pin validation fails. This is especially important for mobile/IoT applications connecting to known backend servers. The tls library supports custom certificate validation callbacks." 181 + }, 182 + { 183 + "source_repo": "third_party/python/uplink", 184 + "source_language": "Python", 185 + "criticality": "medium", 186 + "change_type": "feature", 187 + "title": "Add Async Iterator Support for Streaming Large Responses", 188 + "description": "Add iterator/stream interface for processing large responses incrementally. Uplink supports async iteration over response chunks. OCaml library has Response.body_stream but could benefit from a more ergonomic iterator pattern using Eio.Stream.", 189 + "affected_files": [ 190 + "lib/response.ml", 191 + "lib/response.mli" 192 + ], 193 + "rationale": "The OCaml library has Response.body_stream : t -> string Eio.Flow.source which returns a flow source, but lacks higher-level abstractions for common streaming patterns. Uplink's async iterator allows: for chunk in response: process(chunk). In OCaml with Eio, this could be implemented as: (1) Response.iter_chunks : ?chunk_size:int -> t -> (string -> unit) -> unit that reads chunks and applies function, (2) Response.to_stream : t -> string Eio.Stream.t for use with Eio.Stream combinators, (3) Response.fold_chunks : ('a -> string -> 'a) -> 'a -> t -> 'a for functional folding over chunks. This would make common patterns like streaming to file, computing hashes, or processing line-by-line much more ergonomic." 194 + }, 195 + { 196 + "source_repo": "third_party/python/uplink", 197 + "source_language": "Python", 198 + "criticality": "low", 199 + "change_type": "enhancement", 200 + "title": "Add Request Builder Pattern for Complex Request Construction", 201 + "description": "Add a fluent builder API for constructing complex requests incrementally. Uplink's RequestBuilder allows step-by-step request construction with method chaining. This would complement the existing functional API.", 202 + "affected_files": [ 203 + "lib/requests.ml", 204 + "lib/requests.mli" 205 + ], 206 + "rationale": "The OCaml library uses functional parameters for request construction: session.get ~headers:h ~params:p ~auth:a url. For complex requests with many optional parameters, this can become unwieldy. Uplink's RequestBuilder uses method chaining. In OCaml, this could be implemented as: type request_builder; val build : method_ -> string -> request_builder; val with_headers : Headers.t -> request_builder -> request_builder; val with_params : (string * string) list -> request_builder -> request_builder; val execute : Session.t -> request_builder -> Response.t. Example usage: build GET url |> with_headers headers |> with_params params |> with_auth auth |> execute session. This provides better ergonomics for complex requests and is more discoverable via IDE autocomplete." 207 + }, 208 + { 209 + "source_repo": "third_party/python/uplink", 210 + "source_language": "Python", 211 + "criticality": "medium", 212 + "change_type": "enhancement", 213 + "title": "Add Structured Logging with Request/Response Metadata", 214 + "description": "Enhance logging to include structured metadata (request ID, method, URL, status, duration) that can be consumed by log aggregation systems. Uplink's hook system makes it easy to add instrumentation hooks that log structured data.", 215 + "affected_files": [ 216 + "lib/requests.ml", 217 + "lib/http_client.ml" 218 + ], 219 + "rationale": "The OCaml library uses the Logs library but logging is primarily debug-level unstructured text. Modern observability practices require structured logging with metadata. Uplink's hook system enables adding instrumentation hooks that log: request_id, method, url, status_code, duration_ms, bytes_sent, bytes_received. Implementation would involve: (1) Generating unique request IDs (via Uuidm), (2) Recording request start time, (3) Computing duration after response, (4) Logging structured data using Logs tags: Logs.info (fun m -> m ~tags:Logs.Tag.(empty |> add request_id id |> add status_code code) 'Request completed'), (5) Making this configurable via session options. This is essential for production debugging and performance monitoring." 220 + }, 221 + { 222 + "source_repo": "third_party/python/uplink", 223 + "source_language": "Python", 224 + "criticality": "low", 225 + "change_type": "enhancement", 226 + "title": "Add Session Clone Method for Derived Configurations", 227 + "description": "Add a session cloning/derivation method that creates a new session with modified configuration while sharing the connection pool. Uplink's session can be modified dynamically, OCaml's immutable approach could use cloning with shared resources.", 228 + "affected_files": [ 229 + "lib/requests.ml", 230 + "lib/requests.mli" 231 + ], 232 + "rationale": "The OCaml library uses record update syntax for session modification: { session with auth = new_auth }, but this creates a completely new session without sharing the connection pool. For performance, it's better to share connection pools when creating derived sessions. Implementation would involve: (1) Making the connection pool a shared reference (ref or atomic) in Session.t, (2) Adding Session.clone : ?auth:Auth.t -> ?headers:Headers.t -> ... -> t -> t that creates a new session with modified config but same pool reference, (3) Documenting when to use clone vs create. This allows efficient multi-tenant scenarios where different auth credentials need separate sessions but should share connection limits." 233 + }, 234 + { 235 + "source_repo": "third_party/python/uplink", 236 + "source_language": "Python", 237 + "criticality": "medium", 238 + "change_type": "feature", 239 + "title": "Add GraphQL Query Support Helper", 240 + "description": "Add convenience methods for GraphQL queries since many modern APIs use GraphQL. While not in base Uplink, the extensibility pattern suggests helpers for common API patterns. Add graphql method that handles query/variables/operationName structure.", 241 + "affected_files": [ 242 + "lib/requests.ml", 243 + "lib/requests.mli" 244 + ], 245 + "rationale": "Many modern APIs use GraphQL instead of REST. Users currently have to manually construct JSON bodies with query/variables fields. Adding a convenience method would improve ergonomics: Session.graphql : t -> ?variables:(string * Jsont.json) list -> ?operation_name:string -> string -> Response.t. Implementation: (1) Create JSON body with {query, variables, operationName} structure, (2) Set Content-Type: application/json, (3) POST to endpoint, (4) Add Response.graphql_data : t -> Jsont.json that extracts 'data' field and validates no 'errors' field. This is a common enough pattern that built-in support adds significant value." 246 + }, 247 + { 248 + "source_repo": "third_party/python/uplink", 249 + "source_language": "Python", 250 + "criticality": "low", 251 + "change_type": "enhancement", 252 + "title": "Add Retry Budget to Prevent Retry Storms", 253 + "description": "Implement a retry budget system that limits the total percentage of requests that can be retried across all concurrent requests. This prevents cascading failures where retries overwhelm downstream services. Uplink doesn't have this but it's a best practice from Google SRE.", 254 + "affected_files": [ 255 + "lib/retry.ml", 256 + "lib/retry.mli" 257 + ], 258 + "rationale": "The OCaml library's retry mechanism has no global budget control. If a backend service degrades, all clients may retry simultaneously, creating a retry storm that worsens the problem. A retry budget (e.g., allow only 10% of requests to be retries) prevents this. Implementation: (1) Add shared atomic counter tracking retry_count and total_requests, (2) Calculate ratio = retry_count / total_requests, (3) If ratio > budget threshold, disable retries temporarily, (4) Make budget configurable: type retry_budget = { max_percentage: float; window_size: int }. This is critical for production resilience. The mechanism should use Eio.Mutex or atomic operations to track the budget safely across concurrent requests." 259 + }, 260 + { 261 + "source_repo": "third_party/python/uplink", 262 + "source_language": "Python", 263 + "criticality": "medium", 264 + "change_type": "enhancement", 265 + "title": "Add Circuit Breaker Pattern for Fault Tolerance", 266 + "description": "Implement circuit breaker pattern that stops sending requests to failing services temporarily. After N consecutive failures, enter 'open' state for a timeout period, then 'half-open' to test recovery. Uplink doesn't have this but it's a critical production pattern.", 267 + "affected_files": [ 268 + "lib/circuit_breaker.ml", 269 + "lib/circuit_breaker.mli", 270 + "lib/requests.ml" 271 + ], 272 + "rationale": "The OCaml library's retry mechanism continues retrying indefinitely (up to max_retries per request) even when a backend is completely down. A circuit breaker prevents wasting resources on doomed requests. Implementation: (1) Create circuit_breaker.ml with states: type state = Closed | Open of { opened_at: float } | HalfOpen, (2) Track failure/success counts per endpoint (use Uri.host as key), (3) After threshold failures, open circuit and fail fast for timeout period, (4) After timeout, enter half-open and allow one test request, (5) Success -> close circuit, failure -> reopen. Config: type t = { failure_threshold: int; timeout: float; half_open_max_calls: int }. This is essential for preventing cascading failures in microservice architectures." 273 + } 274 + ] 275 + }
+329
third_party/python/urllib3.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "urllib3", 5 + "source_language": "Python", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add SecurityWarning types for TLS degradation", 9 + "description": "urllib3 has specific SecurityWarning exceptions (InsecureRequestWarning, SystemTimeWarning, NotOpenSSLWarning) to warn users about security-reducing actions. The OCaml library currently only has SSLError without graduated warnings for different security concerns.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/error.mli" 13 + ], 14 + "rationale": "Security warnings help users identify when they are making insecure decisions (e.g., disabling TLS verification) without breaking their code. This enables better security hygiene by making degraded security states visible. urllib3's approach of differentiating between errors (which halt execution) and warnings (which alert but continue) provides better user experience." 15 + }, 16 + { 17 + "source_repo": "urllib3", 18 + "source_language": "Python", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Add retry counter differentiation by error type", 22 + "description": "urllib3 tracks separate retry counters for connect errors, read errors, status errors, and other errors, allowing fine-grained control. The OCaml library only has a single max_retries counter.", 23 + "affected_files": [ 24 + "lib/retry.ml", 25 + "lib/retry.mli" 26 + ], 27 + "rationale": "Different error types have different retry characteristics. Connection errors (pre-request) are safer to retry than read errors (post-request). urllib3's approach allows users to set connect=5, read=2, status=3 to reflect that connection errors are idempotent while read errors might have side effects. This provides better control over retry behavior based on request safety." 28 + }, 29 + { 30 + "source_repo": "urllib3", 31 + "source_language": "Python", 32 + "criticality": "medium", 33 + "change_type": "feature", 34 + "title": "Implement request history tracking in retry logic", 35 + "description": "urllib3 maintains a history tuple of RequestHistory(method, url, error, status, redirect_location) for each retry attempt. This allows inspection of what went wrong and how many attempts were made.", 36 + "affected_files": [ 37 + "lib/retry.ml", 38 + "lib/retry.mli", 39 + "lib/response.ml", 40 + "lib/response.mli" 41 + ], 42 + "rationale": "Request history provides valuable debugging information and transparency into retry behavior. Users can inspect why requests failed and how many attempts were needed. This is particularly useful for diagnosing intermittent issues and tuning retry parameters. The history should be accessible through the response or as metadata." 43 + }, 44 + { 45 + "source_repo": "urllib3", 46 + "source_language": "Python", 47 + "criticality": "high", 48 + "change_type": "bug", 49 + "title": "Fix timeout calculation to account for time already spent", 50 + "description": "urllib3's Timeout class has start_connect() and get_connect_duration() methods to track elapsed time and adjust read_timeout based on time consumed during connection. The read_timeout is calculated as min(total - connect_duration, read). The OCaml library doesn't appear to subtract connection time from total timeout.", 51 + "affected_files": [ 52 + "lib/timeout.ml", 53 + "lib/timeout.mli", 54 + "lib/http_client.ml" 55 + ], 56 + "rationale": "When a total timeout is specified, the connection time should be subtracted from available time for reading the response. Otherwise, a slow connection could consume the entire timeout budget before any data is read. This is a correctness issue that could cause unexpected timeout behavior." 57 + }, 58 + { 59 + "source_repo": "urllib3", 60 + "source_language": "Python", 61 + "criticality": "medium", 62 + "change_type": "enhancement", 63 + "title": "Add backoff_jitter as separate configuration from jitter boolean", 64 + "description": "urllib3 has both backoff_factor (multiplier) and backoff_jitter (random amount added, default 0.0) as separate parameters. The OCaml library has a boolean jitter flag that doubles the random range.", 65 + "affected_files": [ 66 + "lib/retry.ml", 67 + "lib/retry.mli" 68 + ], 69 + "rationale": "Configurable jitter amount provides more control over retry timing. urllib3's approach allows users to set exact jitter ranges (e.g., backoff_jitter=1.0 adds 0-1 seconds of randomness) rather than a binary choice. The current OCaml implementation adds random.float(base_delay) which could add significant variance for large backoffs." 70 + }, 71 + { 72 + "source_repo": "urllib3", 73 + "source_language": "Python", 74 + "criticality": "medium", 75 + "change_type": "feature", 76 + "title": "Add remove_headers_on_redirect configuration", 77 + "description": "urllib3 has a remove_headers_on_redirect parameter (default: Cookie, Authorization, Proxy-Authorization) that strips sensitive headers when redirecting to different hosts. This prevents credential leakage across domains.", 78 + "affected_files": [ 79 + "lib/requests.ml", 80 + "lib/requests.mli", 81 + "lib/one.ml" 82 + ], 83 + "rationale": "Security best practice requires removing authentication headers when redirecting to different domains to prevent credential leakage. urllib3 makes this configurable with safe defaults. This is a security enhancement that prevents accidentally sending credentials to third-party domains during redirects." 84 + }, 85 + { 86 + "source_repo": "urllib3", 87 + "source_language": "Python", 88 + "criticality": "high", 89 + "change_type": "security", 90 + "title": "Add connection pool security: assert_hostname and assert_fingerprint", 91 + "description": "urllib3 supports assert_hostname and assert_fingerprint parameters for connection pools to verify server identity beyond standard TLS verification. These provide defense-in-depth for sensitive connections.", 92 + "affected_files": [ 93 + "lib/requests.ml", 94 + "lib/requests.mli", 95 + "lib/one.ml", 96 + "lib/one.mli" 97 + ], 98 + "rationale": "Certificate pinning (assert_fingerprint) and hostname assertion provide additional security layers for high-security use cases. This is particularly important for applications that need to ensure they're connecting to specific servers (e.g., financial services, healthcare). These features enable defense-in-depth security strategies." 99 + }, 100 + { 101 + "source_repo": "urllib3", 102 + "source_language": "Python", 103 + "criticality": "low", 104 + "change_type": "enhancement", 105 + "title": "Add IncompleteRead exception for partial response errors", 106 + "description": "urllib3 has specific IncompleteRead exception that includes partial bytes read and expected bytes, helping diagnose truncated responses. The OCaml library uses generic ConnectionError.", 107 + "affected_files": [ 108 + "lib/error.ml", 109 + "lib/error.mli" 110 + ], 111 + "rationale": "Specific error types help with debugging. When a response is truncated, knowing how many bytes were received vs expected helps diagnose network issues, server problems, or timeout tuning. This improves observability and debugging capabilities." 112 + }, 113 + { 114 + "source_repo": "urllib3", 115 + "source_language": "Python", 116 + "criticality": "medium", 117 + "change_type": "enhancement", 118 + "title": "Add InvalidChunkLength exception for chunk encoding errors", 119 + "description": "urllib3 has InvalidChunkLength exception specifically for chunked transfer encoding errors, including the invalid length value received. This helps debug protocol issues.", 120 + "affected_files": [ 121 + "lib/error.ml", 122 + "lib/error.mli" 123 + ], 124 + "rationale": "Chunked transfer encoding errors are common with misbehaving servers. Having a specific exception type with diagnostic information (invalid length, bytes read, expected remaining) helps users identify server-side issues vs. client-side issues." 125 + }, 126 + { 127 + "source_repo": "urllib3", 128 + "source_language": "Python", 129 + "criticality": "medium", 130 + "change_type": "feature", 131 + "title": "Implement .netrc authentication support", 132 + "description": "urllib3 supports reading credentials from .netrc files for automatic authentication. The OCaml library has TODOs noting this feature is not implemented.", 133 + "affected_files": [ 134 + "lib/auth.ml", 135 + "lib/auth.mli", 136 + "lib/requests.ml", 137 + "lib/one.ml" 138 + ], 139 + "rationale": "The code already has TODO comments for .netrc support in both requests.ml and one.ml. This is a standard Unix convention for storing credentials that many HTTP clients support. Implementing this would improve usability and align with user expectations from other HTTP clients." 140 + }, 141 + { 142 + "source_repo": "urllib3", 143 + "source_language": "Python", 144 + "criticality": "low", 145 + "change_type": "enhancement", 146 + "title": "Add UnrewindableBodyError for retry body repositioning failures", 147 + "description": "urllib3 has UnrewindableBodyError raised when attempting to retry a request but unable to rewind the body stream to its starting position. This is important for retry logic with streaming bodies.", 148 + "affected_files": [ 149 + "lib/error.ml", 150 + "lib/error.mli", 151 + "lib/retry.ml" 152 + ], 153 + "rationale": "When retrying requests with streaming bodies, the stream must be repositioned to the beginning. If the stream isn't seekable, the retry cannot proceed. A specific error type helps users understand why retry failed and how to fix it (e.g., by buffering the body first)." 154 + }, 155 + { 156 + "source_repo": "urllib3", 157 + "source_language": "Python", 158 + "criticality": "medium", 159 + "change_type": "enhancement", 160 + "title": "Add MaxRetryError with reason chaining", 161 + "description": "urllib3's MaxRetryError exception includes the underlying reason (the last exception encountered) and displays it in the error message. The OCaml library doesn't chain the underlying errors in retry failures.", 162 + "affected_files": [ 163 + "lib/error.ml", 164 + "lib/error.mli", 165 + "lib/retry.ml" 166 + ], 167 + "rationale": "When retries are exhausted, users need to know what the underlying failure was. urllib3's MaxRetryError includes the original exception as .reason, providing context about why retries failed. This improves debuggability by preserving the error chain." 168 + }, 169 + { 170 + "source_repo": "urllib3", 171 + "source_language": "Python", 172 + "criticality": "low", 173 + "change_type": "enhancement", 174 + "title": "Add connection pool state exceptions (EmptyPoolError, FullPoolError, ClosedPoolError)", 175 + "description": "urllib3 has specific exceptions for connection pool states: EmptyPoolError (no connections available), FullPoolError (pool full in blocking mode), ClosedPoolError (pool closed). These help diagnose resource exhaustion.", 176 + "affected_files": [ 177 + "lib/error.ml", 178 + "lib/error.mli" 179 + ], 180 + "rationale": "Connection pool errors help users identify resource exhaustion and configuration issues. Differentiating between 'no connections available' vs 'pool is closed' vs 'pool is full' helps with debugging and monitoring. These exceptions can guide users to appropriate fixes (increase pool size, check for connection leaks, etc.)." 181 + }, 182 + { 183 + "source_repo": "urllib3", 184 + "source_language": "Python", 185 + "criticality": "high", 186 + "change_type": "enhancement", 187 + "title": "Add Retry-After header parsing with HTTP-date support", 188 + "description": "urllib3's parse_retry_after handles both integer seconds and HTTP-date formats (RFC 7231). The OCaml implementation attempts RFC3339 parsing which may not handle HTTP-date format correctly.", 189 + "affected_files": [ 190 + "lib/retry.ml", 191 + "lib/retry.mli" 192 + ], 193 + "rationale": "HTTP Retry-After headers can be either delay-seconds (integer) or HTTP-date (RFC 7231 format like 'Wed, 21 Oct 2015 07:28:00 GMT'). The current OCaml code uses Ptime.of_rfc3339 which parses ISO8601/RFC3339, not HTTP-date format. This could cause failures to honor Retry-After headers from standards-compliant servers." 194 + }, 195 + { 196 + "source_repo": "urllib3", 197 + "source_language": "Python", 198 + "criticality": "medium", 199 + "change_type": "feature", 200 + "title": "Add raise_on_redirect and raise_on_status configuration", 201 + "description": "urllib3 allows controlling whether to raise exceptions when redirect/retry limits are exceeded (raise_on_redirect, raise_on_status) or return the response. The OCaml library always raises exceptions.", 202 + "affected_files": [ 203 + "lib/retry.ml", 204 + "lib/retry.mli", 205 + "lib/requests.ml" 206 + ], 207 + "rationale": "Some applications want to handle redirect loops or status code retries exhaustion themselves rather than catching exceptions. urllib3's approach allows returning 3xx responses when redirects are exhausted or status code responses when retries are exhausted, giving users more control over error handling." 208 + }, 209 + { 210 + "source_repo": "urllib3", 211 + "source_language": "Python", 212 + "criticality": "low", 213 + "change_type": "enhancement", 214 + "title": "Add consecutive error tracking for backoff calculation", 215 + "description": "urllib3's get_backoff_time only counts consecutive errors (excluding redirects) when calculating backoff. It uses takewhile to find the last consecutive error sequence. The OCaml library counts all attempts.", 216 + "affected_files": [ 217 + "lib/retry.ml" 218 + ], 219 + "rationale": "Backoff should reset after successful redirects since redirects indicate forward progress. urllib3's approach of only counting consecutive non-redirect errors prevents excessive backoff when a request succeeds at intermediate steps. This results in more appropriate retry timing." 220 + }, 221 + { 222 + "source_repo": "urllib3", 223 + "source_language": "Python", 224 + "criticality": "medium", 225 + "change_type": "enhancement", 226 + "title": "Add NameResolutionError separate from ConnectionError", 227 + "description": "urllib3 has NameResolutionError (subclass of NewConnectionError) specifically for DNS resolution failures, including the hostname and reason (socket.gaierror). This helps distinguish DNS issues from connection refusals.", 228 + "affected_files": [ 229 + "lib/error.ml", 230 + "lib/error.mli" 231 + ], 232 + "rationale": "DNS resolution failures have different debugging and resolution steps than connection refusals. A specific error type with hostname information helps users identify DNS configuration issues, typos in URLs, or network connectivity problems. This improves observability for common failure modes." 233 + }, 234 + { 235 + "source_repo": "urllib3", 236 + "source_language": "Python", 237 + "criticality": "low", 238 + "change_type": "feature", 239 + "title": "Add ResponseError for tracking too many error responses", 240 + "description": "urllib3 has ResponseError used as a container for tracking too many error responses with specific status codes. It has GENERIC_ERROR and SPECIFIC_ERROR message templates.", 241 + "affected_files": [ 242 + "lib/error.ml", 243 + "lib/error.mli" 244 + ], 245 + "rationale": "When status code retry limits are exhausted, users benefit from specific error messages indicating which status code was encountered too many times. This helps diagnose server-side issues and tune retry configurations." 246 + }, 247 + { 248 + "source_repo": "urllib3", 249 + "source_language": "Python", 250 + "criticality": "high", 251 + "change_type": "bug", 252 + "title": "Implement proper timeout state tracking and validation", 253 + "description": "urllib3's Timeout class tracks connection start time with start_connect() and validates state transitions (raises TimeoutStateError if start_connect called twice or get_connect_duration called before start_connect). This prevents timing bugs.", 254 + "affected_files": [ 255 + "lib/timeout.ml", 256 + "lib/timeout.mli", 257 + "lib/http_client.ml" 258 + ], 259 + "rationale": "Stateful timeout tracking is essential for accurate total timeout enforcement. Without tracking when connection started, the read timeout cannot be properly adjusted for time already spent. urllib3's validation prevents misuse of the timeout API that could lead to incorrect timeout behavior." 260 + }, 261 + { 262 + "source_repo": "urllib3", 263 + "source_language": "Python", 264 + "criticality": "medium", 265 + "change_type": "enhancement", 266 + "title": "Add comprehensive TLS configuration options", 267 + "description": "urllib3 supports detailed TLS configuration: ssl_minimum_version, ssl_maximum_version, key_password, ca_cert_dir, ca_cert_data (in-memory CA certs), and hostname_checks_common_name. The OCaml library has basic tls_config and verify_tls.", 268 + "affected_files": [ 269 + "lib/requests.ml", 270 + "lib/requests.mli", 271 + "lib/one.ml", 272 + "lib/one.mli" 273 + ], 274 + "rationale": "Production applications need fine-grained TLS control. Minimum/maximum TLS versions prevent downgrade attacks. In-memory CA certificates support environments without filesystem access. Hostname checking options support special cases. These are important for security-conscious applications." 275 + }, 276 + { 277 + "source_repo": "urllib3", 278 + "source_language": "Python", 279 + "criticality": "medium", 280 + "change_type": "feature", 281 + "title": "Add socket_options parameter for low-level socket configuration", 282 + "description": "urllib3 allows passing socket_options for configuring low-level socket behavior (SO_KEEPALIVE, TCP_NODELAY, etc.). This enables performance tuning and special networking requirements.", 283 + "affected_files": [ 284 + "lib/requests.ml", 285 + "lib/requests.mli", 286 + "lib/one.ml" 287 + ], 288 + "rationale": "Advanced users need control over socket options for performance tuning (TCP_NODELAY for latency-sensitive apps) or reliability (SO_KEEPALIVE for long-lived connections). This is particularly important for connection pooling where socket settings affect all pooled connections." 289 + }, 290 + { 291 + "source_repo": "urllib3", 292 + "source_language": "Python", 293 + "criticality": "low", 294 + "change_type": "enhancement", 295 + "title": "Add blocksize parameter for configurable buffer sizes", 296 + "description": "urllib3 allows configuring blocksize for HTTPConnection read operations (default 16KB). This allows performance tuning for different workloads.", 297 + "affected_files": [ 298 + "lib/http_client.ml", 299 + "lib/requests.ml" 300 + ], 301 + "rationale": "Buffer size affects memory usage and performance. Large responses benefit from larger buffers (fewer system calls), while memory-constrained environments need smaller buffers. urllib3 exposes this as a tunable parameter. This enables performance optimization for different deployment scenarios." 302 + }, 303 + { 304 + "source_repo": "urllib3", 305 + "source_language": "Python", 306 + "criticality": "medium", 307 + "change_type": "feature", 308 + "title": "Add HostChangedError for cross-host request detection in pools", 309 + "description": "urllib3 raises HostChangedError when a connection pool receives a request for a different host than it was configured for. This prevents connection reuse bugs.", 310 + "affected_files": [ 311 + "lib/error.ml", 312 + "lib/error.mli" 313 + ], 314 + "rationale": "Connection pools are host-specific. Attempting to use a pool for a different host indicates a bug in pool management or URL handling. A specific error type helps identify these bugs quickly. This is important for connection pooling correctness." 315 + }, 316 + { 317 + "source_repo": "urllib3", 318 + "source_language": "Python", 319 + "criticality": "low", 320 + "change_type": "enhancement", 321 + "title": "Add comprehensive test coverage for edge cases", 322 + "description": "urllib3 has 38 test files covering SSL, timeouts, retries, connection pooling, proxies, and edge cases. The OCaml library has 3 test files focused on basic functionality.", 323 + "affected_files": [ 324 + "test/" 325 + ], 326 + "rationale": "Comprehensive testing improves reliability and prevents regressions. urllib3's extensive test suite covers edge cases like SSL errors, timeout edge cases, retry exhaustion, chunked encoding errors, etc. More tests would improve confidence in the OCaml library's robustness." 327 + } 328 + ] 329 + }
+277
third_party/rust/curl-rust.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/rust/curl-rust", 5 + "source_language": "Rust", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add granular error inspection methods for improved error handling", 9 + "description": "The OCaml library currently uses broad error categories (`Timeout`, `ConnectionError`, `SSLError`, etc.) without fine-grained inspection capabilities. The Rust curl library provides 50+ error inspection methods like `is_couldnt_resolve_host()`, `is_peer_failed_verification()`, `is_ssl_connect_error()`, `is_send_error()`, `is_recv_error()`, allowing developers to distinguish between specific failure modes and implement targeted recovery strategies.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/error.mli" 13 + ], 14 + "rationale": "Developers need to distinguish between different types of connection failures (DNS resolution vs. TCP connection vs. SSL handshake) and SSL errors (certificate verification vs. cipher negotiation vs. protocol version mismatch) to implement appropriate retry logic, fallback mechanisms, and user-facing error messages. Currently, the OCaml library lumps these into broad categories, making it difficult to handle specific scenarios like 'retry on connection refused but not on certificate validation failure'." 15 + }, 16 + { 17 + "source_repo": "third_party/rust/curl-rust", 18 + "source_language": "Rust", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Add error context buffer for detailed error messages", 22 + "description": "The Rust curl library captures additional error context via `CURLOPT_ERRORBUFFER`, storing detailed error descriptions in the `Error.extra` field. This provides human-readable diagnostics beyond generic error codes. The OCaml library's error types should include optional detailed error messages from the underlying libraries (TLS, DNS resolver, etc.).", 23 + "affected_files": [ 24 + "lib/error.ml", 25 + "lib/error.mli", 26 + "lib/http_client.ml" 27 + ], 28 + "rationale": "When SSL handshakes fail or DNS resolution errors occur, generic error types provide minimal debugging information. Capturing and exposing detailed error messages from underlying libraries (Tls-eio, domain-name, etc.) would significantly improve debuggability for developers and reduce support burden. The current `SSLError of string` is a start, but should be consistently applied across all error types and capture more detailed context." 29 + }, 30 + { 31 + "source_repo": "third_party/rust/curl-rust", 32 + "source_language": "Rust", 33 + "criticality": "medium", 34 + "change_type": "feature", 35 + "title": "Implement low-speed timeout limits for stalled transfers", 36 + "description": "The Rust curl library provides `low_speed_limit` (minimum bytes/sec) and `low_speed_time` (duration below threshold) to detect and abort stalled transfers that haven't fully timed out. This is distinct from total timeout and prevents indefinitely slow transfers. The OCaml library only has connect, read, and total timeouts.", 37 + "affected_files": [ 38 + "lib/timeout.ml", 39 + "lib/timeout.mli", 40 + "lib/http_client.ml" 41 + ], 42 + "rationale": "Network transfers can become pathologically slow without fully stalling, causing requests to take minutes or hours while technically making progress. A 30-second read timeout may not trigger if the server sends 1 byte every 29 seconds. Low-speed limits allow detection of this scenario: 'if transfer speed drops below 1000 bytes/sec for more than 10 seconds, abort'. This is particularly important for downloading large files or streaming responses where you want to ensure minimum throughput." 43 + }, 44 + { 45 + "source_repo": "third_party/rust/curl-rust", 46 + "source_language": "Rust", 47 + "criticality": "medium", 48 + "change_type": "feature", 49 + "title": "Add progress callback support for uploads and downloads", 50 + "description": "The Rust curl library provides `progress_function` callback that receives (download_total, download_now, upload_total, upload_now) to monitor transfer progress. This enables progress bars, bandwidth monitoring, and custom timeout logic. The OCaml library has no equivalent mechanism.", 51 + "affected_files": [ 52 + "lib/requests.ml", 53 + "lib/requests.mli", 54 + "lib/one.ml", 55 + "lib/one.mli" 56 + ], 57 + "rationale": "Long-running transfers (large file uploads/downloads) need progress visibility for user experience. Applications want to display progress bars, estimate time remaining, or implement dynamic timeouts based on transfer speed. Without progress callbacks, applications must poll response status or implement custom streaming logic. Progress callbacks are essential for building responsive user interfaces and implementing sophisticated transfer monitoring." 58 + }, 59 + { 60 + "source_repo": "third_party/rust/curl-rust", 61 + "source_language": "Rust", 62 + "criticality": "low", 63 + "change_type": "feature", 64 + "title": "Add DNS over HTTPS (DoH) support", 65 + "description": "The Rust curl library supports DNS over HTTPS via `doh_url()` configuration, allowing DNS queries to be sent over HTTPS to privacy-preserving resolvers like Cloudflare (1.1.1.1) or Google (8.8.8.8). This bypasses traditional DNS which may be monitored, censored, or hijacked. The OCaml library uses system DNS resolution without DoH support.", 66 + "affected_files": [ 67 + "lib/requests.ml", 68 + "lib/requests.mli", 69 + "lib/http_client.ml" 70 + ], 71 + "rationale": "In privacy-sensitive or censorship-prone environments, traditional DNS queries can be monitored or manipulated. DoH provides encrypted DNS resolution, preventing eavesdropping and tampering. This is increasingly important as users demand privacy features. Implementation would involve adding DoH URL configuration and integrating a DoH client library or implementing the protocol. Priority is lower as this requires significant new dependencies and most users can configure system-level DoH." 72 + }, 73 + { 74 + "source_repo": "third_party/rust/curl-rust", 75 + "source_language": "Rust", 76 + "criticality": "low", 77 + "change_type": "feature", 78 + "title": "Support loading SSL certificates from memory blobs", 79 + "description": "The Rust curl library supports loading certificates from memory via `ssl_cert_blob()`, `ssl_key_blob()`, and `ssl_cainfo_blob()`, avoiding filesystem access. This enables embedding certificates in binaries, loading from encrypted storage, or using certificates from key management systems. The OCaml library currently requires certificates to be files.", 80 + "affected_files": [ 81 + "lib/requests.ml", 82 + "lib/requests.mli", 83 + "lib/http_client.ml" 84 + ], 85 + "rationale": "Applications may need to load certificates from non-filesystem sources: embedded in binaries, retrieved from HashiCorp Vault, stored in databases, or generated dynamically. File-based certificate loading is limiting in containerized or serverless environments where filesystem access is restricted. Supporting in-memory certificates increases deployment flexibility. Implementation would require extending the Tls library configuration to accept X.509 structures directly rather than file paths." 86 + }, 87 + { 88 + "source_repo": "third_party/rust/curl-rust", 89 + "source_language": "Rust", 90 + "criticality": "low", 91 + "change_type": "feature", 92 + "title": "Add AWS Signature V4 authentication support", 93 + "description": "The Rust curl library provides native AWS SigV4 authentication via `aws_sigv4()` method, automatically signing requests for AWS services. This eliminates the need for external signing libraries and simplifies AWS API integration. The OCaml library would need to implement SigV4 signing algorithm or provide hooks for custom auth.", 94 + "affected_files": [ 95 + "lib/auth.ml", 96 + "lib/auth.mli" 97 + ], 98 + "rationale": "AWS is the dominant cloud provider and its APIs require Signature V4 authentication. While developers can implement SigV4 signing externally, native support simplifies AWS integration significantly. However, this requires implementing the complex SigV4 algorithm including canonicalization, credential scoping, and HMAC-SHA256 signing. Given the complexity and the existence of `Auth.custom()` for custom authentication, this is lower priority. Developers can use external libraries and apply signatures via custom auth functions." 99 + }, 100 + { 101 + "source_repo": "third_party/rust/curl-rust", 102 + "source_language": "Rust", 103 + "criticality": "medium", 104 + "change_type": "enhancement", 105 + "title": "Add proxy authentication support with separate proxy credentials", 106 + "description": "The Rust curl library provides separate proxy authentication via `proxy_username()`, `proxy_password()`, and `proxy_auth()` methods, distinct from origin server authentication. The OCaml library appears to lack explicit proxy authentication configuration, though proxies may be used through environment variables.", 107 + "affected_files": [ 108 + "lib/requests.ml", 109 + "lib/requests.mli", 110 + "lib/auth.ml", 111 + "lib/auth.mli" 112 + ], 113 + "rationale": "Corporate and enterprise environments commonly require authenticated HTTP proxies. Users need to provide proxy credentials separately from destination server credentials (e.g., authenticate to corporate proxy with Windows credentials, then use Basic auth for the destination API). Without explicit proxy auth support, users must either configure system-wide proxy settings or cannot use authenticated proxies at all. This limits enterprise usability." 114 + }, 115 + { 116 + "source_repo": "third_party/rust/curl-rust", 117 + "source_language": "Rust", 118 + "criticality": "medium", 119 + "change_type": "security", 120 + "title": "Add NTLM and SPNEGO/Negotiate authentication support", 121 + "description": "The Rust curl library supports NTLM, NTLM_WB (WinBind), and GSS-Negotiate (SPNEGO) authentication methods via the `Auth` configuration. These are essential for Windows/Active Directory environments. The OCaml library only supports Basic, Bearer, and Digest authentication.", 122 + "affected_files": [ 123 + "lib/auth.ml", 124 + "lib/auth.mli" 125 + ], 126 + "rationale": "Enterprise Windows environments heavily use NTLM and Kerberos (via SPNEGO) for HTTP authentication, especially with IIS and SharePoint. Without NTLM/SPNEGO support, the library cannot authenticate to many enterprise web services. However, implementing NTLM/SPNEGO is complex (requires SSPI on Windows or Kerberos libraries on Unix). This could be addressed by providing hooks for external authentication libraries or using the `Custom` auth function with third-party NTLM libraries." 127 + }, 128 + { 129 + "source_repo": "third_party/rust/curl-rust", 130 + "source_language": "Rust", 131 + "criticality": "high", 132 + "change_type": "security", 133 + "title": "Implement automatic HTTP auth type negotiation", 134 + "description": "The Rust curl library supports `auth.auto()` which automatically selects the most secure authentication method supported by the server (from Basic, Digest, NTLM, Negotiate). The OCaml library requires explicit auth type selection. Without auto-negotiation, developers may default to Basic auth even when servers support more secure Digest.", 135 + "affected_files": [ 136 + "lib/auth.ml", 137 + "lib/auth.mli", 138 + "lib/http_client.ml" 139 + ], 140 + "rationale": "Developers often default to Basic authentication for simplicity, sending credentials in easily-decoded base64 over potentially insecure connections. If the server supports Digest (challenge-response, no password transmitted), that should be used automatically. Auto-negotiation inspects the WWW-Authenticate header and selects the strongest supported method, improving security without developer intervention. The library already implements Digest; adding auto-selection logic would upgrade security where possible." 141 + }, 142 + { 143 + "source_repo": "third_party/rust/curl-rust", 144 + "source_language": "Rust", 145 + "criticality": "low", 146 + "change_type": "feature", 147 + "title": "Add HTTP/2 and HTTP/3 protocol version selection", 148 + "description": "The Rust curl library provides `HttpVersion` enum allowing selection of HTTP/1.0, HTTP/1.1, HTTP/2, HTTP/2 over TLS, HTTP/2 prior knowledge, HTTP/3, or automatic selection. The OCaml library appears to be HTTP/1.1 only based on the http_client implementation.", 149 + "affected_files": [ 150 + "lib/requests.ml", 151 + "lib/requests.mli", 152 + "lib/http_client.ml" 153 + ], 154 + "rationale": "HTTP/2 provides significant performance benefits (multiplexing, header compression, server push) and is widely deployed. HTTP/3 (QUIC) offers even better performance over lossy networks. However, implementing HTTP/2 requires substantial protocol work (HPACK, stream multiplexing, flow control) and HTTP/3 requires QUIC implementation. This is a major undertaking. As a lower-effort alternative, the library could integrate with existing OCaml HTTP/2 libraries (h2, ocaml-h2) and expose protocol version configuration to users." 155 + }, 156 + { 157 + "source_repo": "third_party/rust/curl-rust", 158 + "source_language": "Rust", 159 + "criticality": "low", 160 + "change_type": "feature", 161 + "title": "Add support for HTTP range requests and resume", 162 + "description": "The Rust curl library provides methods for range requests (partial downloads) and download resumption. The OCaml library does not appear to have explicit range request support, though developers can manually add Range headers.", 163 + "affected_files": [ 164 + "lib/requests.ml", 165 + "lib/requests.mli", 166 + "lib/headers.ml" 167 + ], 168 + "rationale": "Range requests are essential for resuming interrupted downloads, implementing video streaming with seeking, and downloading large files in chunks for parallel processing. While developers can manually add 'Range: bytes=0-1023' headers, providing first-class support with helper methods like `resume_from(offset)` or `range(start, end)` improves usability and correctness (proper handling of 206 Partial Content vs 200 OK responses). This is lower priority as the functionality is achievable through manual header manipulation." 169 + }, 170 + { 171 + "source_repo": "third_party/rust/curl-rust", 172 + "source_language": "Rust", 173 + "criticality": "medium", 174 + "change_type": "enhancement", 175 + "title": "Add configurable SSL/TLS version selection and cipher suite control", 176 + "description": "The Rust curl library provides `ssl_version()` to select minimum TLS version (TLS 1.0/1.1/1.2/1.3) and `ssl_cipher_list()` to specify allowed cipher suites. The OCaml library uses default TLS configuration from the tls-eio library without exposing version or cipher configuration.", 177 + "affected_files": [ 178 + "lib/requests.ml", 179 + "lib/requests.mli" 180 + ], 181 + "rationale": "Security-conscious applications need to enforce minimum TLS versions (e.g., TLS 1.2+ only, disabling obsolete TLS 1.0/1.1) and restrict cipher suites (e.g., AEAD ciphers only, no CBC mode). Compliance requirements (PCI-DSS, HIPAA, FIPS) often mandate specific TLS configurations. While the underlying tls-eio library supports version and cipher configuration, it's not exposed through the requests API. Adding optional `?min_tls_version` and `?cipher_suites` parameters to session creation would enable security hardening." 182 + }, 183 + { 184 + "source_repo": "third_party/rust/curl-rust", 185 + "source_language": "Rust", 186 + "criticality": "medium", 187 + "change_type": "enhancement", 188 + "title": "Add SSL/TLS peer certificate inspection", 189 + "description": "The Rust curl library provides methods to retrieve peer certificate information after connection establishment, enabling certificate pinning, custom validation, and audit logging. The OCaml library does not expose certificate information to applications.", 190 + "affected_files": [ 191 + "lib/response.ml", 192 + "lib/response.mli", 193 + "lib/http_client.ml" 194 + ], 195 + "rationale": "Applications may need to implement certificate pinning (accepting only specific certificates/public keys), log certificate details for security auditing, or perform custom validation beyond standard PKI. Without access to peer certificate information (subject, issuer, public key, validity period), these security enhancements are impossible. The underlying tls-eio connection provides certificate access; exposing it through the response object (e.g., `Response.peer_certificate`) would enable advanced security features." 196 + }, 197 + { 198 + "source_repo": "third_party/rust/curl-rust", 199 + "source_language": "Rust", 200 + "criticality": "low", 201 + "change_type": "enhancement", 202 + "title": "Add DNS cache timeout configuration", 203 + "description": "The Rust curl library provides `dns_cache_timeout()` to configure DNS cache TTL, controlling how long resolved addresses are reused. The OCaml library relies on system DNS caching without explicit control.", 204 + "affected_files": [ 205 + "lib/requests.ml", 206 + "lib/requests.mli" 207 + ], 208 + "rationale": "In dynamic cloud environments where IP addresses change frequently (auto-scaling, blue-green deployments), aggressive DNS caching can route requests to terminated instances. Conversely, excessive DNS queries impact performance. Configurable DNS cache timeout allows tuning this tradeoff. However, since the OCaml library uses system DNS resolution and connection pooling (which caches connections, implicitly caching DNS), the practical impact is limited. Users can configure system DNS cache settings instead." 209 + }, 210 + { 211 + "source_repo": "third_party/rust/curl-rust", 212 + "source_language": "Rust", 213 + "criticality": "low", 214 + "change_type": "enhancement", 215 + "title": "Add TCP keepalive configuration", 216 + "description": "The Rust curl library provides TCP keepalive configuration via `tcp_keepalive()`, `tcp_keepintvl()`, and `tcp_keepidle()` to detect broken connections and prevent connection drops through firewalls/NATs. The OCaml library uses default socket options.", 217 + "affected_files": [ 218 + "lib/requests.ml", 219 + "lib/requests.mli", 220 + "lib/http_client.ml" 221 + ], 222 + "rationale": "Long-lived HTTP connections (watching SSE streams, long-polling) can be silently dropped by stateful firewalls or NAT gateways that timeout idle connections. TCP keepalive probes detect and prevent this. However, the Eio runtime and connection pooling may already handle this at a lower level. Exposing TCP keepalive configuration provides fine-grained control for specialized applications, but is lower priority as the default socket behavior is usually sufficient." 223 + }, 224 + { 225 + "source_repo": "third_party/rust/curl-rust", 226 + "source_language": "Rust", 227 + "criticality": "medium", 228 + "change_type": "enhancement", 229 + "title": "Add verbose debug callback for request/response inspection", 230 + "description": "The Rust curl library provides `debug_function()` callback that receives all protocol data (headers sent/received, SSL info, connection info) with `InfoType` classification. This enables detailed request/response logging and debugging. The OCaml library uses Logs but doesn't provide request/response inspection callbacks.", 231 + "affected_files": [ 232 + "lib/requests.ml", 233 + "lib/requests.mli", 234 + "lib/http_client.ml" 235 + ], 236 + "rationale": "When debugging HTTP issues, developers need to see exact bytes sent and received: request line, headers, SSL handshake details. The library currently logs high-level events but doesn't expose raw protocol data. Adding an optional debug callback that receives (direction: sent|received, type: header|data|ssl, content: string) would enable applications to implement detailed logging, traffic analysis, or debugging tools. This is particularly valuable for troubleshooting authentication, encoding, or protocol issues." 237 + }, 238 + { 239 + "source_repo": "third_party/rust/curl-rust", 240 + "source_language": "Rust", 241 + "criticality": "low", 242 + "change_type": "refactor", 243 + "title": "Implement connection sharing across handles via Share interface", 244 + "description": "The Rust curl library provides a Share interface for sharing DNS cache, SSL session IDs, and connections across multiple Easy handles. The OCaml library uses connection pooling per session but doesn't provide explicit sharing configuration.", 245 + "affected_files": [ 246 + "lib/requests.ml", 247 + "lib/requests.mli" 248 + ], 249 + "rationale": "The OCaml library already implements connection pooling via Conpool, which provides similar benefits (connection reuse, DNS caching). The current architecture with separate http_pool and https_pool effectively shares connections. Explicit Share configuration would provide finer control (e.g., share SSL sessions but not DNS cache) but offers minimal practical benefit over the current pooling approach. This is lowest priority as the existing pooling architecture already delivers the key benefits." 250 + }, 251 + { 252 + "source_repo": "third_party/rust/curl-rust", 253 + "source_language": "Rust", 254 + "criticality": "high", 255 + "change_type": "bug", 256 + "title": "Add timeout enforcement during decompression operations", 257 + "description": "The OCaml library implements gzip/deflate/zlib decompression but does not enforce timeouts during decompression. If a malicious server sends a decompression bomb (small compressed payload that expands to gigabytes), the decompression operation could hang indefinitely or exhaust memory.", 258 + "affected_files": [ 259 + "lib/http_client.ml" 260 + ], 261 + "rationale": "The http_client.ml decompression functions (decompress_gzip, decompress_deflate, decompress_zlib) use the decompress library without size limits or timeout enforcement. A malicious server could send a 1KB gzip payload that decompresses to 1GB, causing OOM or indefinite blocking. The curl library handles this through overall timeout enforcement. The OCaml library should either: (1) decompress incrementally with size limits, (2) enforce total timeout during decompression, or (3) limit maximum decompressed size. This is a security issue as it enables DoS attacks." 262 + }, 263 + { 264 + "source_repo": "third_party/rust/curl-rust", 265 + "source_language": "Rust", 266 + "criticality": "medium", 267 + "change_type": "enhancement", 268 + "title": "Add Expect: 100-continue support with configurable timeout", 269 + "description": "The Rust curl library supports Expect: 100-continue header for large POST/PUT requests with `expect_100_timeout()` configuration. This allows servers to reject requests before receiving the body, saving bandwidth. The OCaml library does not explicitly handle 100-continue.", 270 + "affected_files": [ 271 + "lib/http_client.ml", 272 + "lib/requests.ml" 273 + ], 274 + "rationale": "When uploading large bodies, sending 'Expect: 100-continue' and waiting for '100 Continue' response before sending the body allows servers to reject requests early (authentication failure, invalid path) without wasting bandwidth on the upload. This is particularly important for multi-gigabyte uploads. The library should support: (1) optionally sending Expect: 100-continue, (2) waiting for 100 Continue or error response, (3) timeout for 100 Continue response. Implementation requires protocol state machine changes in http_client.ml." 275 + } 276 + ] 277 + }
+269
third_party/rust/hyper.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "hyper", 5 + "source_language": "Rust", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add strict HTTP header validation", 9 + "description": "Implement strict validation for HTTP headers including connection headers in HTTP/2, Transfer-Encoding header validation, and detection of prohibited headers. Hyper strips connection-specific headers (keep-alive, proxy-connection, transfer-encoding, upgrade) in HTTP/2 per RFC 9110 and validates TE header to only allow 'trailers'. The OCaml library currently lacks these protocol-level validations.", 10 + "affected_files": [ 11 + "lib/http_client.ml", 12 + "lib/headers.ml" 13 + ], 14 + "rationale": "Without proper header validation, the library may violate HTTP/2 protocol specifications and potentially expose security vulnerabilities. Connection headers sent in HTTP/2 can cause protocol errors or security issues. This is a compliance and security concern that should be addressed at the protocol implementation level." 15 + }, 16 + { 17 + "source_repo": "hyper", 18 + "source_language": "Rust", 19 + "criticality": "high", 20 + "change_type": "security", 21 + "title": "Add configurable limits for message size and header count", 22 + "description": "Implement configurable limits for maximum URI length, maximum number of headers, maximum header list size, and maximum message size to prevent denial-of-service attacks through oversized requests/responses. Hyper provides parser configuration with max_headers, max_uri_length, and max_header_list_size (16KB default for HTTP/2).", 23 + "affected_files": [ 24 + "lib/http_client.ml", 25 + "lib/requests.mli", 26 + "lib/one.mli" 27 + ], 28 + "rationale": "Without size limits, malicious or buggy servers can send arbitrarily large headers or messages that consume excessive memory, leading to DoS vulnerabilities. This is a critical security feature that every production HTTP client should have. Hyper's approach of making these configurable via builder patterns allows users to tune based on their security/compatibility needs." 29 + }, 30 + { 31 + "source_repo": "hyper", 32 + "source_language": "Rust", 33 + "criticality": "high", 34 + "change_type": "bug", 35 + "title": "Implement proper Content-Length validation", 36 + "description": "Add strict Content-Length header parsing and validation to detect invalid values, multiple Content-Length headers with different values, and conflicts between Content-Length and Transfer-Encoding. Hyper has dedicated Parse::ContentLength error variants for these cases.", 37 + "affected_files": [ 38 + "lib/http_client.ml", 39 + "lib/response.ml" 40 + ], 41 + "rationale": "Improper Content-Length validation can lead to request smuggling vulnerabilities and protocol confusion attacks. The current implementation uses a simple Int64.of_string which doesn't handle edge cases like multiple conflicting Content-Length headers or invalid formats. This is a security-critical validation that prevents HTTP desync attacks." 42 + }, 43 + { 44 + "source_repo": "hyper", 45 + "source_language": "Rust", 46 + "criticality": "medium", 47 + "change_type": "enhancement", 48 + "title": "Add error categorization with is_* query methods", 49 + "description": "Enhance the Error module with categorization methods like is_timeout(), is_parse(), is_user(), is_closed(), is_canceled() to allow better error handling and recovery logic. Hyper's error type provides these helpers for programmatic error inspection without string matching.", 50 + "affected_files": [ 51 + "lib/error.ml", 52 + "lib/error.mli" 53 + ], 54 + "rationale": "Currently, error handling requires matching on the full error variant. Adding query methods makes it easier to categorize errors for retry logic, logging, and user-facing messages. This improves API ergonomics and makes retry logic more robust (e.g., only retry network errors, not user errors)." 55 + }, 56 + { 57 + "source_repo": "hyper", 58 + "source_language": "Rust", 59 + "criticality": "medium", 60 + "change_type": "enhancement", 61 + "title": "Implement error source chains for better debugging", 62 + "description": "Add support for error cause chains to track the full error context. Similar to Hyper's Option<Cause> internal storage, allow errors to carry their underlying causes (e.g., TLS error wrapping socket error). This enables better error reporting and debugging.", 63 + "affected_files": [ 64 + "lib/error.ml", 65 + "lib/error.mli" 66 + ], 67 + "rationale": "Error chains provide crucial debugging context. When a high-level operation fails (e.g., HTTPS request), developers need to see the full chain (request failed -> TLS handshake failed -> certificate validation failed -> expired certificate). Hyper's approach keeps Error type small (single pointer) while maintaining full cause chains." 68 + }, 69 + { 70 + "source_repo": "hyper", 71 + "source_language": "Rust", 72 + "criticality": "medium", 73 + "change_type": "feature", 74 + "title": "Add HTTP/2 protocol support", 75 + "description": "Implement HTTP/2 protocol support with features like multiplexed streams, header compression (HPACK), flow control, and server push (optional). Hyper provides full HTTP/2 implementation with configurable parameters like keep-alive intervals, window sizes, and max concurrent streams.", 76 + "affected_files": [ 77 + "lib/http_client.ml", 78 + "lib/requests.ml", 79 + "lib/one.ml" 80 + ], 81 + "rationale": "HTTP/2 provides significant performance improvements through multiplexing (concurrent requests on single connection), header compression, and binary protocol efficiency. Modern APIs increasingly require or recommend HTTP/2. While this is a major feature addition, it's becoming essential for production HTTP clients." 82 + }, 83 + { 84 + "source_repo": "hyper", 85 + "source_language": "Rust", 86 + "criticality": "medium", 87 + "change_type": "enhancement", 88 + "title": "Add header read timeout for servers", 89 + "description": "Implement a dedicated header read timeout (separate from total timeout) to protect against slowloris attacks where clients send headers very slowly. Hyper provides h1_header_read_timeout specifically for this attack vector in HTTP/1 servers.", 90 + "affected_files": [ 91 + "lib/timeout.ml", 92 + "lib/timeout.mli", 93 + "lib/http_client.ml" 94 + ], 95 + "rationale": "A header read timeout protects against slowloris-style DoS attacks where attackers send HTTP headers one byte at a time to keep connections open indefinitely. This is distinct from a total request timeout and is a security best practice for any HTTP server/client that accepts incoming connections." 96 + }, 97 + { 98 + "source_repo": "hyper", 99 + "source_language": "Rust", 100 + "criticality": "medium", 101 + "change_type": "feature", 102 + "title": "Add keep-alive ping/pong mechanism", 103 + "description": "Implement HTTP/2-style keep-alive with configurable ping intervals and timeout for detecting dead connections. Hyper provides keep_alive_interval, keep_alive_timeout, and keep_alive_while_idle settings to actively probe connection health.", 104 + "affected_files": [ 105 + "lib/requests.ml", 106 + "lib/one.ml" 107 + ], 108 + "rationale": "Keep-alive pings detect dead connections faster than relying on TCP timeouts (which can take many minutes). This improves user experience by failing fast on broken connections and allows connection pools to remove stale connections proactively. Hyper defaults to 20-second timeout, which is reasonable for most applications." 109 + }, 110 + { 111 + "source_repo": "hyper", 112 + "source_language": "Rust", 113 + "criticality": "medium", 114 + "change_type": "enhancement", 115 + "title": "Add graceful shutdown mechanism", 116 + "description": "Implement graceful shutdown that disables keep-alive, finishes active requests, and cleanly closes connections. Hyper provides conn.graceful_shutdown() that signals the connection to finish in-flight requests without accepting new ones.", 117 + "affected_files": [ 118 + "lib/requests.ml", 119 + "lib/http_client.ml" 120 + ], 121 + "rationale": "Graceful shutdown prevents request failures during application shutdown. Currently, closing a switch immediately terminates all connections, potentially interrupting active requests. A graceful shutdown mechanism allows in-flight requests to complete while preventing new requests, improving reliability during deployments and restarts." 122 + }, 123 + { 124 + "source_repo": "hyper", 125 + "source_language": "Rust", 126 + "criticality": "medium", 127 + "change_type": "feature", 128 + "title": "Add informational response (1xx) handling", 129 + "description": "Add support for handling HTTP informational responses (100 Continue, 101 Switching Protocols, 103 Early Hints) with callback mechanism. Hyper provides OnInformational extension trait that allows applications to receive 1xx responses before the final response.", 130 + "affected_files": [ 131 + "lib/http_client.ml", 132 + "lib/response.ml", 133 + "lib/requests.mli" 134 + ], 135 + "rationale": "Some APIs use informational responses for optimization (100 Continue for large uploads) or feature negotiation (101 for WebSocket upgrades). The current implementation likely discards these. Adding callback support allows applications to react to informational responses without complicating the basic API." 136 + }, 137 + { 138 + "source_repo": "hyper", 139 + "source_language": "Rust", 140 + "criticality": "low", 141 + "change_type": "enhancement", 142 + "title": "Add header case preservation option", 143 + "description": "Add optional header case preservation and title-case formatting options. Hyper provides h1_title_case_headers and h1_preserve_header_case builder options for compatibility with servers that expect specific header casing.", 144 + "affected_files": [ 145 + "lib/headers.ml", 146 + "lib/headers.mli", 147 + "lib/requests.mli" 148 + ], 149 + "rationale": "While HTTP headers are case-insensitive per spec, some legacy systems or APIs expect specific casing (e.g., 'Content-Type' vs 'content-type'). Providing case preservation options improves compatibility without affecting the default behavior. This is a low-priority enhancement but useful for edge cases." 150 + }, 151 + { 152 + "source_repo": "hyper", 153 + "source_language": "Rust", 154 + "criticality": "low", 155 + "change_type": "enhancement", 156 + "title": "Add trailer support for chunked encoding", 157 + "description": "Implement support for HTTP trailers (headers sent after chunked message body). Hyper fully supports trailers in both HTTP/1 chunked encoding and HTTP/2. Currently the OCaml library reads chunked bodies but discards trailers.", 158 + "affected_files": [ 159 + "lib/http_client.ml", 160 + "lib/response.ml" 161 + ], 162 + "rationale": "Trailers allow sending metadata that's only known after the body is generated (e.g., content checksums, signatures). While uncommon, some APIs use trailers for integrity verification. The current skip_trailers() in http_client.ml line 223-226 discards this potentially important data." 163 + }, 164 + { 165 + "source_repo": "hyper", 166 + "source_language": "Rust", 167 + "criticality": "high", 168 + "change_type": "bug", 169 + "title": "Fix decompression error handling", 170 + "description": "Improve decompression error handling to fail requests when decompression fails rather than silently returning raw compressed data. Hyper-based clients typically fail the request on decompression errors. The current implementation in http_client.ml lines 101-117 falls back to raw body on decompression errors, which could lead to downstream parsing failures.", 171 + "affected_files": [ 172 + "lib/http_client.ml" 173 + ], 174 + "rationale": "Silently falling back to compressed data when decompression fails masks errors and can cause confusing failures downstream when code tries to parse compressed data as text/JSON. It's better to fail fast with a clear error message. This should be configurable (strict vs permissive) but the current silent fallback is problematic." 175 + }, 176 + { 177 + "source_repo": "hyper", 178 + "source_language": "Rust", 179 + "criticality": "medium", 180 + "change_type": "enhancement", 181 + "title": "Add request/response extensions system", 182 + "description": "Implement an extensions map (type-indexed storage) for attaching protocol-specific metadata to requests and responses. Hyper uses extensions for HTTP/2 :protocol pseudo-header, reason phrases, upgrade handlers, and custom metadata. This enables protocol extensions without breaking API compatibility.", 183 + "affected_files": [ 184 + "lib/response.ml", 185 + "lib/response.mli", 186 + "lib/requests.mli" 187 + ], 188 + "rationale": "Extensions provide a clean way to attach protocol-specific or application-specific metadata without adding fields to core types. This is useful for HTTP/2 features, authentication challenges, custom middleware data, and future protocol extensions. Hyper's approach keeps the core API stable while allowing extensibility." 189 + }, 190 + { 191 + "source_repo": "hyper", 192 + "source_language": "Rust", 193 + "criticality": "low", 194 + "change_type": "enhancement", 195 + "title": "Add comprehensive benchmarking suite", 196 + "description": "Create a benchmarking suite covering key operations: connection handshake, body streaming, request/response cycle, HTTP pipelining, and end-to-end scenarios. Hyper includes benches/ directory with body.rs, connect.rs, end_to_end.rs, pipeline.rs, and server.rs benchmarks.", 197 + "affected_files": [ 198 + "test/", 199 + "bench/" 200 + ], 201 + "rationale": "Benchmarks are essential for tracking performance regressions and optimizing hot paths. The current test suite focuses on correctness but lacks performance testing. Adding benchmarks helps validate that connection pooling, streaming, and decompression perform efficiently, especially when making protocol or implementation changes." 202 + }, 203 + { 204 + "source_repo": "hyper", 205 + "source_language": "Rust", 206 + "criticality": "medium", 207 + "change_type": "enhancement", 208 + "title": "Add comprehensive example suite", 209 + "description": "Expand the examples directory with common patterns: graceful shutdown, HTTP proxy, protocol upgrades, WebSocket handshake, streaming upload/download, error handling, middleware patterns, and custom body types. Hyper provides 14+ examples covering these scenarios.", 210 + "affected_files": [ 211 + "examples/" 212 + ], 213 + "rationale": "Good examples serve as documentation, testing, and templates for users. The current examples/ directory is minimal. Hyper's extensive examples demonstrate advanced features and best practices, reducing support burden and helping users understand correct usage patterns. Examples also serve as integration tests." 214 + }, 215 + { 216 + "source_repo": "hyper", 217 + "source_language": "Rust", 218 + "criticality": "low", 219 + "change_type": "feature", 220 + "title": "Add connection upgrade support", 221 + "description": "Implement HTTP/1.1 connection upgrade mechanism for protocol switching (WebSocket, HTTP/2, custom protocols). Hyper provides OnUpgrade future and Upgraded type that allows reclaiming the underlying connection after protocol upgrade negotiation.", 222 + "affected_files": [ 223 + "lib/http_client.ml", 224 + "lib/response.ml", 225 + "lib/requests.mli" 226 + ], 227 + "rationale": "Connection upgrades enable WebSocket support and other protocol switching use cases. While the library focuses on HTTP, providing the upgrade primitive allows users to build WebSocket clients on top. Hyper's approach returns the raw IO stream after upgrade headers are exchanged, giving full control to the upgraded protocol handler." 228 + }, 229 + { 230 + "source_repo": "hyper", 231 + "source_language": "Rust", 232 + "criticality": "medium", 233 + "change_type": "refactor", 234 + "title": "Add feature flags for optional functionality", 235 + "description": "Introduce feature flags to make HTTP/2, compression, JSON parsing, and other features optional dependencies. Hyper uses extensive feature gating (http1/http2/client/server/full) to keep the core library minimal and allow users to opt into only what they need.", 236 + "affected_files": [ 237 + "dune-project", 238 + "requests.opam", 239 + "lib/requests.mli" 240 + ], 241 + "rationale": "Feature flags reduce dependency bloat and compilation time for users who only need subset functionality. For example, users who only need HTTP/1 shouldn't pull in HTTP/2 dependencies. This is particularly important in OCaml ecosystem where compilation time matters. Following hyper's modular approach improves library composability." 242 + }, 243 + { 244 + "source_repo": "hyper", 245 + "source_language": "Rust", 246 + "criticality": "medium", 247 + "change_type": "enhancement", 248 + "title": "Implement retry-after header parsing", 249 + "description": "Add proper Retry-After header parsing that handles both delay-seconds format and HTTP-date format, as implemented in retry.ml parse_retry_after but not actually used in the retry logic. Hyper's retry implementations in ecosystem libraries (e.g., reqwest) use Retry-After to backoff appropriately.", 250 + "affected_files": [ 251 + "lib/retry.ml" 252 + ], 253 + "rationale": "The parse_retry_after function exists (lines 73-93) but isn't integrated into the retry logic. Respecting Retry-After headers is critical for rate-limited APIs (429 responses) and prevents unnecessary retries that will fail. The current exponential backoff ignores server guidance, potentially causing API bans or wasted retries." 254 + }, 255 + { 256 + "source_repo": "hyper", 257 + "source_language": "Rust", 258 + "criticality": "high", 259 + "change_type": "bug", 260 + "title": "Add timeout enforcement for total request time", 261 + "description": "Implement proper total timeout enforcement that includes all retry attempts, not just individual request timeouts. The current retry logic in retry.ml doesn't track total elapsed time across all attempts, which can lead to requests running far longer than expected.", 262 + "affected_files": [ 263 + "lib/retry.ml", 264 + "lib/timeout.ml" 265 + ], 266 + "rationale": "Without total timeout tracking, a request with max_retries=3 and 30s timeout per attempt could run for 90+ seconds. Users expect the total timeout to bound the entire operation including retries. This is a correctness issue that can cause unexpected latency spikes in production." 267 + } 268 + ] 269 + }
+280
third_party/rust/isahc.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/rust/isahc", 5 + "source_language": "Rust", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add detailed request/response metrics collection", 9 + "description": "Implement comprehensive timing and performance metrics similar to isahc's Metrics system. Track DNS lookup time, connection time, TLS handshake time, time-to-first-byte, transfer time, upload/download speeds, and cumulative redirect time. These metrics are invaluable for debugging performance issues and monitoring HTTP client behavior in production.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/response.mli", 13 + "lib/requests.ml", 14 + "lib/one.ml" 15 + ], 16 + "rationale": "The OCaml library currently only tracks elapsed time (lib/response.ml:14). Isahc provides granular timing metrics (src/metrics.rs) that help developers identify bottlenecks in DNS resolution, connection establishment, TLS handshake, and data transfer phases. This is particularly important for debugging slow requests and understanding where time is being spent. The metrics can be optionally enabled to avoid overhead when not needed." 17 + }, 18 + { 19 + "source_repo": "third_party/rust/isahc", 20 + "source_language": "Rust", 21 + "criticality": "high", 22 + "change_type": "security", 23 + "title": "Enhance cross-origin redirect security by scrubbing Cookie headers", 24 + "description": "When following redirects across origins, strip Cookie headers in addition to Authorization headers to prevent cookie leakage to untrusted domains. Currently only Authorization headers are stripped (lib/requests.ml:211-213).", 25 + "affected_files": [ 26 + "lib/requests.ml" 27 + ], 28 + "rationale": "Isahc's redirect implementation (src/redirect.rs:283-289) scrubs multiple sensitive headers including Cookie, Cookie2, Proxy-Authorization, and WWW-Authenticate on cross-origin redirects. The OCaml library only removes Authorization headers. This is a security vulnerability as cookies could leak to malicious redirect targets. The same_origin check exists but Cookie headers should also be stripped to match industry best practices." 29 + }, 30 + { 31 + "source_repo": "third_party/rust/isahc", 32 + "source_language": "Rust", 33 + "criticality": "medium", 34 + "change_type": "enhancement", 35 + "title": "Add error classification methods for better error handling", 36 + "description": "Add methods to Error module: is_client(), is_network(), is_server(), is_tls() to classify errors by category. This enables better retry logic and error handling decisions without matching against specific error variants.", 37 + "affected_files": [ 38 + "lib/error.ml", 39 + "lib/error.mli" 40 + ], 41 + "rationale": "Isahc provides semantic error classification methods (src/error.rs:309-372) that help applications decide how to handle errors. For example, is_network() identifies retryable network failures, is_client() indicates configuration errors that shouldn't be retried, and is_server() identifies server-side faults. The OCaml library has is_retryable, is_client_error, and is_server_error but these operate only on HTTP status codes, not on the full error type. Adding similar classification for all error types would improve error handling ergonomics." 42 + }, 43 + { 44 + "source_repo": "third_party/rust/isahc", 45 + "source_language": "Rust", 46 + "criticality": "medium", 47 + "change_type": "enhancement", 48 + "title": "Add socket address information to error types", 49 + "description": "Include local and remote socket addresses in error types when available. This helps with debugging network issues by showing which interface/port was used and which server endpoint failed.", 50 + "affected_files": [ 51 + "lib/error.ml", 52 + "lib/error.mli" 53 + ], 54 + "rationale": "Isahc enriches errors with connection metadata including local_addr() and remote_addr() (src/error.rs:374-400). This is extremely helpful for debugging, especially in environments with multiple network interfaces or when troubleshooting connection failures. The information can be captured from the Eio network stack and included in error records for better observability." 55 + }, 56 + { 57 + "source_repo": "third_party/rust/isahc", 58 + "source_language": "Rust", 59 + "criticality": "medium", 60 + "change_type": "feature", 61 + "title": "Add RequestBodyNotRewindable error for non-rewindable streaming bodies", 62 + "description": "Add a specific error type for when redirect or retry requires re-sending a request body but the body stream cannot be rewound. Currently this may fail silently or with a generic error.", 63 + "affected_files": [ 64 + "lib/error.ml", 65 + "lib/error.mli", 66 + "lib/body.ml", 67 + "lib/requests.ml" 68 + ], 69 + "rationale": "Isahc explicitly handles body rewindability (src/error.rs:78-85, src/redirect.rs:119-137) and returns a specific error when a redirect/retry requires resending a streaming body that cannot be reset. The OCaml library has body reset capability (lib/body.ml) but doesn't have a specific error for when this fails during redirects/retries. This makes debugging difficult when uploads fail on redirect scenarios." 70 + }, 71 + { 72 + "source_repo": "third_party/rust/isahc", 73 + "source_language": "Rust", 74 + "criticality": "medium", 75 + "change_type": "enhancement", 76 + "title": "Support automatic Referer header on redirects", 77 + "description": "Add an auto_referer configuration option that automatically sets the Referer header when following redirects, with security rules to prevent leaking HTTPS referers to HTTP targets.", 78 + "affected_files": [ 79 + "lib/requests.ml", 80 + "lib/requests.mli", 81 + "lib/one.ml" 82 + ], 83 + "rationale": "Isahc provides auto_referer functionality (src/redirect.rs:84-90, 246-277) that automatically sets the Referer header when following redirects, with proper security (doesn't leak HTTPS referers to HTTP). This is useful for server analytics and some APIs require it. The implementation includes smart security rules: strips fragments, credentials, and prevents downgrade leaks." 84 + }, 85 + { 86 + "source_repo": "third_party/rust/isahc", 87 + "source_language": "Rust", 88 + "criticality": "medium", 89 + "change_type": "enhancement", 90 + "title": "Improve redirect method transformation logic", 91 + "description": "Implement HTTP spec-compliant method transformation on redirects: POST/PUT should become GET on 301/302/303 responses. Currently the OCaml library preserves the original method on all redirects.", 92 + "affected_files": [ 93 + "lib/requests.ml" 94 + ], 95 + "rationale": "Isahc properly handles method transformation during redirects (src/redirect.rs:93-102), converting POST/PUT to GET for 301/302/303 status codes as per common HTTP client behavior (following curl). The OCaml library currently preserves the original method for all redirects. While HTTP specs are ambiguous on this, following established behavior improves compatibility." 96 + }, 97 + { 98 + "source_repo": "third_party/rust/isahc", 99 + "source_language": "Rust", 100 + "criticality": "low", 101 + "change_type": "enhancement", 102 + "title": "Add effective URI tracking through redirects", 103 + "description": "Provide access to the final effective URI after following redirects, distinct from the original request URI. This helps clients understand where they ultimately landed.", 104 + "affected_files": [ 105 + "lib/response.ml", 106 + "lib/response.mli" 107 + ], 108 + "rationale": "Isahc tracks the effective URI separately (src/redirect.rs:20-21, 148-151) allowing clients to know the final URL after redirects. The OCaml library stores the final URL in response.url, which is good, but doesn't clearly distinguish this from the original request URL in the API. Making this more explicit would improve clarity." 109 + }, 110 + { 111 + "source_repo": "third_party/rust/isahc", 112 + "source_language": "Rust", 113 + "criticality": "low", 114 + "change_type": "enhancement", 115 + "title": "Support non-ASCII characters in Location headers", 116 + "description": "Add robustness for malformed Location headers containing UTF-8 characters by percent-encoding them before parsing, matching browser behavior for lenient parsing.", 117 + "affected_files": [ 118 + "lib/requests.ml" 119 + ], 120 + "rationale": "Isahc handles non-ASCII Location headers gracefully (src/redirect.rs:180-225) by detecting UTF-8 and percent-encoding non-ASCII bytes before parsing. While technically invalid per HTTP specs, some misconfigured servers send UTF-8 in Location headers and most browsers handle this. Adding this robustness would improve compatibility with real-world servers." 121 + }, 122 + { 123 + "source_repo": "third_party/rust/isahc", 124 + "source_language": "Rust", 125 + "criticality": "medium", 126 + "change_type": "feature", 127 + "title": "Add client certificate support for mutual TLS authentication", 128 + "description": "Implement support for client certificates (mTLS) including PEM, DER, and PKCS#12 formats with private keys. This is essential for enterprise environments and services requiring mutual TLS authentication.", 129 + "affected_files": [ 130 + "lib/requests.ml", 131 + "lib/requests.mli" 132 + ], 133 + "rationale": "Isahc provides comprehensive client certificate support (src/config/ssl.rs) for mutual TLS including PEM, DER, and PKCS#12 formats, both from files and memory. The OCaml library currently only supports CA certificate configuration for server validation but has no client certificate support. This is a significant gap for enterprise use cases requiring mTLS." 134 + }, 135 + { 136 + "source_repo": "third_party/rust/isahc", 137 + "source_language": "Rust", 138 + "criticality": "low", 139 + "change_type": "feature", 140 + "title": "Add configurable SSL/TLS options for cipher control", 141 + "description": "Provide configuration options for TLS cipher suites and other SSL options to support compliance requirements and security hardening.", 142 + "affected_files": [ 143 + "lib/requests.ml", 144 + "lib/requests.mli" 145 + ], 146 + "rationale": "Isahc exposes SSL/TLS configuration options including cipher list control and SSL engine options. While the OCaml library uses Tls.Config.client which may support this, it's not exposed in the API. Some enterprises need to restrict cipher suites for compliance or security reasons." 147 + }, 148 + { 149 + "source_repo": "third_party/rust/isahc", 150 + "source_language": "Rust", 151 + "criticality": "medium", 152 + "change_type": "enhancement", 153 + "title": "Add progress callbacks for upload/download tracking", 154 + "description": "Provide hooks for tracking upload and download progress with bytes transferred and total size. Essential for implementing progress bars and monitoring large transfers.", 155 + "affected_files": [ 156 + "lib/requests.ml", 157 + "lib/requests.mli", 158 + "lib/response.ml" 159 + ], 160 + "rationale": "Isahc provides real-time progress tracking via Metrics (src/metrics.rs:58-80) for both uploads and downloads, including speed measurements. This is essential for user-facing applications that need progress bars or for monitoring large file transfers. The OCaml library currently has no progress tracking mechanism." 161 + }, 162 + { 163 + "source_repo": "third_party/rust/isahc", 164 + "source_language": "Rust", 165 + "criticality": "low", 166 + "change_type": "enhancement", 167 + "title": "Distinguish empty body from zero-length body semantically", 168 + "description": "Differentiate between the absence of a body (empty/None) and the presence of a zero-length body, as these have different HTTP semantics.", 169 + "affected_files": [ 170 + "lib/body.ml", 171 + "lib/body.mli" 172 + ], 173 + "rationale": "Isahc makes a semantic distinction between empty bodies (no body) and zero-length bodies (src/body/mod.rs:122-133). While both result in no content, they have different meanings in HTTP: empty means no Content-Length header, zero-length means Content-Length: 0. This matters for some APIs. The OCaml library's Body module doesn't clearly distinguish these cases." 174 + }, 175 + { 176 + "source_repo": "third_party/rust/isahc", 177 + "source_language": "Rust", 178 + "criticality": "high", 179 + "change_type": "enhancement", 180 + "title": "Add NameResolution error type for DNS failures", 181 + "description": "Add a distinct error type for DNS/hostname resolution failures, separate from general connection errors. This helps applications handle DNS issues differently from network connectivity problems.", 182 + "affected_files": [ 183 + "lib/error.ml", 184 + "lib/error.mli" 185 + ], 186 + "rationale": "Isahc distinguishes DNS resolution failures (ErrorKind::NameResolution) from connection failures (ErrorKind::ConnectionFailed) in src/error.rs:64-69. The OCaml library groups all network issues under ConnectionError. DNS failures often require different handling (checking /etc/hosts, DNS configuration) versus connection failures (firewall, network routing), so separating these improves debuggability." 187 + }, 188 + { 189 + "source_repo": "third_party/rust/isahc", 190 + "source_language": "Rust", 191 + "criticality": "medium", 192 + "change_type": "enhancement", 193 + "title": "Add ProtocolViolation error for HTTP spec violations", 194 + "description": "Add a specific error type for when servers violate the HTTP protocol specification. This distinguishes bugs in server implementations from network issues.", 195 + "affected_files": [ 196 + "lib/error.ml", 197 + "lib/error.mli" 198 + ], 199 + "rationale": "Isahc has a dedicated ProtocolViolation error (src/error.rs:71-74) for when servers violate HTTP specs. The OCaml library doesn't distinguish protocol violations from other errors. This is useful because protocol violations indicate server bugs and should generally not be retried, unlike transient network errors." 200 + }, 201 + { 202 + "source_repo": "third_party/rust/isahc", 203 + "source_language": "Rust", 204 + "criticality": "medium", 205 + "change_type": "enhancement", 206 + "title": "Improve error context with additional debugging information", 207 + "description": "Add an optional context string field to errors that can provide additional details about the error circumstances beyond just the error kind.", 208 + "affected_files": [ 209 + "lib/error.ml", 210 + "lib/error.mli" 211 + ], 212 + "rationale": "Isahc errors include an optional context field (src/error.rs:171) that provides additional human-readable context beyond the error kind. This is displayed in error messages to give more specific information. The OCaml library's errors contain some context in the error variant data, but having a general context mechanism would allow attaching debugging hints." 213 + }, 214 + { 215 + "source_repo": "third_party/rust/isahc", 216 + "source_language": "Rust", 217 + "criticality": "low", 218 + "change_type": "enhancement", 219 + "title": "Add InvalidContentEncoding error for malformed compression", 220 + "description": "Add a specific error for when the server returns unsupported or malformed content encoding, distinct from general encoding errors.", 221 + "affected_files": [ 222 + "lib/error.ml", 223 + "lib/error.mli" 224 + ], 225 + "rationale": "Isahc distinguishes invalid content encoding (src/error.rs:38-40) from other encoding errors. The OCaml library has EncodingError but doesn't distinguish between content-encoding issues (compression) and other encoding problems (charset). This helps identify server misconfiguration versus client-side parsing issues." 226 + }, 227 + { 228 + "source_repo": "third_party/rust/isahc", 229 + "source_language": "Rust", 230 + "criticality": "high", 231 + "change_type": "enhancement", 232 + "title": "Add retry-after header parsing for rate limit compliance", 233 + "description": "Enhance retry logic to parse and respect Retry-After headers with both integer seconds and HTTP-date formats. While parse_retry_after exists, ensure it's properly integrated into the automatic retry mechanism.", 234 + "affected_files": [ 235 + "lib/retry.ml", 236 + "lib/requests.ml" 237 + ], 238 + "rationale": "The OCaml library has Retry-After parsing (lib/retry.ml:73-93) and a respect_retry_after flag, but reviewing the retry implementation in lib/requests.ml:519-559, the actual Retry-After header is never read from responses during retries. The retry logic only uses calculate_backoff, never checking for Retry-After headers. This should be integrated so retries respect server-specified delays." 239 + }, 240 + { 241 + "source_repo": "third_party/rust/isahc", 242 + "source_language": "Rust", 243 + "criticality": "medium", 244 + "change_type": "feature", 245 + "title": "Add connection pooling statistics and monitoring", 246 + "description": "Expose connection pool statistics including active connections, connection reuse count, and pool efficiency metrics to help diagnose connection issues and optimize pool sizing.", 247 + "affected_files": [ 248 + "lib/requests.ml", 249 + "lib/requests.mli" 250 + ], 251 + "rationale": "While the OCaml library uses Conpool for connection pooling, pool statistics aren't exposed through the Requests API. Isahc-style metrics and monitoring would help developers understand connection reuse patterns and optimize pool configuration. The test files show Conpool.stats exists but isn't exposed to library users." 252 + }, 253 + { 254 + "source_repo": "third_party/rust/isahc", 255 + "source_language": "Rust", 256 + "criticality": "low", 257 + "change_type": "enhancement", 258 + "title": "Add BadClientCertificate and BadServerCertificate error distinction", 259 + "description": "Split SSLError into separate error types for client certificate problems versus server certificate validation failures to improve error diagnostics.", 260 + "affected_files": [ 261 + "lib/error.ml", 262 + "lib/error.mli" 263 + ], 264 + "rationale": "Isahc distinguishes client cert issues (BadClientCertificate) from server cert issues (BadServerCertificate) in src/error.rs:20-24. The OCaml library only has SSLError. Separating these helps developers quickly identify whether the problem is with their client configuration or the server's certificate." 265 + }, 266 + { 267 + "source_repo": "third_party/rust/isahc", 268 + "source_language": "Rust", 269 + "criticality": "medium", 270 + "change_type": "enhancement", 271 + "title": "Add per-request timeout overrides with granular control", 272 + "description": "While timeout overrides exist, ensure clear documentation that timeouts can be overridden per-request and consider adding per-phase timeout control (connect vs read vs total) at the request level.", 273 + "affected_files": [ 274 + "lib/requests.ml", 275 + "lib/timeout.ml" 276 + ], 277 + "rationale": "The OCaml library supports timeout overrides per request, which is good. However, Isahc allows granular timeout control at both client and request levels. The OCaml library has Timeout.t with connect/read/total but these are primarily used at the session level. Ensuring per-request override capability for all timeout phases would match isahc's flexibility." 278 + } 279 + ] 280 + }
+332
third_party/rust/reqwest.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/rust/reqwest", 5 + "source_language": "Rust", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add URL sanitization API to prevent credential leakage in errors", 9 + "description": "Implement a method to strip sensitive information (like API keys, tokens) from URLs before including them in error messages. Reqwest provides `Error::without_url()` and `Error::url_mut()` methods to allow users to remove or sanitize URLs that may contain credentials in query parameters or path segments.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/error.mli" 13 + ], 14 + "rationale": "Currently, OCaml library includes full URLs in error messages (HTTPError, TooManyRedirects). If URLs contain API keys or tokens as query parameters, these could be exposed in logs. Reqwest addresses this by providing `without_url()` to strip URLs and `url_mut()` for selective sanitization. This is particularly important for HTTPError exceptions that may be logged or displayed." 15 + }, 16 + { 17 + "source_repo": "third_party/rust/reqwest", 18 + "source_language": "Rust", 19 + "criticality": "high", 20 + "change_type": "bug", 21 + "title": "Improve timeout detection by checking error source chain", 22 + "description": "Enhance the timeout error detection to walk the error chain and check for timeout indicators from underlying libraries (like IO errors with TimedOut kind). Reqwest's `is_timeout()` method traverses the error source chain to detect timeouts from Hyper or IO errors, not just its own timeout wrapper.", 23 + "affected_files": [ 24 + "lib/error.ml", 25 + "lib/error.mli" 26 + ], 27 + "rationale": "The current `is_retryable` implementation only checks for the top-level `Timeout exception. However, timeouts can originate from lower layers (Eio, TLS, DNS resolution). Reqwest walks the error chain using `source()` to detect timeouts from underlying libraries. This would improve retry logic accuracy by catching all timeout scenarios." 28 + }, 29 + { 30 + "source_repo": "third_party/rust/reqwest", 31 + "source_language": "Rust", 32 + "criticality": "medium", 33 + "change_type": "enhancement", 34 + "title": "Add retry budget mechanism to prevent retry storms", 35 + "description": "Implement a token bucket-based retry budget that limits the percentage of extra load retries can generate. Reqwest uses Tower's TpsBudget with a default 20% extra load allowance. The budget deposits tokens on success and withdraws on retry, preventing cascading failures from retry storms.", 36 + "affected_files": [ 37 + "lib/retry.ml", 38 + "lib/retry.mli", 39 + "lib/requests.ml" 40 + ], 41 + "rationale": "Current retry implementation has no budget control - it will retry up to max_retries regardless of system load. This can cause 'retry storms' where retries overwhelm the system. Reqwest's budget approach (default 20% extra load) prevents this by tracking retry rate over a sliding window. This is especially important for production systems under degraded conditions." 42 + }, 43 + { 44 + "source_repo": "third_party/rust/reqwest", 45 + "source_language": "Rust", 46 + "criticality": "medium", 47 + "change_type": "feature", 48 + "title": "Add scoped retry policies for per-host retry budgets", 49 + "description": "Implement scoped retry policies that apply retry budgets per-host or based on custom predicates. Reqwest provides `retry::for_host()` and `retry::scoped()` to limit retry scope, preventing one failing host from consuming the entire retry budget and affecting other hosts.", 50 + "affected_files": [ 51 + "lib/retry.ml", 52 + "lib/retry.mli", 53 + "lib/requests.ml" 54 + ], 55 + "rationale": "Current retry policy applies globally to all requests in a session. This means failures to one host can exhaust retry budget affecting requests to healthy hosts. Reqwest's scoped approach (per-host budgets) provides better isolation. Each host gets its own retry budget, preventing cascading failures across different services." 56 + }, 57 + { 58 + "source_repo": "third_party/rust/reqwest", 59 + "source_language": "Rust", 60 + "criticality": "medium", 61 + "change_type": "enhancement", 62 + "title": "Add protocol-level NACK detection for automatic safe retries", 63 + "description": "Detect and automatically retry HTTP/2 protocol-level NACKs like GOAWAY (NO_ERROR) and REFUSED_STREAM. These are safe to retry as they indicate server-side issues without side effects. Reqwest's default retry classifier detects h2::Error::is_go_away() with NO_ERROR reason and REFUSED_STREAM per RFC 9113.", 64 + "affected_files": [ 65 + "lib/retry.ml", 66 + "lib/error.ml", 67 + "lib/http_client.ml" 68 + ], 69 + "rationale": "The library currently only implements HTTP/1.1 protocol. However, when HTTP/2 support is added, protocol-level NACKs should be automatically retried. These errors (GOAWAY NO_ERROR, REFUSED_STREAM) indicate the server cannot handle the request on this connection but hasn't processed it - making retry safe. Reqwest handles this by default in its ProtocolNacks classifier." 70 + }, 71 + { 72 + "source_repo": "third_party/rust/reqwest", 73 + "source_language": "Rust", 74 + "criticality": "medium", 75 + "change_type": "enhancement", 76 + "title": "Add request body cloneability check before retry attempts", 77 + "description": "Before attempting retries, verify that the request body can be re-sent. Reqwest checks if the body is cloneable via `try_clone()` before adding retry capability. Non-cloneable bodies (e.g., consumed streams) cannot be retried and should fail fast rather than on retry attempt.", 78 + "affected_files": [ 79 + "lib/retry.ml", 80 + "lib/body.ml", 81 + "lib/requests.ml" 82 + ], 83 + "rationale": "Current implementation may attempt to retry requests with non-rewindable bodies (like consumed streams), leading to confusing errors during retry. Reqwest's `clone_request()` checks if body is cloneable upfront. This would allow the library to provide clear error messages when retries are requested but the body cannot be re-sent, improving API ergonomics." 84 + }, 85 + { 86 + "source_repo": "third_party/rust/reqwest", 87 + "source_language": "Rust", 88 + "criticality": "medium", 89 + "change_type": "feature", 90 + "title": "Add configurable classifier function for custom retry logic", 91 + "description": "Allow users to provide custom classifiers to determine if a request/response should be retried based on method, status, headers, or error. Reqwest provides `retry::Builder::classify_fn()` that receives request+response info and returns Action::Retryable or Action::Success.", 92 + "affected_files": [ 93 + "lib/retry.ml", 94 + "lib/retry.mli" 95 + ], 96 + "rationale": "Current retry logic is hardcoded to specific status codes and methods. Different APIs have different retry semantics (e.g., some POST endpoints are idempotent, some 401s should trigger re-auth). Reqwest's classifier pattern allows users to implement custom retry logic based on their API's behavior, making the library more flexible for diverse use cases." 97 + }, 98 + { 99 + "source_repo": "third_party/rust/reqwest", 100 + "source_language": "Rust", 101 + "criticality": "low", 102 + "change_type": "enhancement", 103 + "title": "Add is_connect() error classification method", 104 + "description": "Add a method to specifically identify connection establishment errors (DNS resolution, TCP connection, TLS handshake failures). Reqwest's `Error::is_connect()` checks the error chain for Hyper connection errors, allowing different handling for connection vs. request/response errors.", 105 + "affected_files": [ 106 + "lib/error.ml", 107 + "lib/error.mli" 108 + ], 109 + "rationale": "Connection errors have different retry characteristics than request/body errors. They're generally safe to retry but may indicate DNS or network issues requiring different backoff strategies. Reqwest distinguishes connection errors by walking the error chain. This would enable smarter retry logic and better error reporting to users." 110 + }, 111 + { 112 + "source_repo": "third_party/rust/reqwest", 113 + "source_language": "Rust", 114 + "criticality": "low", 115 + "change_type": "enhancement", 116 + "title": "Add builder vs runtime error classification", 117 + "description": "Distinguish between configuration errors (builder errors) that occur during client/request setup versus runtime errors during request execution. Reqwest has a dedicated Kind::Builder for configuration errors that are never retryable and indicate programmer error.", 118 + "affected_files": [ 119 + "lib/error.ml", 120 + "lib/error.mli" 121 + ], 122 + "rationale": "Current error types mix configuration errors (InvalidURL, InvalidRequest) with runtime errors. Reqwest separates builder/configuration errors as a distinct category. This helps: (1) retry logic skip non-retryable config errors, (2) users understand if error is usage mistake vs runtime issue, (3) libraries built on top can handle these differently." 123 + }, 124 + { 125 + "source_repo": "third_party/rust/reqwest", 126 + "source_language": "Rust", 127 + "criticality": "low", 128 + "change_type": "enhancement", 129 + "title": "Add HTTP status code and reason phrase to status-based errors", 130 + "description": "When raising HTTP errors via raise_for_status, include the actual StatusCode type and reason phrase from the response. Reqwest's Kind::Status stores StatusCode and ReasonPhrase separately, allowing better error messages and programmatic access to the status.", 131 + "affected_files": [ 132 + "lib/response.ml", 133 + "lib/error.ml" 134 + ], 135 + "rationale": "Currently, HTTPError stores status as int and has a separate reason string field. Reqwest stores the full StatusCode type plus optional ReasonPhrase from the server. This preserves more information and allows better error formatting. The reason phrase from the server can provide additional context beyond standard status text." 136 + }, 137 + { 138 + "source_repo": "third_party/rust/reqwest", 139 + "source_language": "Rust", 140 + "criticality": "medium", 141 + "change_type": "security", 142 + "title": "Mark sensitive headers to prevent logging in debug output", 143 + "description": "Add a mechanism to mark certain headers (Authorization, Cookie, API keys) as sensitive so they are not included in debug logs or error messages. Reqwest uses HeaderMap::set_sensitive() to mark headers, which are then redacted in Debug output.", 144 + "affected_files": [ 145 + "lib/headers.ml", 146 + "lib/headers.mli", 147 + "lib/auth.ml" 148 + ], 149 + "rationale": "Current implementation may log full headers including Authorization and Cookies in error messages or debug output. This can leak credentials to log aggregation systems. Reqwest marks these headers as sensitive during construction, preventing accidental exposure. This is critical for production deployments where logs are aggregated and stored." 150 + }, 151 + { 152 + "source_repo": "third_party/rust/reqwest", 153 + "source_language": "Rust", 154 + "criticality": "low", 155 + "change_type": "enhancement", 156 + "title": "Add decode vs body error classification", 157 + "description": "Distinguish between raw body reading/streaming errors and decoding/decompression errors. Reqwest has separate Kind::Body (stream errors) and Kind::Decode (JSON/decompression errors), allowing targeted error handling for parsing vs I/O issues.", 158 + "affected_files": [ 159 + "lib/error.ml", 160 + "lib/error.mli", 161 + "lib/response.ml" 162 + ], 163 + "rationale": "Current error handling groups all response body issues under general categories. Reqwest separates: (1) Body errors - network/stream failures during read, (2) Decode errors - JSON parse failures, decompression errors. This distinction helps users decide whether to retry (body errors may succeed on retry) vs fix their code (decode errors indicate bad data or wrong parser)." 164 + }, 165 + { 166 + "source_repo": "third_party/rust/reqwest", 167 + "source_language": "Rust", 168 + "criticality": "medium", 169 + "change_type": "feature", 170 + "title": "Add dedicated upgrade error type for WebSocket/protocol upgrades", 171 + "description": "Add a specific error variant for protocol upgrade failures (like WebSocket handshake failures). Reqwest has Kind::Upgrade and is_upgrade() method to handle connection upgrade failures separately from regular HTTP errors.", 172 + "affected_files": [ 173 + "lib/error.ml", 174 + "lib/error.mli" 175 + ], 176 + "rationale": "While the library doesn't currently support WebSocket upgrades, adding this error type prepares for future protocol upgrade support. Upgrade errors are distinct from regular request errors - they indicate successful initial request but failed protocol negotiation. Reqwest treats these separately, which would be valuable if OCaml library adds upgrade support." 177 + }, 178 + { 179 + "source_repo": "third_party/rust/reqwest", 180 + "source_language": "Rust", 181 + "criticality": "high", 182 + "change_type": "security", 183 + "title": "Add minimum TLS version configuration", 184 + "description": "Allow users to configure minimum acceptable TLS version (TLS 1.2, TLS 1.3) for security compliance. Reqwest provides ClientBuilder::min_tls_version() to enforce minimum TLS versions, rejecting connections to servers offering only older protocols.", 185 + "affected_files": [ 186 + "lib/requests.ml", 187 + "lib/one.ml" 188 + ], 189 + "rationale": "Current implementation uses default TLS configuration without minimum version enforcement. Many security policies require TLS 1.2+ (PCI DSS, HIPAA, etc.). Reqwest allows explicit minimum version setting. The OCaml library should expose this capability through the Tls.Config API to meet compliance requirements and prevent downgrade attacks." 190 + }, 191 + { 192 + "source_repo": "third_party/rust/reqwest", 193 + "source_language": "Rust", 194 + "criticality": "medium", 195 + "change_type": "security", 196 + "title": "Add TLS SNI (Server Name Indication) configuration option", 197 + "description": "Make TLS Server Name Indication configurable, allowing it to be disabled for certain edge cases. Reqwest provides tls_sni(bool) to control SNI, which some servers or proxies require to be disabled for compatibility.", 198 + "affected_files": [ 199 + "lib/requests.ml", 200 + "lib/one.ml" 201 + ], 202 + "rationale": "Current implementation always uses SNI (via Domain_name conversion). While this is correct for most cases, some corporate proxies or legacy servers have issues with SNI. Reqwest allows disabling SNI for compatibility. Exposing this through the Tls.Config would handle edge cases where SNI causes connection failures." 203 + }, 204 + { 205 + "source_repo": "third_party/rust/reqwest", 206 + "source_language": "Rust", 207 + "criticality": "low", 208 + "change_type": "enhancement", 209 + "title": "Add pool idle timeout and max connection lifetime configuration", 210 + "description": "Expose fine-grained connection pool tuning including pool_idle_timeout (how long idle connections are kept) and max_connection_lifetime (maximum age of any connection). Reqwest exposes both as separate ClientBuilder options.", 211 + "affected_files": [ 212 + "lib/requests.ml" 213 + ], 214 + "rationale": "Current implementation has these features (connection_idle_timeout=60s, connection_lifetime=300s) but they're hardcoded as default parameters. Reqwest separates these concerns clearly. Making these more prominent in the API documentation and possibly adding preset profiles (conservative, balanced, aggressive) would help users tune connection pooling for their workloads." 215 + }, 216 + { 217 + "source_repo": "third_party/rust/reqwest", 218 + "source_language": "Rust", 219 + "criticality": "low", 220 + "change_type": "enhancement", 221 + "title": "Add HTTP/2 and HTTP/3 protocol support flags", 222 + "description": "Add feature flags or configuration options to enable HTTP/2 and experimental HTTP/3 support when the underlying libraries support them. Reqwest has http2 (default) and http3 (experimental) feature flags with corresponding ALPN negotiation.", 223 + "affected_files": [ 224 + "lib/http_client.ml", 225 + "lib/requests.ml" 226 + ], 227 + "rationale": "Current implementation only supports HTTP/1.1. Reqwest has built-in HTTP/2 (via h2 crate) and experimental HTTP/3 (via quinn). While full implementation is a large effort, adding the API surface for protocol selection prepares for future HTTP/2 support. This would enable multiplexing, header compression, and server push when implemented." 228 + }, 229 + { 230 + "source_repo": "third_party/rust/reqwest", 231 + "source_language": "Rust", 232 + "criticality": "medium", 233 + "change_type": "feature", 234 + "title": "Add support for additional compression algorithms (brotli, zstd)", 235 + "description": "Extend auto-decompression support beyond gzip/deflate to include modern algorithms like Brotli and Zstandard. Reqwest supports brotli and zstd via feature flags, automatically decompressing responses and advertising support in Accept-Encoding.", 236 + "affected_files": [ 237 + "lib/http_client.ml" 238 + ], 239 + "rationale": "Current implementation supports gzip/deflate/zlib, which is good. However, Brotli offers ~20% better compression for text and is widely supported. Zstandard is becoming standard for large payloads. Reqwest supports both via feature flags. Adding these (with OCaml bindings like ocaml-brotli) would reduce bandwidth usage and improve performance, especially for API responses." 240 + }, 241 + { 242 + "source_repo": "third_party/rust/reqwest", 243 + "source_language": "Rust", 244 + "criticality": "low", 245 + "change_type": "enhancement", 246 + "title": "Add dedicated redirect error variant", 247 + "description": "Create a distinct error variant for redirect-specific errors (too many redirects, redirect loop detection, invalid redirect URLs). Reqwest has Kind::Redirect separate from other errors, with is_redirect() for identification.", 248 + "affected_files": [ 249 + "lib/error.ml", 250 + "lib/error.mli" 251 + ], 252 + "rationale": "Current TooManyRedirects exception is good but not classified separately in error handling. Reqwest has a dedicated redirect error category. This would allow: (1) distinguishing redirect issues from other errors in retry logic, (2) better error messages specific to redirect problems, (3) future enhancements like redirect loop detection with cycle tracking." 253 + }, 254 + { 255 + "source_repo": "third_party/rust/reqwest", 256 + "source_language": "Rust", 257 + "criticality": "medium", 258 + "change_type": "feature", 259 + "title": "Add system proxy auto-detection with opt-out", 260 + "description": "Automatically detect and use system proxy configuration (HTTP_PROXY, HTTPS_PROXY environment variables, platform proxy settings) with ability to disable. Reqwest auto-detects system proxy by default with no_proxy() opt-out.", 261 + "affected_files": [ 262 + "lib/requests.ml", 263 + "lib/one.ml" 264 + ], 265 + "rationale": "Current implementation doesn't have built-in proxy support. Many enterprise environments require proxies. Reqwest automatically respects HTTP_PROXY/HTTPS_PROXY/NO_PROXY environment variables. Adding this with proper proxy authentication support would make the library work out-of-box in corporate environments without manual configuration." 266 + }, 267 + { 268 + "source_repo": "third_party/rust/reqwest", 269 + "source_language": "Rust", 270 + "criticality": "low", 271 + "change_type": "feature", 272 + "title": "Add per-request timeout overrides via extensions", 273 + "description": "Allow individual requests to override client-level timeout settings without creating new clients. Reqwest uses request extensions to store per-request TotalTimeout and ReadTimeout, checked during execution.", 274 + "affected_files": [ 275 + "lib/requests.ml", 276 + "lib/one.ml" 277 + ], 278 + "rationale": "Current implementation requires passing timeout parameter to each request method. Reqwest's extension-based approach allows middleware and internal code to override timeouts cleanly. This pattern could be useful for special-case requests (like file uploads needing longer timeouts) while maintaining session defaults, reducing API surface complexity." 279 + }, 280 + { 281 + "source_repo": "third_party/rust/reqwest", 282 + "source_language": "Rust", 283 + "criticality": "low", 284 + "change_type": "enhancement", 285 + "title": "Add DNS resolver customization support", 286 + "description": "Allow custom DNS resolvers to be plugged in, supporting async DNS libraries like hickory-dns or custom resolution logic. Reqwest has a modular DNS resolution system with gai (getaddrinfo), hickory, and custom resolver support.", 287 + "affected_files": [ 288 + "lib/one.ml", 289 + "lib/requests.ml" 290 + ], 291 + "rationale": "Current implementation uses Eio.Net.getaddrinfo_stream which is fine for most cases. However, advanced use cases benefit from custom resolvers: (1) DNS-based load balancing, (2) DNS caching, (3) service discovery integration (Consul, etc.). Reqwest's pluggable resolver architecture could be adapted using Eio's resolver abstraction if/when needed." 292 + }, 293 + { 294 + "source_repo": "third_party/rust/reqwest", 295 + "source_language": "Rust", 296 + "criticality": "low", 297 + "change_type": "enhancement", 298 + "title": "Add response extension mechanism for middleware metadata", 299 + "description": "Provide an extensions mechanism on responses to store metadata from middleware, plugins, or internal processing (like retry attempt count, connection info). Reqwest uses http::Extensions on both requests and responses.", 300 + "affected_files": [ 301 + "lib/response.ml", 302 + "lib/response.mli" 303 + ], 304 + "rationale": "Current response type has fixed fields. Extensions would allow: (1) storing retry attempt count in response, (2) connection pool metadata, (3) timing breakdown (DNS, connect, TLS, TTFB), (4) custom middleware data. Reqwest uses http::Extensions (HashMap) for this. Could implement as a (string * string) list or hash table on response." 305 + }, 306 + { 307 + "source_repo": "third_party/rust/reqwest", 308 + "source_language": "Rust", 309 + "criticality": "medium", 310 + "change_type": "feature", 311 + "title": "Add Certificate Revocation List (CRL) support", 312 + "description": "Support Certificate Revocation Lists for enhanced TLS security, allowing validation against revoked certificates. Reqwest provides ClientBuilder methods to add CRLs when using rustls backend (add_crls_pem/add_crls_der).", 313 + "affected_files": [ 314 + "lib/requests.ml", 315 + "lib/one.ml" 316 + ], 317 + "rationale": "Current implementation uses Ca_certs for certificate validation but doesn't check revocation. CRLs prevent accepting revoked certificates. Reqwest supports CRL loading via rustls. The OCaml tls library may support CRLs - this should be exposed in the API for high-security applications (financial, healthcare) where certificate revocation checking is required." 318 + }, 319 + { 320 + "source_repo": "third_party/rust/reqwest", 321 + "source_language": "Rust", 322 + "criticality": "low", 323 + "change_type": "enhancement", 324 + "title": "Add comprehensive test coverage for TLS certificate validation", 325 + "description": "Add dedicated tests for certificate validation scenarios using badssl.com or similar service (expired certs, wrong host, self-signed, etc.). Reqwest has badssl.rs test file covering various certificate validation scenarios.", 326 + "affected_files": [ 327 + "test/" 328 + ], 329 + "rationale": "Current test suite (httpbin.t) tests basic HTTPS but not certificate validation edge cases. Reqwest has dedicated badssl.rs tests for: expired certificates, wrong hostname, self-signed certs, revoked certs. Adding similar tests ensures TLS security features work correctly and catch regressions. This is important for security-critical applications." 330 + } 331 + ] 332 + }
+161
third_party/rust/surf.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/rust/surf", 5 + "source_language": "Rust", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add cross-origin redirect security header stripping", 9 + "description": "The OCaml library currently only strips the Authorization header during cross-origin redirects (http_client.ml:210-214). Surf's redirect middleware demonstrates a security gap: the OCaml library should also strip Cookie headers during cross-origin redirects to prevent credential leakage. This is a security best practice implemented by major HTTP clients like Python's requests library.", 10 + "affected_files": [ 11 + "lib/http_client.ml", 12 + "lib/requests.ml" 13 + ], 14 + "rationale": "Cross-origin redirects can leak sensitive authentication tokens and cookies to untrusted domains. Currently the code at requests.ml:210-214 only strips Authorization headers, but Cookie headers should also be stripped. This prevents session hijacking and credential theft when servers redirect to different domains." 15 + }, 16 + { 17 + "source_repo": "third_party/rust/surf", 18 + "source_language": "Rust", 19 + "criticality": "medium", 20 + "change_type": "enhancement", 21 + "title": "Implement middleware/plugin architecture", 22 + "description": "Surf provides a composable middleware system using the Middleware trait and Next chain pattern. This allows users to add custom request/response processing (logging, metrics, authentication, caching) without modifying core library code. The OCaml library currently has retry logic and redirect handling baked into the core request flow, which limits extensibility. A middleware system would enable users to add custom behavior like request signing, rate limiting, circuit breakers, or custom logging.", 23 + "affected_files": [ 24 + "lib/requests.ml", 25 + "lib/http_client.ml", 26 + "lib/requests.mli" 27 + ], 28 + "rationale": "Middleware enables separation of concerns and allows users to compose complex HTTP behaviors without library modifications. Surf's implementation shows this pattern works well for HTTP clients. In OCaml, this could be implemented using higher-order functions that take (request -> response) and return (request -> response), similar to Dream's middleware. Benefits include: custom authentication schemes, request/response transformations, metrics collection, caching layers, and testing mocks." 29 + }, 30 + { 31 + "source_repo": "third_party/rust/surf", 32 + "source_language": "Rust", 33 + "criticality": "medium", 34 + "change_type": "feature", 35 + "title": "Add base URL support for multi-endpoint clients", 36 + "description": "Surf's Config provides set_base_url() which allows creating clients configured for a specific API endpoint (e.g., 'https://api.github.com/') and then making relative requests. The OCaml library requires full URLs for every request. This is verbose for API clients that make many calls to the same base URL and makes it harder to switch between environments (dev/staging/prod).", 37 + "affected_files": [ 38 + "lib/requests.ml", 39 + "lib/requests.mli", 40 + "lib/one.ml" 41 + ], 42 + "rationale": "Base URL support is essential for SDK and API client use cases. Surf demonstrates this with Config.base_url (config.rs:33-38, 108-111). Implementation: add optional base_url field to the session type, and in request functions, use Uri.resolve to combine base and relative URLs. This pattern is used by all major HTTP libraries (axios, requests, etc.). Note: trailing slash matters per RFC 3986 - 'http://api.com/v1/' vs 'http://api.com/v1' have different resolution behavior." 43 + }, 44 + { 45 + "source_repo": "third_party/rust/surf", 46 + "source_language": "Rust", 47 + "criticality": "medium", 48 + "change_type": "enhancement", 49 + "title": "Add response encoding detection and multi-charset support", 50 + "description": "Surf supports automatic charset detection from Content-Type headers and decoding with encoding_rs for non-UTF-8 encodings (response.rs:249-257, 495-524). The OCaml library (response.ml:69-73) always assumes UTF-8. This causes failures when reading responses from servers using other encodings (e.g., EUC-KR for Korean sites, Windows-1252 for legacy systems, ISO-8859-1 for European sites).", 51 + "affected_files": [ 52 + "lib/response.ml", 53 + "lib/response.mli", 54 + "lib/error.ml" 55 + ], 56 + "rationale": "International content often uses non-UTF-8 encodings. Surf's decode_body (response.rs:495-555) shows three-tier approach: UTF-8 only (minimal), encoding_rs for native (full support), and TextDecoder for WASM. OCaml can use uutf or camomile for charset conversion. Implementation: extract charset from Content-Type, attempt UTF-8 decode, fall back to detected/specified encoding, return DecodeError with raw bytes if all fail. This prevents data loss and enables working with legacy/international APIs." 57 + }, 58 + { 59 + "source_repo": "third_party/rust/surf", 60 + "source_language": "Rust", 61 + "criticality": "low", 62 + "change_type": "enhancement", 63 + "title": "Enhance redirect handling to support relative URLs properly", 64 + "description": "Surf's redirect middleware (redirect/mod.rs:103-114) handles both absolute URLs and relative URLs using proper URL joining semantics. While the OCaml library has redirect support, examining its Location header handling could benefit from explicit relative URL resolution using Uri.resolve to handle edge cases like protocol-relative URLs, absolute paths, and relative paths.", 65 + "affected_files": [ 66 + "lib/http_client.ml" 67 + ], 68 + "rationale": "The HTTP spec (RFC 7231) allows Location headers to contain relative URLs. Surf's implementation shows proper handling with Url::parse for absolute and base_url.join() for relative (redirect/mod.rs:103-114). The OCaml library should ensure it correctly handles: absolute URLs (http://...), absolute paths (/path), relative paths (../path, path), protocol-relative (//host/path). Use Uri.resolve for proper RFC 3986 compliance." 69 + }, 70 + { 71 + "source_repo": "third_party/rust/surf", 72 + "source_language": "Rust", 73 + "criticality": "low", 74 + "change_type": "enhancement", 75 + "title": "Add structured logging with request/response correlation IDs", 76 + "description": "Surf's Logger middleware (logger/native.rs:32-69) uses atomic counters to assign unique IDs to each request and includes these IDs in all log messages (req.id, req.method, req.uri, elapsed, status). This enables tracing a single request through logs. The OCaml library has logging via the Logs library, but lacks request correlation IDs to connect related log messages (request start, retries, redirects, response).", 77 + "affected_files": [ 78 + "lib/requests.ml", 79 + "lib/http_client.ml", 80 + "lib/retry.ml" 81 + ], 82 + "rationale": "Request correlation IDs are essential for debugging in production environments with concurrent requests. Surf's implementation (logger/native.rs:35-44, 48-65) shows using atomic counters and structured key-value logging. OCaml implementation: add request_id field (use Atomic.t or just counter), include in all log messages using Logs tags. This enables filtering logs by request_id and understanding request flow through retries/redirects. Also consider adding timing information for performance analysis." 83 + }, 84 + { 85 + "source_repo": "third_party/rust/surf", 86 + "source_language": "Rust", 87 + "criticality": "low", 88 + "change_type": "enhancement", 89 + "title": "Add response status-based log levels", 90 + "description": "Surf's Logger middleware (logger/native.rs:50-56) automatically adjusts log levels based on HTTP status: Error level for 5xx, Warn for 4xx, Info for success. The OCaml library logs most HTTP operations at Info level regardless of outcome. This makes it harder to identify failures in logs and configure appropriate log filtering.", 91 + "affected_files": [ 92 + "lib/http_client.ml", 93 + "lib/requests.ml" 94 + ], 95 + "rationale": "Status-based log levels improve log signal-to-noise ratio. Surf's approach (logger/native.rs:50-56): 5xx = Error (server problems need immediate attention), 4xx = Warn (client errors may indicate bugs), 2xx/3xx = Info (normal operation). Implementation in OCaml: check response status after request completes, use Logs.err for >=500, Logs.warn for 400-499, Logs.info for success. This aligns with standard observability practices and makes production debugging easier." 96 + }, 97 + { 98 + "source_repo": "third_party/rust/surf", 99 + "source_language": "Rust", 100 + "criticality": "low", 101 + "change_type": "refactor", 102 + "title": "Extract shared global client for one-shot requests", 103 + "description": "Surf uses a global shared HTTP client instance (client.rs:25-26) for one-off requests to enable connection pooling and reduce overhead. Each one-off request creates a new Client but reuses the underlying HTTP client. The OCaml One module creates fresh connection pools for each request, which is less efficient and doesn't allow connection reuse across multiple one-off requests in the same application.", 104 + "affected_files": [ 105 + "lib/one.ml" 106 + ], 107 + "rationale": "Connection pooling amortizes TLS handshake and TCP connection overhead. Surf's GLOBAL_CLIENT (client.rs:25) using Lazy initialization shows the pattern. OCaml implementation: use Lazy.t to create a shared Requests.t session on first use, reuse for all One.* calls. This maintains One's simple API while gaining connection pooling benefits. Benefits: faster repeated one-off calls, reduced resource usage, better performance for CLI tools making multiple requests." 108 + }, 109 + { 110 + "source_repo": "third_party/rust/surf", 111 + "source_language": "Rust", 112 + "criticality": "medium", 113 + "change_type": "enhancement", 114 + "title": "Add response extensions/metadata storage", 115 + "description": "Surf provides response.ext<T>() and insert_ext<T>() (response.rs:124-132) for type-safe storage of request-scoped metadata. This enables middleware to attach additional context (timing info, cache metadata, trace IDs) to responses without modifying the core Response type. The OCaml library's Response type has fixed fields and no extension mechanism.", 116 + "affected_files": [ 117 + "lib/response.ml", 118 + "lib/response.mli" 119 + ], 120 + "rationale": "Extensions enable middleware to communicate without tight coupling. Surf's implementation (response.rs:124-132) uses type-erased storage. OCaml equivalent: add extensions field of type (string, Obj.t) Hashtbl.t or universal type pattern. Use cases: middleware adding timing data, cache hit/miss status, request tracing context, A/B test variants. This is especially valuable when combined with a middleware system. Alternative: use GADT-based heterogeneous maps for type safety." 121 + }, 122 + { 123 + "source_repo": "third_party/rust/surf", 124 + "source_language": "Rust", 125 + "criticality": "medium", 126 + "change_type": "enhancement", 127 + "title": "Improve redirect implementation to preserve request bodies", 128 + "description": "Surf's redirect middleware includes a detailed comment (redirect/mod.rs:80-92) noting a limitation: it must clone requests without bodies to avoid consuming the body stream prematurely. The OCaml library should be aware of this pattern and ensure redirect handling either: (1) only follows redirects for GET/HEAD that don't have bodies, (2) stores the body for potential replay, or (3) makes it clear that POST redirects may fail.", 129 + "affected_files": [ 130 + "lib/http_client.ml" 131 + ], 132 + "rationale": "HTTP redirects with request bodies are complex. Per RFC 7231, 303 changes POST to GET (body discarded), 307/308 preserve method and should preserve body. Surf's note (redirect/mod.rs:80-92) highlights the challenge: streaming bodies can't be replayed without buffering. OCaml implementation options: (1) disable redirect-following for requests with bodies by default, (2) buffer bodies for redirect replay with size limit, (3) add a config flag for this behavior. Document the limitation clearly to prevent user confusion." 133 + }, 134 + { 135 + "source_repo": "third_party/rust/surf", 136 + "source_language": "Rust", 137 + "criticality": "low", 138 + "change_type": "enhancement", 139 + "title": "Add TCP_NODELAY configuration option", 140 + "description": "Surf's Config provides set_tcp_no_delay() (config.rs:128-131) to control the TCP_NODELAY socket option. This disables Nagle's algorithm, which can be important for latency-sensitive applications making many small requests. The OCaml library doesn't expose this configuration, using whatever defaults Eio provides.", 141 + "affected_files": [ 142 + "lib/requests.ml", 143 + "lib/requests.mli" 144 + ], 145 + "rationale": "TCP_NODELAY trades bandwidth efficiency for latency. For HTTP clients making many small requests (API calls, microservices), disabling Nagle's algorithm reduces latency at the cost of more TCP packets. Surf exposes this (config.rs:128-131, default false). OCaml implementation: add tcp_nodelay field to session config, pass through to Eio socket options. Most useful for: interactive applications, real-time APIs, microservice communication. Less useful for: bulk transfers, file downloads." 146 + }, 147 + { 148 + "source_repo": "third_party/rust/surf", 149 + "source_language": "Rust", 150 + "criticality": "low", 151 + "change_type": "feature", 152 + "title": "Add client cloning with shared connection pools", 153 + "description": "Surf's Client implements Clone (client.rs:58-72) which creates a new client with a copied middleware stack but shared HTTP client and config. This enables creating derived clients with additional middleware while reusing connections. The OCaml library's session type is opaque and doesn't support cloning or derivation patterns.", 154 + "affected_files": [ 155 + "lib/requests.ml", 156 + "lib/requests.mli" 157 + ], 158 + "rationale": "Client cloning enables creating specialized clients from a base client. Surf's Clone (client.rs:58-72) copies middleware but shares http_client Arc for connection pooling. Use cases: base client for API + derived clients for specific services with custom headers/auth, testing with mock middleware, multi-tenant with per-tenant middleware. OCaml implementation: expose clone function that copies session record, keeping pool references shared. Alternatively, use record update syntax with documentation on shared vs copied fields." 159 + } 160 + ] 161 + }
+254
third_party/swift/alamofire.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "alamofire", 5 + "source_language": "swift", 6 + "criticality": "high", 7 + "change_type": "security", 8 + "title": "Add certificate pinning support for enhanced security", 9 + "description": "Alamofire implements certificate pinning and public key pinning through ServerTrustEvaluator protocol with PinnedCertificatesTrustEvaluator and PublicKeysTrustEvaluator. This allows applications to pin specific certificates or public keys to prevent MITM attacks even with compromised CAs. The OCaml library currently only supports basic TLS verification via ca-certs but lacks pinning capabilities.", 10 + "affected_files": [ 11 + "lib/requests.ml", 12 + "lib/requests.mli", 13 + "lib/one.ml", 14 + "lib/one.mli", 15 + "lib/http_client.ml" 16 + ], 17 + "rationale": "Certificate pinning is a critical security feature for high-security applications (banking, healthcare, etc.) that need protection beyond standard CA trust chains. Alamofire provides a well-designed protocol-based approach with separate evaluators for certificate pinning, public key pinning, and composite evaluation. The OCaml library should add similar functionality by: (1) creating a module for loading and validating pinned certificates/keys, (2) extending TLS configuration to accept custom validation callbacks, (3) providing helper functions to extract public keys from certificates, (4) supporting per-host pinning configuration similar to Alamofire's ServerTrustManager." 18 + }, 19 + { 20 + "source_repo": "alamofire", 21 + "source_language": "swift", 22 + "criticality": "high", 23 + "change_type": "security", 24 + "title": "Add OCSP/CRL certificate revocation checking", 25 + "description": "Alamofire implements RevocationTrustEvaluator with support for OCSP (Online Certificate Status Protocol) and CRL (Certificate Revocation List) checking with configurable options (prefer CRL, require positive response, network access control). The OCaml library lacks certificate revocation checking entirely, which means it cannot detect if a certificate has been revoked.", 26 + "affected_files": [ 27 + "lib/requests.ml", 28 + "lib/requests.mli", 29 + "lib/one.ml", 30 + "lib/error.ml" 31 + ], 32 + "rationale": "Certificate revocation checking is essential for production security as it detects compromised certificates that haven't expired yet. Without it, the library will trust revoked certificates. Alamofire's RevocationTrustEvaluator provides configurable OCSP and CRL checking with fallback strategies. The OCaml library should leverage ocaml-tls's revocation checking capabilities (if available) or implement OCSP checking using existing HTTP client capabilities to query OCSP responders. This is high priority because it closes a significant security gap." 33 + }, 34 + { 35 + "source_repo": "alamofire", 36 + "source_language": "swift", 37 + "criticality": "medium", 38 + "change_type": "feature", 39 + "title": "Implement request/response interceptor protocol for middleware", 40 + "description": "Alamofire provides RequestInterceptor protocol combining RequestAdapter (modify requests before sending) and RequestRetrier (custom retry logic). This enables powerful middleware patterns like: adding auth headers, logging, request modification, custom retry strategies, OAuth token refresh, and request queueing. The OCaml library has auth support but lacks a general interceptor mechanism for pre-request modification and custom retry logic.", 41 + "affected_files": [ 42 + "lib/requests.ml", 43 + "lib/requests.mli", 44 + "lib/one.ml", 45 + "lib/retry.ml" 46 + ], 47 + "rationale": "Interceptors provide a clean separation of concerns and enable composable request/response processing. Alamofire's design allows multiple adapters and retriers to be composed together. The OCaml library should add: (1) a request_adapter type = Headers.t -> Uri.t -> (Headers.t * Uri.t, Error.t) result function type to modify requests, (2) a request_retrier type for custom retry decisions, (3) support for adapter/retrier composition, (4) integration points in the request pipeline before sending and after receiving responses. This would enable users to implement OAuth refresh flows, request signing, custom logging, and domain-specific retry logic without modifying the library." 48 + }, 49 + { 50 + "source_repo": "alamofire", 51 + "source_language": "swift", 52 + "criticality": "medium", 53 + "change_type": "feature", 54 + "title": "Add comprehensive request/response lifecycle event monitoring", 55 + "description": "Alamofire provides EventMonitor protocol with 30+ lifecycle events covering URLSession events, request creation, adaptation, retry, task completion, metrics collection, and caching. This enables detailed logging, analytics, debugging, and performance monitoring without modifying core code. The OCaml library has basic logging via Logs library but no structured event monitoring API.", 56 + "affected_files": [ 57 + "lib/requests.ml", 58 + "lib/requests.mli", 59 + "lib/http_client.ml", 60 + "lib/retry.ml" 61 + ], 62 + "rationale": "Event monitoring is crucial for production observability, debugging, and analytics. Alamofire's EventMonitor provides hooks into every stage of the request lifecycle with queue-based dispatch for thread safety. The OCaml library should add: (1) an event_monitor module with event types (request_created, request_adapted, request_sent, response_received, request_retrying, request_completed, request_failed, metrics_collected), (2) a monitor registration API in Requests.create, (3) event dispatch at key points in the request pipeline, (4) include timing information and error details. This enables users to implement custom logging, send telemetry to monitoring services, debug connection issues, and track request performance." 63 + }, 64 + { 65 + "source_repo": "alamofire", 66 + "source_language": "swift", 67 + "criticality": "medium", 68 + "change_type": "enhancement", 69 + "title": "Enhance error types with more granular failure reasons", 70 + "description": "Alamofire's AFError uses nested enums for detailed failure reasons (e.g., MultipartEncodingFailureReason, ResponseValidationFailureReason, ServerTrustFailureReason) with associated values preserving context like URLs, status codes, acceptable content types, and underlying errors. It also provides convenience accessors (.responseCode, .acceptableContentTypes, .underlyingError) and boolean checks (.isExplicitlyCancelledError). The OCaml library has basic error types but lacks granular failure categorization.", 71 + "affected_files": [ 72 + "lib/error.ml", 73 + "lib/error.mli" 74 + ], 75 + "rationale": "Granular error types enable better error handling and debugging. Alamofire's approach of nested failure reasons within main error cases (e.g., ResponseValidationFailureReason with cases for unacceptableStatusCode, unacceptableContentType, dataFileNil) provides rich context while maintaining type safety. The OCaml library should enhance its error module to: (1) add nested variant types for failure reasons (e.g., type validation_failure_reason = Unacceptable_status_code of {code: int; acceptable: int list} | Unacceptable_content_type of {actual: string; acceptable: string list}), (2) extend HTTPError and other errors to include these detailed reasons, (3) add helper functions to extract common error properties, (4) preserve more context in error cases (acceptable ranges, expected vs actual values). This improves error messages and enables more precise error handling." 76 + }, 77 + { 78 + "source_repo": "alamofire", 79 + "source_language": "swift", 80 + "criticality": "medium", 81 + "change_type": "feature", 82 + "title": "Add automatic OAuth2 authentication with token refresh interceptor", 83 + "description": "Alamofire provides AuthenticationInterceptor with Authenticator protocol that handles OAuth2-style authentication including: automatic token refresh when expired, request queuing during refresh, excessive refresh protection via RefreshWindow, thread-safe credential management, and automatic retry of failed requests after refresh. The OCaml library has Bearer token support but no automatic refresh mechanism.", 84 + "affected_files": [ 85 + "lib/auth.ml", 86 + "lib/auth.mli", 87 + "lib/requests.ml", 88 + "lib/requests.mli" 89 + ], 90 + "rationale": "Automatic token refresh is essential for OAuth2 flows in long-running applications. Alamofire's design queues requests when a token is refreshing (preventing multiple simultaneous refresh attempts) and has protection against refresh loops. The OCaml library should add: (1) a credential type with expiration tracking, (2) an authenticator signature with functions for applying credentials, refreshing, detecting auth failures, and checking credential usage, (3) an authentication_interceptor that integrates with the request pipeline to detect 401 responses, trigger refresh, queue pending requests, and retry after refresh, (4) refresh window tracking to prevent excessive refresh loops. This would enable seamless OAuth2 integration for APIs requiring token refresh." 91 + }, 92 + { 93 + "source_repo": "alamofire", 94 + "source_language": "swift", 95 + "criticality": "medium", 96 + "change_type": "enhancement", 97 + "title": "Add response validation API with custom validators", 98 + "description": "Alamofire provides validation API with .validate() for default validation (200-299 status, Content-Type matching) and .validate(_ validation: @escaping Validation) for custom validation logic. Validators can check status codes, content types, response data, and return detailed validation failures. The OCaml library has Response.ok and Response.raise_for_status but no composable validation API.", 99 + "affected_files": [ 100 + "lib/response.ml", 101 + "lib/response.mli", 102 + "lib/requests.ml" 103 + ], 104 + "rationale": "Validation API provides a clean way to specify response acceptance criteria and automatically raise errors for invalid responses. Alamofire's approach allows chaining multiple validators and provides detailed validation failure reasons. The OCaml library should add: (1) a validation module with validator type = Response.t -> (unit, Error.t) result, (2) built-in validators for status code ranges, content types, custom predicates, (3) validation composition via validator list, (4) integration with request execution to run validators before returning response, (5) detailed validation errors in Error module. This enables declarative response validation (e.g., validate ~status:[200-299] ~content_types:[\"application/json\"])." 105 + }, 106 + { 107 + "source_repo": "alamofire", 108 + "source_language": "swift", 109 + "criticality": "medium", 110 + "change_type": "enhancement", 111 + "title": "Improve retry logic to use Retry-After header value in backoff calculation", 112 + "description": "Alamofire's RetryPolicy respects the Retry-After HTTP header (both integer seconds and HTTP date formats) and uses it as the retry delay when present, overriding the exponential backoff calculation. The OCaml library has parse_retry_after function in retry.ml but it's not actively used in the with_retry function - the backoff is always calculated from config regardless of Retry-After header presence.", 113 + "affected_files": [ 114 + "lib/retry.ml", 115 + "lib/retry.mli", 116 + "lib/requests.ml" 117 + ], 118 + "rationale": "The Retry-After header is specifically designed to tell clients when to retry (commonly used with 429 Too Many Requests, 503 Service Unavailable). Ignoring it can lead to wasted retry attempts or premature retries that get rejected. The code at retry.ml already has parse_retry_after but it's not integrated into the retry loop. The with_retry function needs to: (1) accept response headers as input when retrying HTTP errors, (2) check for Retry-After header and parse it, (3) use Retry-After value instead of calculated backoff when config.respect_retry_after is true and header is present, (4) log when using Retry-After vs calculated backoff. This is a medium priority enhancement that improves retry behavior and respects server guidance." 119 + }, 120 + { 121 + "source_repo": "alamofire", 122 + "source_language": "swift", 123 + "criticality": "medium", 124 + "change_type": "enhancement", 125 + "title": "Add response caching with custom cache policies", 126 + "description": "Alamofire provides CachedResponseHandler protocol allowing custom cache behavior (cache all responses, cache only successful, modify cached responses, prevent caching for sensitive data). It integrates with URLCache for HTTP caching with configurable policies. The OCaml library explicitly disables caching for simplicity (noted in TODO.md).", 127 + "affected_files": [ 128 + "lib/requests.ml", 129 + "lib/requests.mli", 130 + "lib/response.ml" 131 + ], 132 + "rationale": "Response caching improves performance and reduces bandwidth for repeated requests. Alamofire's CachedResponseHandler provides fine-grained control over what gets cached and how. While the OCaml library currently avoids caching for simplicity, adding optional caching support would benefit applications making repeated requests. Implementation should: (1) create a cache module with in-memory and disk-based cache options, (2) implement HTTP cache semantics (Cache-Control, ETag, If-Modified-Since), (3) add cache_policy configuration to requests, (4) provide default policies (no-cache, cache-all, cache-successful, respect-headers), (5) allow custom cache handlers. This can be optional (disabled by default) to maintain current simplicity while enabling caching when needed." 133 + }, 134 + { 135 + "source_repo": "alamofire", 136 + "source_language": "swift", 137 + "criticality": "low", 138 + "change_type": "enhancement", 139 + "title": "Add custom redirect handling with RedirectHandler protocol", 140 + "description": "Alamofire provides RedirectHandler protocol allowing custom redirect behavior (follow all, follow with modifications, block certain redirects, log redirects). The default Redirector.follow follows redirects while Redirector.doNotFollow blocks them. The OCaml library automatically follows redirects up to a configured maximum but doesn't provide hooks for custom redirect logic.", 141 + "affected_files": [ 142 + "lib/requests.ml", 143 + "lib/requests.mli", 144 + "lib/http_client.ml" 145 + ], 146 + "rationale": "Custom redirect handling enables security policies (block cross-origin redirects, require HTTPS), logging, and redirect modification. Alamofire's protocol-based approach allows users to implement custom redirect logic without modifying the library. The OCaml library should add: (1) a redirect_handler type = Response.t -> string option -> (string option, Error.t) result where None blocks redirect and Some url allows it, (2) default handlers (follow_all, follow_same_origin, follow_https_only), (3) integration with redirect loop in http_client.ml to call handler before following redirects. This is lower priority since basic redirect following works well, but custom handlers enable advanced use cases like redirect logging and security policies." 147 + }, 148 + { 149 + "source_repo": "alamofire", 150 + "source_language": "swift", 151 + "criticality": "high", 152 + "change_type": "bug", 153 + "title": "Fix retry logic to pass response headers for Retry-After parsing", 154 + "description": "The retry.ml module has parse_retry_after function and respect_retry_after config field, but the with_retry function only receives exceptions and cannot access response headers needed to parse Retry-After. In Alamofire, the RequestRetrier protocol receives the full request and response context, enabling access to HTTP headers for intelligent retry decisions.", 155 + "affected_files": [ 156 + "lib/retry.ml", 157 + "lib/retry.mli", 158 + "lib/requests.ml" 159 + ], 160 + "rationale": "This is a bug where implemented functionality (parse_retry_after) cannot be used due to architectural limitation. The with_retry function signature is `~should_retry_exn:(exn -> bool)` which only provides exception information. For HTTP errors, response headers are not accessible in exception form. The fix requires: (1) modifying HTTPError exception to include all headers (currently included), (2) extracting headers from HTTPError in retry logic, (3) parsing Retry-After from headers when available, (4) using parsed value instead of calculated backoff when respect_retry_after=true. This should be high priority as it makes the respect_retry_after configuration actually functional. The parse_retry_after function exists but is dead code until headers are accessible in retry logic." 161 + }, 162 + { 163 + "source_repo": "alamofire", 164 + "source_language": "swift", 165 + "criticality": "medium", 166 + "change_type": "enhancement", 167 + "title": "Add comprehensive test coverage for authentication mechanisms", 168 + "description": "Alamofire has dedicated test files (AuthenticationTests.swift, AuthenticationInterceptorTests.swift) testing Basic auth, Bearer token, Digest auth with various challenges, and OAuth token refresh flows with concurrent requests, refresh failures, and excessive refresh protection. The OCaml library has auth.ml with Digest implementation but no tests in test/ directory validating authentication behavior.", 169 + "affected_files": [ 170 + "test/test_auth.ml" 171 + ], 172 + "rationale": "The OCaml library has sophisticated Digest auth implementation (RFC 7616 compliant with MD5, SHA-256, SHA-512/256, qop support, cnonce generation) but no tests validating correctness. Alamofire's auth tests cover: Basic auth encoding, Bearer token headers, Digest challenge parsing, response computation, multiple auth attempts, and OAuth refresh scenarios. The OCaml library needs: (1) tests for Basic auth header formatting, (2) tests for Bearer token application, (3) tests for Digest challenge parsing with various algorithms and qop values, (4) tests for Digest response computation against known test vectors, (5) tests for Custom auth handlers. This is medium priority as auth code exists but lacks validation." 173 + }, 174 + { 175 + "source_repo": "alamofire", 176 + "source_language": "swift", 177 + "criticality": "medium", 178 + "change_type": "enhancement", 179 + "title": "Add comprehensive test coverage for retry logic and timeout handling", 180 + "description": "Alamofire has extensive retry tests covering exponential backoff calculation, jitter, status code filtering, method filtering, Retry-After header parsing, and concurrent retry scenarios. It also has timeout tests for connection and read timeouts. The OCaml library has retry.ml and timeout.ml implementations but no dedicated tests validating retry behavior, backoff calculations, or timeout enforcement.", 181 + "affected_files": [ 182 + "test/test_retry.ml", 183 + "test/test_timeout.ml" 184 + ], 185 + "rationale": "Retry and timeout logic is critical for reliability but complex to get right (exponential backoff, jitter, Retry-After parsing, timeout coordination). Alamofire's tests validate: (1) backoff calculation with different factors and attempt counts, (2) jitter randomization, (3) max backoff capping, (4) status code filtering, (5) method filtering (idempotent only), (6) Retry-After header parsing (both integer seconds and HTTP dates), (7) timeout enforcement at various stages. The OCaml library needs similar tests to ensure: retry config defaults are correct, backoff formula matches documentation, jitter prevents thundering herd, Retry-After parsing handles edge cases, retries don't exceed max_retries, timeouts fire correctly. This is medium priority as retry/timeout bugs can cause cascading failures in production." 186 + }, 187 + { 188 + "source_repo": "alamofire", 189 + "source_language": "swift", 190 + "criticality": "medium", 191 + "change_type": "enhancement", 192 + "title": "Add comprehensive test coverage for TLS/certificate validation", 193 + "description": "Alamofire has ServerTrustEvaluatorTests.swift and TLSEvaluationTests.swift testing certificate validation, certificate pinning, public key pinning, revocation checking, self-signed certificate handling, and various trust evaluation scenarios. The OCaml library uses tls-eio and ca-certs but has no tests validating TLS behavior, certificate verification, or error handling for TLS failures.", 194 + "affected_files": [ 195 + "test/test_tls.ml", 196 + "test/test_security.ml" 197 + ], 198 + "rationale": "TLS/certificate validation is critical for security but the OCaml library has no tests validating: (1) successful HTTPS connections, (2) certificate verification failures for invalid certificates, (3) hostname mismatch detection, (4) expired certificate rejection, (5) self-signed certificate rejection (when verify_tls=true), (6) verify_tls=false bypassing validation, (7) TLS handshake errors, (8) SNI support. Alamofire's tests use test certificates and mock servers to validate all trust evaluation paths. The OCaml library should add similar tests using test certificates (valid, expired, self-signed, wrong hostname) to ensure tls-eio integration works correctly. This is medium priority as TLS misconfiguration can have severe security implications." 199 + }, 200 + { 201 + "source_repo": "alamofire", 202 + "source_language": "swift", 203 + "criticality": "low", 204 + "change_type": "enhancement", 205 + "title": "Add request/response metrics collection", 206 + "description": "Alamofire collects URLSessionTaskMetrics including timing information (DNS lookup, connection establishment, TLS handshake, request/response transfer), transfer sizes, connection info (protocol, cipher suite), and network quality. Metrics are available via EventMonitor or response completion. The OCaml library tracks basic elapsed time but no detailed metrics.", 207 + "affected_files": [ 208 + "lib/response.ml", 209 + "lib/response.mli", 210 + "lib/requests.ml" 211 + ], 212 + "rationale": "Detailed metrics enable performance optimization and debugging. Alamofire's metrics include DNS resolution time, connection time, TLS handshake time, first byte time, and transfer times. The OCaml library should add: (1) a metrics module tracking timing breakdowns (dns_lookup_duration, connection_duration, tls_handshake_duration, request_duration, response_duration), (2) transfer size tracking (request_body_size, response_body_size, compressed vs uncompressed), (3) connection info (protocol version, reused connection), (4) include metrics in Response.t or make available via callback. This is lower priority as basic timing (elapsed) exists, but detailed metrics help identify bottlenecks (slow DNS, slow TLS handshake, large responses)." 213 + }, 214 + { 215 + "source_repo": "alamofire", 216 + "source_language": "swift", 217 + "criticality": "low", 218 + "change_type": "feature", 219 + "title": "Add network reachability monitoring for retry decisions", 220 + "description": "Alamofire provides NetworkReachabilityManager monitoring network connectivity changes (WiFi, cellular, unreachable) with notification callbacks. It integrates with retry logic via ConnectionLostRetrier which waits for network reachability before retrying. The OCaml library has no network reachability monitoring.", 221 + "affected_files": [ 222 + "lib/retry.ml", 223 + "lib/retry.mli" 224 + ], 225 + "rationale": "Network reachability monitoring enables smarter retry strategies that wait for network availability instead of blindly retrying during network outages. Alamofire's ConnectionLostRetrier pauses retries when network is unreachable and resumes when connectivity returns. For OCaml, this could leverage platform-specific reachability APIs or implement simple connectivity checks (ping known server, check default gateway). Implementation should: (1) add optional reachability monitoring, (2) integrate with retry logic to pause retries when network is down, (3) provide reachability status in session state. This is lower priority as exponential backoff with jitter already handles temporary network issues, but reachability monitoring provides better UX for long network outages." 226 + }, 227 + { 228 + "source_repo": "alamofire", 229 + "source_language": "swift", 230 + "criticality": "low", 231 + "change_type": "enhancement", 232 + "title": "Add multipart streaming with progress callbacks", 233 + "description": "Alamofire supports multipart uploads with progress callbacks tracking bytes sent/total bytes for upload progress UI. The OCaml library has multipart support in body.ml but no progress tracking for large file uploads.", 234 + "affected_files": [ 235 + "lib/body.ml", 236 + "lib/body.mli", 237 + "lib/requests.ml" 238 + ], 239 + "rationale": "Progress callbacks enable upload progress UI for large file uploads, important for user experience in applications uploading photos, videos, documents. Alamofire provides uploadProgress callback with fractionCompleted, completedUnitCount, totalUnitCount. The OCaml library should add: (1) optional progress callback to multipart upload functions, (2) track bytes written during upload, (3) invoke callback periodically during upload, (4) provide both upload and download progress. This is lower priority as uploads work without it, but progress tracking significantly improves UX for large transfers." 240 + }, 241 + { 242 + "source_repo": "alamofire", 243 + "source_language": "swift", 244 + "criticality": "low", 245 + "change_type": "enhancement", 246 + "title": "Add brotli compression support alongside gzip and deflate", 247 + "description": "Alamofire supports all common HTTP compression schemes (gzip, deflate, brotli) via URLSession's automatic decompression. The OCaml library supports gzip, deflate, and zlib decompression in http_client.ml but not brotli, which is increasingly common (used by many CDNs and modern web servers).", 248 + "affected_files": [ 249 + "lib/http_client.ml" 250 + ], 251 + "rationale": "Brotli provides better compression than gzip (typically 15-25% smaller) and is supported by all modern browsers and many CDNs. Adding brotli support would enable the library to handle more server responses and potentially reduce bandwidth. Implementation requires: (1) adding decompress-brotli dependency (if available in OCaml ecosystem), (2) adding brotli case to decompress_body function, (3) adding 'br' to Accept-Encoding header. This is low priority as gzip/deflate cover most cases, but brotli support is increasingly standard in HTTP clients. Check if ocaml-brotli or similar library exists before implementing." 252 + } 253 + ] 254 + }
+178
third_party/swift/just.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/swift/just", 5 + "source_language": "Swift", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add progress tracking/streaming callbacks for upload and download operations", 9 + "description": "The Swift library provides asyncProgressHandler that reports bytes processed and expected during uploads/downloads with chunk data access. This enables real-time progress indicators and streaming chunk processing. The OCaml library lacks this capability - responses are fully materialized before being returned, making it impossible to track progress or process data incrementally for large transfers.", 10 + "affected_files": [ 11 + "lib/requests.mli", 12 + "lib/requests.ml", 13 + "lib/response.mli", 14 + "lib/response.ml", 15 + "lib/one.mli", 16 + "lib/one.ml" 17 + ], 18 + "rationale": "Progress callbacks are essential for modern HTTP clients handling large files. Users need real-time feedback for uploads/downloads (e.g., progress bars in CLI tools, monitoring data transfer in long-running operations). The current implementation forces full materialization of responses, which is inefficient for large files and provides no visibility into transfer progress. Adding optional progress callbacks (bytes_processed, bytes_total, chunk_data) would enable: 1) Progress indicators for user feedback, 2) Incremental processing of streaming data, 3) Early termination of transfers, 4) Better resource management for large files." 19 + }, 20 + { 21 + "source_repo": "third_party/swift/just", 22 + "source_language": "Swift", 23 + "criticality": "medium", 24 + "change_type": "feature", 25 + "title": "Add Link header parsing support for pagination", 26 + "description": "The Swift library includes automatic parsing of RFC 8288 Link headers into a structured format (r.links['next']['url']). This is commonly used for REST API pagination (GitHub, GitLab, etc.). The OCaml library only provides raw header access via Headers.get, requiring users to manually parse complex Link headers with multiple rel values.", 27 + "affected_files": [ 28 + "lib/response.mli", 29 + "lib/response.ml" 30 + ], 31 + "rationale": "Link header parsing is a common requirement when working with paginated REST APIs. The Link header format is complex (multiple comma-separated entries, quoted/unquoted values, various rel types). Providing a Response.links function that returns a (string * (string * string) list) list mapping rel names to their parameters would significantly improve API ergonomics. This is particularly valuable for GitHub, GitLab, and other APIs following RFC 8288 for pagination links (next, prev, first, last)." 32 + }, 33 + { 34 + "source_repo": "third_party/swift/just", 35 + "source_language": "Swift", 36 + "criticality": "medium", 37 + "change_type": "enhancement", 38 + "title": "Add convenience response status predicates (is_redirect, is_permanent_redirect)", 39 + "description": "The Swift library provides r.isRedirect (status 3xx), r.isPermanentRedirect (status 301), and r.ok (status 2xx) as convenient boolean properties. The OCaml library only has Response.ok for 2xx checks. Users must manually check status_code against ranges for redirects, which is error-prone and less readable.", 40 + "affected_files": [ 41 + "lib/response.mli", 42 + "lib/response.ml", 43 + "lib/status.mli", 44 + "lib/status.ml" 45 + ], 46 + "rationale": "Providing convenience predicates improves code readability and reduces errors. Common status code checks (is_redirect, is_permanent_redirect, is_client_error, is_server_error, is_informational) make client code more expressive: 'if Response.is_redirect resp then ...' vs 'let s = Response.status_code resp in if s >= 300 && s < 400 then ...'. The Status module already has some of these (is_success, is_client_error, is_server_error, is_retryable) but Response doesn't expose convenience wrappers. Adding Response-level helpers and ensuring Status module has all common predicates would improve usability." 47 + }, 48 + { 49 + "source_repo": "third_party/swift/just", 50 + "source_language": "Swift", 51 + "criticality": "low", 52 + "change_type": "enhancement", 53 + "title": "Add response description/formatting for logging and debugging", 54 + "description": "The Swift library provides a concise description property on responses: 'GET https://example.com 200'. This is useful for logging and debugging. The OCaml library has Response.pp and Response.pp_detailed but these may not produce the compact single-line format useful for logs.", 55 + "affected_files": [ 56 + "lib/response.mli", 57 + "lib/response.ml" 58 + ], 59 + "rationale": "A compact, single-line response representation is valuable for logging HTTP traffic in applications. The format 'METHOD URL STATUS' provides essential information at a glance. While the library has pretty-printers, adding a Response.to_string or ensuring Response.pp produces a compact format would improve debugging ergonomics. This is particularly useful when logging multiple requests in concurrent applications where the output needs to be scannable." 60 + }, 61 + { 62 + "source_repo": "third_party/swift/just", 63 + "source_language": "Swift", 64 + "criticality": "low", 65 + "change_type": "enhancement", 66 + "title": "Add session-level default parameters and automatic header merging", 67 + "description": "The Swift library JustSessionDefaults allows configuring default headers, JSON serialization options, encoding, cache policy, and multipart boundary at the session level. These defaults are automatically merged with per-request parameters. The OCaml library has default_headers in the session but lacks some other session-level defaults like JSON encoding options or multipart boundary customization.", 68 + "affected_files": [ 69 + "lib/requests.mli", 70 + "lib/requests.ml" 71 + ], 72 + "rationale": "Session-level defaults reduce boilerplate when making multiple requests with similar configuration. While the OCaml library has some session state (default_headers, auth, timeout), adding more configurable defaults (e.g., custom multipart boundary, default User-Agent, default Accept header) would improve consistency across requests. The multipart boundary is currently hardcoded in body.ml - making it configurable at the session level would allow testing and customization scenarios." 73 + }, 74 + { 75 + "source_repo": "third_party/swift/just", 76 + "source_language": "Swift", 77 + "criticality": "medium", 78 + "change_type": "security", 79 + "title": "Add credential persistence configuration options", 80 + "description": "The Swift library exposes credentialPersistence settings (URLCredential.Persistence: .none, .forSession, .permanent, .synchronizable) allowing control over how auth credentials are stored. The OCaml library handles Digest auth credentials but doesn't expose explicit persistence controls for credential storage between sessions.", 81 + "affected_files": [ 82 + "lib/requests.mli", 83 + "lib/requests.ml", 84 + "lib/auth.mli", 85 + "lib/auth.ml" 86 + ], 87 + "rationale": "Credential persistence has security implications. Applications need control over whether credentials are stored in-memory only, persisted to disk, or synchronized across devices. While the OCaml library doesn't use a platform credential store like Swift, exposing explicit configuration for credential handling would improve security posture: 1) Clear documentation of persistence behavior, 2) Options to prevent credential persistence for sensitive applications, 3) Integration with system keychains if added in future. Currently credentials are only ephemeral in the session object, but making this explicit with configuration options would clarify security boundaries." 88 + }, 89 + { 90 + "source_repo": "third_party/swift/just", 91 + "source_language": "Swift", 92 + "criticality": "low", 93 + "change_type": "enhancement", 94 + "title": "Support urlQuery parameter for raw query string injection", 95 + "description": "The Swift library supports both 'params' (key-value dict automatically encoded) and 'urlQuery' (raw query string passed through verbatim). The OCaml library only supports 'params' for typed parameter construction. This makes it difficult to pass pre-encoded query strings or work with non-standard query formats.", 96 + "affected_files": [ 97 + "lib/requests.mli", 98 + "lib/requests.ml", 99 + "lib/one.mli", 100 + "lib/one.ml" 101 + ], 102 + "rationale": "Some APIs use non-standard query string formats or require pre-encoded query strings that don't fit the key-value model. Adding an optional raw_query:string parameter alongside params would provide escape hatch for edge cases: 1) Pre-encoded query strings from external sources, 2) Complex query formats not representable as key-value pairs, 3) Performance optimization when query string is already constructed. The two parameters would be mutually exclusive or merged appropriately." 103 + }, 104 + { 105 + "source_repo": "third_party/swift/just", 106 + "source_language": "Swift", 107 + "criticality": "high", 108 + "change_type": "feature", 109 + "title": "Add response.request property to access original request details", 110 + "description": "The Swift library exposes response.request (the URLRequest object) and response.task (the URLSessionTask), allowing inspection of what was actually sent. The OCaml library stores url and elapsed on responses but doesn't expose the original request headers, method, or body that were sent.", 111 + "affected_files": [ 112 + "lib/response.mli", 113 + "lib/response.ml" 114 + ], 115 + "rationale": "Access to the original request is critical for debugging HTTP issues. When a request fails or behaves unexpectedly, developers need to inspect what was actually sent (headers after auth, final URL after redirects, merged headers, etc.). This is especially important for: 1) Debugging authentication issues (was auth header added correctly?), 2) Verifying header merging (did default headers get applied?), 3) Logging complete request/response pairs, 4) Testing frameworks that need to assert on sent requests. Adding Response.request_method, Response.request_headers, and Response.request_url (in addition to the existing response.url which is the final URL after redirects) would enable these scenarios." 116 + }, 117 + { 118 + "source_repo": "third_party/swift/just", 119 + "source_language": "Swift", 120 + "criticality": "medium", 121 + "change_type": "enhancement", 122 + "title": "Add support for cancellable requests", 123 + "description": "The Swift library provides HTTPResult.cancel() to abort in-flight requests and returns a task object for each request. The OCaml library using Eio can cancel via switch cancellation, but doesn't expose request-level cancellation or provide handles to individual request fibers.", 124 + "affected_files": [ 125 + "lib/requests.mli", 126 + "lib/requests.ml", 127 + "lib/response.mli", 128 + "lib/response.ml" 129 + ], 130 + "rationale": "Individual request cancellation is important for responsive applications. While Eio allows switch-based cancellation of fiber groups, fine-grained request cancellation enables: 1) User-initiated cancellation (cancel button in UI), 2) Timeout-based cancellation of specific requests in a batch, 3) Speculative request cancellation when results are no longer needed. Exposing the request fiber or a cancel_promise in the Response type would enable this. Alternatively, providing an async request API that returns a Promise/Future with cancellation support would achieve the same goal while maintaining the current synchronous API as default." 131 + }, 132 + { 133 + "source_repo": "third_party/swift/just", 134 + "source_language": "Swift", 135 + "criticality": "low", 136 + "change_type": "enhancement", 137 + "title": "Add response.reason property for human-readable status descriptions", 138 + "description": "The Swift library provides response.reason which returns human-readable status text ('ok', 'not found', 'internal server error') based on a comprehensive status code dictionary. The OCaml library has Status module with status codes but doesn't expose status reason phrases in responses.", 139 + "affected_files": [ 140 + "lib/response.mli", 141 + "lib/response.ml", 142 + "lib/status.mli", 143 + "lib/status.ml" 144 + ], 145 + "rationale": "Human-readable status descriptions improve error messages and logging. Rather than showing '404' to users, applications can display 'Not Found'. The Status module should include a complete mapping of status codes to standard reason phrases (matching RFC 7231 and common extensions like 429 'Too Many Requests'). Adding Response.reason or Response.status_text would expose this. This is particularly useful for: 1) User-facing error messages, 2) Log readability, 3) Debugging without memorizing status codes." 146 + }, 147 + { 148 + "source_repo": "third_party/swift/just", 149 + "source_language": "Swift", 150 + "criticality": "medium", 151 + "change_type": "feature", 152 + "title": "Add proper error type wrapping in responses for async completion handlers", 153 + "description": "The Swift library stores both response data AND errors in HTTPResult.error, allowing async completion handlers to receive a single result object containing either success or failure information. The OCaml library uses exceptions for errors, which is appropriate for Eio but doesn't provide a unified response+error type for scenarios where users want Result-based error handling.", 154 + "affected_files": [ 155 + "lib/response.mli", 156 + "lib/response.ml", 157 + "lib/error.mli", 158 + "lib/error.ml", 159 + "lib/requests.mli", 160 + "lib/requests.ml" 161 + ], 162 + "rationale": "While the Error module provides Result-based combinators, the main request functions return Response.t and raise exceptions. Some users prefer Result types for explicit error handling. Adding request_result variants (e.g., request_result: ... -> (Response.t, Error.t) result) would accommodate both styles. This is particularly valuable for: 1) Functional error handling without exceptions, 2) Explicit error type propagation in typed contexts, 3) Integration with Result-based application architectures. The Error module already has the infrastructure (catch, to_exn, of_exn), but the main API doesn't expose Result-returning variants." 163 + }, 164 + { 165 + "source_repo": "third_party/swift/just", 166 + "source_language": "Swift", 167 + "criticality": "medium", 168 + "change_type": "bug", 169 + "title": "Fix missing Retry-After header handling in retry logic", 170 + "description": "The Swift library doesn't implement Retry-After header handling in its code, but the OCaml library has retry.respect_retry_after:bool config and retry.parse_retry_after function. However, the actual request retry logic in requests.ml doesn't check response headers for Retry-After and use that delay instead of exponential backoff. This means the config option is defined but not actually used.", 171 + "affected_files": [ 172 + "lib/requests.ml", 173 + "lib/retry.ml" 174 + ], 175 + "rationale": "The retry configuration has respect_retry_after: true by default, and Retry.parse_retry_after is implemented to parse both integer seconds and HTTP-date formats. However, requests.ml:541-557 uses Retry.calculate_backoff unconditionally without checking if the response contained a Retry-After header. This is a bug - when a 429 or 503 response includes Retry-After, the client should honor that delay instead of using exponential backoff. Fix: In the retry loop, when a retryable status is received, check if Headers.get 'Retry-After' is present, parse it with Retry.parse_retry_after, and use that delay (respecting backoff_max cap) instead of calculate_backoff when respect_retry_after is true." 176 + } 177 + ] 178 + }
+307
third_party/swift/kingfisher.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/swift/kingfisher", 5 + "source_language": "Swift", 6 + "criticality": "high", 7 + "change_type": "bug", 8 + "title": "Add error code enumeration for programmatic error handling", 9 + "description": "Implement numeric error codes (similar to Kingfisher's 1001-5006 system) to enable programmatic error handling. Currently, the OCaml library uses variant types which are excellent for pattern matching, but adding error codes would facilitate logging, monitoring, metrics collection, and cross-language error reporting. Each error variant should map to a unique integer code.", 10 + "affected_files": [ 11 + "lib/error.ml", 12 + "lib/error.mli" 13 + ], 14 + "rationale": "Kingfisher uses a hierarchical error code system (RequestError: 1001-1005, ResponseError: 2001-2006, CacheError: 3001-3012, etc.) that enables structured error logging and monitoring. This is particularly valuable for production systems that need to aggregate error metrics, create alerts based on error types, or interface with monitoring systems. The OCaml library would benefit from adding an error_code function that maps each error variant to a unique integer." 15 + }, 16 + { 17 + "source_repo": "third_party/swift/kingfisher", 18 + "source_language": "Swift", 19 + "criticality": "medium", 20 + "change_type": "feature", 21 + "title": "Add Low Data Mode detection and fallback mechanism", 22 + "description": "Implement detection for constrained network conditions (similar to iOS Low Data Mode) and provide a fallback mechanism. This would involve detecting network constraint errors and allowing users to configure alternative sources or degraded quality responses when network is constrained.", 23 + "affected_files": [ 24 + "lib/error.ml", 25 + "lib/error.mli", 26 + "lib/requests.ml", 27 + "lib/requests.mli", 28 + "lib/one.ml", 29 + "lib/one.mli" 30 + ], 31 + "rationale": "Kingfisher detects Low Data Mode via URLError and provides fallback mechanisms. While this is iOS-specific, the concept of handling constrained network conditions applies to any client. OCaml HTTP clients could detect similar conditions (connection throttling, quota errors) and provide graceful degradation. This improves user experience in bandwidth-limited environments." 32 + }, 33 + { 34 + "source_repo": "third_party/swift/kingfisher", 35 + "source_language": "Swift", 36 + "criticality": "medium", 37 + "change_type": "enhancement", 38 + "title": "Add network-aware retry strategy based on connectivity changes", 39 + "description": "Implement a reactive retry strategy that monitors network connectivity and automatically retries requests when network becomes available, similar to Kingfisher's NetworkRetryStrategy. This complements the existing delay-based retry with an event-driven approach that doesn't waste time polling during network outages.", 40 + "affected_files": [ 41 + "lib/retry.ml", 42 + "lib/retry.mli", 43 + "lib/requests.ml" 44 + ], 45 + "rationale": "Kingfisher implements two retry strategies: DelayRetryStrategy (time-based) and NetworkRetryStrategy (connectivity-based). The OCaml library only implements delay-based retries. A network-aware strategy would immediately retry when connectivity is restored rather than waiting for the next exponential backoff interval. This is particularly useful for mobile/laptop clients that experience network transitions (WiFi to cellular, airplane mode, etc.)." 46 + }, 47 + { 48 + "source_repo": "third_party/swift/kingfisher", 49 + "source_language": "Swift", 50 + "criticality": "medium", 51 + "change_type": "enhancement", 52 + "title": "Enhance Retry-After header parsing with better date format support", 53 + "description": "Improve the parse_retry_after function to handle a wider variety of HTTP date formats beyond RFC 3339, including IMF-fixdate (RFC 7231), RFC 850, and asctime formats as required by HTTP specifications.", 54 + "affected_files": [ 55 + "lib/retry.ml", 56 + "lib/retry.mli" 57 + ], 58 + "rationale": "The current implementation in retry.ml:73-93 attempts RFC 3339 parsing but notes it's simplified. Kingfisher handles multiple date formats through URLSession's native parsing. The HTTP specification allows Retry-After as either delta-seconds or HTTP-date. Robust HTTP clients should parse all valid HTTP date formats. Consider using an HTTP date parsing library or implementing support for IMF-fixdate (the preferred HTTP date format per RFC 7231)." 59 + }, 60 + { 61 + "source_repo": "third_party/swift/kingfisher", 62 + "source_language": "Swift", 63 + "criticality": "high", 64 + "change_type": "security", 65 + "title": "Add task cancellation tokens and race condition detection", 66 + "description": "Implement cancellation tokens for requests and detect race conditions where a response arrives for a task that has been superseded by a newer request to the same resource. This prevents stale data from overwriting fresh data in scenarios where multiple rapid requests are made for the same resource.", 67 + "affected_files": [ 68 + "lib/requests.ml", 69 + "lib/requests.mli", 70 + "lib/one.ml", 71 + "lib/one.mli", 72 + "lib/response.ml", 73 + "lib/response.mli" 74 + ], 75 + "rationale": "Kingfisher tracks task identity and raises notCurrentSourceTask errors (5002, 5005) when a response arrives but the request has been superseded. This prevents race conditions in UI updates where rapid successive requests could result in stale data being displayed. The OCaml library uses Eio's structured concurrency and switches, but doesn't explicitly track task identity or prevent stale response processing. Adding request IDs and validation would improve correctness in high-concurrency scenarios." 76 + }, 77 + { 78 + "source_repo": "third_party/swift/kingfisher", 79 + "source_language": "Swift", 80 + "criticality": "low", 81 + "change_type": "enhancement", 82 + "title": "Add alternative source fallback mechanism", 83 + "description": "Implement a fallback system where requests can specify alternative sources to try if the primary source fails. This allows graceful degradation by trying CDN mirrors, fallback endpoints, or cached versions when the primary source is unavailable.", 84 + "affected_files": [ 85 + "lib/requests.ml", 86 + "lib/requests.mli", 87 + "lib/one.ml", 88 + "lib/one.mli" 89 + ], 90 + "rationale": "Kingfisher's alternativeSources option allows specifying backup sources that are tried when the primary source fails. This pattern improves reliability and availability. An OCaml implementation could accept a list of fallback URLs or a fallback function that's called on primary failure. This is particularly useful for CDN scenarios or multi-region deployments." 91 + }, 92 + { 93 + "source_repo": "third_party/swift/kingfisher", 94 + "source_language": "Swift", 95 + "criticality": "medium", 96 + "change_type": "feature", 97 + "title": "Add request priority support for connection scheduling", 98 + "description": "Implement request priority levels that affect connection pool scheduling, allowing high-priority requests to be processed before low-priority background requests. This maps to URLSessionTask.priority in networking layers.", 99 + "affected_files": [ 100 + "lib/requests.ml", 101 + "lib/requests.mli", 102 + "lib/one.ml", 103 + "lib/one.mli" 104 + ], 105 + "rationale": "Kingfisher supports downloadPriority option that maps to URLSessionTask.priority. Priority queuing ensures critical user-facing requests complete before background prefetching or analytics. While the OCaml library uses Conpool for connection pooling, there's no explicit priority mechanism. Adding priority levels (high, normal, low) would improve responsiveness in applications making many concurrent requests." 106 + }, 107 + { 108 + "source_repo": "third_party/swift/kingfisher", 109 + "source_language": "Swift", 110 + "criticality": "low", 111 + "change_type": "enhancement", 112 + "title": "Add response caching layer with memory and disk storage", 113 + "description": "Implement a dual-layer caching system with in-memory (LRU) and disk-based caches for responses. Include cache invalidation policies based on HTTP cache headers (Cache-Control, Expires, ETag, Last-Modified), size limits, and time-based expiration.", 114 + "affected_files": [ 115 + "lib/cache.ml", 116 + "lib/cache.mli", 117 + "lib/requests.ml", 118 + "lib/requests.mli" 119 + ], 120 + "rationale": "Kingfisher implements sophisticated dual-layer caching with MemoryStorage (NSCache-based with cost limits and LRU eviction) and DiskStorage (file-based with size/time limits). The OCaml library currently has no built-in response caching - only cookie persistence. Adding HTTP-compliant caching would reduce network traffic, improve performance, and enable offline operation. This is a significant feature addition but valuable for production use." 121 + }, 122 + { 123 + "source_repo": "third_party/swift/kingfisher", 124 + "source_language": "Swift", 125 + "criticality": "medium", 126 + "change_type": "enhancement", 127 + "title": "Add comprehensive network metrics collection", 128 + "description": "Implement collection of detailed network metrics including DNS lookup time, TCP handshake time, TLS handshake time, time to first byte, download time, and total request time. Expose these metrics through the Response type for performance monitoring and debugging.", 129 + "affected_files": [ 130 + "lib/response.ml", 131 + "lib/response.mli", 132 + "lib/http_client.ml", 133 + "lib/http_client.mli", 134 + "lib/requests.ml" 135 + ], 136 + "rationale": "Kingfisher's NetworkMetrics collects detailed timing information for each network operation phase. The OCaml library only tracks total elapsed time (response.ml:14). Adding granular metrics enables performance profiling, identifying bottlenecks (slow DNS, TLS negotiation, server response time), and SLA monitoring. This is particularly valuable for debugging production performance issues." 137 + }, 138 + { 139 + "source_repo": "third_party/swift/kingfisher", 140 + "source_language": "Swift", 141 + "criticality": "low", 142 + "change_type": "enhancement", 143 + "title": "Add prefetching mechanism for predictive resource loading", 144 + "description": "Implement a prefetcher that can warm up the connection pool and cache by loading resources before they're needed. Include priority mechanisms where prefetch requests don't starve user-initiated requests, and memory pressure handling to promote prefetched items when accessed.", 145 + "affected_files": [ 146 + "lib/prefetch.ml", 147 + "lib/prefetch.mli", 148 + "lib/requests.ml", 149 + "lib/requests.mli" 150 + ], 151 + "rationale": "Kingfisher's ImagePrefetcher enables warming caches and connection pools before resources are needed. This improves perceived performance by hiding latency. An OCaml implementation would use the existing connection pool and could implement resource prioritization (user requests over prefetch). Particularly useful for applications with predictable access patterns (next page, thumbnail grids, etc.)." 152 + }, 153 + { 154 + "source_repo": "third_party/swift/kingfisher", 155 + "source_language": "Swift", 156 + "criticality": "medium", 157 + "change_type": "enhancement", 158 + "title": "Implement request deduplication to prevent redundant concurrent requests", 159 + "description": "Add deduplication logic that detects when multiple concurrent requests are made for the same resource and consolidates them into a single network request, with all callers receiving the same response. This prevents redundant network traffic and server load.", 160 + "affected_files": [ 161 + "lib/requests.ml", 162 + "lib/requests.mli", 163 + "lib/http_client.ml" 164 + ], 165 + "rationale": "Kingfisher implements request deduplication - when multiple parts of the application request the same resource concurrently, only one network request is made and the result is shared. The OCaml library makes independent requests even if they target the same URL. Deduplication reduces bandwidth, server load, and improves efficiency. Implementation would track in-flight requests by URL+method+headers hash and share the result." 166 + }, 167 + { 168 + "source_repo": "third_party/swift/kingfisher", 169 + "source_language": "Swift", 170 + "criticality": "high", 171 + "change_type": "security", 172 + "title": "Enhance redirect handler with custom validation and HTTPS enforcement", 173 + "description": "Add a redirect handler mechanism that allows users to validate, modify, or reject redirects before they're followed. Include built-in validators for HTTPS enforcement (reject http redirects from https origins) and redirect loop detection beyond simple count limits.", 174 + "affected_files": [ 175 + "lib/one.ml", 176 + "lib/one.mli", 177 + "lib/requests.ml", 178 + "lib/requests.mli" 179 + ], 180 + "rationale": "Kingfisher's RedirectHandler protocol allows custom redirect validation before following. The OCaml library (one.ml:154-196, requests.ml:293-424) implements basic redirect following with cross-origin header stripping but no custom validation hooks. Security-conscious applications may want to reject certain redirects (http downgrade, suspicious domains, open redirects). Adding a redirect_validator callback would enable custom security policies." 181 + }, 182 + { 183 + "source_repo": "third_party/swift/kingfisher", 184 + "source_language": "Swift", 185 + "criticality": "medium", 186 + "change_type": "enhancement", 187 + "title": "Add async request modifier hooks for dynamic header injection", 188 + "description": "Implement async request modification hooks that can asynchronously modify requests before they're sent. This enables use cases like token refresh, dynamic signature generation, or external configuration fetching that require async operations before the request can be sent.", 189 + "affected_files": [ 190 + "lib/requests.ml", 191 + "lib/requests.mli", 192 + "lib/one.ml", 193 + "lib/one.mli" 194 + ], 195 + "rationale": "Kingfisher provides both sync (ImageDownloadRequestModifier) and async (AsyncImageDownloadRequestModifier) request modification hooks. The OCaml library applies auth synchronously (auth.ml:36-51). Async modification enables complex auth flows like OAuth token refresh, AWS signature generation with clock skew compensation, or fetching short-lived credentials from a metadata service. Given the Eio async runtime, this is a natural addition." 196 + }, 197 + { 198 + "source_repo": "third_party/swift/kingfisher", 199 + "source_language": "Swift", 200 + "criticality": "low", 201 + "change_type": "enhancement", 202 + "title": "Add customizable HTTP status code validation with delegate pattern", 203 + "description": "Implement a mechanism to customize which HTTP status codes are considered errors or retriable. Currently status code handling is hardcoded (error.ml:117, retry.ml:50-57). Allow users to provide custom validators for their specific API requirements where non-standard status codes may have special meanings.", 204 + "affected_files": [ 205 + "lib/error.ml", 206 + "lib/error.mli", 207 + "lib/retry.ml", 208 + "lib/retry.mli", 209 + "lib/requests.ml" 210 + ], 211 + "rationale": "Kingfisher allows delegate-based validation of HTTP status codes via isInvalidResponseStatusCode. The OCaml library hardcodes status code interpretation. Some APIs use non-standard status codes or need custom retry logic (e.g., treating 202 Accepted as retriable while waiting for async processing). Adding an optional status_validator callback would provide flexibility for API-specific requirements." 212 + }, 213 + { 214 + "source_repo": "third_party/swift/kingfisher", 215 + "source_language": "Swift", 216 + "criticality": "low", 217 + "change_type": "enhancement", 218 + "title": "Add response processing pipeline with chainable processors", 219 + "description": "Implement a chainable processing pipeline for responses before they're returned to the caller. This enables transformations like validation, decryption, parsing, or format conversion in a composable way. Use a pipeline operator pattern where processors can be chained.", 220 + "affected_files": [ 221 + "lib/processor.ml", 222 + "lib/processor.mli", 223 + "lib/response.ml", 224 + "lib/response.mli", 225 + "lib/requests.ml" 226 + ], 227 + "rationale": "Kingfisher implements chainable ImageProcessor with |> operator for composable transformations. While image-specific, the pattern applies to HTTP responses generally. OCaml could benefit from composable response processors for use cases like: validating response schema, decrypting encrypted responses, decompressing custom encodings, or transforming data formats. Given OCaml's functional nature, this would be a natural fit with operator overloading." 228 + }, 229 + { 230 + "source_repo": "third_party/swift/kingfisher", 231 + "source_language": "Swift", 232 + "criticality": "medium", 233 + "change_type": "enhancement", 234 + "title": "Improve testing infrastructure with HTTP mocking and stubbing", 235 + "description": "Add comprehensive HTTP mocking/stubbing infrastructure similar to LSNocilla for testing. Enable tests to stub HTTP responses, verify request parameters, simulate network errors, and test timeout/retry behavior without real network calls. Include helper utilities for common test scenarios.", 236 + "affected_files": [ 237 + "test/mock.ml", 238 + "test/mock.mli", 239 + "test/helpers.ml", 240 + "test/test_*.ml" 241 + ], 242 + "rationale": "Kingfisher uses LSNocilla for HTTP stubbing in tests (KingfisherTests/). The OCaml library has minimal tests (test_simple.ml, test_localhost.ml, httpbin.t) that rely on real network calls. Production-grade libraries need extensive mocking for testing error conditions, timeouts, retries, authentication flows, redirect handling, etc. Adding a mock HTTP layer would enable comprehensive unit tests without network dependencies." 243 + }, 244 + { 245 + "source_repo": "third_party/swift/kingfisher", 246 + "source_language": "Swift", 247 + "criticality": "medium", 248 + "change_type": "enhancement", 249 + "title": "Add connection timeout separate from read timeout", 250 + "description": "Currently the OCaml library has connect timeout in Timeout.t but it's only applied to total connection time in one.ml:109-113. Kingfisher and most HTTP clients distinguish between connection establishment timeout and data transfer timeout. Ensure connection timeout is enforced specifically for the TCP/TLS handshake phase, separate from read operations.", 251 + "affected_files": [ 252 + "lib/timeout.ml", 253 + "lib/timeout.mli", 254 + "lib/one.ml", 255 + "lib/requests.ml", 256 + "lib/http_client.ml" 257 + ], 258 + "rationale": "The timeout.ml:9-12 defines separate connect/read/total timeouts, which is excellent. However, the implementation in one.ml:109-113 only applies total timeout to the connection. The connect timeout should be enforced specifically during TCP connection and TLS handshake (one.ml:33-84), while read timeout should apply during HTTP data transfer. This allows fine-grained control: quick connect timeout to fail fast on unreachable hosts, but longer read timeout for large downloads." 259 + }, 260 + { 261 + "source_repo": "third_party/swift/kingfisher", 262 + "source_language": "Swift", 263 + "criticality": "low", 264 + "change_type": "enhancement", 265 + "title": "Add builder pattern API alongside functional API", 266 + "description": "Implement a builder pattern API (similar to Kingfisher's KF builder) that provides a more fluent, method-chaining interface as an alternative to the current function parameter approach. This is particularly ergonomic for requests with many optional parameters.", 267 + "affected_files": [ 268 + "lib/builder.ml", 269 + "lib/builder.mli", 270 + "lib/requests.ml", 271 + "lib/requests.mli" 272 + ], 273 + "rationale": "Kingfisher provides multiple API styles including a builder pattern (KF.url().placeholder().setProcessor()). The OCaml library uses labeled optional parameters which is idiomatic OCaml, but for complex requests with many options, a builder pattern can improve discoverability and readability. Example: Request.builder(url).with_auth(auth).with_retry(config).with_timeout(30.0).execute(). This complements, not replaces, the existing API." 274 + }, 275 + { 276 + "source_repo": "third_party/swift/kingfisher", 277 + "source_language": "Swift", 278 + "criticality": "medium", 279 + "change_type": "enhancement", 280 + "title": "Add background decoding/processing to avoid blocking request threads", 281 + "description": "Implement optional background processing for CPU-intensive operations like decompression and JSON parsing. Currently these operations block the request fiber. Allow users to offload parsing to a background domain/thread pool to keep connection pool responsive.", 282 + "affected_files": [ 283 + "lib/response.ml", 284 + "lib/response.mli", 285 + "lib/http_client.ml", 286 + "lib/requests.ml" 287 + ], 288 + "rationale": "Kingfisher's backgroundDecode option moves image decoding off the main thread to prevent UI blocking. The OCaml library performs decompression (http_client.ml:96-117) and JSON parsing (response.ml:75-79) synchronously in the request fiber. For large responses, this can block the fiber and reduce connection pool throughput. Using OCaml 5's domains or Eio's executor pattern for background processing would improve concurrency, especially important given the library uses connection pooling where blocking fibers reduce effective pool size." 289 + }, 290 + { 291 + "source_repo": "third_party/swift/kingfisher", 292 + "source_language": "Swift", 293 + "criticality": "low", 294 + "change_type": "enhancement", 295 + "title": "Add transition callbacks for response lifecycle events", 296 + "description": "Implement lifecycle callbacks at key transition points: on_request_start, on_connected, on_tls_handshake_complete, on_first_byte, on_headers_received, on_body_chunk, on_completion, on_error. This enables instrumentation, progress tracking, and custom logging without modifying core library code.", 297 + "affected_files": [ 298 + "lib/requests.ml", 299 + "lib/requests.mli", 300 + "lib/one.ml", 301 + "lib/one.mli", 302 + "lib/http_client.ml" 303 + ], 304 + "rationale": "Kingfisher provides lifecycle callbacks (onSuccess, onFailure, onProgress) and transition animations. The OCaml library has limited callback support (download progress in one.ml:269-291 is stubbed). Fine-grained lifecycle hooks enable: real-time progress UIs, performance profiling, custom metrics collection, debug logging, and integration with monitoring systems. This is particularly valuable for long-running downloads or streaming responses." 305 + } 306 + ] 307 + }
+175
third_party/swift/moya.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/swift/moya", 5 + "source_language": "Swift", 6 + "criticality": "high", 7 + "change_type": "feature", 8 + "title": "Add Plugin/Interceptor Architecture for Request/Response Modification", 9 + "description": "Moya's plugin system provides extensible hooks at key lifecycle points (prepare, willSend, didReceive, process). This allows users to implement cross-cutting concerns like logging, authentication token refresh, metrics collection, and request/response transformation without modifying core library code. The OCaml library should add a similar plugin/interceptor mechanism.", 10 + "affected_files": [ 11 + "lib/requests.mli", 12 + "lib/requests.ml", 13 + "lib/one.mli", 14 + "lib/one.ml" 15 + ], 16 + "rationale": "Currently, the OCaml library embeds authentication and logging directly into the request flow. A plugin architecture would allow users to add custom behavior (e.g., automatic token refresh on 401, request signing, custom logging formats, performance metrics) without forking the library. This improves extensibility and separation of concerns. Moya's success demonstrates this pattern works well for HTTP clients." 17 + }, 18 + { 19 + "source_repo": "third_party/swift/moya", 20 + "source_language": "Swift", 21 + "criticality": "medium", 22 + "change_type": "enhancement", 23 + "title": "Add Response Validation and Filtering API", 24 + "description": "Moya provides declarative response validation through ValidationType (none, successCodes, successAndRedirectCodes, customCodes) and chainable filter methods on Response (filter, filterSuccessfulStatusCodes). This allows users to specify which status codes should raise errors vs be returned normally. The OCaml library currently has raise_for_status but lacks flexible validation configuration.", 25 + "affected_files": [ 26 + "lib/response.mli", 27 + "lib/response.ml", 28 + "lib/requests.mli", 29 + "lib/requests.ml" 30 + ], 31 + "rationale": "The current approach only offers raise_for_status which treats all 4xx/5xx as errors. Many APIs have nuanced status code handling (e.g., 404 might be expected, 429 should trigger retry). Adding chainable filter methods like `response |> Response.filter_status_codes [200; 201; 204]` or `response |> Response.expect_success` would improve ergonomics. This also aligns with functional programming patterns common in OCaml." 32 + }, 33 + { 34 + "source_repo": "third_party/swift/moya", 35 + "source_language": "Swift", 36 + "criticality": "medium", 37 + "change_type": "feature", 38 + "title": "Add Progress Tracking for Upload/Download Operations", 39 + "description": "Moya provides ProgressBlock callbacks that report upload/download progress with ProgressResponse objects containing both progress fraction and the response. The OCaml library has basic progress callbacks in One.upload/download but lacks integration with the main Requests API and doesn't provide progress during body streaming.", 40 + "affected_files": [ 41 + "lib/requests.mli", 42 + "lib/requests.ml", 43 + "lib/body.mli", 44 + "lib/body.ml", 45 + "lib/response.mli", 46 + "lib/response.ml" 47 + ], 48 + "rationale": "Progress tracking is essential for user-facing applications uploading/downloading large files. While One.upload/download have basic support, the main Requests API lacks this. Adding optional progress callbacks to request methods and integrating with Body.of_stream and Response.body would allow UI progress bars and bandwidth throttling. The callbacks should provide bytes transferred and total size (if known)." 49 + }, 50 + { 51 + "source_repo": "third_party/swift/moya", 52 + "source_language": "Swift", 53 + "criticality": "medium", 54 + "change_type": "enhancement", 55 + "title": "Enhance Error Types to Include Response Data", 56 + "description": "Moya's MoyaError enum consistently includes the Response object in error cases (statusCode, underlying, objectMapping, etc.), allowing error handlers to access the full response context. The OCaml library's Error.HTTPError includes some response data but other error types (ConnectionError, SSLError) don't preserve context about the failed request.", 57 + "affected_files": [ 58 + "lib/error.mli", 59 + "lib/error.ml" 60 + ], 61 + "rationale": "When debugging connection failures or SSL errors, having access to the attempted URL, headers sent, and timing information is invaluable. Moya's approach of including the Response (or nil) in all error variants ensures consistent error handling. The OCaml library should add optional request context (url, method, headers, attempt number) to ConnectionError, SSLError, and Timeout exceptions to aid debugging." 62 + }, 63 + { 64 + "source_repo": "third_party/swift/moya", 65 + "source_language": "Swift", 66 + "criticality": "low", 67 + "change_type": "enhancement", 68 + "title": "Add Chainable Response Mapping Functions", 69 + "description": "Moya provides convenient mapping methods on Response: mapJSON, mapString, mapImage, and map<T: Decodable>. These allow transforming responses into typed data structures. The OCaml library has Response.json and Response.text but lacks similar composable mapping for custom types and doesn't support key path extraction.", 70 + "affected_files": [ 71 + "lib/response.mli", 72 + "lib/response.ml" 73 + ], 74 + "rationale": "Moya's map methods support key path extraction (e.g., mapString(atKeyPath: 'user.name')) which is useful for APIs that wrap data in envelope objects. Adding similar functionality to OCaml with Jsont integration would improve ergonomics: `response |> Response.map_json ~decoder:my_decoder` or `response |> Response.json_at_path ['data'; 'items']`. This reduces boilerplate in API client code." 75 + }, 76 + { 77 + "source_repo": "third_party/swift/moya", 78 + "source_language": "Swift", 79 + "criticality": "high", 80 + "change_type": "feature", 81 + "title": "Add Stubbing/Mocking Support for Testing", 82 + "description": "Moya has built-in stubbing support through StubBehavior (never, immediate, delayed) and sampleData in TargetType. This allows testing without network calls. The OCaml library lacks any stubbing/mocking mechanism, making it difficult to test code that uses the library without hitting real endpoints.", 83 + "affected_files": [ 84 + "lib/requests.mli", 85 + "lib/requests.ml", 86 + "lib/one.mli", 87 + "lib/one.ml", 88 + "test/test_simple.ml" 89 + ], 90 + "rationale": "Testing HTTP client code should not require real network access. Moya's approach of built-in stubbing is elegant: specify sample data per endpoint and control timing. For OCaml, a similar approach could use a variant type for the network backend (Real | Stubbed) with a stub_response function. This would enable deterministic testing and faster test suites. Alternatively, expose hooks to inject custom flow implementations." 91 + }, 92 + { 93 + "source_repo": "third_party/swift/moya", 94 + "source_language": "Swift", 95 + "criticality": "medium", 96 + "change_type": "enhancement", 97 + "title": "Add Typed Target/Endpoint Abstraction", 98 + "description": "Moya's TargetType protocol provides a type-safe way to define API endpoints with baseURL, path, method, task, headers, and validation type. This creates a single source of truth for API structure. The OCaml library uses plain URLs and scattered configuration, making it harder to maintain consistency across multiple endpoints.", 99 + "affected_files": [ 100 + "lib/requests.mli", 101 + "lib/requests.ml" 102 + ], 103 + "rationale": "A typed endpoint abstraction (using OCaml modules or first-class modules) would improve type safety and reduce duplication when calling multiple endpoints on the same API. For example: `module GitHubAPI = struct let base_url = \"https://api.github.com\" let get_user user = Endpoint.make ~path:(\"/users/\" ^ user) ~method_:Get end`. This pattern encourages better API client organization and makes refactoring easier." 104 + }, 105 + { 106 + "source_repo": "third_party/swift/moya", 107 + "source_language": "Swift", 108 + "criticality": "low", 109 + "change_type": "enhancement", 110 + "title": "Add Request/Response Interceptor for Debugging", 111 + "description": "Moya's NetworkLoggerPlugin provides configurable logging with options for request method, headers, body, response body, and cURL format. It uses a flexible formatter system allowing custom output. The OCaml library has basic logging via the Logs library but lacks structured request/response logging.", 112 + "affected_files": [ 113 + "lib/requests.mli", 114 + "lib/requests.ml", 115 + "lib/one.ml" 116 + ], 117 + "rationale": "While the library has Logs integration, there's no high-level logging plugin that pretty-prints full requests and responses. Adding a configurable logging interceptor (once plugin architecture exists) with options for verbosity levels (minimal: just URL+status, full: headers+body, curl: generate curl commands) would significantly improve debugging experience. This should integrate with the existing Logs.Src hierarchy." 118 + }, 119 + { 120 + "source_repo": "third_party/swift/moya", 121 + "source_language": "Swift", 122 + "criticality": "medium", 123 + "change_type": "security", 124 + "title": "Add Certificate Pinning Support", 125 + "description": "While not directly in Moya core, the ecosystem supports SSL pinning through Alamofire's ServerTrustManager. The OCaml library accepts custom TLS configuration but doesn't provide high-level helpers for common security patterns like certificate pinning, which prevents MITM attacks.", 126 + "affected_files": [ 127 + "lib/requests.mli", 128 + "lib/requests.ml", 129 + "lib/one.mli", 130 + "lib/one.ml" 131 + ], 132 + "rationale": "Certificate pinning is crucial for security-sensitive applications. While users can technically configure this via tls_config, providing a high-level API (e.g., `~pin_certificates:[cert1; cert2]` or `~pin_public_keys:[hash1; hash2]`) would make this security feature more accessible. This should work with both PEM files and raw certificate data, and provide clear error messages on pin validation failure." 133 + }, 134 + { 135 + "source_repo": "third_party/swift/moya", 136 + "source_language": "Swift", 137 + "criticality": "low", 138 + "change_type": "enhancement", 139 + "title": "Add Request Cancellation Tokens", 140 + "description": "Moya returns a Cancellable token from request methods, allowing users to cancel in-flight requests. This is essential for UI-driven applications where users navigate away before requests complete. The OCaml library relies on switch cancellation but lacks fine-grained per-request cancellation.", 141 + "affected_files": [ 142 + "lib/requests.mli", 143 + "lib/requests.ml" 144 + ], 145 + "rationale": "While Eio's switch-based cancellation is powerful, it cancels all resources in a switch. For applications making multiple concurrent requests where only some should be cancelled (e.g., user cancels one search while others continue), per-request cancellation is valuable. Consider returning a cancellation token with a `cancel()` function that can abort an individual request without affecting siblings in the same switch." 146 + }, 147 + { 148 + "source_repo": "third_party/swift/moya", 149 + "source_language": "Swift", 150 + "criticality": "medium", 151 + "change_type": "feature", 152 + "title": "Add MultiTarget Pattern for Dynamic Endpoint Handling", 153 + "description": "Moya's MultiTarget allows using multiple TargetType implementations with a single provider, enabling dynamic endpoint selection at runtime. This is useful for APIs with many endpoints or plugin-based architectures. The OCaml library's static approach makes it harder to build flexible API abstractions.", 154 + "affected_files": [ 155 + "lib/requests.mli", 156 + "lib/requests.ml" 157 + ], 158 + "rationale": "A MultiTarget-style pattern in OCaml could use GADTs or first-class modules to allow: `type 'a endpoint` where 'a is the response type, enabling type-safe dynamic dispatch. This would support building API client libraries where endpoints are discovered at runtime or defined in plugins. The pattern provides type safety while maintaining flexibility, which is valuable for complex applications." 159 + }, 160 + { 161 + "source_repo": "third_party/swift/moya", 162 + "source_language": "Swift", 163 + "criticality": "low", 164 + "change_type": "enhancement", 165 + "title": "Improve Error Recovery with Automatic Retry on Specific Errors", 166 + "description": "While both libraries support retry, Moya's plugin architecture allows custom retry logic based on error type and response content. The OCaml library's retry is configured upfront but can't adapt based on response headers (like Retry-After with custom parsing) or error patterns.", 167 + "affected_files": [ 168 + "lib/retry.mli", 169 + "lib/retry.ml", 170 + "lib/requests.ml" 171 + ], 172 + "rationale": "The current retry implementation respects Retry-After headers but uses a static configuration. Adding hooks to customize retry decisions based on error type, response headers, or response body would enable sophisticated retry strategies. For example: retry on 429 with Retry-After, retry on 503 with exponential backoff, but never retry on 400. This could be implemented as a retry_predicate callback in retry.config." 173 + } 174 + ] 175 + }
+273
third_party/swift/net.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/swift/net", 5 + "source_language": "Swift", 6 + "criticality": "medium", 7 + "change_type": "bug", 8 + "title": "HTTP status code validation is too restrictive", 9 + "description": "The Swift library only treats HTTP 200 as success in ResponseData.json(), ResponseData.image(), and ResponseData.parseXml(). This is overly restrictive as HTTP 2xx codes (201-299) are all success codes. The OCaml library correctly checks `status >= 400` for errors but doesn't enforce success checking by default.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/error.ml" 13 + ], 14 + "rationale": "Swift's NetResponseData.swift:31 checks `if httpResponse.statusCode == 200` which rejects valid success codes like 201 Created, 202 Accepted, 204 No Content. While OCaml's response.ml:40 correctly uses `Status.is_success` for the ok() method, the library should consider adding helper methods that validate success ranges (2xx) vs specific codes. Consider adding Response.json_exn or similar methods that automatically call raise_for_status before parsing, preventing silent failures when servers return error pages as JSON." 15 + }, 16 + { 17 + "source_repo": "third_party/swift/net", 18 + "source_language": "Swift", 19 + "criticality": "high", 20 + "change_type": "security", 21 + "title": "Implement progress callbacks with integrity validation", 22 + "description": "The Swift library provides progress tracking via ProgressHandler closures for downloads (NetDownloadTask.swift:114) and uploads (NetUploadTask.swift:107). Progress callbacks are useful for long-running transfers, but the Swift implementation lacks integrity validation. The OCaml library could add progress callbacks with content-length validation.", 23 + "affected_files": [ 24 + "lib/response.ml", 25 + "lib/body.ml", 26 + "lib/http_client.ml" 27 + ], 28 + "rationale": "Swift's progress tracking in Net.swift:266-270 calculates progress as `totalBytesWritten / totalBytesExpectedToWrite` but doesn't validate the final size matches Content-Length. The OCaml library should add optional progress callback parameters to request functions, but MUST validate that received data matches Content-Length header (if present) to prevent truncation attacks. This is especially important for downloads of security-critical files. Consider adding a signature: `?on_progress:(bytes_transferred:int64 -> total_bytes:int64 option -> unit) -> ...`" 29 + }, 30 + { 31 + "source_repo": "third_party/swift/net", 32 + "source_language": "Swift", 33 + "criticality": "medium", 34 + "change_type": "feature", 35 + "title": "Add download/upload task management with pause/resume capabilities", 36 + "description": "The Swift library implements sophisticated download/upload task management with state machines (NetDownloadTask.swift:18-21, NetUploadTask.swift:18-20) supporting Init, Downloading/Uploading, Suspending, Canceled, Completed, Failed states. Tasks support suspend/resume/cancel operations with resumeData for partial downloads.", 37 + "affected_files": [ 38 + "lib/requests.ml", 39 + "lib/one.ml", 40 + "lib/response.ml" 41 + ], 42 + "rationale": "Swift's NetDownloadTask.swift:62-75 allows pausing downloads and resuming with resumeData if server supports byte-range requests. This is valuable for large file transfers over unreliable networks. The OCaml library's streaming approach (Eio.Flow.source_ty) provides low-level control but doesn't expose high-level pause/resume. Consider adding a Task module with: (1) Task state tracking, (2) Cancellation via Eio.Cancel, (3) Resume support using HTTP Range headers if server supports it (check Accept-Ranges header), (4) Progress tracking integrated with the streaming body. This would complement the existing streaming capabilities." 43 + }, 44 + { 45 + "source_repo": "third_party/swift/net", 46 + "source_language": "Swift", 47 + "criticality": "low", 48 + "change_type": "enhancement", 49 + "title": "Add background transfer completion handlers", 50 + "description": "The Swift library supports background URL sessions with completion handlers (Net.swift:223-226) via URLSessionDidFinishEventsForBackgroundURLSession delegate. This allows transfers to continue when the app is backgrounded and provides callbacks when all background tasks complete.", 51 + "affected_files": [ 52 + "lib/requests.ml" 53 + ], 54 + "rationale": "Swift's Net.swift:36 provides `eventsForBackgroundHandler` that's called via delegate method at line 225. This is iOS-specific functionality for app lifecycle management. The OCaml library runs on servers/CLI where background operations work differently. However, the concept of notification when a batch of async operations complete is useful. Consider adding a utility function that uses Eio.Fiber.all with a completion callback: `let with_completion_handler ~on_complete tasks = let results = Fiber.all tasks in on_complete results; results`. This provides similar \"all transfers done\" semantics in Eio's concurrency model." 55 + }, 56 + { 57 + "source_repo": "third_party/swift/net", 58 + "source_language": "Swift", 59 + "criticality": "medium", 60 + "change_type": "enhancement", 61 + "title": "Improve error messages with contextual information", 62 + "description": "The Swift library creates minimal NSError objects with only domain and status code: `NSError(domain: \"HTTP_ERROR_CODE\", code: httpResponse.statusCode, userInfo: nil)` (NetResponseData.swift:36). No user-facing error descriptions, no response body, no request context. The OCaml library is better with structured errors but could add more context.", 63 + "affected_files": [ 64 + "lib/error.ml", 65 + "lib/http_client.ml" 66 + ], 67 + "rationale": "Swift's error handling provides minimal debugging information - just a status code with no message. OCaml's error.ml:16-28 defines rich error types with context (url, status, reason, body, headers for HTTPError) which is excellent. However, ConnectionError and SSLError only include string messages. Consider enhancing these to include: (1) For ConnectionError: host, port, underlying system error code, retry attempt number. (2) For SSLError: certificate details, validation failure reason, hostname. (3) Add Error.add_context function to wrap errors with additional information during retry attempts. This helps debugging production issues." 68 + }, 69 + { 70 + "source_repo": "third_party/swift/net", 71 + "source_language": "Swift", 72 + "criticality": "low", 73 + "change_type": "enhancement", 74 + "title": "Add session-level configuration for Accept headers and other defaults", 75 + "description": "The Swift library sets default Accept headers at session creation: `headers.updateValue(\"application/json,application/xml,image/png,image/jpeg\", forKey: \"Accept\")` (Net.swift:62). This allows all requests from that session to inherit common headers.", 76 + "affected_files": [ 77 + "lib/requests.ml", 78 + "lib/headers.ml" 79 + ], 80 + "rationale": "Swift's Net.swift:62 hardcodes Accept header defaults in the session config. The OCaml library has `default_headers` in the session (requests.ml:39) which is good, but doesn't set any defaults. Consider adding a helper function `Headers.with_accept_defaults` that sets sensible Accept headers: \"text/html,application/json,application/xml,*/*;q=0.8\". Also add `Headers.with_user_agent` to set a default User-Agent like \"ocaml-requests/VERSION\". Make these opt-in via session creation parameters: `?set_default_accept:bool` and `?user_agent:string option`. This improves compatibility with servers that require these headers." 81 + }, 82 + { 83 + "source_repo": "third_party/swift/net", 84 + "source_language": "Swift", 85 + "criticality": "high", 86 + "change_type": "bug", 87 + "title": "Validate redirect locations to prevent SSRF attacks", 88 + "description": "The Swift library has an empty redirect handler (Net.swift:261-262) that doesn't validate redirect locations. The OCaml library follows redirects (requests.ml:68-69) but should validate redirect URLs to prevent Server-Side Request Forgery (SSRF) attacks.", 89 + "affected_files": [ 90 + "lib/requests.ml", 91 + "lib/error.ml" 92 + ], 93 + "rationale": "Neither library validates redirect URLs. Malicious servers could redirect to internal URLs (http://localhost:6379, http://169.254.169.254/latest/meta-data/) to access internal services or cloud metadata endpoints. The OCaml library should add redirect validation in requests.ml around line 198+ where same_origin is checked. Add checks to reject: (1) Redirects to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16). (2) Redirects to file:// or other non-http(s) schemes. (3) Optionally, a whitelist of allowed redirect hosts. Add a configuration option `?allow_private_ips:bool` (default false) and raise InvalidRequest exception for blocked redirects." 94 + }, 95 + { 96 + "source_repo": "third_party/swift/net", 97 + "source_language": "Swift", 98 + "criticality": "medium", 99 + "change_type": "enhancement", 100 + "title": "Add request/response interceptors or middleware hooks", 101 + "description": "The Swift library's delegate pattern (NSURLSessionDataDelegate, Net.swift:23) provides hooks for customizing request/response handling. The OCaml library could benefit from a middleware/interceptor pattern for logging, metrics, request modification, and response transformation.", 102 + "affected_files": [ 103 + "lib/requests.ml", 104 + "lib/http_client.ml" 105 + ], 106 + "rationale": "Swift's delegate methods like willPerformHTTPRedirection (Net.swift:261) provide extension points. The OCaml library is well-architected but bakes in behavior like auto-decompression, redirect handling, retry logic. Consider adding a middleware system: `type middleware = request -> (request -> response) -> response` that wraps the request execution. Add session field `middlewares : middleware list` and apply them in order. This enables: (1) Custom logging middleware, (2) Request signing, (3) Response caching, (4) Metrics collection, (5) Custom retry logic beyond the built-in Retry module. Example: `let logging_middleware req next = Log.info \"Request: %s\" req.url; next req`. This makes the library more extensible without modifying core code." 107 + }, 108 + { 109 + "source_repo": "third_party/swift/net", 110 + "source_language": "Swift", 111 + "criticality": "medium", 112 + "change_type": "feature", 113 + "title": "Add support for streaming request bodies from files", 114 + "description": "The Swift library supports uploading from files with `uploadTaskWithRequest:fromFile:` (NetUploadTask.swift:76). This avoids loading large files entirely into memory. The OCaml library has Body.of_stream but could add a convenience function for file uploads.", 115 + "affected_files": [ 116 + "lib/body.ml" 117 + ], 118 + "rationale": "Swift's NetUploadTask.swift:72-78 creates upload tasks directly from file URLs, letting NSURLSession stream the file efficiently. OCaml's body.ml has Body.of_stream (line ~200-250) which can stream from any source, but doesn't have a dedicated file streaming helper. Add `Body.of_file : Eio.Fs.dir_ty Eio.Path.t -> t` that: (1) Opens file with Eio.Path.open_in, (2) Gets file size for Content-Length, (3) Creates streaming body. Also add `Body.of_file_part` for Range uploads using Eio.Flow.read_exact to skip bytes. This makes large file uploads more ergonomic and memory-efficient, complementing the existing multipart file upload support." 119 + }, 120 + { 121 + "source_repo": "third_party/swift/net", 122 + "source_language": "Swift", 123 + "criticality": "low", 124 + "change_type": "enhancement", 125 + "title": "Add statistics tracking for requests per host and connection reuse metrics", 126 + "description": "The Swift library has session extensions to query task counts (Net.swift:348-366) for downloads, uploads, and total transferring tasks. The OCaml library tracks basic statistics (requests_made, total_time, retries_count in requests.ml:55-57) but could add connection pool metrics.", 127 + "affected_files": [ 128 + "lib/requests.ml" 129 + ], 130 + "rationale": "Swift's Net.swift:348-366 provides methods like getDownloadingTasksCount, getUploadingTaskCount, getTransferingTaskCount for observability. OCaml's requests.ml:55-57 tracks basic stats but doesn't expose connection pool metrics. The Conpool library likely has internal metrics. Consider adding: (1) Method to query pool stats: `val pool_stats : t -> (host * port * active_connections * idle_connections) list`, (2) Track per-host request counts, (3) Track connection reuse rate (requests_with_reused_connection / total_requests), (4) Track cache hit rates if caching is added. Add these to the session type and expose via `val stats : t -> stats_record`. This helps users optimize their usage patterns and debug connection issues." 131 + }, 132 + { 133 + "source_repo": "third_party/swift/net", 134 + "source_language": "Swift", 135 + "criticality": "medium", 136 + "change_type": "refactor", 137 + "title": "Consider adding typed response parsing with error context", 138 + "description": "The Swift library provides response parsing methods (json, image, parseXml) directly on ResponseData class (NetResponseData.swift:29-79). They return nil on failure with an optional NSError pointer. The OCaml library has Response.json/text but returns generic Result types without request context.", 139 + "affected_files": [ 140 + "lib/response.ml" 141 + ], 142 + "rationale": "Swift's ResponseData.json (line 29) returns `NSDictionary?` with error populated on failure, but loses response context. OCaml's response.ml:75-79 has `val json : t -> (Jsont.json, string) result` which is type-safe but the error is just a string. Consider adding: (1) Response.json_exn that calls raise_for_status first, then parses JSON, wrapping parse errors in EncodingError with full response context (url, status, body preview). (2) Similar _exn variants for other parsers. (3) Keep the Result-returning versions but enhance error type: `type parse_error = { reason: string; url: string; status: int; body_preview: string }`. This provides better error messages for debugging API integration issues." 143 + }, 144 + { 145 + "source_repo": "third_party/swift/net", 146 + "source_language": "Swift", 147 + "criticality": "high", 148 + "change_type": "security", 149 + "title": "Add request timeout enforcement at network level", 150 + "description": "The Swift library sets timeouts in NSURLSessionConfiguration (Net.swift:33-34, 65-66) with separate timeoutIntervalForRequest and timeoutIntervalForResource. These are enforced by the underlying URLSession. The OCaml library has Timeout configuration but should verify enforcement at all levels.", 151 + "affected_files": [ 152 + "lib/timeout.ml", 153 + "lib/http_client.ml", 154 + "lib/requests.ml" 155 + ], 156 + "rationale": "Swift's Net.swift:65-66 sets both request timeout (30s - per request) and resource timeout (60s - total time including retries). The OCaml timeout.ml:53 defines connect, read, and total timeouts. Verify that: (1) Connect timeout is enforced in Conpool connection establishment, (2) Read timeout is enforced during response body streaming in http_client.ml, (3) Total timeout wraps the entire request including redirects and retries. Review requests.ml retry logic to ensure total timeout isn't reset on each retry attempt - it should be cumulative. Consider adding a timeout test that verifies a slow server response (using Eio.Time.sleep in a test server) properly triggers Timeout exception within the configured duration." 157 + }, 158 + { 159 + "source_repo": "third_party/swift/net", 160 + "source_language": "Swift", 161 + "criticality": "low", 162 + "change_type": "enhancement", 163 + "title": "Add support for custom HTTP methods beyond standard set", 164 + "description": "The Swift library defines HTTP methods as a simple enum (Net.swift:16-21) with only GET, POST, PUT, DELETE. The OCaml library has a more extensible design with polymorphic variants including `Other of string` (Method module) which is better.", 165 + "affected_files": [ 166 + "lib/method.ml" 167 + ], 168 + "rationale": "Swift's HttpMethod enum at line 16 is closed - adding new methods requires modifying the enum. OCaml's method.ml uses polymorphic variants with an `Other of string` case for custom methods, which is excellent. However, consider adding more common HTTP methods as first-class variants: `CONNECT for proxying, `COPY and `MOVE for WebDAV, `LINK and `UNLINK from RFC 5988. Keep `Other for truly custom methods. Also add validation in Method.to_string to reject methods with invalid characters (only uppercase letters per RFC 7230). This prevents header injection if method strings come from untrusted sources." 169 + }, 170 + { 171 + "source_repo": "third_party/swift/net", 172 + "source_language": "Swift", 173 + "criticality": "medium", 174 + "change_type": "feature", 175 + "title": "Add configurable connection limits per host", 176 + "description": "The Swift library configures HTTPMaximumConnectionsPerHost (Net.swift:35, 67, 98) which limits concurrent connections to each host. The OCaml library has max_connections_per_host parameter (requests.ml:72) but should document the implications and consider dynamic adjustment.", 177 + "affected_files": [ 178 + "lib/requests.ml", 179 + "lib/requests.mli" 180 + ], 181 + "rationale": "Swift's Net.swift:67 sets `sessionConfig.HTTPMaximumConnectionsPerHost = 5` which prevents overwhelming servers and reduces resource usage. OCaml's requests.ml:72 has `max_connections_per_host` defaulting to 10 (line 72), passed to Conpool. Consider: (1) Document in requests.mli why this limit matters (prevent server overload, reduce local resources, respect server capabilities), (2) Add per-request override: some hosts can handle more concurrent requests (CDNs) while others need lower limits (rate-limited APIs), (3) Consider adding adaptive connection limits based on response times or rate limit headers (429 responses), (4) Add session method `set_host_connection_limit : host:string -> limit:int -> t -> t` for per-host configuration." 182 + }, 183 + { 184 + "source_repo": "third_party/swift/net", 185 + "source_language": "Swift", 186 + "criticality": "low", 187 + "change_type": "enhancement", 188 + "title": "Add HTTP pipelining configuration option", 189 + "description": "The Swift library has HTTPShouldUsePipelining configuration (implied by NSURLSessionConfiguration defaults). HTTP pipelining can improve performance but has compatibility issues. The OCaml library should allow users to enable/disable it.", 190 + "affected_files": [ 191 + "lib/requests.ml", 192 + "lib/http_client.ml" 193 + ], 194 + "rationale": "HTTP/1.1 pipelining sends multiple requests without waiting for responses, but many servers and proxies don't support it correctly. The OCaml library doesn't explicitly configure this. Since the library uses HTTP/1.1 (http_client.ml), consider adding: (1) Session parameter `?enable_pipelining:bool` (default false for safety), (2) If enabled, send multiple requests over same connection without waiting for responses, (3) Add pipelining support to Conpool to queue requests. However, given HTTP/2 adoption and pipelining's poor support, this is low priority. Better to document that HTTP/1.1 keep-alive is supported but pipelining is not, and suggest HTTP/2 support as future enhancement." 195 + }, 196 + { 197 + "source_repo": "third_party/swift/net", 198 + "source_language": "Swift", 199 + "criticality": "medium", 200 + "change_type": "enhancement", 201 + "title": "Add request/response body size limits for safety", 202 + "description": "Neither library explicitly documents or enforces maximum request/response body sizes. The Swift library relies on iOS memory limits. The OCaml library uses Eio.Buf_read with max_size parameter (response.ml:73) but should make limits more prominent.", 203 + "affected_files": [ 204 + "lib/response.ml", 205 + "lib/body.ml", 206 + "lib/requests.ml" 207 + ], 208 + "rationale": "Unbounded response bodies can cause OOM when servers return huge responses (intentionally or due to bugs). OCaml's response.ml:73 uses `~max_size:max_int` which is effectively unbounded. Add: (1) Session parameter `?max_response_size:int64` (default 100MB), (2) Pass to Buf_read.of_flow as ~max_size, (3) Raise EncodingError if exceeded with message including Content-Length, (4) Similar limit for request bodies in body.ml to prevent client bugs, (5) Document these limits in requests.mli. For streaming use cases, add Response.body_stream that returns the raw flow for users who want to handle large bodies themselves. This prevents accidental OOM from unexpected large responses." 209 + }, 210 + { 211 + "source_repo": "third_party/swift/net", 212 + "source_language": "Swift", 213 + "criticality": "low", 214 + "change_type": "enhancement", 215 + "title": "Add support for cellular network access control", 216 + "description": "The Swift library has allowsCellularAccess configuration (Net.swift:32, 59) to control whether requests can use cellular networks vs WiFi-only. This is mobile-specific but the concept of network interface selection applies generally.", 217 + "affected_files": [ 218 + "lib/requests.ml" 219 + ], 220 + "rationale": "Swift's Net.swift:59 sets `allowsCellularAccess = true` for iOS apps to control cost/performance tradeoffs. This is not directly applicable to OCaml server/CLI usage. However, the broader concept of network interface selection could be useful: (1) Bind to specific IP address for multi-homed servers, (2) Use specific network interface (VPN, localhost), (3) Respect system proxy settings. The Eio Net module might support this through connection creation parameters. Document in requests.mli how to achieve network control using Eio's facilities. Not a high priority for typical use cases but useful for advanced networking scenarios." 221 + }, 222 + { 223 + "source_repo": "third_party/swift/net", 224 + "source_language": "Swift", 225 + "criticality": "high", 226 + "change_type": "feature", 227 + "title": "Add comprehensive integration test suite with real HTTP interactions", 228 + "description": "The Swift library has minimal unit tests (exampleTests.swift) but extensive integration testing via iOS example apps with three view controllers testing different scenarios. The OCaml library has examples but should expand test coverage.", 229 + "affected_files": [ 230 + "test/test_simple.ml" 231 + ], 232 + "rationale": "Swift's ios_example contains HttpViewController, DownloadViewController, UploadViewController that manually test: JSON/XML parsing, nested parameters, multipart uploads, download resume, progress tracking, task cancellation. The OCaml test/test_simple.ml only has basic connection pooling tests. Add comprehensive test suite using httpbin.org (as in examples/session_example.ml): (1) Test all HTTP methods, (2) Test authentication (Basic, Bearer, Digest with httpbin.org/digest-auth), (3) Test retry logic with httpbin.org/status/:code, (4) Test redirect handling including cross-origin, (5) Test timeout with httpbin.org/delay/:n, (6) Test compression with httpbin.org/gzip, (7) Test multipart, (8) Test error cases. Use Alcotest framework and make tests deterministic." 233 + }, 234 + { 235 + "source_repo": "third_party/swift/net", 236 + "source_language": "Swift", 237 + "criticality": "medium", 238 + "change_type": "feature", 239 + "title": "Add batch/concurrent request utility functions", 240 + "description": "The Swift library has a TODO comment for batch operations (Net.swift:14). The OCaml examples show concurrent requests using Fiber.both/all (session_example.ml) but this should be part of the main API with proper error handling and resource limits.", 241 + "affected_files": [ 242 + "lib/requests.ml", 243 + "lib/requests.mli" 244 + ], 245 + "rationale": "Swift marks batch operations as TODO. OCaml examples demonstrate concurrent requests with `Fiber.both (fun () -> get req url1) (fun () -> get req url2)` but this is manual. Add helper functions: (1) `val get_all : t -> string list -> Response.t list` that uses Fiber.all internally, (2) `val get_any : t -> string list -> Response.t` using Promise.create_resolved for first successful response, (3) `val with_concurrency_limit : max:int -> (unit -> 'a) list -> 'a list` using semaphore to limit concurrent requests, (4) Proper error handling to collect all errors vs fail-fast modes. These patterns are common enough to warrant library support, especially the concurrency limiting which prevents overwhelming servers." 246 + }, 247 + { 248 + "source_repo": "third_party/swift/net", 249 + "source_language": "Swift", 250 + "criticality": "medium", 251 + "change_type": "feature", 252 + "title": "Add HTTP caching support with cache control headers", 253 + "description": "The Swift library has caching marked as TODO (Net.swift:13). HTTP caching based on Cache-Control, ETag, and Last-Modified headers can significantly reduce bandwidth and latency. The OCaml library should implement RFC 7234 caching.", 254 + "affected_files": [ 255 + "lib/requests.ml", 256 + "lib/cache.ml" 257 + ], 258 + "rationale": "Swift's TODO at line 13 indicates planned caching support. The OCaml library has no caching currently. Add new cache.ml module implementing: (1) In-memory LRU cache with configurable size, (2) Optional disk cache using XDG cache directory, (3) Parse Cache-Control: max-age, no-cache, no-store, must-revalidate, (4) Support ETag-based conditional requests (If-None-Match), (5) Support Last-Modified-based conditional requests (If-Modified-Since), (6) Return cached response with 304 Not Modified, (7) Vary header support for content negotiation. Add session parameter `?cache:(module Cache.S)` for pluggable cache backends. This is common in HTTP clients (Python requests-cache, HTTP::Cache in Perl) and valuable for production usage." 259 + }, 260 + { 261 + "source_repo": "third_party/swift/net", 262 + "source_language": "Swift", 263 + "criticality": "low", 264 + "change_type": "enhancement", 265 + "title": "Add XML response parsing support", 266 + "description": "The Swift library provides XML parsing via NSXMLParser with delegate pattern (NetResponseData.swift:66-79). The OCaml library focuses on JSON but should consider adding XML support for completeness.", 267 + "affected_files": [ 268 + "lib/response.ml" 269 + ], 270 + "rationale": "Swift's NetResponseData.swift:66-79 has parseXml method accepting NSXMLParserDelegate. Many REST APIs still use XML (AWS, SOAP services, RSS/Atom feeds). The OCaml library has response.ml:75-79 for JSON using jsont but no XML support. Consider adding: (1) Add dependency on xmlm or markup.ml for XML parsing, (2) Add `Response.xml : t -> (xml_tree, string) result` that parses response body, (3) Support common formats: RSS/Atom via existing libraries, (4) Document that users can call Response.text and use their preferred XML library for custom needs. Given JSON's dominance, this is lower priority but would improve library completeness for enterprise scenarios." 271 + } 272 + ] 273 + }
+222
third_party/swift/swifthttp.json
··· 1 + { 2 + "recommendations": [ 3 + { 4 + "source_repo": "third_party/swift/moya", 5 + "source_language": "Swift", 6 + "criticality": "medium", 7 + "change_type": "enhancement", 8 + "title": "Add response filtering and validation helpers", 9 + "description": "Moya provides convenient response filtering methods like `filterSuccessfulStatusCodes()`, `filter(statusCodes: 200...299)`, and `filter(statusCode: 404)` that throw typed errors when status codes don't match. The OCaml library currently requires manual status checking with `Response.ok` or `Response.status_code`. Adding similar helpers would improve ergonomics and reduce boilerplate.", 10 + "affected_files": [ 11 + "lib/response.ml", 12 + "lib/response.mli" 13 + ], 14 + "rationale": "Moya's Response.swift (lines 49-83) shows how filtering methods provide cleaner error handling. Instead of 'if Response.ok resp then ...' users could write 'Response.filter_successful resp |> ignore' or use Result-based variants. This pattern makes status validation explicit and composable with error handling, reducing bugs from forgotten status checks." 15 + }, 16 + { 17 + "source_repo": "third_party/swift/moya", 18 + "source_language": "Swift", 19 + "criticality": "low", 20 + "change_type": "enhancement", 21 + "title": "Add convenient response mapping methods with keypath support", 22 + "description": "Moya provides `mapJSON()`, `mapString()`, and generic `map<D: Decodable>()` methods on Response objects with optional keyPath parameters for extracting nested data. The OCaml library has basic `json` and `text` methods but lacks keypath extraction. Adding helpers like `map_json_at ~keypath:\"data.items\"` would reduce manual JSON traversal code.", 23 + "affected_files": [ 24 + "lib/response.ml", 25 + "lib/response.mli" 26 + ], 27 + "rationale": "Response.swift lines 111-125 show keyPath extraction for nested JSON. This is particularly useful for APIs that wrap data (e.g., {\"data\": {...}, \"meta\": {...}}). While OCaml has strong JSON libraries, convenience methods matching common patterns would improve API ergonomics without requiring users to write traversal code for every endpoint." 28 + }, 29 + { 30 + "source_repo": "third_party/swift/moya", 31 + "source_language": "Swift", 32 + "criticality": "high", 33 + "change_type": "feature", 34 + "title": "Implement plugin/interceptor architecture for request/response lifecycle", 35 + "description": "Moya's plugin system (PluginType protocol) provides hooks: prepare() to modify requests, willSend() for side effects before sending, didReceive() after responses, and process() to transform results. This enables modular functionality like logging, authentication refresh, metrics, and custom error handling without modifying core library code. The OCaml library lacks this extensibility mechanism.", 36 + "affected_files": [ 37 + "lib/requests.ml", 38 + "lib/requests.mli", 39 + "lib/one.ml", 40 + "lib/one.mli" 41 + ], 42 + "rationale": "NetworkLoggerPlugin.swift and Moya plugin architecture demonstrate how interceptors enable separation of concerns. Users could implement plugins for: automatic token refresh on 401, request/response logging with custom formatters, metrics collection, request signing, response caching, or mock data injection for testing. This is a fundamental architectural pattern in production HTTP clients that enables composition without coupling." 43 + }, 44 + { 45 + "source_repo": "third_party/swift/moya", 46 + "source_language": "Swift", 47 + "criticality": "medium", 48 + "change_type": "enhancement", 49 + "title": "Add structured logging plugin with configurable verbosity levels", 50 + "description": "Moya's NetworkLoggerPlugin provides granular logging control with LogOptions (requestMethod, requestHeaders, requestBody, successResponseBody, errorResponseBody, formatRequestAscURL for cURL commands) and customizable formatters. The OCaml library uses Logs but lacks structured configuration for what to log at different levels. A logging plugin/configuration module would provide similar flexibility.", 51 + "affected_files": [ 52 + "lib/requests.ml", 53 + "lib/requests.mli" 54 + ], 55 + "rationale": "NetworkLoggerPlugin.swift lines 117-186 show how OptionSet-based configuration enables precise logging control. The OCaml library logs at Info level unconditionally (requests.ml:343-378), which can be too verbose for production or insufficient for debugging. A configurable logging system would let users choose verbosity per environment, with presets like 'quiet', 'normal', 'verbose', and 'curl_format' for easy reproduction of requests." 56 + }, 57 + { 58 + "source_repo": "third_party/swift/moya", 59 + "source_language": "Swift", 60 + "criticality": "medium", 61 + "change_type": "feature", 62 + "title": "Add progress tracking support for uploads and downloads", 63 + "description": "Moya provides ProgressResponse with progress callbacks that report upload/download progress as a fraction (0.0 to 1.0) based on Content-Length headers. The OCaml library has Body types for files and streams but no progress reporting mechanism. Adding optional progress callbacks would enable UI progress indicators and monitoring of large transfers.", 64 + "affected_files": [ 65 + "lib/requests.ml", 66 + "lib/requests.mli", 67 + "lib/one.ml", 68 + "lib/one.mli", 69 + "lib/body.ml" 70 + ], 71 + "rationale": "MoyaProvider.swift lines 9-39 show ProgressResponse design with completed flag and normalized progress values. This is essential for user-facing applications with large file uploads/downloads. Implementation could use Eio's structured concurrency to periodically sample transfer progress without blocking, calling a user-provided callback with bytes transferred and total bytes." 72 + }, 73 + { 74 + "source_repo": "third_party/swift/moya", 75 + "source_language": "Swift", 76 + "criticality": "low", 77 + "change_type": "enhancement", 78 + "title": "Enhance error types with response preservation for all error cases", 79 + "description": "Moya's MoyaError attaches the Response object to most error variants (imageMapping, jsonMapping, statusCode, underlying), enabling error handlers to inspect response data for debugging. The OCaml Error.HTTPError includes response details, but other errors like ConnectionError and SSLError lack contextual information that could aid debugging (e.g., partial response data, server headers).", 80 + "affected_files": [ 81 + "lib/error.ml", 82 + "lib/error.mli" 83 + ], 84 + "rationale": "MoyaError.swift lines 34-48 demonstrate error.response accessor that provides context for all applicable errors. When an SSLError occurs after partial TLS handshake, or ConnectionError happens mid-stream, having access to any received data or headers helps debugging. Adding optional response/metadata fields to more error types would improve troubleshooting without breaking existing code." 85 + }, 86 + { 87 + "source_repo": "third_party/swift/moya", 88 + "source_language": "Swift", 89 + "criticality": "low", 90 + "change_type": "enhancement", 91 + "title": "Add request/response body pretty-printing helpers for debugging", 92 + "description": "Moya's NetworkLoggerPlugin includes customizable data formatters that convert request/response bodies to strings with fallbacks for binary data. The OCaml library logs bodies as-is but lacks formatting utilities for common content types (JSON pretty-printing, form data parsing, multipart boundary visualization). Adding debug formatters would improve log readability.", 93 + "affected_files": [ 94 + "lib/requests.ml", 95 + "lib/body.ml" 96 + ], 97 + "rationale": "NetworkLoggerPlugin.swift lines 188-237 show pluggable formatters (DataFormatterType) that handle UTF-8 text, JSON, and binary data differently. The OCaml library could provide formatters that: pretty-print JSON bodies, decode URL-encoded forms, show multipart boundaries with part summaries, and truncate large binary responses with size indicators. This would make Logs output more actionable during development." 98 + }, 99 + { 100 + "source_repo": "third_party/swift/moya", 101 + "source_language": "Swift", 102 + "criticality": "medium", 103 + "change_type": "enhancement", 104 + "title": "Add inflight request tracking to prevent duplicate concurrent requests", 105 + "description": "Moya's trackInflights feature prevents duplicate requests to the same endpoint by queueing completion handlers. When enabled, concurrent requests to identical endpoints share the same network call. The OCaml library with connection pooling reuses connections but doesn't deduplicate identical concurrent requests, potentially causing unnecessary load.", 106 + "affected_files": [ 107 + "lib/requests.ml", 108 + "lib/requests.mli" 109 + ], 110 + "rationale": "MoyaProvider.swift lines 82-88 show @Atomic thread-safe inflight tracking. This prevents the 'thundering herd' problem where many concurrent requests for the same resource (e.g., user profile) create redundant network calls. Implementation would use a hashtable of (method, url, body_hash) to pending Fibers, with all callers waiting on the same Fiber. This is especially valuable for web applications with rapid-fire identical requests." 111 + }, 112 + { 113 + "source_repo": "third_party/swift/moya", 114 + "source_language": "Swift", 115 + "criticality": "medium", 116 + "change_type": "enhancement", 117 + "title": "Add stubbing/mocking support for testing without network", 118 + "description": "Moya provides built-in stubbing with StubBehavior (.immediate, .delayed(seconds)) and sample data on endpoints. This enables offline development and fast deterministic tests. The OCaml library lacks first-class mocking support, requiring users to set up separate mock servers or dependency injection. Adding a stubbing mode would simplify testing.", 119 + "affected_files": [ 120 + "lib/requests.ml", 121 + "lib/requests.mli", 122 + "lib/one.ml" 123 + ], 124 + "rationale": "MoyaProvider.swift lines 64, 133-149 show stubbing infrastructure. Tests can run without network by providing sample responses, with optional delays to simulate latency. This is critical for CI/CD environments and offline development. Implementation could add a ~stub:bool parameter that returns pre-configured responses from a sample_data function, with Eio.Time.sleep for latency simulation." 125 + }, 126 + { 127 + "source_repo": "third_party/swift/moya", 128 + "source_language": "Swift", 129 + "criticality": "medium", 130 + "change_type": "feature", 131 + "title": "Add request cancellation tokens for all request types", 132 + "description": "Moya returns Cancellable tokens for all requests, enabling safe cancellation from any thread with isCancelled checking. The OCaml library uses Eio's structured concurrency with fibers but lacks explicit cancellation tokens that can be passed around and checked. Adding cancellation tokens would enable better resource cleanup and UI responsiveness (cancel on user navigation).", 133 + "affected_files": [ 134 + "lib/requests.ml", 135 + "lib/requests.mli", 136 + "lib/one.ml", 137 + "lib/one.mli" 138 + ], 139 + "rationale": "Cancellable.swift and CancellableToken implementation show thread-safe cancellation with semaphore-based locking. While Eio provides fiber cancellation via Cancel.cancel, explicit cancellation tokens allow passing cancellation capability to other code without exposing the full fiber handle. This enables patterns like: let token = request(...) in ... ; if should_cancel then token.cancel(). For long-running requests, checking isCancelled before parsing large responses improves responsiveness." 140 + }, 141 + { 142 + "source_repo": "third_party/swift/moya", 143 + "source_language": "Swift", 144 + "criticality": "low", 145 + "change_type": "enhancement", 146 + "title": "Add URLRequest preservation in Response for debugging", 147 + "description": "Moya's Response object stores the original URLRequest (request field) alongside the response, enabling debugging of exactly what was sent. The OCaml Response stores the final URL but not the original request headers, method, or body. Preserving the request would help debugging redirect chains and header modifications.", 148 + "affected_files": [ 149 + "lib/response.ml", 150 + "lib/response.mli" 151 + ], 152 + "rationale": "Response.swift lines 13-16 show request preservation. When debugging issues, seeing both request and response together is essential. The OCaml library logs requests at Info level (requests.ml:343-350) but this data isn't available programmatically. Adding optional request: {method; headers; body_summary} to Response would enable better error messages like 'POST to /api/users with auth header resulted in 401'." 153 + }, 154 + { 155 + "source_repo": "third_party/swift/moya", 156 + "source_language": "Swift", 157 + "criticality": "high", 158 + "change_type": "enhancement", 159 + "title": "Add explicit Retry-After header handling in retry logic", 160 + "description": "While the OCaml library has parse_retry_after function in retry.ml (lines 73-93), it's not actually used in the retry implementation. Moya's documentation and plugin system enable respecting Retry-After headers. The OCaml library should integrate Retry-After parsing into the actual retry decision-making in requests.ml to properly handle rate limiting and server-requested delays.", 161 + "affected_files": [ 162 + "lib/requests.ml", 163 + "lib/retry.ml" 164 + ], 165 + "rationale": "The OCaml library has retry.ml with parse_retry_after and respect_retry_after config flag, but requests.ml:526-558 doesn't check response headers for Retry-After before calculating backoff. This means the library ignores explicit server guidance on retry timing, potentially causing rate limit violations or excessive retries. Integration is straightforward: check response headers after retry-able status, parse Retry-After if present, use that delay instead of exponential backoff." 166 + }, 167 + { 168 + "source_repo": "third_party/swift/moya", 169 + "source_language": "Swift", 170 + "criticality": "medium", 171 + "change_type": "enhancement", 172 + "title": "Add typed mapping errors distinct from HTTP errors", 173 + "description": "Moya distinguishes between HTTP errors (statusCode), network errors (underlying), and mapping errors (jsonMapping, stringMapping, objectMapping). The OCaml library has EncodingError but doesn't differentiate between 'request succeeded but JSON parsing failed' vs 'request failed'. Adding specific mapping error types would enable better error handling granularity.", 174 + "affected_files": [ 175 + "lib/error.ml", 176 + "lib/error.mli", 177 + "lib/response.ml" 178 + ], 179 + "rationale": "MoyaError.swift lines 4-32 show separation of concerns: .jsonMapping(Response) indicates successful HTTP but failed JSON parsing, distinct from .statusCode(Response) or .underlying(Error). The OCaml library's Response.json returns Result but errors are generic. Adding Error.JSONDecoding, Error.StringDecoding variants that wrap the response and underlying decode error would enable patterns like 'retry on network errors but not decode errors'." 180 + }, 181 + { 182 + "source_repo": "third_party/swift/moya", 183 + "source_language": "Swift", 184 + "criticality": "low", 185 + "change_type": "enhancement", 186 + "title": "Add response body mapping with empty data handling options", 187 + "description": "Moya's map() and mapJSON() methods include failsOnEmptyData parameter (default true) to control whether empty responses should error or return defaults (empty object/array). The OCaml library's Response.json/text methods don't have this flexibility, making it harder to handle 204 No Content responses or empty success responses from some APIs.", 188 + "affected_files": [ 189 + "lib/response.ml", 190 + "lib/response.mli" 191 + ], 192 + "rationale": "Response.swift lines 97-106, 132-180 show how failsOnEmptyData enables graceful handling of empty 204/205 responses. Some APIs return 200 with empty body for DELETE operations. The OCaml library could add optional ~empty_ok parameter to json method that returns Ok (Jsont.null) for empty responses instead of Err, or accept a ~default value. This avoids having to write special case handling for empty bodies." 193 + }, 194 + { 195 + "source_repo": "third_party/swift/moya", 196 + "source_language": "Swift", 197 + "criticality": "low", 198 + "change_type": "enhancement", 199 + "title": "Add endpoint closures for request customization before execution", 200 + "description": "Moya uses EndpointClosure and RequestClosure to allow request modification at different stages (endpoint -> URLRequest conversion). This enables per-target customization like adding query parameters, modifying headers based on environment, or changing the request based on runtime conditions. The OCaml library has static configuration; adding pre-request hooks would enable dynamic behavior.", 201 + "affected_files": [ 202 + "lib/requests.ml", 203 + "lib/requests.mli" 204 + ], 205 + "rationale": "MoyaProvider.swift lines 54-70, 112-115 show closure-based customization points. This enables patterns like: adding API version to all requests, signing requests with current timestamp, adding debug headers in development, or modifying timeouts based on request size. While the plugin architecture (recommendation #3) would cover this, lighter-weight endpoint closures provide simpler customization without full plugin implementation." 206 + }, 207 + { 208 + "source_repo": "third_party/swift/moya", 209 + "source_language": "Swift", 210 + "criticality": "medium", 211 + "change_type": "security", 212 + "title": "Add validation type configuration for response status codes", 213 + "description": "Moya provides ValidationType (.none, .successCodes, .successAndRedirectCodes, .customCodes) to control automatic HTTP error throwing. The OCaml library doesn't raise exceptions for 4xx/5xx by default (design decision) but lacks configuration to enable automatic validation. Adding optional validation modes would catch unhandled error responses early.", 214 + "affected_files": [ 215 + "lib/requests.ml", 216 + "lib/requests.mli", 217 + "lib/response.ml" 218 + ], 219 + "rationale": "ValidationType in Moya enables fail-fast on unexpected status codes, preventing silent failures where error responses are treated as success. The OCaml library requires explicit Response.ok checks (response.ml:40). Adding optional ~validate:Validate.(Success_only | Success_and_redirect | Custom [200; 201; 404] | None) parameter would enable automatic raise_for_status behavior when desired, preventing bugs from forgotten status checks while maintaining current default permissive behavior." 220 + } 221 + ] 222 + }