react-native-windows 0.69.7 → 0.69.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Microsoft.ReactNative/Base/CoreNativeModules.cpp +25 -0
- package/Microsoft.ReactNative/Pch/pch.h +0 -1
- package/Microsoft.ReactNative.Managed/packages.lock.json +27 -2
- package/PropertySheets/Generated/PackageVersion.g.props +2 -2
- package/Shared/Modules/BlobModule.cpp +4 -4
- package/Shared/Modules/BlobModule.h +1 -1
- package/Shared/Modules/FileReaderModule.cpp +2 -2
- package/Shared/Modules/HttpModule.cpp +4 -2
- package/Shared/Modules/IBlobPersistor.h +1 -1
- package/Shared/Networking/IHttpResource.h +2 -1
- package/Shared/Networking/IRedirectEventSource.h +18 -0
- package/Shared/Networking/IWinRTHttpRequestFactory.h +22 -0
- package/Shared/Networking/OriginPolicyHttpFilter.cpp +47 -15
- package/Shared/Networking/OriginPolicyHttpFilter.h +16 -3
- package/Shared/Networking/RedirectHttpFilter.cpp +283 -0
- package/Shared/Networking/RedirectHttpFilter.h +97 -0
- package/Shared/Networking/WinRTHttpResource.cpp +225 -140
- package/Shared/Networking/WinRTHttpResource.h +17 -4
- package/Shared/OInstance.cpp +10 -2
- package/Shared/Shared.vcxitems +4 -0
- package/Shared/Shared.vcxitems.filters +12 -0
- package/package.json +1 -1
|
@@ -19,8 +19,12 @@
|
|
|
19
19
|
|
|
20
20
|
namespace Microsoft::ReactNative {
|
|
21
21
|
|
|
22
|
+
using winrt::Microsoft::ReactNative::ReactPropertyBag;
|
|
23
|
+
|
|
22
24
|
namespace {
|
|
23
25
|
|
|
26
|
+
using winrt::Microsoft::ReactNative::ReactPropertyId;
|
|
27
|
+
|
|
24
28
|
bool HasPackageIdentity() noexcept {
|
|
25
29
|
static const bool hasPackageIdentity = []() noexcept {
|
|
26
30
|
auto packageStatics = winrt::get_activation_factory<winrt::Windows::ApplicationModel::IPackageStatics>(
|
|
@@ -35,6 +39,13 @@ bool HasPackageIdentity() noexcept {
|
|
|
35
39
|
return hasPackageIdentity;
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
ReactPropertyId<bool> HttpUseMonolithicModuleProperty() noexcept {
|
|
43
|
+
static ReactPropertyId<bool> propId{
|
|
44
|
+
L"ReactNative.Http"
|
|
45
|
+
L"UseMonolithicModule"};
|
|
46
|
+
return propId;
|
|
47
|
+
}
|
|
48
|
+
|
|
38
49
|
} // namespace
|
|
39
50
|
|
|
40
51
|
std::vector<facebook::react::NativeModuleDescription> GetCoreModules(
|
|
@@ -50,11 +61,25 @@ std::vector<facebook::react::NativeModuleDescription> GetCoreModules(
|
|
|
50
61
|
[props = context->Properties()]() { return Microsoft::React::CreateHttpModule(props); },
|
|
51
62
|
jsMessageQueue);
|
|
52
63
|
|
|
64
|
+
if (!ReactPropertyBag(context->Properties()).Get(HttpUseMonolithicModuleProperty())) {
|
|
65
|
+
modules.emplace_back(
|
|
66
|
+
Microsoft::React::GetBlobModuleName(),
|
|
67
|
+
[props = context->Properties()]() { return Microsoft::React::CreateBlobModule(props); },
|
|
68
|
+
batchingUIMessageQueue);
|
|
69
|
+
|
|
70
|
+
modules.emplace_back(
|
|
71
|
+
Microsoft::React::GetFileReaderModuleName(),
|
|
72
|
+
[props = context->Properties()]() { return Microsoft::React::CreateFileReaderModule(props); },
|
|
73
|
+
batchingUIMessageQueue);
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
modules.emplace_back(
|
|
54
77
|
"Timing",
|
|
55
78
|
[batchingUIMessageQueue]() { return facebook::react::CreateTimingModule(batchingUIMessageQueue); },
|
|
56
79
|
batchingUIMessageQueue);
|
|
57
80
|
|
|
81
|
+
// Note: `context` is moved to remove the reference from the current scope.
|
|
82
|
+
// This should either be the last usage of `context`, or the std::move call should happen later in this method.
|
|
58
83
|
modules.emplace_back(
|
|
59
84
|
NativeAnimatedModule::name,
|
|
60
85
|
[context = std::move(context)]() mutable { return std::make_unique<NativeAnimatedModule>(std::move(context)); },
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
#include <winrt/Windows.Storage.Streams.h>
|
|
44
44
|
#include <winrt/Windows.UI.ViewManagement.Core.h>
|
|
45
45
|
#include <winrt/Windows.UI.ViewManagement.h>
|
|
46
|
-
#include <winrt/Windows.Web.Http.Filters.h>
|
|
47
46
|
#include <winrt/Windows.Web.Http.Headers.h>
|
|
48
47
|
|
|
49
48
|
#include "Base/CxxReactIncludes.h"
|
|
@@ -24,6 +24,11 @@
|
|
|
24
24
|
"Microsoft.SourceLink.Common": "1.0.0"
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
|
+
"boost": {
|
|
28
|
+
"type": "Transitive",
|
|
29
|
+
"resolved": "1.76.0",
|
|
30
|
+
"contentHash": "p+w3YvNdXL8Cu9Fzrmexssu0tZbWxuf6ywsQqHjDlKFE5ojXHof1HIyMC3zDLfLnh80dIeFcEUAuR2Asg/XHRA=="
|
|
31
|
+
},
|
|
27
32
|
"Microsoft.Build.Tasks.Git": {
|
|
28
33
|
"type": "Transitive",
|
|
29
34
|
"resolved": "1.0.0",
|
|
@@ -60,14 +65,34 @@
|
|
|
60
65
|
"resolved": "1.0.0",
|
|
61
66
|
"contentHash": "G8DuQY8/DK5NN+3jm5wcMcd9QYD90UV7MiLmdljSJixi3U/vNaeBKmmXUqI4DJCOeWizIUEh4ALhSt58mR+5eg=="
|
|
62
67
|
},
|
|
68
|
+
"Microsoft.UI.Xaml": {
|
|
69
|
+
"type": "Transitive",
|
|
70
|
+
"resolved": "2.7.0",
|
|
71
|
+
"contentHash": "dB4im13tfmMgL/V3Ei+3kD2rUF+/lTxAmR4gjJ45l577eljHfdo/KUrxpq/3I1Vp6e5GCDG1evDaEGuDxypLMg=="
|
|
72
|
+
},
|
|
73
|
+
"Microsoft.Windows.CppWinRT": {
|
|
74
|
+
"type": "Transitive",
|
|
75
|
+
"resolved": "2.0.211028.7",
|
|
76
|
+
"contentHash": "JBGI0c3WLoU6aYJRy9Qo0MLDQfObEp+d4nrhR95iyzf7+HOgjRunHDp/6eGFREd7xq3OI1mll9ecJrMfzBvlyg=="
|
|
77
|
+
},
|
|
78
|
+
"Microsoft.Windows.SDK.BuildTools": {
|
|
79
|
+
"type": "Transitive",
|
|
80
|
+
"resolved": "10.0.22000.194",
|
|
81
|
+
"contentHash": "4L0P3zqut466SIqT3VBeLTNUQTxCBDOrTRymRuROCRJKazcK7ibLz9yAO1nKWRt50ttCj39oAa2Iuz9ZTDmLlg=="
|
|
82
|
+
},
|
|
63
83
|
"NETStandard.Library": {
|
|
64
84
|
"type": "Transitive",
|
|
65
85
|
"resolved": "2.0.3",
|
|
66
|
-
"contentHash": "
|
|
86
|
+
"contentHash": "548M6mnBSJWxsIlkQHfbzoYxpiYFXZZSL00p4GHYv8PkiqFBnnT68mW5mGEsA/ch9fDO9GkPgkFQpWiXZN7mAQ==",
|
|
67
87
|
"dependencies": {
|
|
68
88
|
"Microsoft.NETCore.Platforms": "1.1.0"
|
|
69
89
|
}
|
|
70
90
|
},
|
|
91
|
+
"ReactNative.Hermes.Windows": {
|
|
92
|
+
"type": "Transitive",
|
|
93
|
+
"resolved": "0.11.0-ms.6",
|
|
94
|
+
"contentHash": "WAVLsSZBV4p/3hNC3W67su7xu3f/ZMSKxu0ON7g2GaKRbkJmH0Qyif1IlzcJwtvR48kuOdfgPu7Bgtz3AY+gqg=="
|
|
95
|
+
},
|
|
71
96
|
"runtime.win10-arm.Microsoft.Net.Native.Compiler": {
|
|
72
97
|
"type": "Transitive",
|
|
73
98
|
"resolved": "2.2.7-rel-27913-00",
|
|
@@ -303,4 +328,4 @@
|
|
|
303
328
|
}
|
|
304
329
|
}
|
|
305
330
|
}
|
|
306
|
-
}
|
|
331
|
+
}
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.69.
|
|
13
|
+
<ReactNativeWindowsVersion>0.69.8</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>69</ReactNativeWindowsMinor>
|
|
16
|
-
<ReactNativeWindowsPatch>
|
|
16
|
+
<ReactNativeWindowsPatch>8</ReactNativeWindowsPatch>
|
|
17
17
|
<ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
|
|
18
18
|
</PropertyGroup>
|
|
19
19
|
</Project>
|
|
@@ -139,7 +139,7 @@ vector<module::CxxModule::Method> BlobModule::getMethods() {
|
|
|
139
139
|
auto size = blob[sizeKey].getInt();
|
|
140
140
|
auto socketID = jsArgAsInt(args, 1);
|
|
141
141
|
|
|
142
|
-
winrt::array_view<uint8_t> data;
|
|
142
|
+
winrt::array_view<uint8_t const> data;
|
|
143
143
|
try {
|
|
144
144
|
data = persistor->ResolveMessage(std::move(blobId), offset, size);
|
|
145
145
|
} catch (const std::exception &e) {
|
|
@@ -169,7 +169,7 @@ vector<module::CxxModule::Method> BlobModule::getMethods() {
|
|
|
169
169
|
auto type = part[typeKey].asString();
|
|
170
170
|
if (blobKey == type) {
|
|
171
171
|
auto blob = part[dataKey];
|
|
172
|
-
winrt::array_view<uint8_t> bufferPart;
|
|
172
|
+
winrt::array_view<uint8_t const> bufferPart;
|
|
173
173
|
try {
|
|
174
174
|
bufferPart = persistor->ResolveMessage(
|
|
175
175
|
blob[blobIdKey].asString(), blob[offsetKey].asInt(), blob[sizeKey].asInt());
|
|
@@ -216,7 +216,7 @@ vector<module::CxxModule::Method> BlobModule::getMethods() {
|
|
|
216
216
|
|
|
217
217
|
#pragma region IBlobPersistor
|
|
218
218
|
|
|
219
|
-
winrt::array_view<uint8_t> MemoryBlobPersistor::ResolveMessage(string &&blobId, int64_t offset, int64_t size) {
|
|
219
|
+
winrt::array_view<uint8_t const> MemoryBlobPersistor::ResolveMessage(string &&blobId, int64_t offset, int64_t size) {
|
|
220
220
|
if (size < 1)
|
|
221
221
|
return {};
|
|
222
222
|
|
|
@@ -233,7 +233,7 @@ winrt::array_view<uint8_t> MemoryBlobPersistor::ResolveMessage(string &&blobId,
|
|
|
233
233
|
if (endBound > bytes.size() || offset >= static_cast<int64_t>(bytes.size()) || offset < 0)
|
|
234
234
|
throw std::out_of_range("Offset or size out of range");
|
|
235
235
|
|
|
236
|
-
return winrt::array_view<uint8_t>(bytes.data() + offset, bytes.data() + endBound);
|
|
236
|
+
return winrt::array_view<uint8_t const>(bytes.data() + offset, bytes.data() + endBound);
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
void MemoryBlobPersistor::RemoveMessage(string &&blobId) noexcept {
|
|
@@ -30,7 +30,7 @@ class MemoryBlobPersistor final : public IBlobPersistor {
|
|
|
30
30
|
public:
|
|
31
31
|
#pragma region IBlobPersistor
|
|
32
32
|
|
|
33
|
-
winrt::array_view<uint8_t> ResolveMessage(std::string &&blobId, int64_t offset, int64_t size) override;
|
|
33
|
+
winrt::array_view<uint8_t const> ResolveMessage(std::string &&blobId, int64_t offset, int64_t size) override;
|
|
34
34
|
|
|
35
35
|
void RemoveMessage(std::string &&blobId) noexcept override;
|
|
36
36
|
|
|
@@ -71,7 +71,7 @@ std::vector<module::CxxModule::Method> FileReaderModule::getMethods() {
|
|
|
71
71
|
auto offset = blob["offset"].asInt();
|
|
72
72
|
auto size = blob["size"].asInt();
|
|
73
73
|
|
|
74
|
-
winrt::array_view<uint8_t> bytes;
|
|
74
|
+
winrt::array_view<uint8_t const> bytes;
|
|
75
75
|
try {
|
|
76
76
|
bytes = blobPersistor->ResolveMessage(std::move(blobId), offset, size);
|
|
77
77
|
} catch (const std::exception &e) {
|
|
@@ -116,7 +116,7 @@ std::vector<module::CxxModule::Method> FileReaderModule::getMethods() {
|
|
|
116
116
|
auto offset = blob["offset"].asInt();
|
|
117
117
|
auto size = blob["size"].asInt();
|
|
118
118
|
|
|
119
|
-
winrt::array_view<uint8_t> bytes;
|
|
119
|
+
winrt::array_view<uint8_t const> bytes;
|
|
120
120
|
try {
|
|
121
121
|
bytes = blobPersistor->ResolveMessage(std::move(blobId), offset, size);
|
|
122
122
|
} catch (const std::exception &e) {
|
|
@@ -72,9 +72,11 @@ static void SetUpHttpResource(
|
|
|
72
72
|
};
|
|
73
73
|
resource->SetOnData(std::move(onDataDynamic));
|
|
74
74
|
|
|
75
|
-
resource->SetOnError([weakReactInstance](int64_t requestId, string &&message) {
|
|
75
|
+
resource->SetOnError([weakReactInstance](int64_t requestId, string &&message, bool isTimeout) {
|
|
76
76
|
dynamic args = dynamic::array(requestId, std::move(message));
|
|
77
|
-
|
|
77
|
+
if (isTimeout) {
|
|
78
|
+
args.push_back(true);
|
|
79
|
+
}
|
|
78
80
|
|
|
79
81
|
SendEvent(weakReactInstance, completedResponse, std::move(args));
|
|
80
82
|
});
|
|
@@ -18,7 +18,7 @@ struct IBlobPersistor {
|
|
|
18
18
|
/// When an entry for blobId cannot be found.
|
|
19
19
|
/// </exception>
|
|
20
20
|
///
|
|
21
|
-
virtual winrt::array_view<uint8_t> ResolveMessage(std::string &&blobId, int64_t offset, int64_t size) = 0;
|
|
21
|
+
virtual winrt::array_view<uint8_t const> ResolveMessage(std::string &&blobId, int64_t offset, int64_t size) = 0;
|
|
22
22
|
|
|
23
23
|
virtual void RemoveMessage(std::string &&blobId) noexcept = 0;
|
|
24
24
|
|
|
@@ -71,6 +71,7 @@ struct IHttpResource {
|
|
|
71
71
|
/// </param>
|
|
72
72
|
/// <param name="timeout">
|
|
73
73
|
/// Request timeout in miliseconds.
|
|
74
|
+
/// Note: A value of 0 means no timeout. The resource will await the response indefinitely.
|
|
74
75
|
/// </param>
|
|
75
76
|
/// <param name="withCredentials">
|
|
76
77
|
/// Allow including credentials in request.
|
|
@@ -95,7 +96,7 @@ struct IHttpResource {
|
|
|
95
96
|
virtual void SetOnData(std::function<void(int64_t requestId, std::string &&responseData)> &&handler) noexcept = 0;
|
|
96
97
|
virtual void SetOnData(std::function<void(int64_t requestId, folly::dynamic &&responseData)> &&handler) noexcept = 0;
|
|
97
98
|
virtual void SetOnError(
|
|
98
|
-
std::function<void(int64_t requestId, std::string &&errorMessage
|
|
99
|
+
std::function<void(int64_t requestId, std::string &&errorMessage, bool isTimeout)> &&handler) noexcept = 0;
|
|
99
100
|
};
|
|
100
101
|
|
|
101
102
|
} // namespace Microsoft::React::Networking
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <winrt/Windows.Foundation.h>
|
|
7
|
+
#include <winrt/Windows.Web.Http.h>
|
|
8
|
+
#include <winrt/base.h>
|
|
9
|
+
|
|
10
|
+
namespace Microsoft::React::Networking {
|
|
11
|
+
|
|
12
|
+
struct IRedirectEventSource : winrt::implements<IRedirectEventSource, winrt::Windows::Foundation::IInspectable> {
|
|
13
|
+
virtual bool OnRedirecting(
|
|
14
|
+
winrt::Windows::Web::Http::HttpRequestMessage const &request,
|
|
15
|
+
winrt::Windows::Web::Http::HttpResponseMessage const &response) noexcept = 0;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
} // namespace Microsoft::React::Networking
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <winrt/Windows.Foundation.Collections.h>
|
|
7
|
+
#include <winrt/Windows.Foundation.h>
|
|
8
|
+
#include <winrt/Windows.Web.Http.h>
|
|
9
|
+
|
|
10
|
+
namespace Microsoft::React::Networking {
|
|
11
|
+
|
|
12
|
+
struct IWinRTHttpRequestFactory {
|
|
13
|
+
virtual ~IWinRTHttpRequestFactory() noexcept {}
|
|
14
|
+
|
|
15
|
+
virtual winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Web::Http::HttpRequestMessage> CreateRequest(
|
|
16
|
+
winrt::Windows::Web::Http::HttpMethod &&method,
|
|
17
|
+
winrt::Windows::Foundation::Uri &&uri,
|
|
18
|
+
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Windows::Foundation::IInspectable>
|
|
19
|
+
props) noexcept = 0;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
} // namespace Microsoft::React::Networking
|
|
@@ -11,9 +11,6 @@
|
|
|
11
11
|
#include <boost/algorithm/string.hpp>
|
|
12
12
|
#include <boost/lexical_cast/try_lexical_convert.hpp>
|
|
13
13
|
|
|
14
|
-
// Windows API
|
|
15
|
-
#include <winrt/Windows.Web.Http.Headers.h>
|
|
16
|
-
|
|
17
14
|
// Standard Library
|
|
18
15
|
#include <queue>
|
|
19
16
|
#include <regex>
|
|
@@ -27,6 +24,7 @@ using winrt::to_hstring;
|
|
|
27
24
|
using winrt::Windows::Foundation::IInspectable;
|
|
28
25
|
using winrt::Windows::Foundation::IPropertyValue;
|
|
29
26
|
using winrt::Windows::Foundation::Uri;
|
|
27
|
+
using winrt::Windows::Foundation::Collections::IMap;
|
|
30
28
|
using winrt::Windows::Web::Http::HttpMethod;
|
|
31
29
|
using winrt::Windows::Web::Http::HttpRequestMessage;
|
|
32
30
|
using winrt::Windows::Web::Http::HttpResponseMessage;
|
|
@@ -118,7 +116,7 @@ bool OriginPolicyHttpFilter::ConstWcharComparer::operator()(const wchar_t *a, co
|
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
/*static*/ bool OriginPolicyHttpFilter::IsSameOrigin(Uri const &u1, Uri const &u2) noexcept {
|
|
121
|
-
return u1.SchemeName() == u2.SchemeName() && u1.Host() == u2.Host() && u1.Port() == u2.Port();
|
|
119
|
+
return (u1 && u2) && u1.SchemeName() == u2.SchemeName() && u1.Host() == u2.Host() && u1.Port() == u2.Port();
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
/*static*/ bool OriginPolicyHttpFilter::IsSimpleCorsRequest(HttpRequestMessage const &request) noexcept {
|
|
@@ -373,7 +371,7 @@ bool OriginPolicyHttpFilter::ConstWcharComparer::operator()(const wchar_t *a, co
|
|
|
373
371
|
}
|
|
374
372
|
}
|
|
375
373
|
|
|
376
|
-
OriginPolicyHttpFilter::OriginPolicyHttpFilter(IHttpFilter
|
|
374
|
+
OriginPolicyHttpFilter::OriginPolicyHttpFilter(IHttpFilter const &innerFilter) : m_innerFilter{innerFilter} {}
|
|
377
375
|
|
|
378
376
|
OriginPolicyHttpFilter::OriginPolicyHttpFilter()
|
|
379
377
|
: OriginPolicyHttpFilter(winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter{}) {}
|
|
@@ -442,21 +440,24 @@ OriginPolicy OriginPolicyHttpFilter::ValidateRequest(HttpRequestMessage const &r
|
|
|
442
440
|
void OriginPolicyHttpFilter::ValidateAllowOrigin(
|
|
443
441
|
hstring const &allowedOrigin,
|
|
444
442
|
hstring const &allowCredentials,
|
|
445
|
-
IInspectable
|
|
443
|
+
IMap<hstring, IInspectable> props) const {
|
|
446
444
|
// 4.10.1-2 - null allow origin
|
|
447
445
|
if (L"null" == allowedOrigin)
|
|
448
446
|
throw hresult_error{
|
|
449
447
|
E_INVALIDARG,
|
|
450
448
|
L"Response header Access-Control-Allow-Origin has a value of [null] which differs from the supplied origin"};
|
|
451
449
|
|
|
452
|
-
bool withCredentials =
|
|
450
|
+
bool withCredentials = props.Lookup(L"RequestArgs").as<RequestArgs>()->WithCredentials;
|
|
453
451
|
// 4.10.3 - valid wild card allow origin
|
|
454
452
|
if (!withCredentials && L"*" == allowedOrigin)
|
|
455
453
|
return;
|
|
456
454
|
|
|
457
455
|
// We assume the source (request) origin is not "*", "null", or empty string. Valid URI is expected
|
|
458
456
|
// 4.10.4 - Mismatched allow origin
|
|
459
|
-
|
|
457
|
+
auto taintedOriginProp = props.TryLookup(L"TaintedOrigin");
|
|
458
|
+
auto taintedOrigin = taintedOriginProp && winrt::unbox_value<bool>(taintedOriginProp);
|
|
459
|
+
auto origin = taintedOrigin ? nullptr : s_origin;
|
|
460
|
+
if (allowedOrigin.empty() || !IsSameOrigin(origin, Uri{allowedOrigin})) {
|
|
460
461
|
hstring errorMessage;
|
|
461
462
|
if (allowedOrigin.empty())
|
|
462
463
|
errorMessage = L"No valid origin in response";
|
|
@@ -510,14 +511,14 @@ void OriginPolicyHttpFilter::ValidatePreflightResponse(
|
|
|
510
511
|
|
|
511
512
|
auto controlValues = ExtractAccessControlValues(response.Headers());
|
|
512
513
|
|
|
513
|
-
auto
|
|
514
|
+
auto props = request.Properties();
|
|
514
515
|
// Check if the origin is allowed in conjuction with the withCredentials flag
|
|
515
516
|
// CORS preflight should always exclude credentials although the subsequent CORS request may include credentials.
|
|
516
|
-
ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials,
|
|
517
|
+
ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, props);
|
|
517
518
|
|
|
518
519
|
// See https://fetch.spec.whatwg.org/#cors-preflight-fetch, section 4.8.7.5
|
|
519
520
|
// Check if the request method is allowed
|
|
520
|
-
bool withCredentials =
|
|
521
|
+
bool withCredentials = props.Lookup(L"RequestArgs").as<RequestArgs>()->WithCredentials;
|
|
521
522
|
bool requestMethodAllowed = false;
|
|
522
523
|
for (const auto &method : controlValues.AllowedMethods) {
|
|
523
524
|
if (L"*" == method) {
|
|
@@ -578,8 +579,8 @@ void OriginPolicyHttpFilter::ValidateResponse(HttpResponseMessage const &respons
|
|
|
578
579
|
if (originPolicy == OriginPolicy::SimpleCrossOriginResourceSharing ||
|
|
579
580
|
originPolicy == OriginPolicy::CrossOriginResourceSharing) {
|
|
580
581
|
auto controlValues = ExtractAccessControlValues(response.Headers());
|
|
581
|
-
auto
|
|
582
|
-
|
|
582
|
+
auto props = response.RequestMessage().Properties();
|
|
583
|
+
auto withCredentials = props.Lookup(L"RequestArgs").try_as<RequestArgs>()->WithCredentials;
|
|
583
584
|
|
|
584
585
|
if (GetRuntimeOptionBool("Http.StrictOriginCheckSimpleCors") &&
|
|
585
586
|
originPolicy == OriginPolicy::SimpleCrossOriginResourceSharing) {
|
|
@@ -594,8 +595,7 @@ void OriginPolicyHttpFilter::ValidateResponse(HttpResponseMessage const &respons
|
|
|
594
595
|
throw hresult_error{E_INVALIDARG, L"The server does not support CORS or the origin is not allowed"};
|
|
595
596
|
}
|
|
596
597
|
} else {
|
|
597
|
-
|
|
598
|
-
ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, iRequestArgs);
|
|
598
|
+
ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, props);
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
if (originPolicy == OriginPolicy::SimpleCrossOriginResourceSharing) {
|
|
@@ -678,6 +678,38 @@ ResponseOperation OriginPolicyHttpFilter::SendPreflightAsync(HttpRequestMessage
|
|
|
678
678
|
co_return {co_await m_innerFilter.SendRequestAsync(preflightRequest)};
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
#pragma region IRedirectEventSource
|
|
682
|
+
|
|
683
|
+
bool OriginPolicyHttpFilter::OnRedirecting(
|
|
684
|
+
HttpRequestMessage const &request,
|
|
685
|
+
HttpResponseMessage const &response) noexcept {
|
|
686
|
+
// Consider the following scenario.
|
|
687
|
+
// User signs in to http://a.com and visits a page that makes CORS request to http://b.com with origin=http://a.com.
|
|
688
|
+
// Http://b.com reponds with a redirect to http://a.com. The browser follows the redirect to http://a.com with
|
|
689
|
+
// origin=http://a.com. Since the origin matches the URL, the request is authorized at http://a.com, but it actually
|
|
690
|
+
// allows http://b.com to bypass the CORS check at http://a.com since the redirected URL is from http://b.com.
|
|
691
|
+
if (!IsSameOrigin(response.Headers().Location(), request.RequestUri()) &&
|
|
692
|
+
!IsSameOrigin(s_origin, request.RequestUri())) {
|
|
693
|
+
// By masking the origin field in the request header, we make it impossible for the server to set a single value for
|
|
694
|
+
// the access-control-allow-origin header. It means, the only way to support redirect is that server allows access
|
|
695
|
+
// from all sites through wildcard.
|
|
696
|
+
request.Headers().Insert(L"Origin", L"null");
|
|
697
|
+
|
|
698
|
+
auto props = request.Properties();
|
|
699
|
+
// Look for 'RequestArgs' key to ensure we are redirecting the main request.
|
|
700
|
+
if (auto iReqArgs = props.TryLookup(L"RequestArgs")) {
|
|
701
|
+
props.Insert(L"TaintedOrigin", winrt::box_value(true));
|
|
702
|
+
} else {
|
|
703
|
+
// Abort redirection if the request is either preflight or extraneous.
|
|
704
|
+
return false;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
#pragma endregion IRedirectEventSource
|
|
712
|
+
|
|
681
713
|
#pragma region IHttpFilter
|
|
682
714
|
|
|
683
715
|
ResponseOperation OriginPolicyHttpFilter::SendRequestAsync(HttpRequestMessage const &request) {
|
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
#pragma once
|
|
5
5
|
|
|
6
|
+
#include "IRedirectEventSource.h"
|
|
6
7
|
#include "OriginPolicy.h"
|
|
7
8
|
|
|
8
9
|
// Windows API
|
|
10
|
+
#include <winrt/Windows.Foundation.Collections.h>
|
|
9
11
|
#include <winrt/Windows.Foundation.h>
|
|
10
12
|
#include <winrt/Windows.Web.Http.Filters.h>
|
|
13
|
+
#include <winrt/Windows.Web.Http.Headers.h>
|
|
11
14
|
#include <winrt/Windows.Web.Http.h>
|
|
12
15
|
|
|
13
16
|
// Standard Library
|
|
@@ -16,7 +19,8 @@
|
|
|
16
19
|
namespace Microsoft::React::Networking {
|
|
17
20
|
|
|
18
21
|
class OriginPolicyHttpFilter
|
|
19
|
-
: public winrt::
|
|
22
|
+
: public winrt::
|
|
23
|
+
implements<OriginPolicyHttpFilter, winrt::Windows::Web::Http::Filters::IHttpFilter, IRedirectEventSource> {
|
|
20
24
|
public:
|
|
21
25
|
struct ConstWcharComparer {
|
|
22
26
|
bool operator()(const wchar_t *, const wchar_t *) const;
|
|
@@ -75,7 +79,7 @@ class OriginPolicyHttpFilter
|
|
|
75
79
|
winrt::Windows::Web::Http::HttpResponseMessage const &response,
|
|
76
80
|
bool removeAll);
|
|
77
81
|
|
|
78
|
-
OriginPolicyHttpFilter(winrt::Windows::Web::Http::Filters::IHttpFilter
|
|
82
|
+
OriginPolicyHttpFilter(winrt::Windows::Web::Http::Filters::IHttpFilter const &innerFilter);
|
|
79
83
|
|
|
80
84
|
OriginPolicyHttpFilter();
|
|
81
85
|
|
|
@@ -92,13 +96,22 @@ class OriginPolicyHttpFilter
|
|
|
92
96
|
void ValidateAllowOrigin(
|
|
93
97
|
winrt::hstring const &allowedOrigin,
|
|
94
98
|
winrt::hstring const &allowCredentials,
|
|
95
|
-
winrt::Windows::Foundation::IInspectable
|
|
99
|
+
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Windows::Foundation::IInspectable> props)
|
|
100
|
+
const;
|
|
96
101
|
|
|
97
102
|
winrt::Windows::Foundation::IAsyncOperationWithProgress<
|
|
98
103
|
winrt::Windows::Web::Http::HttpResponseMessage,
|
|
99
104
|
winrt::Windows::Web::Http::HttpProgress>
|
|
100
105
|
SendPreflightAsync(winrt::Windows::Web::Http::HttpRequestMessage const &request) const;
|
|
101
106
|
|
|
107
|
+
#pragma region IRedirectEventSource
|
|
108
|
+
|
|
109
|
+
bool OnRedirecting(
|
|
110
|
+
winrt::Windows::Web::Http::HttpRequestMessage const &request,
|
|
111
|
+
winrt::Windows::Web::Http::HttpResponseMessage const &response) noexcept override;
|
|
112
|
+
|
|
113
|
+
#pragma endregion IRedirectEventSource
|
|
114
|
+
|
|
102
115
|
#pragma region IHttpFilter
|
|
103
116
|
|
|
104
117
|
winrt::Windows::Foundation::IAsyncOperationWithProgress<
|