Skip to content

Fix: relative references in subdirectory documents are not loading #1674 - #2243

Merged
Maggie Kimani (MaggieKimani1) merged 4 commits into
microsoft:mainfrom
dldl-cmd:fix_reference_loading_with_subfolders
Apr 9, 2025
Merged

Fix: relative references in subdirectory documents are not loading #1674#2243
Maggie Kimani (MaggieKimani1) merged 4 commits into
microsoft:mainfrom
dldl-cmd:fix_reference_loading_with_subfolders

Conversation

@dldl-cmd

@dldl-cmddldl-cmd commented Mar 10, 2025

Copy link
Copy Markdown
Contributor

Use OpenApiDocuments BaseUri as location of the document. This allows to have during loading further documents a base Url for retrieval, which can be combined with a relative Uri to get an absolute.
Fixes#1674

…crosoft#1674
Use OpenApiDocuments BaseUri as location of the document. This allows to have during loading further documents a base Url for retrieval, which can be combined with a relative Uri to get an absolute.
@baywet

Copy link
Copy Markdown
Member

Thanks for the contribution!

Maggie Kimani (@MaggieKimani1) can you do an initial review here please?

Comment threadsrc/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Fixed
@MaggieKimani1

Maggie Kimani (MaggieKimani1) commented Mar 20, 2025

Copy link
Copy Markdown
Contributor

dldl-cmd sorry for the delay in response/review.
I have checked out the issue that this PR resolves and it seems that this is by design.
Have you considered creating a custom external refs loader, an implementation of our IStreamLoader interface as per Darrel's comment here?
Our default stream reader class is a bit limited as file/resource location might vary depending on use case, hence the exposed interface that you can use to resolve the relative references for documents contained in subdirectories, and pass the custom loader as part of the OpenApiReaderSettings as shown here


Once you do so, the files will automatically be registered with the source document's workspace.

Reference:

publicclassResourceLoader:IStreamLoader
{
publicStreamLoad(Uriuri)
{
returnnull;
}
publicTask<Stream>LoadAsync(Uriuri,CancellationTokencancellationToken=default)
{
varpath=newUri(new("http://example.org/V3Tests/Samples/OpenApiWorkspace/"),uri).AbsolutePath;
path=path[1..];// remove leading slash
returnTask.FromResult(Resources.GetStream(path));
}
}

@dldl-cmd

dldl-cmd commented Mar 20, 2025

Copy link
Copy Markdown
ContributorAuthor

Maggie Kimani (@MaggieKimani1) implementing just an own stream loader cannot solve the problem. The reason is, that the stream loader has no idea, which document is the current parent and where this document is located. Therefore it cannot resolve the relative reference as it doesn't know to which location it is relative. An example:

  • root.yaml
....$ref: ./DirA/DirB/DirC/second.yaml#/components/schema/Second
  • DirA/DirB/DirC/second.yaml
...
$ref: ../third.yaml#/components/schema/Third
  • DirA/DirB/third.yaml
...
$ref: ./DirC/Fourth.yaml#/components/schema/Fourth.yaml

When the reference $ref: ./DirC/Fourth.yaml#/components/schema/Fourth.yaml should be resolved. It is necessary to known that this reference is relative to the document at DirA/DirB/third.yaml.

This information is not only necessary at the time of loading the document but also when OpenApiDocument.ResolveReference tries to resolve a reference.

@MaggieKimani1

Copy link
Copy Markdown
Contributor

Also do you mind resolving the conflicts?

Comment threadsrc/Microsoft.OpenApi/Services/OpenApiWorkspace.cs Outdated
@dldl-cmd

Copy link
Copy Markdown
ContributorAuthor

Also do you mind resolving the conflicts?

Sorry for my late reply, I was unavailable a few days. I didn't notice the merge conflict until now. I have started to resolve them, but I need to check at least one conflict more in detail. Hopefully I can resolve it in the next days.

@dldl-cmd
dldl-cmd requested a review from a team as a code ownerApril 8, 2025 17:50
(_, true, false) when baseUrl.Scheme.Equals("file", StringComparison.OrdinalIgnoreCase) && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) =>
new Uri(Path.Combine(baseUrl.AbsoluteUri, uri.ToString())),
(_, _, _) => new Uri(baseUrl, uri),
true => new Uri(Path.Combine(Directory.GetCurrentDirectory(), uri.ToString())),

Check notice

Code scanning / CodeQL

Call to System.IO.Path.Combine

Call to 'System.IO.Path.Combine'.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relative reference in subdirectory OpenApi document fails to load

4 participants

@dldl-cmd@baywet@MaggieKimani1@github-advanced-security