Skip to content

feat(http): Add opt-in default socket inactivity timeout - #3367

Merged
stobrien89 merged 7 commits into
aws:masterfrom
rohangavankar:feat/default-socket-timeout
Oct 8, 2026
Merged

stobrien89 merged 7 commits into
aws:masterfrom
rohangavankar:feat/default-socket-timeout

Conversation

@rohangavankar

Copy link
Copy Markdown
Contributor

Implements the PHP side of the cross-SDK default socket read/write timeout (Socket Read Timeout Risk Mitigation SEP). Adds a per-service socket inactivity timeout for cURL-based clients, gated off by default — no behavior change unless AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026=true.

Mechanism: when enabled, attaches cURL's LOW_SPEED_LIMIT=1 / LOW_SPEED_TIME pair, turning the throughput monitor into a pure inactivity timer (trips on genuine silence, never on a slow-but-progressing transfer). One bidirectional window satisfies both the read and write mandate.

Tiers (shipped table keyed by serviceId): unlisted → 5 min interim default; partially-exempt → 15 min; fully-exempt → no timeout. Interim wide safety net; the tuned end-goal default lives in the default-configuration mechanism.

Scope: cURL-only, no public API change, internal init middleware. All-or-nothing caller precedence (if the caller set either LOW_SPEED option, the SDK sets neither). A missing/corrupt tier file degrades to attaching nothing.

Testing: 25 unit tests / 204 assertions (resolver gate + tiers + ms→s, middleware all-or-nothing, exempt/default/gate-off paths, drift guard, corrupt-file degrade, null-serviceId defensive). Behavior verified against real libcurl locally.

Interim opt-in mechanism, not intended for end users.

Add a default socket read/write inactivity timeout for cURL-based
clients, resolved per service and gated off by default. The feature
eliminates the "no socket timeout at all" case, where a connection
establishes, exchanges some bytes, then goes silent and hangs until the
OS gives up.

The timeout is OFF unless AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026 is set
to the exact string "true". When on, it attaches cURL's LOW_SPEED pair
(a fixed 1 byte/sec floor plus a per-service time window), turning
cURL's throughput monitor into a pure inactivity timer: it trips on
genuine silence, never on a slow-but-progressing transfer. One
bidirectional window satisfies both the read and the write mandate.

Per-service tiers come from a shipped table keyed by serviceId: unlisted
services get a 5-minute interim default, partially-exempt services get
15 minutes, and fully-exempt services get no timeout. The window is a
deliberately wide interim safety net; the tuned end-goal default lives
in the separate default-configuration mechanism.

The feature is cURL-only (the LOW_SPEED options are a libcurl
primitive), makes no public API change, and is an internal init
middleware. If a caller already set either LOW_SPEED option, the SDK
sets neither, so a caller who touches one key owns both. A missing or
corrupt tier file degrades to attaching no timeout rather than failing
client construction or applying a wrong default.

This is an interim opt-in mechanism and is not intended for end users.
@rohangavankar
rohangavankar requested a review from a team as a code owner October 6, 2026 19:16

@stobrien89 stobrien89 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me aside from some structural issues that are easy fixes

Comment thread src/AwsClient.php Outdated
Comment thread tests/SocketTimeout/AwsClientSocketTimeoutTest.php Outdated
Comment thread src/data/socket-timeout-tiers.json
Relocate socket_timeout_tiers.json from src/data/ (the generated API-model
tree, rejected by the model-change scan) to src/SocketTimeout/, next to the
feature code. Update the loader path constant and the test reference.

Also apply PSR-12 formatting fixes to AwsClient.php surfaced by PHPCS now
that the file is touched by this change.
- Merge addDefaultSocketTimeout() and getDefaultSocketTimeoutMiddleware()
  into a single addDefaultSocketTimeoutMiddleware().
- Move the socket-timeout tests into AwsClientTest and delete the separate
  tests/SocketTimeout/AwsClientSocketTimeoutTest.php.
- Rename socket_timeout_tiers.json to socket-timeout-tiers.json (dashes).
Place the tier table under src/data/socket-timeout-tiers.json so it is
picked up by the compile-json build step (compiled to a shipped
.json.php) like the SDK's other data files. Update the loader path and
the test reference.

@stobrien89 stobrien89 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one nit. No need to worry about the socket-timeout-tiers file- that will be compiled to JSON and preserved during build and release time.

Comment thread src/AwsClient.php Outdated
rohangavankar and others added 2 commits October 7, 2026 21:05
Co-authored-by: Sean O'Brien <60306702+stobrien89@users.noreply.github.com>

@stobrien89 stobrien89 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@stobrien89
stobrien89 merged commit dd891d9 into aws:master Oct 8, 2026
19 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants