Describe the bug
The TypeScript emitter generates a URL template with a slash on both sides of the extension-resource scope parameter:
"/{+resourceUri}/providers/Azure.ResourceManager.Resources/extensionsResources/{extensionsResourceName}{?api%2Dversion}"
For tenant-scoped extension resources, resourceUri is correctly passed as an empty string. Expanding the template then produces a route beginning with two slashes:
//providers/Azure.ResourceManager.Resources/extensionsResources/extension
The Spector server does not match this route and returns 404.
Reproduction
Use the azure/resource-manager/resources Spector scenario and run:
await client.extensionsResources.get("", "extension");
The same problem affects all tenant-scoped extension-resource operations currently covered by packages/typespec-ts/test/azure-modular-integration/azure-arm-resources.test.ts:
get("", "extension")
createOrUpdate("", "extension", resource)
update("", "extension", resource)
delete("", "extension")
listByScope("")
Expected behavior
The request URL contains a single slash before providers:
/providers/Azure.ResourceManager.Resources/extensionsResources/extension
An empty resource URI represents tenant scope. Callers should not need to pass "." or another placeholder to obtain the correct URL.
Actual behavior
The generated requests contain //providers/... and receive 404 responses. For example:
GET //providers/Azure.ResourceManager.Resources/extensionsResources/extension?api-version=2023-12-01-preview 404
The PUT, PATCH, DELETE, and list operations fail in the same way.
Root cause
The generated expandUrlTemplate call expands this template:
/{+resourceUri}/providers/...
With resourceUri === "", the parameter contributes no characters while both literal slashes remain.
@typespec/ts-http-runtime@0.3.7 intentionally preserves consecutive slashes inside a route path. Azure SDK for JS PR Azure/azure-sdk-for-js#37302 removed the previous global slash normalization from buildRequestUrl and limits normalization to the endpoint/route boundary. Therefore, the runtime does not normalize this generated internal //.
Suggested fix
Have the TypeScript emitter generate or expand the route so tenant scope produces /providers/... directly, without relying on runtime slash normalization. The fix should preserve the empty-string API for tenant scope and should not require the "." workaround.
Environment
@azure-tools/typespec-ts: 0.56.0
@typespec/ts-http-runtime: 0.3.7
@azure-rest/core-client: 2.8.0
- TypeSpec compiler: 1.14.0
Describe the bug
The TypeScript emitter generates a URL template with a slash on both sides of the extension-resource scope parameter:
"/{+resourceUri}/providers/Azure.ResourceManager.Resources/extensionsResources/{extensionsResourceName}{?api%2Dversion}"For tenant-scoped extension resources,
resourceUriis correctly passed as an empty string. Expanding the template then produces a route beginning with two slashes:The Spector server does not match this route and returns 404.
Reproduction
Use the
azure/resource-manager/resourcesSpector scenario and run:The same problem affects all tenant-scoped extension-resource operations currently covered by
packages/typespec-ts/test/azure-modular-integration/azure-arm-resources.test.ts:get("", "extension")createOrUpdate("", "extension", resource)update("", "extension", resource)delete("", "extension")listByScope("")Expected behavior
The request URL contains a single slash before
providers:An empty resource URI represents tenant scope. Callers should not need to pass
"."or another placeholder to obtain the correct URL.Actual behavior
The generated requests contain
//providers/...and receive 404 responses. For example:The PUT, PATCH, DELETE, and list operations fail in the same way.
Root cause
The generated
expandUrlTemplatecall expands this template:With
resourceUri === "", the parameter contributes no characters while both literal slashes remain.@typespec/ts-http-runtime@0.3.7intentionally preserves consecutive slashes inside a route path. Azure SDK for JS PR Azure/azure-sdk-for-js#37302 removed the previous global slash normalization frombuildRequestUrland limits normalization to the endpoint/route boundary. Therefore, the runtime does not normalize this generated internal//.Suggested fix
Have the TypeScript emitter generate or expand the route so tenant scope produces
/providers/...directly, without relying on runtime slash normalization. The fix should preserve the empty-string API for tenant scope and should not require the"."workaround.Environment
@azure-tools/typespec-ts: 0.56.0@typespec/ts-http-runtime: 0.3.7@azure-rest/core-client: 2.8.0