Skip to content

Commit

Permalink
Adds support for RequestBodyFilters and ParameterFilters when constru…
Browse files Browse the repository at this point in the history
…cting schema from Metadata fixes domaindrivendev#2613 and domaindrivendev#2561
  • Loading branch information
Havunen committed Feb 21, 2024
1 parent 178ff8a commit 2e91ca5
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,18 @@ private OpenApiOperation GenerateOpenApiOperationFromMetadata(ApiDescription api
apiParameter.PropertyInfo(),
apiParameter.ParameterInfo(),
apiParameter.RouteInfo);

var filterContext = new ParameterFilterContext(
apiParameter,
_schemaGenerator,
schemaRepository,
apiParameter.PropertyInfo(),
apiParameter.ParameterInfo());

foreach (var filter in _options.ParameterFilters)
{
filter.Apply(parameter, filterContext);
}
}
}

Expand All @@ -290,14 +302,23 @@ private OpenApiOperation GenerateOpenApiOperationFromMetadata(ApiDescription api
{
foreach (var content in requestContentTypes)
{
RequestBodyFilterContext filterContext = null;
var fromBodyParam = apiDescription.ParameterDescriptions.SingleOrDefault(desc => desc.IsFromBody());
if (fromBodyParam is not null)
{
content.Schema = GenerateSchema(
fromBodyParam.Type,
schemaRepository,
fromBodyParam.PropertyInfo(),
fromBodyParam.ParameterInfo());
fromBodyParam.ParameterInfo()
);

filterContext = new RequestBodyFilterContext(
bodyParameterDescription: fromBodyParam,
formParameterDescriptions: null,
schemaGenerator: _schemaGenerator,
schemaRepository: schemaRepository
);
}
else
{
Expand All @@ -313,9 +334,21 @@ private OpenApiOperation GenerateOpenApiOperationFromMetadata(ApiDescription api
entry => entry.Key,
entry => new OpenApiEncoding { Style = ParameterStyle.Form }
);
filterContext = new RequestBodyFilterContext(
bodyParameterDescription: null,
formParameterDescriptions: fromFormParam,
schemaGenerator: _schemaGenerator,
schemaRepository: schemaRepository);
}
}

if (filterContext != null)
{
foreach (var filter in _options.RequestBodyFilters)
{
filter.Apply(operation.RequestBody, filterContext);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,56 @@ public void GetSwagger_SupportsOption_ParameterFilters()
Assert.Equal("v1", ((OpenApiString)operation.Parameters[0].Extensions["X-docName"]).Value);
}

[Fact]
public void GetSwagger_SupportsOption_ParameterFilters_WithMetaData()
{
var apiDesc = ApiDescriptionFactory.Create<FakeController>(
c => nameof(c.ActionWithParameter),
groupName: "v1",
httpMethod: "POST",
relativePath: "resource",
parameterDescriptions: new[]
{
new ApiParameterDescription { Name = "param", Source = BindingSource.Query }
});
apiDesc.ActionDescriptor.EndpointMetadata = new List<object>()
{
new OpenApiOperation
{
Parameters = new List<OpenApiParameter>() {
new OpenApiParameter
{
Name = "param",
Content = new Dictionary<string, OpenApiMediaType>
{
}
}
}
}
};
var subject = Subject(
apiDescriptions: new[] { apiDesc },
options: Options.Create<SwaggerGeneratorOptions>(new SwaggerGeneratorOptions
{
SwaggerDocs = new Dictionary<string, OpenApiInfo>(StringComparer.Ordinal)
{
["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" }
},
ParameterFilters = new List<IParameterFilter>
{
new TestParameterFilter()
}
})
);

var document = subject.GetSwagger("v1");

var operation = document.Paths["/resource"].Operations[OperationType.Post];
Assert.Equal(2, operation.Parameters[0].Extensions.Count());
Assert.Equal("bar", ((OpenApiString)operation.Parameters[0].Extensions["X-foo"]).Value);
Assert.Equal("v1", ((OpenApiString)operation.Parameters[0].Extensions["X-docName"]).Value);
}

[Fact]
public void GetSwagger_SupportsOption_RequestBodyFilters()
{
Expand Down Expand Up @@ -1367,6 +1417,59 @@ public void GetSwagger_SupportsOption_RequestBodyFilters()
Assert.Equal("v1", ((OpenApiString)operation.RequestBody.Extensions["X-docName"]).Value);
}

[Fact]
public void GetSwagger_SupportsOption_RequestBodyFilters_WithMetaData()
{
var apiDesc = ApiDescriptionFactory.Create<FakeController>(
c => nameof(c.ActionWithParameter),
groupName: "v1",
httpMethod: "POST",
relativePath: "resource",
parameterDescriptions: new[]
{
new ApiParameterDescription { Name = "param", Source = BindingSource.Body }
});
apiDesc.ActionDescriptor.EndpointMetadata = new List<object>()
{
new OpenApiOperation
{
RequestBody = new OpenApiRequestBody
{
Content = new Dictionary<string, OpenApiMediaType>
{
["multipart/form-data"] = new OpenApiMediaType
{
// These values are null
Schema = null,
Encoding = null
}
}
}
}
};
var subject = Subject(
apiDescriptions: new[] { apiDesc },
options: Options.Create(new SwaggerGeneratorOptions
{
SwaggerDocs = new Dictionary<string, OpenApiInfo>(StringComparer.Ordinal)
{
["v1"] = new OpenApiInfo { Version = "V1", Title = "Test API" }
},
RequestBodyFilters = new List<IRequestBodyFilter>
{
new TestRequestBodyFilter()
}
})
);

var document = subject.GetSwagger("v1");

var operation = document.Paths["/resource"].Operations[OperationType.Post];
Assert.Equal(2, operation.RequestBody.Extensions.Count);
Assert.Equal("bar", ((OpenApiString)operation.RequestBody.Extensions["X-foo"]).Value);
Assert.Equal("v1", ((OpenApiString)operation.RequestBody.Extensions["X-docName"]).Value);
}

[Fact]
public void GetSwagger_SupportsOption_OperationFilters()
{
Expand Down

0 comments on commit 2e91ca5

Please sign in to comment.