Open darrelmiller opened 10 months ago
For the first issue, with the invalid written securityScheme this can be reproduced, by the following code, which indicates that it happens while writting the document.
var openApiDocument = new OpenApiDocument
{
Components = new OpenApiComponents
{
SecuritySchemes = new Dictionary<string, OpenApiSecurityScheme>
{
["ReferenceObject"] = new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Id = "RealObject",
Type = ReferenceType.Tag,
ExternalResource = "external.yaml"
}
},
["RealObject"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "scheme"
}
}
}
};
var memoryStream = new MemoryStream();
var streamWriter = new FormattingStreamWriter(memoryStream, CultureInfo.InvariantCulture);
var writer = new OpenApiYamlWriter(streamWriter);
openApiDocument.SerializeAsV3(writer);
writer.Flush();
var writtenDocument = Encoding.UTF8.GetString(memoryStream.ToArray());
The issues is, that in the serialization of an OpenApiReference
a SecurityScheme
is always written as
<ReferenceV3>
instead of considering the context (e.g. being in the components section of the document) where the following is expected
$ref: <ReferenceV3>
The relevant code section is this one, where I could not find and easy way to detect the context in which the element is written. https://github.com/microsoft/OpenAPI.NET/blob/6899d5f161bd0087ccea0a090cebbe4eaffdf99a/src/Microsoft.OpenApi/Models/OpenApiReference.cs#L180C1-L185C14
public void SerializeAsV3(IOpenApiWriter writer)
{
Utils.CheckArgumentNull(writer);
if (Type == ReferenceType.Tag)
{
// Write the string value only
writer.WriteValue(ReferenceV3);
return;
}
if (Type == ReferenceType.SecurityScheme)
{
// Write the string as property name
writer.WritePropertyName(ReferenceV3);
return;
}
writer.WriteStartObject();
// $ref
writer.WriteProperty(OpenApiConstants.DollarRef, ReferenceV3);
writer.WriteEndObject();
}
The second issue happens while reading the document:
var inputYaml = @"
openapi: 3.0
info:
version: 2.0.0
title: hello world
paths:
/:
get:
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ReferenceObject'
components:
schemas:
ReferenceObject:
$ref: '#/components/schemas/RealObject'
RealObject:
type: object
properties:
name:
type: string
";
var reader = new OpenApiStringReader(); ;
var document = reader.Read(inputYaml, out OpenApiDiagnostic diagnostic);
var reference = document.Paths["/"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.Reference.ReferenceV3;
Console.WriteLine(reference);
The code above prints #/components/schemas/RealObject
so the reference to ReferenceObject is lost while reading the document.
Turning of reference resolving does not create this issue. Without it the read and written document can be the same.
var reader = new OpenApiStringReader(new OpenApiReaderSettings
{
ReferenceResolution = ReferenceResolutionSetting.DoNotResolveReferences
});
Here is an example of a security object. Reading and writing this example fails to produce a valid OpenAPI.
A schema component that is reference object also fails for different reasons. In the output OpoenAPI, the transitive reference is lost and the inline reference points directly to the "realObject" instead of the "referenceObject".
Because of these bugs we need to revert PR #1491