feat(typespec-go): support paging with a relative nextLink - #5079
feat(typespec-go): support paging with a relative nextLink#5079tadelesh wants to merge 1 commit into
Conversation
runtime.FetcherForNextLink requires an absolute URL, so a service that returns a next link relative to its endpoint (e.g. "/page/2") failed with "no Host in request URL". Generated pagers now resolve a relative next link against the client endpoint before fetching the next page; absolute next links are passed through unmodified. Enables the previously disabled azure/core/page withRelativeNextLink Spector test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a2fed377-7b26-45fc-b3aa-8b6d6df8b46a
|
All changed packages have been documented.
Show changes
|
Go emitter diffBaseline Diff summary: 18 file(s), +204 / -5 Rendered diff: inline on the run summary, or the emitter-diff-go-html artifact. Informational check (core/eng/emitter-diff); does not block the PR. |
commit: |
|
@jhendrixMSFT I remembered that you said we already support it in swagger cases. But I could not find the related code. Current implementation will change all the generated code, which I do not prefer. Any suggestions? |
|
You can try these changes here
|
| Fetcher: func(ctx context.Context, page *PageableLROsClientListPrivateEndPointsResponse) (PageableLROsClientListPrivateEndPointsResponse, error) { | ||
| resp, err := runtime.FetcherForNextLink(ctx, client.internal.Pipeline(), *page.NextLink, func(ctx context.Context) (*policy.Request, error) { | ||
| nextLink := *page.NextLink | ||
| // the service can return a next link that's relative to the endpoint, however |
There was a problem hiding this comment.
We shouldn't be emitting comments.
| // the service can return a next link that's relative to the endpoint, however | ||
| // runtime.FetcherForNextLink requires an absolute URL, so resolve it here. | ||
| if nextLink != "" { | ||
| if u, err := url.Parse(nextLink); err == nil && !u.IsAbs() { |
There was a problem hiding this comment.
A few problems here.
erris discarded when notnil- we parse just to check
IsAbs()then throw that away- this happens for all paths and IIRC relative paths are rare
Do we know at codegen time if the path is relative?
There was a problem hiding this comment.
No, we could not know that. It's kind of a runtime behavior. I remembered that you said we already support it in swagger cases. But I could not find the related code. Current implementation will change all the generated code, which I do not prefer. Any suggestions?
Resolves #4994.
What
Adds support for paging with a relative nextLink to the Go emitter, and enables the previously disabled
azure/core/pagewithRelativeNextLinkSpector test.Problem
runtime.FetcherForNextLinkbuilds the follow-up request withruntime.NewRequest(ctx, verb, nextLink), which rejects a non-absolute URL withno Host in request URL. A service that returns a next link relative to its endpoint (e.g./azure/core/page/with-relative-next-link/page/2, per the Spector scenario) therefore failed on the second page. This is whyTestPageClient_NewWithRelativeNextLinkPagerwas commented out with aTODO: runtime.FetcherForNextLink doesn't support relative next link URLs.The code model and codegen already carry everything needed (
PageableStrategyNextLink+ thenextLinkfield path); only the emitted fetcher was missing the resolution step. Relative-ness is a property of the runtime value, not something TCGC can express statically, so the check has to be in generated code.Fix
In
packages/typespec-go/src/codegen/core/operations.ts,emitPagerDefinitionnow emits a resolution step before callingruntime.FetcherForNextLink:Notes:
client.<endpointParam>for data-plane clients andclient.internal.Endpoint()for ARM clients, matching what*CreateRequestalready uses.runtime.JoinPathsis the same helper every generated*CreateRequestuses to combine the endpoint with a path, so relative links are resolved consistently with first-page requests (this also matches how the Python/JS emitters append a relative next link to the endpoint). It preserves the next link's query string.u.IsAbs()fast path and are passed through byte-for-byte, so behavior for compliant services is unchanged.FetcherForNextLinkOptions.NextReq), since that operation builds the request (and joins the endpoint) itself, and when the client has no single endpoint (the Autorest-onlytemplatedHostcompat case).Tests
TestPageClient_NewWithRelativeNextLinkPagerintest/azure-http-specs/azure/core/azurepagegroup/custom_client_test.go; it passes against the Spector mock server (2 pages, second fetched via the relative link).pageable-lroandtenant-resourceunit scenario snapshots.pnpm vitest run(49 unit tests pass); full regeneration of all Spector modules followed bypnpm go-test— all generated modules pass.