diff --git a/change/react-native-windows-52945ab1-3039-4dfd-944a-7dd398602d34.json b/change/react-native-windows-52945ab1-3039-4dfd-944a-7dd398602d34.json new file mode 100644 index 00000000000..5377c4630a8 --- /dev/null +++ b/change/react-native-windows-52945ab1-3039-4dfd-944a-7dd398602d34.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Test Access-Control-Request-Headers #11034", + "packageName": "react-native-windows", + "email": "jurocha@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Desktop.UnitTests/OriginPolicyHttpFilterTest.cpp b/vnext/Desktop.UnitTests/OriginPolicyHttpFilterTest.cpp index a31afb0ff05..7bf22675485 100644 --- a/vnext/Desktop.UnitTests/OriginPolicyHttpFilterTest.cpp +++ b/vnext/Desktop.UnitTests/OriginPolicyHttpFilterTest.cpp @@ -4,19 +4,28 @@ #include #include +#include +#include "WinRTNetworkingMocks.h" // Windows API #include #include using namespace Microsoft::VisualStudio::CppUnitTestFramework; +using namespace winrt::Windows::Web::Http; using Microsoft::React::Networking::OriginPolicyHttpFilter; +using Microsoft::React::Networking::RequestArgs; +using Microsoft::React::Networking::ResponseOperation; using winrt::Windows::Foundation::Uri; namespace Microsoft::React::Test { TEST_CLASS (OriginPolicyHttpFilterTest) { + TEST_CLASS_INITIALIZE(Initialize) { + winrt::uninit_apartment(); + } + // TEMP tests to see if Uri has comparison capabilities TEST_METHOD(UrlsHaveSameOrigin) { // clang-format off @@ -242,6 +251,49 @@ TEST_CLASS (OriginPolicyHttpFilterTest) { Assert::AreEqual(2, static_cast(response.Headers().Size())); } } + + TEST_METHOD(ValidatePreflightResponseMainAndContentHeadersSucceeds) { + auto mockFilter = winrt::make(); + mockFilter.as()->Mocks.SendRequestAsync = + [](HttpRequestMessage const &request) -> ResponseOperation { + HttpResponseMessage response{}; + + response.StatusCode(HttpStatusCode::Ok); + response.Headers().Insert(L"Access-Control-Allow-Origin", L"*"); + // Return allowed headers as requested by client + response.Headers().Insert( + L"Access-Control-Allow-Headers", request.Headers().Lookup(L"Access-Control-Request-Headers")); + + co_return response; + }; + + auto reqArgs = winrt::make(); + auto request = HttpRequestMessage(HttpMethod::Get(), Uri{L"http://somehost"}); + request.Properties().Insert(L"RequestArgs", reqArgs); + request.Headers().TryAppendWithoutValidation(L"Authorization", L"Bearer abc"); + // Should implicitly set Conent-Length and Content-Type + request.Content(HttpStringContent{L"PreflightContent"}); + + auto filter = winrt::make(mockFilter); + auto opFilter = filter.as(); + + OriginPolicyHttpFilter::SetStaticOrigin("http://somehost"); + try { + auto sendOp = opFilter->SendPreflightAsync(request); + sendOp.get(); + + auto response = sendOp.GetResults(); + opFilter->ValidatePreflightResponse(request, response); + + OriginPolicyHttpFilter::SetStaticOrigin({}); + Assert::AreEqual( + L"Authorization, Content-Length, Content-Type", + response.Headers().Lookup(L"Access-Control-Allow-Headers").c_str()); + } catch (const winrt::hresult_error &e) { + OriginPolicyHttpFilter::SetStaticOrigin({}); + Assert::Fail(e.message().c_str()); + } + } }; } // namespace Microsoft::React::Test diff --git a/vnext/Shared/Networking/OriginPolicyHttpFilter.cpp b/vnext/Shared/Networking/OriginPolicyHttpFilter.cpp index 65079ac5d45..4cd97230005 100644 --- a/vnext/Shared/Networking/OriginPolicyHttpFilter.cpp +++ b/vnext/Shared/Networking/OriginPolicyHttpFilter.cpp @@ -113,6 +113,8 @@ bool OriginPolicyHttpFilter::ConstWcharComparer::operator()(const wchar_t *a, co /*static*/ void OriginPolicyHttpFilter::SetStaticOrigin(std::string &&url) { if (!url.empty()) s_origin = Uri{to_hstring(url)}; + else + s_origin = nullptr; } /*static*/ bool OriginPolicyHttpFilter::IsSameOrigin(Uri const &u1, Uri const &u2) noexcept {