Skip to content

Commit 49fba2b

Browse files
committed
Create generic request builder
1 parent 6b28ce3 commit 49fba2b

File tree

2 files changed

+117
-52
lines changed

2 files changed

+117
-52
lines changed

RNFetchBlobWin/windows/RNFetchBlobWin/RNFetchBlob.cpp

Lines changed: 96 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
#include <winrt/Windows.Web.Http.h>
1111
#include <winrt/Windows.Web.Http.Headers.h>
12+
#include <winrt/windows.web.http.filters.h>
1213

1314
#include <filesystem>
15+
#include <sstream>
1416

1517
using namespace winrt;
1618
using namespace winrt::Windows::ApplicationModel;
@@ -1049,9 +1051,37 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
10491051
std::string body,
10501052
std::function<void(std::string, std::string, std::string)> callback) noexcept
10511053
{
1052-
//winrt::Windows::Web::Http::HttpMethod::Hea
1053-
1054-
// Method
1054+
winrt::Microsoft::ReactNative::JSValueArray emptyArray;
1055+
createBlobForm(options, taskId, method, url, headers, body, emptyArray, callback);
1056+
co_return;
1057+
}
1058+
1059+
winrt::fire_and_forget RNFetchBlob::fetchBlobForm(
1060+
winrt::Microsoft::ReactNative::JSValueObject options,
1061+
std::string taskId,
1062+
std::string method,
1063+
std::wstring url,
1064+
winrt::Microsoft::ReactNative::JSValueObject headers,
1065+
winrt::Microsoft::ReactNative::JSValueArray body,
1066+
std::function<void(std::string, std::string, std::string)> callback) noexcept
1067+
{
1068+
createBlobForm(options, taskId, method, url, headers, "", body, callback);
1069+
co_return;
1070+
}
1071+
1072+
winrt::fire_and_forget RNFetchBlob::createBlobForm(
1073+
const winrt::Microsoft::ReactNative::JSValueObject& options,
1074+
const std::string& taskId,
1075+
const std::string& method,
1076+
const std::wstring& url,
1077+
const winrt::Microsoft::ReactNative::JSValueObject& headers,
1078+
const std::string& bodyString,
1079+
const winrt::Microsoft::ReactNative::JSValueArray& bodyArray,
1080+
std::function<void(std::string, std::string, std::string)> callback) noexcept
1081+
{
1082+
1083+
winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
1084+
10551085
RNFetchBlobConfig config;
10561086
if (options["appendExt"].IsNull() == true)
10571087
{
@@ -1063,6 +1093,7 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
10631093
path.make_preferred();
10641094
config.appendExt = winrt::to_string(path.c_str());
10651095
}
1096+
config.taskId = taskId;
10661097
config.appendExt = options["appendExt"].IsNull() ? "" : options["appendExt"].AsString();
10671098
config.fileCache = options["fileCache"].AsBoolean();
10681099
config.followRedirect = options["followRedirect"].AsBoolean();
@@ -1082,25 +1113,26 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
10821113

10831114
if (config.followRedirect == true)
10841115
{
1085-
// TODO: find winrt config property
1116+
filter.AllowAutoRedirect(true);
10861117
}
1087-
if (config.fileCache == true)
1118+
else
10881119
{
1089-
1120+
filter.AllowAutoRedirect(false);
10901121
}
1122+
10911123
if (config.timeout > 0)
10921124
{
10931125
// TODO: find winrt config property
10941126
}
1095-
if (config.trusty == true)
1127+
1128+
if (!config.trusty)
10961129
{
1097-
// TODO: find winrt config property
1130+
filter.IgnorableServerCertificateErrors().Append(Cryptography::Certificates::ChainValidationResult::Untrusted);
10981131
}
10991132

1100-
1133+
winrt::Windows::Web::Http::HttpClient httpClient{ filter };
11011134

11021135
winrt::Windows::Web::Http::HttpMethod httpMethod{ winrt::Windows::Web::Http::HttpMethod::Post() };
1103-
11041136
std::string methodUpperCase{ method };
11051137
for (auto& c : methodUpperCase)
11061138
{
@@ -1151,32 +1183,18 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
11511183
}
11521184
}
11531185

1154-
std::string temp{ body };
1155-
if (body.length() > 0) {
1156-
winrt::Windows::Web::Http::HttpBufferContent content{ CryptographicBuffer::ConvertStringToBinary(winrt::to_hstring(body), BinaryStringEncoding::Utf8) };
1186+
if (bodyString.length() > 0) {
1187+
winrt::Windows::Web::Http::HttpBufferContent content{ CryptographicBuffer::ConvertStringToBinary(winrt::to_hstring(bodyString), BinaryStringEncoding::Utf8) };
11571188
requestMessage.Content(content);
11581189
}
1159-
//requestMessage.Content(requestContent);
1160-
1161-
//winrt::Windows::Web::Http::HttpResponseMessage response = co_await m_httpClient.SendRequestAsync(requestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead);
1190+
else if (!bodyArray.empty())
1191+
{
1192+
// TODO: Add in multipart aspects
1193+
}
11621194

1163-
co_await m_tasks.Add(taskId, ProcessRequestAsync(requestMessage, config, callback));
1195+
co_await m_tasks.Add(taskId, ProcessRequestAsync(filter, requestMessage, config, callback));
11641196
}
11651197

1166-
void RNFetchBlob::fetchBlobForm(
1167-
winrt::Microsoft::ReactNative::JSValueObject options,
1168-
std::string taskId,
1169-
std::string method,
1170-
std::wstring url,
1171-
winrt::Microsoft::ReactNative::JSValueObject headers,
1172-
winrt::Microsoft::ReactNative::JSValueArray body,
1173-
std::function<void(std::string)> callback) noexcept
1174-
{
1175-
return;
1176-
}
1177-
1178-
1179-
11801198
void RNFetchBlob::enableProgressReport(
11811199
std::string taskId,
11821200
int interval,
@@ -1208,11 +1226,23 @@ catch (const hresult_error& ex)
12081226
callback(winrt::to_string(ex.message()), "");
12091227
}
12101228

1211-
void RNFetchBlob::removeSession(
1212-
winrt::Microsoft::ReactNative::JSValueObject paths,
1229+
winrt::fire_and_forget RNFetchBlob::removeSession(
1230+
winrt::Microsoft::ReactNative::JSValueArray paths,
12131231
std::function<void(std::string)> callback) noexcept
1232+
try
12141233
{
1215-
return;
1234+
for (auto& path : paths)
1235+
{
1236+
std::filesystem::path toDelete{ path.AsString() };
1237+
toDelete.make_preferred();
1238+
StorageFile file{ co_await StorageFile::GetFileFromPathAsync(winrt::to_hstring(toDelete.c_str())) };
1239+
co_await file.DeleteAsync();
1240+
}
1241+
callback("");
1242+
}
1243+
catch (const hresult_error& ex)
1244+
{
1245+
callback(winrt::to_string(ex.message()).c_str());
12161246
}
12171247

12181248
void RNFetchBlob::closeStream(
@@ -1250,35 +1280,56 @@ void RNFetchBlob::splitPath(const std::wstring& fullPath, winrt::hstring& direct
12501280
}
12511281

12521282
winrt::Windows::Foundation::IAsyncAction RNFetchBlob::ProcessRequestAsync(
1283+
const winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter& filter,
12531284
winrt::Windows::Web::Http::HttpRequestMessage& httpRequestMessage,
1254-
const RNFetchBlobConfig& config,
1255-
std::function<void(std::string, std::string, std::string)>& callback)
1285+
RNFetchBlobConfig& config,
1286+
std::function<void(std::string, std::string, std::string)> callback) noexcept
1287+
try
12561288
{
1257-
winrt::Windows::Web::Http::HttpResponseMessage response = co_await m_httpClient.SendRequestAsync(httpRequestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead);
1289+
// TODO: implement timeouts
1290+
winrt::Windows::Web::Http::HttpClient httpClient{filter};
1291+
winrt::Windows::Web::Http::HttpResponseMessage response = co_await httpClient.SendRequestAsync(httpRequestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead);
1292+
12581293

1259-
if (config.path.empty() == false)
1294+
if (config.fileCache)
12601295
{
1296+
if (config.path.empty())
1297+
{
1298+
config.path = winrt::to_string(ApplicationData::Current().TemporaryFolder().Path()) + "\\RNFetchBlobTmp_" + config.taskId;
1299+
if (config.appendExt.length() > 0)
1300+
{
1301+
config.path += "." + config.appendExt;
1302+
}
1303+
}
1304+
12611305
std::filesystem::path path{ config.path };
1262-
StorageFolder storageFolder{ co_await StorageFolder::GetFolderFromPathAsync(path.parent_path().wstring()) };
1263-
StorageFile storageFile{ co_await storageFolder.CreateFileAsync(path.filename().wstring(), CreationCollisionOption::ReplaceExisting) };
1306+
StorageFolder storageFolder{ co_await StorageFolder::GetFolderFromPathAsync(ApplicationData::Current().TemporaryFolder().Path()) };
1307+
StorageFile storageFile{ co_await storageFolder.CreateFileAsync(path.filename().wstring(), CreationCollisionOption::FailIfExists) };
12641308
IRandomAccessStream stream{ co_await storageFile.OpenAsync(FileAccessMode::ReadWrite) };
12651309
IOutputStream outputStream{ stream.GetOutputStreamAt(0) };
1266-
//
1267-
auto contentStream = co_await response.Content().ReadAsInputStreamAsync();
1268-
Buffer buffer{ 8 * 1024 };
1310+
1311+
auto contentStream{ co_await response.Content().ReadAsInputStreamAsync() };
1312+
Buffer buffer{ 10 * 1024 };
12691313

12701314
for (;;)
12711315
{
12721316
buffer.Length(0);
1273-
auto readBuffer = co_await contentStream.ReadAsync(buffer, buffer.Capacity(), InputStreamOptions::None);
1317+
// TODO: fix 0x80072EFF
1318+
auto readBuffer = contentStream.ReadAsync(buffer, buffer.Capacity(), InputStreamOptions::None).get();
12741319
if (readBuffer.Length() == 0)
12751320
{
12761321
break;
12771322
}
1278-
12791323
co_await outputStream.WriteAsync(readBuffer);
12801324
}
1325+
1326+
callback("", "path", config.path);
12811327
}
1328+
co_return;
1329+
}
1330+
catch (const hresult_error& ex)
1331+
{
1332+
callback(winrt::to_string(ex.message().c_str()), "error", "");
12821333
}
12831334

12841335
RNFetchBlobStream::RNFetchBlobStream(Streams::IRandomAccessStream& _streamInstance, EncodingOptions _encoding) noexcept

RNFetchBlobWin/windows/RNFetchBlobWin/RNFetchBlob.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ struct RNFetchBlobConfig
6565
int timeout;
6666
bool trusty;
6767
bool fileCache;
68+
std::string key;
6869
std::string appendExt;
6970
std::string path;
7071
bool followRedirect;
72+
std::string taskId;
7173
};
7274

7375

@@ -250,14 +252,14 @@ struct RNFetchBlob
250252
std::function<void(std::string, std::string, std::string)> callback) noexcept;
251253

252254
REACT_METHOD(fetchBlobForm);
253-
void fetchBlobForm(
255+
winrt::fire_and_forget fetchBlobForm(
254256
winrt::Microsoft::ReactNative::JSValueObject options,
255257
std::string taskId,
256258
std::string method,
257259
std::wstring url,
258260
winrt::Microsoft::ReactNative::JSValueObject headers,
259261
winrt::Microsoft::ReactNative::JSValueArray body,
260-
std::function<void(std::string)> callback) noexcept;
262+
std::function<void(std::string, std::string, std::string)> callback) noexcept;
261263

262264
REACT_METHOD(enableProgressReport);
263265
void enableProgressReport(
@@ -279,8 +281,8 @@ struct RNFetchBlob
279281
std::function<void(std::string, std::string)> callback) noexcept;
280282

281283
REACT_METHOD(removeSession);
282-
void removeSession(
283-
winrt::Microsoft::ReactNative::JSValueObject paths,
284+
winrt::fire_and_forget RNFetchBlob::removeSession(
285+
winrt::Microsoft::ReactNative::JSValueArray paths,
284286
std::function<void(std::string)> callback) noexcept;
285287

286288
REACT_METHOD(closeStream);
@@ -290,18 +292,20 @@ struct RNFetchBlob
290292

291293
// Helper methods
292294
private:
293-
winrt::Windows::Web::Http::HttpClient m_httpClient;
295+
294296

295297
constexpr static int64_t UNIX_EPOCH_IN_WINRT_SECONDS = 11644473600;
296298

297299
std::map<StreamId, RNFetchBlobStream> m_streamMap;
300+
//winrt::Windows::Web::Http::HttpClient m_httpClient;
298301
winrt::Microsoft::ReactNative::ReactContext m_reactContext;
299302
TaskCancellationManager m_tasks;
300303

301304
winrt::Windows::Foundation::IAsyncAction ProcessRequestAsync(
305+
const winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter& filter,
302306
winrt::Windows::Web::Http::HttpRequestMessage& httpRequestMessage,
303-
const RNFetchBlobConfig& config,
304-
std::function<void(std::string, std::string, std::string)>& callback);
307+
RNFetchBlobConfig& config,
308+
std::function<void(std::string, std::string, std::string)> callback) noexcept;
305309

306310
const std::map<std::string, std::function<CryptographyCore::HashAlgorithmProvider()>> availableHashes{
307311
{"md5", []() { return CryptographyCore::HashAlgorithmProvider::OpenAlgorithm(CryptographyCore::HashAlgorithmNames::Md5()); } },
@@ -311,6 +315,16 @@ struct RNFetchBlob
311315
{"sha512", []() { return CryptographyCore::HashAlgorithmProvider::OpenAlgorithm(CryptographyCore::HashAlgorithmNames::Sha512()); } }
312316
};
313317

318+
winrt::fire_and_forget createBlobForm(
319+
const winrt::Microsoft::ReactNative::JSValueObject& options,
320+
const std::string& taskId,
321+
const std::string& method,
322+
const std::wstring& url,
323+
const winrt::Microsoft::ReactNative::JSValueObject& headers,
324+
const std::string& bodyString,
325+
const winrt::Microsoft::ReactNative::JSValueArray& bodyArray,
326+
std::function<void(std::string, std::string, std::string)> callback) noexcept;
327+
314328
void splitPath(const std::string& fullPath,
315329
winrt::hstring& directoryPath,
316330
winrt::hstring& fileName) noexcept;

0 commit comments

Comments
 (0)