From 73882417c73bd85c44d9b68280b235c59a561d8b Mon Sep 17 00:00:00 2001 From: Keegan Campbell Date: Mon, 26 Aug 2024 10:09:39 -0700 Subject: [PATCH 1/2] If any response contains octet-stream, make response binary --- src/Kiota.Builder/KiotaBuilder.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index e4ade3b5f5..2e10c12de1 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1159,6 +1159,7 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten }; } private const string RequestBodyPlainTextContentType = "text/plain"; + private const string RequestBodyOctetStreamContentType = "application/octet-stream"; private static readonly HashSet noContentStatusCodes = new(StringComparer.OrdinalIgnoreCase) { "201", "202", "204", "205", "301", "302", "303", "304", "307" }; private static readonly HashSet errorStatusCodes = new(Enumerable.Range(400, 599).Select(static x => x.ToString(CultureInfo.InvariantCulture)) .Concat([CodeMethod.ErrorMappingClientRange, CodeMethod.ErrorMappingServerRange]), StringComparer.OrdinalIgnoreCase); @@ -1249,7 +1250,9 @@ private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, Ope else if (modelType is null) { string returnType; - if (operation.Responses.Any(static x => noContentStatusCodes.Contains(x.Key))) + if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyOctetStreamContentType))) + returnType = "binary"; + else if (operation.Responses.Any(static x => noContentStatusCodes.Contains(x.Key))) returnType = VoidType; else if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType))) returnType = "string"; From 435d9022df6c07d484a98b24939b3c6c676e64f9 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 26 Aug 2024 14:31:45 -0400 Subject: [PATCH 2/2] feat: adds binary return type for redirect responses Signed-off-by: Vincent Biret --- CHANGELOG.md | 1 + src/Kiota.Builder/KiotaBuilder.cs | 36 +++++++++---------- .../ContentTypeMappingTests.cs | 1 + 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aaefb356d..ba94d4b03b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed shorthand for refresh option in workspace experience. [#5240](https://github.com/microsoft/kiota/issues/5240) - Fixed missing type options in help for plugin commands. [#5230](https://github.com/microsoft/kiota/issues/5230) - Removed OpenAI plugins generation since the service does not support them anymore. +- Redirect status codes documenting an application/octet-stream content type now generate a stream return type. [#5246](https://github.com/microsoft/kiota/issues/5246) - Fixed an issue where models would be missing when they had no properties and a single allOf entry. [#5014](https://github.com/microsoft/kiota/issues/5014) - Reverts modification of responses in output openApi file when generating plugins [#4945](https://github.com/microsoft/kiota/issues/4945) - Expand properties types with null type for Typescript. [#4993](https://github.com/microsoft/kiota-typescript/issues/1188) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 2e10c12de1..79bce3666e 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1160,7 +1160,8 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten } private const string RequestBodyPlainTextContentType = "text/plain"; private const string RequestBodyOctetStreamContentType = "application/octet-stream"; - private static readonly HashSet noContentStatusCodes = new(StringComparer.OrdinalIgnoreCase) { "201", "202", "204", "205", "301", "302", "303", "304", "307" }; + private static readonly HashSet redirectStatusCodes = new(StringComparer.OrdinalIgnoreCase) { "301", "302", "303", "307" }; + private static readonly HashSet noContentStatusCodes = new(redirectStatusCodes, StringComparer.OrdinalIgnoreCase) { "201", "202", "204", "205", "304" }; private static readonly HashSet errorStatusCodes = new(Enumerable.Range(400, 599).Select(static x => x.ToString(CultureInfo.InvariantCulture)) .Concat([CodeMethod.ErrorMappingClientRange, CodeMethod.ErrorMappingServerRange]), StringComparer.OrdinalIgnoreCase); private void AddErrorMappingsForExecutorMethod(OpenApiUrlTreeNode currentNode, OpenApiOperation operation, CodeMethod executorMethod) @@ -1249,31 +1250,28 @@ private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, Ope } else if (modelType is null) { - string returnType; - if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyOctetStreamContentType))) - returnType = "binary"; - else if (operation.Responses.Any(static x => noContentStatusCodes.Contains(x.Key))) - returnType = VoidType; - else if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType))) - returnType = "string"; - else - returnType = "binary"; - return (new CodeType { Name = returnType, IsExternal = true, }, null); + return (GetExecutorMethodDefaultReturnType(operation), null); } return (modelType, null); } else { - string returnType; - if (operation.Responses.Any(static x => noContentStatusCodes.Contains(x.Key))) - returnType = VoidType; - else if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType))) - returnType = "string"; - else - returnType = "binary"; - return (new CodeType { Name = returnType, IsExternal = true, }, null); + return (GetExecutorMethodDefaultReturnType(operation), null); } } + private static CodeType GetExecutorMethodDefaultReturnType(OpenApiOperation operation) + { + string returnType; + if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyOctetStreamContentType) && redirectStatusCodes.Contains(x.Key))) + returnType = "binary"; + else if (operation.Responses.Any(static x => noContentStatusCodes.Contains(x.Key))) + returnType = VoidType; + else if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType))) + returnType = "string"; + else + returnType = "binary"; + return new CodeType { Name = returnType, IsExternal = true, }; + } private void CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationType operationType, OpenApiOperation operation, CodeClass parentClass) { try diff --git a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs index 6707f96684..07cd3bd7c4 100644 --- a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs +++ b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs @@ -57,6 +57,7 @@ public void Dispose() [InlineData("application/octet-stream", "204", false, "default", "void")] [InlineData("application/octet-stream", "200", true, "default", "binary")] [InlineData("application/octet-stream", "200", false, "default", "binary")] + [InlineData("application/octet-stream", "302", false, "default", "binary")] // on a redirect to a binary content we generate a binary return type for download [InlineData("text/html", "204", true, "default", "void")] [InlineData("text/html", "204", false, "default", "void")] [InlineData("text/html", "200", true, "default", "binary")]