From 4af31575c64d1eaa60c768b72ec10378879547c1 Mon Sep 17 00:00:00 2001 From: Tsar Nikolay Date: Thu, 10 Dec 2020 17:14:24 +0500 Subject: [PATCH] Fix duplicate batch Cookie header. --- .../Batch/ODataBatchReaderExtensions.cs | 3 +- .../Batch/DefaultODataBatchHandlerTest.cs | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.OData/Batch/ODataBatchReaderExtensions.cs b/src/Microsoft.AspNetCore.OData/Batch/ODataBatchReaderExtensions.cs index 64ca375ddd..638eb6af6e 100644 --- a/src/Microsoft.AspNetCore.OData/Batch/ODataBatchReaderExtensions.cs +++ b/src/Microsoft.AspNetCore.OData/Batch/ODataBatchReaderExtensions.cs @@ -269,7 +269,8 @@ private static HttpContext CreateHttpContext(HttpContext originalContext) context.Request.Headers.Add(header.Key, preferencesToInherit); } } - else + // do not copy already existing headers, such as Cookie + else if (!context.Request.Headers.ContainsKey(header.Key)) { context.Request.Headers.Add(header); } diff --git a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Batch/DefaultODataBatchHandlerTest.cs b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Batch/DefaultODataBatchHandlerTest.cs index cc3c815b32..0ed98616be 100644 --- a/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Batch/DefaultODataBatchHandlerTest.cs +++ b/test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Batch/DefaultODataBatchHandlerTest.cs @@ -709,6 +709,72 @@ public async Task SendAsync_CorrectlyCopiesHeadersToIndividualRequests( Assert.Contains(deleteRequest, responseContent); Assert.Contains(postRequest, responseContent); } + + [Fact] + public async Task SendAsync_CorrectlyHandlesCookieHeader() + { + var batchRef = $"batch_{Guid.NewGuid()}"; + var changesetRef = $"changeset_{Guid.NewGuid()}"; + var endpoint = "http://localhost"; + + Type[] controllers = new[] { typeof(BatchTestCustomersController), typeof(BatchTestOrdersController), }; + var server = TestServerFactory.Create(controllers, (config) => + { + var builder = ODataConventionModelBuilderFactory.Create(config); + builder.EntitySet("BatchTestOrders"); + + config.MapODataServiceRoute("odata", null, builder.GetEdmModel(), new DefaultODataBatchHandler()); + config.Expand(); + config.EnableDependencyInjection(); + }); + + var client = TestServerFactory.CreateClient(server); + + var orderId = 2; + var createOrderPayload = $@"{{""@odata.type"":""Microsoft.AspNet.OData.Test.Batch.BatchTestOrder"",""Id"":{orderId},""Amount"":50}}"; + + var batchRequest = new HttpRequestMessage(HttpMethod.Post, $"{endpoint}/$batch"); + batchRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("text/plain")); + + // Add cookie (for example IdentityServer adds antiforgery after login) + batchRequest.Headers.TryAddWithoutValidation("Cookie", ".AspNetCore.Antiforgery.9TtSrW0hzOs=" + Guid.NewGuid()); + + var batchContent = $@" +--{batchRef} +Content-Type: multipart/mixed;boundary={changesetRef} + +--{changesetRef} +Content-Type: application/http +Content-Transfer-Encoding: binary +Content-ID: 1 + +POST {endpoint}/BatchTestOrders HTTP/1.1 +Content-Type: application/json;type=entry +Prefer: return=representation + +{createOrderPayload} +--{changesetRef}-- +--{batchRef} +Content-Type: application/http +Content-Transfer-Encoding: binary + +GET {endpoint}/BatchTestOrders({orderId}) HTTP/1.1 +Content-Type: application/json;type=entry +Prefer: return=representation + +--{batchRef}-- +"; + + var httpContent = new StringContent(batchContent); + httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse($"multipart/mixed;boundary={batchRef}"); + httpContent.Headers.ContentLength = batchContent.Length; + batchRequest.Content = httpContent; + var response = await client.SendAsync(batchRequest); + + ExceptionAssert.DoesNotThrow(() => response.EnsureSuccessStatusCode()); + + // TODO: assert somehow? + } #endif } @@ -810,6 +876,12 @@ public IEnumerable Get() return BatchTestOrder.Orders; } + [EnableQuery] + public SingleResult Get([FromODataUri]int key) + { + return SingleResult.Create(BatchTestOrder.Orders.Where(d => d.Id.Equals(key)).AsQueryable()); + } + public ITestActionResult Post([FromBody]BatchTestOrder order) { BatchTestOrder.Orders.Add(order);