Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JonPurvis
left a comment
There was a problem hiding this comment.
Thanks for this @Cbrad24 🚀
The connector boots HasApiVersion before the request, so the connector replaces {version} first and the request never gets a chance.
I've left a few comment but nothing too major. If those could be addressed, that'd be great. Regarding a point you made in your PR:
Side note: #564 description lists UrlPath and Subdomain as enum cases, but the merged enum has a single Url case covering both.
This was a very late change made pre merge because UrlPath and Subdomain both involved replacing part of the URL, so we decided to just make one Url case to handle both.
| VersionMode::QueryParam => $pendingRequest->query()->add($this->versionKey, $this->apiVersion), | ||
| VersionMode::Url => $pendingRequest->setUrl( | ||
| str_replace('{version}', $this->ensureVersionIsSafeForUrl($this->apiVersion), $pendingRequest->getUrl()) | ||
| str_replace('{version}', $this->ensureVersionIsSafeForUrl($this->getRequestApiVersion($pendingRequest) ?? $this->apiVersion), $pendingRequest->getUrl()) |
There was a problem hiding this comment.
Small readability tweak: call a resolveUrlApiVersion($pendingRequest) helper here (see my next comment for possible implementation). Same behaviour you’re going for, we still substitute the request’s version when the connector boots first, just not inlined as getRequestApiVersion() ?? $this->apiVersion.
| protected function getRequestApiVersion(PendingRequest $pendingRequest): ?string | ||
| { | ||
| $request = $pendingRequest->getRequest(); | ||
|
|
||
| return method_exists($request, 'getApiVersion') ? $request->getApiVersion() : null; | ||
| } |
There was a problem hiding this comment.
Please could you rename this to resolveUrlApiVersion() so it’s more obvious it’s for the {version} placeholder, not header/query.
Couple of other suggestions too:
Only look at the request when the connector is booting ($pendingRequest->getConnector() === $this). When the request boots URL mode later, $this is already the request, so we can just use $this->apiVersion.
Only use the request’s version if the request is also in VersionMode::Url (needs a small getVersionMode() getter on the trait). If someone calls setApiVersion('beta') on a request that’s still in default Header mode, we should not change the URL path, only the header.
Detect HasApiVersion with Helpers::classUsesRecursive($request) instead of method_exists($request, 'getApiVersion'), so unrelated getApiVersion() methods don’t affect URLs.
There was a problem hiding this comment.
Something like:
/**
* Resolve which version to substitute into `{version}` for URL mode.
*/
protected function resolveUrlApiVersion(PendingRequest $pendingRequest): string
{
if ($pendingRequest->getConnector() === $this) {
$request = $pendingRequest->getRequest();
if (in_array(self::class, Helpers::classUsesRecursive($request), true)
&& $request->getVersionMode() === VersionMode::Url) {
$requestVersion = $request->getApiVersion();
if (is_string($requestVersion) && $requestVersion !== '') {
return $requestVersion;
}
}
}
return $this->apiVersion;
}Then a getter:
public function getVersionMode(): VersionMode
{
return $this->versionMode;
}|
|
||
| return true; | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Could you add a test for this scenario?
Connector still uses VersionMode::Url with v1, but the request only overrides via header, makeVersionedRequest('beta', VersionMode::Header). Here setApiVersion('beta') must not change the URL; the path should stay https://api.provider.com/v1, and the header should be api-version: beta.
…mode Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @JonPurvis, all fixed. Your snippet mostly worked out, just had to change |
|
Thanks for sorting, @Cbrad24 👍 I'll be catching up with Sam next week, so this will most likely be merged and tagged then. Cheers |
PR #564 introduces a
HasApiVersiontrait for API versioning, including a{version}placeholder in the URL withVersionMode::Url.I tried to use this with Microsoft Graph's API, as it's a good fit for switching between Graph's
v1.0andbetaAPIs. The problem I ran into was that withVersionMode::Url, the connector's version always wins when it has one, and$request->setApiVersion()is ignored.This is because the connector boots first and replaces
{version}on its pass, so when the request's plugin boots there is no{version}left to replace:$connector->send($request)creates aPendingRequest.{version}.This PR adds a
resolveUrlApiVersionmethod, which the connector uses when it replaces{version}. If the request also usesHasApiVersioninVersionMode::Urland has a version, the request's version wins, as #564's description puts it: "Prefer the request override when only that one call should differ." A request inVersionMode::HeaderorVersionMode::QueryParamkeeps its version out of the URL. To support this, the trait gains agetVersionMode()getter.New tests cover:
getApiVersion()andgetVersionMode()methods, but not the trait, leaving the connector's version in the URLOnly
VersionMode::Urlis affected by the boot order, sinceVersionMode::HeaderandVersionMode::QueryParamboth useadd()which replaces the connector's value under the same key.Example failing code: