Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
81b9dc7
Added HttpResource skeleton
JunielKatarn Sep 3, 2021
d33fb9b
Import WINRT namespaces
JunielKatarn Sep 5, 2021
f2569ec
Merge branch 'main' of github.com:microsoft/react-native-windows into…
JunielKatarn Jan 19, 2022
a24f908
Merge branch 'main' of github.com:microsoft/react-native-windows into…
JunielKatarn Feb 2, 2022
9441a36
Use custom struct instead of folly:dynamic in IHttpResource
JunielKatarn Feb 2, 2022
13f5fa8
Drop factory method from Beast HTTP resource
JunielKatarn Feb 2, 2022
7a9373f
Move WinRT conversion utils into header
JunielKatarn Feb 2, 2022
cc44bf0
Move WinRT conversion utils into header
JunielKatarn Feb 2, 2022
1224e8a
Define class WinRTHttpResource
JunielKatarn Feb 2, 2022
15ad889
Update HttpModule
JunielKatarn Feb 4, 2022
d9d345e
Define IHttpResource::Response
JunielKatarn Feb 4, 2022
0c4624f
Implement callback members
JunielKatarn Feb 4, 2022
305c2c6
Implement AbortRequest
JunielKatarn Feb 5, 2022
4eef0bb
Implement multiple request handling
JunielKatarn Feb 5, 2022
4e99d9d
Drop client argument from PerformSendRequest
JunielKatarn Feb 5, 2022
df51129
Use background thread in PerformSendRequest
JunielKatarn Feb 5, 2022
9005153
Add WinRTConversions.cpp
JunielKatarn Feb 5, 2022
a26a9e5
Merge branch 'main' of github.com:microsoft/react-native-windows into…
JunielKatarn Feb 5, 2022
5676eb0
Init resource in module
JunielKatarn Feb 6, 2022
26a72b4
Implement test RequestGetSucceeds
JunielKatarn Feb 6, 2022
b913c2d
Complete RequestGetSucceeds
JunielKatarn Feb 6, 2022
276380e
Complete RequestGetFails
JunielKatarn Feb 6, 2022
523b490
Add HttpModule to default modules
JunielKatarn Feb 6, 2022
40c56a4
Move resume_in_queue back to WebSocket resource
JunielKatarn Feb 6, 2022
a7810f1
Simplify WinRTConversions includes
JunielKatarn Feb 6, 2022
ef7c9c1
Rename runtime option to Http.UseResourcedModule
JunielKatarn Feb 6, 2022
4af0d7a
clang format
JunielKatarn Feb 6, 2022
b225b8e
Change files
JunielKatarn Feb 6, 2022
a7f9aee
Update x86 DLL boundary
JunielKatarn Feb 7, 2022
61a2f06
Using SetRtOpt in InitModule
JunielKatarn Feb 7, 2022
8d24165
Add test RequestGetHeadersSucceeds
JunielKatarn Feb 7, 2022
de84a79
Allow aborting server
JunielKatarn Feb 9, 2022
e6b9c10
Use case-insensitive comparison for headers
JunielKatarn Feb 9, 2022
1d1b9e9
Collect both response and content headers
JunielKatarn Feb 9, 2022
8b2b2eb
Address feedback
JunielKatarn Feb 9, 2022
7f5017e
Merge branch 'main' of github.com:microsoft/react-native-windows into…
JunielKatarn Feb 9, 2022
773867e
Remove member function HttpModule::SendEvent
JunielKatarn Feb 9, 2022
37afd8a
Merge branch 'main' of github.com:microsoft/react-native-windows into…
JunielKatarn Feb 11, 2022
ec85a95
Remove SetOnRequest
JunielKatarn Feb 11, 2022
d6cf31b
Delete Beast HTTP resource
JunielKatarn Feb 11, 2022
dbd3685
Catch specific exceptions where applicable
JunielKatarn Feb 11, 2022
6645930
Rename Add/Remove Request to Track/Untrack Response
JunielKatarn Feb 11, 2022
585c414
Use r-value references where applicable
JunielKatarn Feb 11, 2022
614e568
Set runtime option Http.UseMonolithicModule
JunielKatarn Feb 12, 2022
ebad3a9
Define GetHttpModuleName and GetWebSocketModuleName
JunielKatarn Feb 12, 2022
bb8833f
Remove WS, HTTP and Timing from Desktop test runner
JunielKatarn Feb 12, 2022
6ffec13
Update XHRTest
JunielKatarn Feb 12, 2022
3e2a266
Implement cxxCallback
JunielKatarn Feb 12, 2022
c4750dd
Pass request ID to callbacks
JunielKatarn Feb 12, 2022
41ed58a
Set default TestStatus for TestResult
JunielKatarn Feb 12, 2022
366bfcc
Update XHR test
JunielKatarn Feb 12, 2022
cebdcce
Format XHR test
JunielKatarn Feb 12, 2022
f2b796a
Merge branch 'main' of github.com:microsoft/react-native-windows into…
JunielKatarn Feb 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Implement IHttpResource",
"packageName": "react-native-windows",
"email": "julio.rocha@microsoft.com",
"dependentChangeType": "patch"
}
2 changes: 1 addition & 1 deletion vnext/Desktop.DLL/react-native-win32.x64.def
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ EXPORTS
?GetRuntimeOptionBool@React@Microsoft@@YA?B_NAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
?GetRuntimeOptionInt@React@Microsoft@@YA?BHAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
?makeChakraRuntime@JSI@Microsoft@@YA?AV?$unique_ptr@VRuntime@jsi@facebook@@U?$default_delete@VRuntime@jsi@facebook@@@std@@@std@@$$QEAUChakraRuntimeArgs@12@@Z
?Make@IHttpResource@React@Microsoft@@SA?AV?$unique_ptr@UIHttpResource@React@Microsoft@@U?$default_delete@UIHttpResource@React@Microsoft@@@std@@@std@@XZ
?Make@IHttpResource@React@Microsoft@@SA?AV?$shared_ptr@UIHttpResource@React@Microsoft@@@std@@XZ
?CreateTimingModule@react@facebook@@YA?AV?$unique_ptr@VCxxModule@module@xplat@facebook@@U?$default_delete@VCxxModule@module@xplat@facebook@@@std@@@std@@AEBV?$shared_ptr@VMessageQueueThread@react@facebook@@@4@@Z
??0WebSocketModule@React@Microsoft@@QEAA@XZ
??0NetworkingModule@React@Microsoft@@QEAA@XZ
Expand Down
2 changes: 1 addition & 1 deletion vnext/Desktop.DLL/react-native-win32.x86.def
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ EXPORTS
?makeChakraRuntime@JSI@Microsoft@@YG?AV?$unique_ptr@VRuntime@jsi@facebook@@U?$default_delete@VRuntime@jsi@facebook@@@std@@@std@@$$QAUChakraRuntimeArgs@12@@Z
?CreateTimingModule@react@facebook@@YG?AV?$unique_ptr@VCxxModule@module@xplat@facebook@@U?$default_delete@VCxxModule@module@xplat@facebook@@@std@@@std@@ABV?$shared_ptr@VMessageQueueThread@react@facebook@@@4@@Z
??0WebSocketModule@React@Microsoft@@QAE@XZ
?Make@IHttpResource@React@Microsoft@@SG?AV?$unique_ptr@UIHttpResource@React@Microsoft@@U?$default_delete@UIHttpResource@React@Microsoft@@@std@@@std@@XZ
?Make@IHttpResource@React@Microsoft@@SG?AV?$shared_ptr@UIHttpResource@React@Microsoft@@@std@@XZ
??0NetworkingModule@React@Microsoft@@QAE@XZ
?MakeJSQueueThread@ReactNative@Microsoft@@YG?AV?$shared_ptr@VMessageQueueThread@react@facebook@@@std@@XZ
?Hash128@SpookyHashV2@hash@folly@@SGXPBXIPA_K1@Z
Expand Down
8 changes: 0 additions & 8 deletions vnext/Desktop.IntegrationTests/DesktopTestRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ shared_ptr<ITestInstance> TestRunner::GetInstance(
},
nativeQueue},

{"WebSocketModule", []() -> unique_ptr<CxxModule> { return std::make_unique<WebSocketModule>(); }, nativeQueue},

{"Networking",
[]() -> unique_ptr<CxxModule> { return std::make_unique<Microsoft::React::NetworkingModule>(); },
nativeQueue},

{"Timing", [nativeQueue]() -> unique_ptr<CxxModule> { return CreateTimingModule(nativeQueue); }, nativeQueue},

// Apparently mandatory for /IntegrationTests
{TestAppStateModule::name,
[]() -> unique_ptr<CxxModule> { return std::make_unique<TestAppStateModule>(); },
Expand Down
158 changes: 137 additions & 21 deletions vnext/Desktop.IntegrationTests/HttpResourceIntegrationTests.cpp
Original file line number Diff line number Diff line change
@@ -1,47 +1,163 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

// C4996: 'gethostbyaddr': Use getnameinfo() or GetNameInfoW() instead
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <CppUnitTest.h>
#include <IHttpResource.h>
#include <Test/HttpServer.h>
#include <boost/beast/http.hpp>
#include <unicode.h>

// Standard Library
#include <future>

using namespace Microsoft::React;
using namespace folly;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace http = boost::beast::http;

using std::promise;
using std::string;
using std::vector;

TEST_CLASS (HttpResourceIntegrationTest) {
TEST_METHOD(MakeIsNotNull) {
auto rc = IHttpResource::Make();
Assert::IsFalse(nullptr == rc);
TEST_METHOD(RequestGetSucceeds) {
promise<void> promise;
string error;
int statusCode = 0;

// HTTP call scope
{
auto server = std::make_shared<Test::HttpServer>("127.0.0.1", static_cast<uint16_t>(5556));
server->SetOnGet([](const http::request<http::string_body> &request) -> http::response<http::dynamic_body> {
http::response<http::dynamic_body> response;
response.result(http::status::ok);

return response;
});
server->Start();

auto resource = IHttpResource::Make();
resource->SetOnResponse([&promise, &statusCode](int64_t, IHttpResource::Response response) {
statusCode = static_cast<int>(response.StatusCode);
promise.set_value();
});
resource->SetOnError([&promise, &error, &server](int64_t, string &&message) {
error = std::move(message);
promise.set_value();

server->Abort();
});
resource->SendRequest(
"GET",
"http://localhost:5556",
{} /*header*/,
{} /*bodyData*/,
"text",
false,
1000 /*timeout*/,
false /*withCredentials*/,
[](int64_t) {});

server->Stop();
}
// Synchronize response.
promise.get_future().wait();

Assert::AreEqual({}, error);
Assert::AreEqual(200, statusCode);
}

// This test always fails because the requested resource does not exist.
// TEST_METHOD(RequestGetSucceeds) {
void Disable_RequestGetSucceeds() {
auto rc = IHttpResource::Make();
bool sent = false;
bool received = false;
TEST_METHOD(RequestGetHeadersSucceeds) {
promise<void> promise;
string error;
rc->SetOnRequest([&sent]() { sent = true; });
rc->SetOnResponse([&received](const string &message) { received = true; });
rc->SetOnError([&error](const string &message) { error = message; });
IHttpResource::Response response;

rc->SendRequest("GET", "http://localhost:8081/debugger-ui", {}, dynamic(), "text", false, 1000, [](int64_t) {});
// HTTP call scope
{
auto server = std::make_shared<Test::HttpServer>("127.0.0.1", static_cast<uint16_t>(5555));
server->SetOnGet([](const http::request<http::string_body> &request) -> http::response<http::dynamic_body> {
http::response<http::dynamic_body> response;
response.result(http::status::ok);

Assert::IsTrue(sent);
Assert::IsTrue(received);
Assert::AreEqual(string(), error);
// Response header
response.set(http::field::server, "Microsoft::React::Test::HttpServer");
// Response content header
response.set(http::field::content_length, "0");
// Response arbitrary header
response.set("ResponseHeaderName1", "ResponseHeaderValue1");

return response;
});
server->Start();

auto resource = IHttpResource::Make();
resource->SetOnResponse([&promise, &response](int64_t, IHttpResource::Response callbackResponse) {
response = callbackResponse;
promise.set_value();
});
resource->SetOnError([&promise, &error, &server](int64_t, string &&message) {
error = std::move(message);
promise.set_value();

server->Abort();
});

//clang-format off
resource->SendRequest(
"GET",
"http://localhost:5555",
{
{"Content-Type", "application/json"},
{"Content-Encoding", "ASCII"},
{"name3", "value3"},
{"name4", "value4"},
},
{} /*bodyData*/,
"text",
false,
1000 /*timeout*/,
false /*withCredentials*/,
[](int64_t) {});
//clang-format on

server->Stop();
}

promise.get_future().wait();

Assert::AreEqual({}, error, L"Error encountered");
for (auto header : response.Headers) {
if (header.first == "Server") {
Assert::AreEqual({"Microsoft::React::Test::HttpServer"}, header.second, L"Wrong header");
} else if (header.first == "Content-Length") {
Assert::AreEqual({"0"}, header.second, L"Wrong header");
} else if (header.first == "ResponseHeaderName1") {
Assert::AreEqual({"ResponseHeaderValue1"}, header.second, L"Wrong header");
} else {
string message = "Unexpected header: [" + header.first + "]=[" + header.second + "]";
Assert::Fail(Microsoft::Common::Unicode::Utf8ToUtf16(message).c_str());
}
}
}

TEST_METHOD(RequestGetFails) {
auto rc = IHttpResource::Make();
string error;
rc->SetOnError([&error](const string &message) { error = message; });
promise<void> promise;

auto resource = IHttpResource::Make();
resource->SetOnError([&error, &promise](int64_t, string &&message) {
error = message;
promise.set_value();
});

resource->SendRequest("GET", "http://nonexistinghost", {}, {}, "text", false, 1000, false, [](int64_t) {});

rc->SendRequest("GET", "http://nonexistinghost", {}, dynamic(), "text", false, 1000, [](int64_t) {});
promise.get_future().wait();

Assert::AreEqual(string("No such host is known"), error);
Logger::WriteMessage(error.c_str());
Assert::AreNotEqual(string{}, error);
}
};
9 changes: 6 additions & 3 deletions vnext/Desktop.IntegrationTests/RNTesterIntegrationTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ std::wstring ToString<TestStatus>(const TestStatus &status) {
} // namespace Microsoft::VisualStudio::CppUnitTestFramework

TEST_MODULE_INITIALIZE(InitModule) {
Microsoft::React::SetRuntimeOptionBool("WebSocket.AcceptSelfSigned", true);
Microsoft::React::SetRuntimeOptionBool("UseBeastWebSocket", false);
using Microsoft::React::SetRuntimeOptionBool;

SetRuntimeOptionBool("WebSocket.AcceptSelfSigned", true);
SetRuntimeOptionBool("UseBeastWebSocket", false);
SetRuntimeOptionBool("Http.UseMonolithicModule", false);

// WebSocketJSExecutor can't register native log hooks.
Microsoft::React::SetRuntimeOptionBool("RNTester.UseWebDebugger", false);
SetRuntimeOptionBool("RNTester.UseWebDebugger", false);
}

TEST_CLASS (RNTesterIntegrationTests) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,4 @@
<Target Name="Test">
<Exec Command="$(OutDir)$(TargetFileName)" IgnoreStandardErrorWarningFormat="true" />
</Target>
</Project>
</Project>
Loading