Repository navigation
feat: sync PHP client with Apify OpenAPI spec v2-2026-10-19T133704Z - #17
Merged
Merged
Conversation
Realigns with the reference apify-client-js updates since the client's last sync (apify/apify-client-js#1139, #1140, #1141, #1145, #1152) and the OpenAPI schema fixes in apify/apify-docs#3087 (Actor/version/schedule/env-var request bodies, which this client already passes through untyped, so no code changes were needed for those specifically). - Add DatasetClient::streamItems(), a streamed (non-buffered) counterpart to downloadItems() for large exports. - Add a $contentEncoding parameter to KeyValueStoreClient::setRecord(), so an already-compressed value is uploaded as is instead of being compressed again. - Add ApifyClientException, a common base for every error the client throws for a failed API interaction; ApifyApiException (and its status subclasses) now extend it. - Add InvalidResponseBodyException (extends ApifyClientException), thrown instead of a raw JsonException when a successful response body fails to parse as JSON. - Bump Version::API_SPEC_VERSION and Version::CLIENT_VERSION. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3FfQf9r45KVCa5VAYAjkd
HttpClientCore::call() now accepts an optional $validateBody hook, run against the buffered response body inside the existing retry loop before a successful status is returned; ResourceContext's JSON-decoding primitives (and the few direct resource-client call sites that decode JSON themselves) pass their decode step through it. A body that fails to parse as JSON - usually a connection dropped mid-response - is now retried with the same backoff as a 5xx/429, instead of failing on the very first attempt, matching the reference client's own retry-loop placement of this check. Also: fix InvalidResponseBodyException's message to emit a real newline (was a literal backslash-n from a single-quoted format string), update its docblock to stop asserting the now-fixed non-retry behavior, and trim changelog-trivia from DatasetClient::streamItems()'s docblock. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3FfQf9r45KVCa5VAYAjkd
A validated (JSON-decoded) response body was read twice: call() ran $validateBody against (string) $response->getBody() and discarded the result, then returned the same $response; every JSON call site in ResourceContext then re-read the body via a second (string) $response->getBody(). A seekable stream (the bundled Guzzle client, MockTransport) rewinds transparently on each cast, masking this, but PSR-18 does not guarantee a seekable/re-readable body, so a transport that returns one exhausts it on the first read and the second read silently returns '' - the resource then looks empty/absent with no exception. Buffer the body into a string exactly once, validate it, and hand the caller a response rewrapped around a fresh stream built from that buffered string via the injected StreamFactoryInterface, which backs it with a seekable resource either way. Added a regression test using a GuzzleHttp\Psr7\NoSeekStream response body (confirmed it fails against the prior code) and a MockTransport::queueRawResponse() helper to queue it. Also collapsed the retry-on-malformed-JSON rationale, previously restated in three docblocks (HttpClientCore::call's $validateBody @PARAM, Json::decode, and InvalidResponseBodyException's class doc), down to one canonical copy on HttpClientCore::call(), with the other two trimmed to a one-line cross-reference. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3FfQf9r45KVCa5VAYAjkd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Syncs the client to OpenAPI spec
v2-2026-10-19T133704Z(apify/apify-docs#3087) and ports the changes from the latestapify-client-jsbatch (apify/apify-client-js#1140, #1145, #1139, #1141, #1152).actorPermissionLeveland the schedule'snotifications).DatasetClient::streamItems()returns a stream over a dataset export instead of buffering it in memory (apify-client-js#1139, #1152). It shares a newResourceContext::streamRaw()helper withLogClient::stream().$contentEncodingparameter onKeyValueStoreClient::setRecord()uploads a value that is already compressed, without compressing it again (apify-client-js#1140).ApifyClientExceptionis a new common base class for every error the client throws for a failed API call, andApifyApiExceptionnow extends it (apify-client-js#1145).InvalidResponseBodyExceptionreplaces the rawJsonExceptionthrown when a successful response body isn't valid JSON. Like the reference client, the client now retries such a response with the same backoff it uses for a retryable status code.HttpClientCore::call()reads the body once and returns it in a fresh stream, so a non-seekable PSR-7 body from a custom HTTP client isn't read twice.