Skip to content

Commit c21653a

Browse files
committed
fix: skip local sibling probe in _preferLocalBaseForRemoteId for non-file:// schemas
When a schema is loaded from an https:// URL (e.g. via a VS Code YAML extension contributor), _preferLocalBaseForRemoteId extracts the basename from sub-schema $id values and probes for them as local siblings. This causes spurious HTTP requests that fail with 404 errors. For example, loading openapi.v3.1.yaml (with $id pointing to github.com/.../schema.yaml) from an https:// contributor causes a probe for <contributor-base>/schema.yaml, which does not exist. The companion function _resolveLocalSiblingFromRemoteUri already guards against this with `if (parentUri.scheme !== 'file') return undefined`. Apply the same scheme guard to _preferLocalBaseForRemoteId so the local sibling optimization only fires for file:// schemas where it makes sense. Made-with: Cursor
1 parent d0b52a8 commit c21653a

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

src/languageservice/services/yamlSchemaService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ export class YAMLSchemaService extends JSONSchemaService {
350350
const _preferLocalBaseForRemoteId = async (currentBase: string, id: string): Promise<string> => {
351351
try {
352352
const currentBaseUri = URI.parse(currentBase);
353+
if (currentBaseUri.scheme !== 'file') {
354+
return _resolveAgainstBase(currentBase, id);
355+
}
353356
const idUri = URI.parse(id);
354357
const localFileName = path.posix.basename(idUri.path);
355358
const localDir = path.posix.dirname(currentBaseUri.path);

test/yamlSchemaService.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,47 @@ describe('YAML Schema Service', () => {
406406
expect(requestedSecondaryUrisAfterChange).to.have.length(2);
407407
});
408408

409+
it('should not probe local sibling paths when schema is loaded from https://', async () => {
410+
const content = `# yaml-language-server: $schema=https://example.com/schemas/openapi-extensions.json\nopenapi: '3.1.0'\ninfo:\n title: Test\n version: '1.0'`;
411+
const yamlDock = parse(content);
412+
413+
const extensionsSchema = {
414+
$id: 'https://example.com/schemas/openapi-extensions.json',
415+
$schema: 'http://json-schema.org/draft-04/schema#',
416+
allOf: [{ $ref: './openapi.v3.1.json' }],
417+
};
418+
const openapiSchema = {
419+
$id: 'https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json',
420+
$schema: 'https://json-schema.org/draft/2020-12/schema',
421+
type: 'object',
422+
properties: {
423+
openapi: { type: 'string', pattern: '^3\\.1\\.\\d+(-.+)?$' },
424+
info: { type: 'object', properties: { title: { type: 'string' }, version: { type: 'string' } }, required: ['title', 'version'] },
425+
},
426+
required: ['openapi', 'info'],
427+
};
428+
429+
requestServiceMock = sandbox.fake((uri: string) => {
430+
if (uri === 'https://example.com/schemas/openapi-extensions.json') {
431+
return Promise.resolve(JSON.stringify(extensionsSchema));
432+
}
433+
if (uri === 'https://example.com/schemas/openapi.v3.1.json') {
434+
return Promise.resolve(JSON.stringify(openapiSchema));
435+
}
436+
return Promise.reject<string>(`Resource ${uri} not found.`);
437+
});
438+
439+
const service = new SchemaService.YAMLSchemaService(requestServiceMock, workspaceContext);
440+
await service.getSchemaForResource('', yamlDock.documents[0]);
441+
442+
const requestedUris = requestServiceMock.getCalls().map((call) => call.args[0]);
443+
expect(requestedUris).to.include('https://example.com/schemas/openapi-extensions.json');
444+
expect(requestedUris).to.include('https://example.com/schemas/openapi.v3.1.json');
445+
// _preferLocalBaseForRemoteId should NOT probe for the $id basename as a local sibling
446+
// when the parent schema was loaded from https:// (not file://)
447+
expect(requestedUris).to.not.include('https://example.com/schemas/schema.json');
448+
});
449+
409450
it('should handle modeline schema comment in the middle of file', () => {
410451
const documentContent = `foo:\n bar\n# yaml-language-server: $schema=https://json-schema.org/draft-07/schema#\naa:bbb\n`;
411452
const content = `${documentContent}`;

0 commit comments

Comments
 (0)