Skip to content

Commit

Permalink
Merge pull request #1471 from microsoft/feature/default-stream
Browse files Browse the repository at this point in the history
defaulting to stream for unknown mime types
  • Loading branch information
baywet authored Mar 31, 2022
2 parents 36f20bf + bba0ee9 commit 6f2c51e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 20 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for vendor specific content types generation/serialization. [#1197](https://github.com/microsoft/kiota/issues/1197)
- Added support for 204 no content in generation and CSharp/Java/Go/TypeScript request adapters. #1410
- Added a draft swift generation implementation. #1444
- Added support for yaml response type generation. [#302](https://github.com/microsoft/kiota/issues/302)
- Added support for xml response type generation. [#302](https://github.com/microsoft/kiota/issues/302)
- Added support for unstructured response generation (stream). [#546](https://github.com/microsoft/kiota/issues/546)

### Changed

- Fixed a bug where the base url of the request adapter would be reset by the client. [#1443](https://github.com/microsoft/kiota/issues/1443)
- Fixed a bug where request builder classes for collections endpoints would have a wrong name. #1052
- Fix issue with ambiguous type names causing build errors and stack overflows. (Shell) #1052
- Fixed issue with ambiguous type names causing build errors and stack overflows. (Shell) #1052
- Fixed a bug where symbols (properties, methods, classes) could contain invalid characters #1436
- Renamed parameters for requests: o => options, q => queryParameters, h => headers. [#1380](https://github.com/microsoft/kiota/issues/1380)

Expand Down
12 changes: 7 additions & 5 deletions src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
namespace Kiota.Builder.Extensions {
public static class OpenApiOperationExtensions {
private static readonly HashSet<string> successCodes = new(StringComparer.OrdinalIgnoreCase) {"200", "201", "202"}; //204 excluded as it won't have a schema
private static readonly HashSet<string> validMimeTypes = new (StringComparer.OrdinalIgnoreCase) {
private static readonly HashSet<string> structuredMimeTypes = new (StringComparer.OrdinalIgnoreCase) {
"application/json",
"text/plain"
"application/xml",
"text/plain",
"text/xml",
"text/yaml",
};
/// <summary>
/// cleans application/vnd.github.mercy-preview+json to application/json
Expand All @@ -19,8 +22,7 @@ public static OpenApiSchema GetResponseSchema(this OpenApiOperation operation)
{
// Return Schema that represents all the possible success responses!
var schemas = operation.Responses.Where(r => successCodes.Contains(r.Key))
.SelectMany(re => re.Value.GetResponseSchemas())
.Where(s => s is not null);
.SelectMany(re => re.Value.GetResponseSchemas());

return schemas.FirstOrDefault();
}
Expand All @@ -29,7 +31,7 @@ public static IEnumerable<OpenApiSchema> GetResponseSchemas(this OpenApiResponse
var schemas = response.Content
.Where(c => !string.IsNullOrEmpty(c.Key))
.Select(c => (Key: c.Key.Split(';', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(), c.Value))
.Where(c => validMimeTypes.Contains(c.Key) || validMimeTypes.Contains(vendorSpecificCleanup.Replace(c.Key, string.Empty)))
.Where(c => structuredMimeTypes.Contains(c.Key) || structuredMimeTypes.Contains(vendorSpecificCleanup.Replace(c.Key, string.Empty)))
.Select(co => co.Value.Schema)
.Where(s => s is not null);

Expand Down
1 change: 0 additions & 1 deletion src/Kiota.Builder/GenerationConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public class GenerationConfiguration {
public GenerationLanguage Language { get; set; } = GenerationLanguage.CSharp;
public string ApiRootUrl { get; set; }
public string[] PropertiesPrefixToStrip { get; set; } = new string[] { "@odata."};
public HashSet<string> IgnoredRequestContentTypes { get; set; } = new();
public bool UsesBackingStore { get; set; }
public List<string> Serializers { get; set; } = new();
public List<string> Deserializers { get; set; } = new();
Expand Down
13 changes: 6 additions & 7 deletions src/Kiota.Builder/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,7 @@ private void CreateRequestBuilderClass(CodeNamespace currentNamespace, OpenApiUr
{
foreach(var operation in currentNode
.PathItems[Constants.DefaultOpenApiLabel]
.Operations
.Where(x => x.Value.RequestBody?.Content?.Any(y => !config.IgnoredRequestContentTypes.Contains(y.Key)) ?? true))
.Operations)
CreateOperationMethods(currentNode, operation.Key, operation.Value, codeClass);
}
CreateUrlManagement(codeClass, currentNode, isApiClientClass);
Expand Down Expand Up @@ -622,13 +621,13 @@ private void CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationTyp
var returnType = CreateModelDeclarations(currentNode, schema, operation, executorMethod, "Response");
executorMethod.ReturnType = returnType ?? throw new InvalidOperationException("Could not resolve return type for operation");
} else {
var returnType = voidType;
if(operation.Responses.Any(x => x.Value.Content.ContainsKey(RequestBodyBinaryContentType)))
returnType = "binary";
string returnType;
if(operation.Responses.Any(x => noContentStatusCodes.Contains(x.Key)))
returnType = voidType;
else if (operation.Responses.Any(x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType)))
returnType = "string";
else if(!operation.Responses.Any(x => noContentStatusCodes.Contains(x.Key)))
logger.LogWarning("could not find operation return type {operationType} {currentNodePath}", operationType, currentNode.Path);
else
returnType = "binary";
executorMethod.ReturnType = new CodeType { Name = returnType, IsExternal = true, };
}

Expand Down
44 changes: 38 additions & 6 deletions tests/Kiota.Builder.Tests/KiotaBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1768,8 +1768,40 @@ public void ModelsUseDescriptionWhenAvailable(){
Assert.NotNull(responseClass);
Assert.Equal("some description", responseClass.Description);
}
[Fact]
public void GeneratesAVoidExecutorForSingle204() {
[InlineData("application/json", "204", true, "void")]
[InlineData("application/json", "204", false, "void")]
[InlineData("application/json", "200", true, "Myobject")]
[InlineData("application/json", "200", false, "binary")]
[InlineData("application/xml", "204", true, "void")]
[InlineData("application/xml", "204", false, "void")]
[InlineData("application/xml", "200", true, "Myobject")]
[InlineData("application/xml", "200", false, "binary")]
[InlineData("text/xml", "204", true, "void")]
[InlineData("text/xml", "204", false, "void")]
[InlineData("text/xml", "200", true, "Myobject")]
[InlineData("text/xml", "200", false, "binary")]
[InlineData("text/yaml", "204", true, "void")]
[InlineData("text/yaml", "204", false, "void")]
[InlineData("text/yaml", "200", true, "Myobject")]
[InlineData("text/yaml", "200", false, "binary")]
[InlineData("application/octet-stream", "204", true, "void")]
[InlineData("application/octet-stream", "204", false, "void")]
[InlineData("application/octet-stream", "200", true, "binary")]
[InlineData("application/octet-stream", "200", false, "binary")]
[InlineData("text/html", "204", true, "void")]
[InlineData("text/html", "204", false, "void")]
[InlineData("text/html", "200", true, "binary")]
[InlineData("text/html", "200", false, "binary")]
[InlineData("*/*", "204", true, "void")]
[InlineData("*/*", "204", false, "void")]
[InlineData("*/*", "200", true, "binary")]
[InlineData("*/*", "200", false, "binary")]
[InlineData("text/plain", "204", true, "void")]
[InlineData("text/plain", "204", false, "void")]
[InlineData("text/plain", "200", true, "Myobject")]
[InlineData("text/plain", "200", false, "string")]
[Theory]
public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentType, string statusCode, bool addModel, string returnType) {
var myObjectSchema = new OpenApiSchema {
Type = "object",
Properties = new Dictionary<string, OpenApiSchema> {
Expand All @@ -1792,10 +1824,10 @@ public void GeneratesAVoidExecutorForSingle204() {
[OperationType.Get] = new OpenApiOperation() {
Responses = new OpenApiResponses
{
["204"] = new OpenApiResponse {
[statusCode] = new OpenApiResponse {
Content = {
["application/json"] = new OpenApiMediaType {
Schema = myObjectSchema
[contentType] = new OpenApiMediaType {
Schema = addModel ? myObjectSchema : null
}
}
},
Expand All @@ -1822,7 +1854,7 @@ public void GeneratesAVoidExecutorForSingle204() {
Assert.NotNull(rbClass);
var executor = rbClass.Methods.FirstOrDefault(x => x.IsOfKind(CodeMethodKind.RequestExecutor));
Assert.NotNull(executor);
Assert.Equal("void", executor.ReturnType.Name);
Assert.Equal(returnType, executor.ReturnType.Name);
}
[Fact]
public void DoesntGenerateVoidExecutorOnMixed204(){
Expand Down

0 comments on commit 6f2c51e

Please sign in to comment.