From ddee0b22fa6ba9b35db78d7a41910a227b2ef622 Mon Sep 17 00:00:00 2001 From: Darrel Miller Date: Sun, 3 Jul 2022 18:38:26 -0400 Subject: [PATCH 1/7] Fixed reading v2 with path parameters that are form data --- .../V2/OpenApiPathItemDeserializer.cs | 55 ++++++++++++++++++- .../Microsoft.OpenApi.Readers.Tests.csproj | 4 ++ .../V2Tests/OpenApiPathItemTests.cs | 23 +++++++- .../pathItemWithFormDataPathParameter.yaml | 41 ++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithFormDataPathParameter.yaml diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs index ba5707480..6134a4bc4 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Readers.ParseNodes; @@ -32,7 +33,7 @@ internal static partial class OpenApiV2Deserializer { "parameters", (o, n) => { - o.Parameters = n.CreateList(LoadParameter); + LoadPathParameters(o,n); } }, }; @@ -53,5 +54,57 @@ public static OpenApiPathItem LoadPathItem(ParseNode node) return pathItem; } + + private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node) + { + node.Context.SetTempStorage(TempStorageKeys.BodyParameter, null); + node.Context.SetTempStorage(TempStorageKeys.FormParameters, null); + + pathItem.Parameters = node.CreateList(LoadParameter); + + // Build request body based on information determined while parsing OpenApiOperation + var bodyParameter = node.Context.GetFromTempStorage(TempStorageKeys.BodyParameter); + if (bodyParameter != null) + { + var requestBody = CreateRequestBody(node.Context, bodyParameter); + foreach(var opPair in pathItem.Operations) + { + if (opPair.Value.RequestBody == null) + { + switch (opPair.Key) + { + case OperationType.Post: + case OperationType.Put: + case OperationType.Patch: + opPair.Value.RequestBody = requestBody; + break; + } + } + } + } + else + { + var formParameters = node.Context.GetFromTempStorage>(TempStorageKeys.FormParameters); + if (formParameters != null) + { + var requestBody = CreateFormBody(node.Context, formParameters); + foreach (var opPair in pathItem.Operations) + { + if (opPair.Value.RequestBody == null) + { + switch (opPair.Key) + { + case OperationType.Post: + case OperationType.Put: + case OperationType.Patch: + opPair.Value.RequestBody = requestBody; + break; + } + } + } + } + } + + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index e1ec38f8f..fda5ed842 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -14,6 +14,7 @@ + @@ -85,6 +86,9 @@ Never + + Never + Never diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index 5d3331207..ffa788bf2 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using FluentAssertions; using Microsoft.OpenApi.Extensions; @@ -253,10 +254,28 @@ public void ParseBasicPathItemWithFormDataShouldSucceed() } // Act - var operation = OpenApiV2Deserializer.LoadPathItem(node); + var pathItem = OpenApiV2Deserializer.LoadPathItem(node); // Assert - operation.Should().BeEquivalentTo(_basicPathItemWithFormData); + pathItem.Should().BeEquivalentTo(_basicPathItemWithFormData); + } + + [Fact] + public void ParsePathItemWithFormDataPathParameterShouldSucceed() + { + // Arrange + MapNode node; + using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "pathItemWithFormDataPathParameter.yaml"))) + { + node = TestHelper.CreateYamlMapNode(stream); + } + + // Act + var pathItem = OpenApiV2Deserializer.LoadPathItem(node); + + // Assert + // FormData parameters at in the path level are pushed into Operation request bodies. + Assert.True(pathItem.Operations.All(o => o.Value.RequestBody != null)); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithFormDataPathParameter.yaml b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithFormDataPathParameter.yaml new file mode 100644 index 000000000..57178b4ba --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithFormDataPathParameter.yaml @@ -0,0 +1,41 @@ +put: + summary: Puts a pet in the store with form data + description: "" + responses: + '200': + description: Pet updated. + '405': + description: Invalid input + x-http-tests: + - parameterValues: + petId: 10 + name: Milo + status: Happy + expectedRequest: + href: /pathitem-form-parameter/10 + headers: + Content-Type: multipart/form-data + content: name=Milo&status=Happy +post: + summary: Posts a pet in the store with form data + description: "" + responses: + '200': + description: Pet updated. +parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: string + - name: name + in: formData + description: Updated name of the pet + required: true + type: string + - name: status + in: formData + description: Updated status of the pet + required: false + type: string From 3dbe5d8040a7c64db0e4c62425c74703f2fc800d Mon Sep 17 00:00:00 2001 From: Darrel Miller Date: Mon, 4 Jul 2022 09:29:28 -0400 Subject: [PATCH 2/7] Fixed reading v2 with path parameter that is a body --- .../Microsoft.OpenApi.Readers.Tests.csproj | 4 +++ .../V2Tests/OpenApiPathItemTests.cs | 24 +++++++++++++- .../pathItemWithBodyPathParameter.yaml | 31 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithBodyPathParameter.yaml diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index fda5ed842..c04eb7fd2 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -14,6 +14,7 @@ + @@ -89,6 +90,9 @@ Never + + Never + Never diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index ffa788bf2..a11497cdf 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -275,7 +275,29 @@ public void ParsePathItemWithFormDataPathParameterShouldSucceed() // Assert // FormData parameters at in the path level are pushed into Operation request bodies. - Assert.True(pathItem.Operations.All(o => o.Value.RequestBody != null)); + Assert.True(pathItem.Operations[OperationType.Put].RequestBody != null); + Assert.True(pathItem.Operations[OperationType.Post].RequestBody != null); + Assert.Equal(2, pathItem.Operations.Count(o => o.Value.RequestBody != null)); } + [Fact] + public void ParsePathItemBodyDataPathParameterShouldSucceed() + { + // Arrange + MapNode node; + using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "pathItemWithBodyPathParameter.yaml"))) + { + node = TestHelper.CreateYamlMapNode(stream); + } + + // Act + var pathItem = OpenApiV2Deserializer.LoadPathItem(node); + + // Assert + // FormData parameters at in the path level are pushed into Operation request bodies. + Assert.True(pathItem.Operations[OperationType.Put].RequestBody != null); + Assert.True(pathItem.Operations[OperationType.Post].RequestBody != null); + Assert.Equal(2, pathItem.Operations.Count(o => o.Value.RequestBody != null)); + } + } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithBodyPathParameter.yaml b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithBodyPathParameter.yaml new file mode 100644 index 000000000..c17f4c54e --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiPathItem/pathItemWithBodyPathParameter.yaml @@ -0,0 +1,31 @@ +put: + summary: Puts a pet in the store with form data + description: "" + responses: + '200': + description: Pet updated. + '405': + description: Invalid input +post: + summary: Posts a pet in the store with form data + description: "" + responses: + '200': + description: Pet updated. +parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: string + - name: name + in: body + description: Updated pet body + required: true + type: object + properties: + name: + type: string + status: + type: string \ No newline at end of file From ea83688677d3c54e2ff3fcc9389187e2e10593db Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 4 Jul 2022 15:18:39 -0400 Subject: [PATCH 3/7] Update src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs index 6134a4bc4..b04eae319 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs @@ -88,7 +88,7 @@ private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node) if (formParameters != null) { var requestBody = CreateFormBody(node.Context, formParameters); - foreach (var opPair in pathItem.Operations) + foreach (var opPair in pathItem.Operations.Where(x => x.Value.RequestBody is null)) { if (opPair.Value.RequestBody == null) { From 364952b423861b6b79d04efbf92de858ee0f7e4d Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 4 Jul 2022 15:19:11 -0400 Subject: [PATCH 4/7] Update src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs Co-authored-by: Vincent Biret --- .../V2/OpenApiPathItemDeserializer.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs index b04eae319..4828f541d 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs @@ -90,16 +90,13 @@ private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node) var requestBody = CreateFormBody(node.Context, formParameters); foreach (var opPair in pathItem.Operations.Where(x => x.Value.RequestBody is null)) { - if (opPair.Value.RequestBody == null) + switch (opPair.Key) { - switch (opPair.Key) - { - case OperationType.Post: - case OperationType.Put: - case OperationType.Patch: - opPair.Value.RequestBody = requestBody; - break; - } + case OperationType.Post: + case OperationType.Put: + case OperationType.Patch: + opPair.Value.RequestBody = requestBody; + break; } } } From bbb6ae068240922755cce73fccef744ef244453d Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 4 Jul 2022 15:19:36 -0400 Subject: [PATCH 5/7] Update src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs Co-authored-by: Vincent Biret --- .../V2/OpenApiPathItemDeserializer.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs index 4828f541d..64252571f 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs @@ -69,16 +69,13 @@ private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node) var requestBody = CreateRequestBody(node.Context, bodyParameter); foreach(var opPair in pathItem.Operations) { - if (opPair.Value.RequestBody == null) + switch (opPair.Key) { - switch (opPair.Key) - { - case OperationType.Post: - case OperationType.Put: - case OperationType.Patch: - opPair.Value.RequestBody = requestBody; - break; - } + case OperationType.Post: + case OperationType.Put: + case OperationType.Patch: + opPair.Value.RequestBody = requestBody; + break; } } } From 8d28c5a587b36a0f63b3c8b7013c95b7c7f1cb30 Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 4 Jul 2022 15:20:04 -0400 Subject: [PATCH 6/7] Update src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs index 64252571f..a2179b31f 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs @@ -67,7 +67,7 @@ private static void LoadPathParameters(OpenApiPathItem pathItem, ParseNode node) if (bodyParameter != null) { var requestBody = CreateRequestBody(node.Context, bodyParameter); - foreach(var opPair in pathItem.Operations) + foreach(var opPair in pathItem.Operations.Where(x => x.Value.RequestBody is null)) { switch (opPair.Key) { From d4b2c7bd3701c67f3f58048fd13d920850598f9c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 4 Jul 2022 15:23:06 -0400 Subject: [PATCH 7/7] - adds missing using for linq --- src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs index a2179b31f..d905ea42e 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiPathItemDeserializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Readers.ParseNodes;