First commit, add source files.

Signed-off-by: maosiping <maosiping@huawei.com>
This commit is contained in:
maosiping 2021-10-30 11:57:54 +08:00
parent 352f63a7e8
commit 1e7fe5148c
26 changed files with 2005 additions and 75 deletions

View File

@ -1,36 +0,0 @@
# communication_netstack
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@ -1,39 +0,0 @@
# communication_netstack
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@ -0,0 +1,160 @@
Language: Cpp
# BasedOnStyle: LLVM
# 访问说明符(public、private等)的偏移
AccessModifierOffset: -4
# 开括号(开圆括号、开尖括号、开方括号)后的对齐
AlignAfterOpenBracket: Align
# 连续赋值时,等号对齐
AlignConsecutiveAssignments: false
# 连续赋值时,变量名对齐
AlignConsecutiveDeclarations: false
# 左对齐逃脱换行(使用反斜杠换行)的反斜杠
AlignEscapedNewlinesLeft: true
# 水平对齐二元和三元表达式的操作数
AlignOperands: true
# 对齐连续的尾随的注释
AlignTrailingComments: true
# 允许函数声明的所有参数在放在下一行
AllowAllParametersOfDeclarationOnNextLine: false
# 允许短的块放在同一行
AllowShortBlocksOnASingleLine: false
# 允许短的case标签放在同一行
AllowShortCaseLabelsOnASingleLine: false
# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All
AllowShortFunctionsOnASingleLine: Empty
# 允许短的if语句保持在同一行
AllowShortIfStatementsOnASingleLine: false
# 允许短的循环保持在同一行
AllowShortLoopsOnASingleLine: false
# 总是在定义返回类型后换行(deprecated)
AlwaysBreakAfterDefinitionReturnType: None
# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义)
AlwaysBreakAfterReturnType: None
# 总是在多行string字面量前换行
AlwaysBreakBeforeMultilineStrings: true
# 总是在template声明后换行
AlwaysBreakTemplateDeclarations: false
# false表示函数实参要么都在同一行要么都各自一行
BinPackArguments: true
# false表示所有形参要么都在同一行要么都各自一行
BinPackParameters: false
# 大括号换行只有当BreakBeforeBraces设置为Custom时才有效
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行)
BreakBeforeBinaryOperators: None
# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义与Attach类似),
# Mozilla(除枚举、函数、记录定义与Attach类似), Stroustrup(除函数定义、catch、else与Attach类似),
# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom
# 注:这里认为语句块也属于函数
BreakBeforeBraces: Custom
# 在三元运算符前换行
BreakBeforeTernaryOperators: true
# 在构造函数的初始化列表的逗号前换行
BreakConstructorInitializersBeforeComma: false
# 每行字符的限制0表示没有限制
ColumnLimit: 120
# 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变
CommentPragmas: "^ IWYU pragma:"
# 构造函数的初始化列表要么都在同一行,要么都各自一行
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# 构造函数的初始化列表的缩进宽度
ConstructorInitializerIndentWidth: 4
# 延续的行的缩进宽度
ContinuationIndentWidth: 4
# 去除C++11的列表初始化的大括号{后和}前的空格
Cpp11BracedListStyle: true
# 继承最常用的指针和引用的对齐方式
DerivePointerAlignment: false
# 关闭格式化
DisableFormat: false
# 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental)
ExperimentalAutoDetectBinPacking: false
# 需要被解读为foreach循环而不是函数调用的宏
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
# 对#include进行排序匹配了某正则表达式的#include拥有对应的优先级匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前)
# 可以定义负数优先级从而保证某些#include永远在最前面
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: ".*"
Priority: 1
# 缩进case标签
IndentCaseLabels: true
# 缩进宽度
IndentWidth: 4
# 函数返回类型换行时,缩进函数声明或函数定义的函数名
IndentWrappedFunctionNames: true
# 保留在块开始处的空行
KeepEmptyLinesAtTheStartOfBlocks: true
# 开始一个块的宏的正则表达式
MacroBlockBegin: ""
# 结束一个块的宏的正则表达式
MacroBlockEnd: ""
# 连续空行的最大数量
MaxEmptyLinesToKeep: 1
# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All
NamespaceIndentation: None
# 使用ObjC块时缩进宽度
ObjCBlockIndentWidth: 4
# 在ObjC的@property后添加一个空格
ObjCSpaceAfterProperty: false
# 在ObjC的protocol列表前添加一个空格
ObjCSpaceBeforeProtocolList: true
# 在call(后对函数调用换行的penalty
PenaltyBreakBeforeFirstCallParameter: 19
# 在一个注释中引入换行的penalty
PenaltyBreakComment: 300
# 第一次在<<前换行的penalty
PenaltyBreakFirstLessLess: 120
# 在一个字符串字面量中引入换行的penalty
PenaltyBreakString: 1000
# 对于每个在行字符数限制之外的字符的penalty
PenaltyExcessCharacter: 1000000
# 将函数的返回类型放到它自己的行的penalty
PenaltyReturnTypeOnItsOwnLine: 60
# 指针和引用的对齐: Left, Right, Middle
PointerAlignment: Right
# 允许重新排版注释
ReflowComments: true
# 允许排序#include
SortIncludes: true
# 在C风格类型转换后添加空格
SpaceAfterCStyleCast: false
# 在赋值运算符之前添加空格
SpaceBeforeAssignmentOperators: true
# 开圆括号之前添加一个空格: Never, ControlStatements, Always
SpaceBeforeParens: ControlStatements
# 在空的圆括号中添加空格
SpaceInEmptyParentheses: false
# 在尾随的评论前添加的空格数(只适用于//)
SpacesBeforeTrailingComments: 1
# 在尖括号的<后和>前添加空格
SpacesInAngles: false
# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格
SpacesInContainerLiterals: true
# 在C风格类型转换的括号中添加空格
SpacesInCStyleCastParentheses: false
# 在圆括号的(后和)前添加空格
SpacesInParentheses: false
# 在方括号的[后和]前添加空格lamda表达式和未指明大小的数组的声明不受影响
SpacesInSquareBrackets: false
# 标准: Cpp03, Cpp11, Auto
Standard: Cpp11
# tab宽度
TabWidth: 4
# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always
UseTab: Never

View File

@ -0,0 +1,2 @@
.idea
cmake-build-debug

View File

@ -0,0 +1,63 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
import("//build/lite/ndk/ndk.gni")
http_lite_sources = [
"fetch_module.cpp",
"http_request/http_request.cpp",
"http_request/http_constant.cpp",
"http_request/http_async_callback.cpp",
"http_request/response_data.cpp",
"http_request/request_data.cpp",
"http_request/http_request_utils.cpp",
]
http_lite_include_dirs = [
"//foundation/communication/netstack/http_lite/frameworks/js/builtin",
"//third_party/curl/include",
"//third_party/bounds_checking_function/include",
"//foundation/ace/ace_engine_lite/interfaces/innerkits/builtin/async",
"//foundation/ace/ace_engine_lite/interfaces/innerkits/builtin/jsi",
"//foundation/ace/ace_engine_lite/interfaces/innerkits/builtin/base",
"//foundation/ace/ace_engine_lite/frameworks/common/utils",
"//foundation/ace/ace_engine_lite/frameworks/common/log",
]
config("http_lite_config") {
include_dirs = http_lite_include_dirs
defines = ["NO_SSL_CERTIFICATION=1"]
}
lite_library("http_lite_shared") {
target_type = "shared_library"
sources = http_lite_sources
public_configs = [":http_lite_config"]
output_name = "http_lite"
deps = [
"//third_party/curl:libcurl_shared",
"//third_party/bounds_checking_function:libsec_shared",
]
}
ndk_lib("http_lite_ndk") {
lib_extension = ".so"
deps = [":http_lite_shared"]
head_files = [
"//foundation/communication/netstack/http_lite/frameworks/js/builtin",
]
}

View File

@ -0,0 +1,64 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.19)
project(ohos_acelite)
set(CMAKE_CXX_STANDARD 14)
include_directories(test_headers)
include_directories(../../../../../../ace/ace_engine_lite/interfaces/innerkits/builtin/jsi)
include_directories(../../../../../../ace/ace_engine_lite/interfaces/innerkits/builtin/async)
include_directories(../../../../../../ace/ace_engine_lite/frameworks/common/utils)
include_directories(../../../../../../ace/ace_engine_lite/frameworks/src/core/context)
include_directories(../../../../../../ace/ace_engine_lite/frameworks/targets/simulator)
include_directories(../../../../../../../third_party/jerryscript/jerry-core/include)
include_directories(../../../../../../../third_party/jerryscript/jerry-ext/include/jerryscript-ext)
include_directories(../../../../../../../third_party/jerryscript/jerry-port/default/include)
include_directories(../../../../../../../third_party/curl/include)
include_directories(../../../../../../../third_party/bounds_checking_function/include)
link_directories(../../../../../../../third_party/jerryscript/cmake-build-debug/lib)
link_directories(../../../../../../../third_party/curl/cmake-build-debug/lib)
link_directories(../../../../../../../third_party/bounds_checking_function/cmake-build-debug)
add_library(test_fetch_module
fetch_module.cpp
http_request/http_async_callback.cpp
http_request/http_request.cpp
http_request/http_constant.cpp
http_request/response_data.cpp
http_request/request_data.cpp
http_request/http_request_utils.cpp
../../../../../../ace/ace_engine_lite/frameworks/native_engine/jsi/jsi.cpp
../../../../../../ace/ace_engine_lite/frameworks/native_engine/async/js_async_work.cpp
../../../../../../ace/ace_engine_lite/frameworks/native_engine/async/message_queue_utils.cpp
../../../../../../ace/ace_engine_lite/frameworks/common/memory/memory_heap.cpp
)
target_link_libraries(test_fetch_module jerry-core)
target_link_libraries(test_fetch_module jerry-ext)
target_link_libraries(test_fetch_module jerry-libm)
target_link_libraries(test_fetch_module jerry-port-default)
target_link_libraries(test_fetch_module curl-d)
target_link_libraries(test_fetch_module securec)
add_compile_definitions(NO_SSL_CERTIFICATION=1)
add_executable(test_fetch_module_exec test_fetch_module.cpp)
target_link_libraries(test_fetch_module_exec test_fetch_module)

View File

@ -0,0 +1,284 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fetch_module.h"
#include "http_request/http_async_callback.h"
#include "http_request/http_request.h"
#include "http_request/http_request_utils.h"
#include "js_async_work.h"
#include "securec.h"
namespace OHOS {
namespace ACELite {
void InitFetchModule(JSIValue exports)
{
JSI::SetModuleAPI(exports, FetchModule::HTTP_API_KEY_FETCH, FetchModule::Fetch);
JSI::SetModuleAPI(exports, FetchModule::HTTP_API_KEY_STRING_TO_ARRAY_BUFFER, FetchModule::StringToArrayBuffer);
}
const char *const FetchModule::HTTP_API_KEY_FETCH = "fetch";
const char *const FetchModule::HTTP_API_KEY_STRING_TO_ARRAY_BUFFER = "stringToArrayBuffer";
JSIValue FetchModule::Fetch(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
if (argsNum < 1) {
return JSI::CreateUndefined();
}
auto requestData = new RequestData();
if (JsObjectToRequestData(args[0], requestData)) {
auto asyncCallback =
new HttpAsyncCallback(const_cast<const RequestData *&>(requestData), MakeCallback(args[0]), thisVal);
JsAsyncWork::DispatchAsyncWork(HttpAsyncCallback::AsyncExecHttpRequest, static_cast<void *>(asyncCallback));
} else {
delete requestData;
}
return JSI::CreateUndefined();
}
JSIValue FetchModule::MakeCallback(JSIValue options)
{
JSIValue obj = JSI::CreateObject();
if (obj == nullptr) {
return nullptr;
}
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> successCallback(JSI::GetNamedProperty(options, CB_SUCCESS),
JSI::ReleaseValue);
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> failCallback(JSI::GetNamedProperty(options, CB_FAIL),
JSI::ReleaseValue);
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> completeCallback(JSI::GetNamedProperty(options, CB_COMPLETE),
JSI::ReleaseValue);
if ((successCallback == nullptr || JSI::ValueIsUndefined(successCallback.get()) ||
!JSI::ValueIsFunction(successCallback.get())) &&
(failCallback == nullptr || JSI::ValueIsUndefined(failCallback.get()) ||
!JSI::ValueIsFunction(failCallback.get())) &&
(completeCallback == nullptr || JSI::ValueIsUndefined(completeCallback.get()) ||
!JSI::ValueIsFunction(completeCallback.get()))) {
return nullptr;
}
JSI::SetNamedProperty(obj, CB_SUCCESS, successCallback.get());
JSI::SetNamedProperty(obj, CB_FAIL, failCallback.get());
JSI::SetNamedProperty(obj, CB_COMPLETE, completeCallback.get());
return obj;
}
bool FetchModule::JsObjectToRequestData(JSIValue options, RequestData *req)
{
if (options == nullptr || JSI::ValueIsUndefined(options) || !JSI::ValueIsObject(options)) {
return false;
}
std::unique_ptr<char, decltype(&JSI::ReleaseString)> urlString(
JSI::GetStringProperty(options, HttpConstant::KEY_HTTP_REQUEST_URL), JSI::ReleaseString);
if (urlString == nullptr) {
return false;
}
HTTP_REQUEST_INFO("request url is %s", urlString.get());
req->SetUrl(urlString.get());
req->SetMethod(GetMethodFromOptions(options));
HTTP_REQUEST_INFO("request method is %s", req->GetMethod().c_str());
req->SetResponseType(GetResponseTypeFromOptions(options));
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> jsHeaders(
JSI::GetNamedProperty(options, HttpConstant::KEY_HTTP_REQUEST_HEADER), JSI::ReleaseValue);
if (jsHeaders != nullptr && !JSI::ValueIsUndefined(jsHeaders.get()) && JSI::ValueIsObject(jsHeaders.get())) {
GetNameValue(jsHeaders.get(), const_cast<std::map<std::string, std::string> &>(req->GetHeader()));
}
ParseExtraData(options, req);
return true;
}
void FetchModule::GetNameValue(JSIValue nv, std::map<std::string, std::string> &map)
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> keys(JSI::GetObjectKeys(nv), JSI::ReleaseValue);
if (keys == nullptr || JSI::ValueIsUndefined(keys.get()) || !JSI::ValueIsArray(keys.get())) {
HTTP_REQUEST_ERROR("get name value failed");
return;
}
uint32_t length = JSI::GetArrayLength(keys.get());
for (uint32_t index = 0; index < length; ++index) {
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> key(JSI::GetPropertyByIndex(keys.get(), index),
JSI::ReleaseValue);
if (key == nullptr || JSI::ValueIsUndefined(key.get()) || !JSI::ValueIsString(key.get())) {
continue;
}
std::unique_ptr<char, decltype(&JSI::ReleaseString)> keyStr(JSI::ValueToString(key.get()), JSI::ReleaseString);
if (keyStr == nullptr) {
HTTP_REQUEST_ERROR("key to string failed");
continue;
}
std::unique_ptr<char, decltype(&JSI::ReleaseString)> valStr(JSI::GetStringProperty(nv, keyStr.get()),
JSI::ReleaseString);
if (valStr == nullptr) {
HTTP_REQUEST_ERROR("get val failed");
continue;
}
map[keyStr.get()] = valStr.get();
}
}
void FetchModule::GetRequestBody(JSIValue options, RequestData *requestData)
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> body(
JSI::GetNamedProperty(options, HttpConstant::KEY_HTTP_REQUEST_DATA), JSI::ReleaseValue);
if (body == nullptr || JSI::ValueIsUndefined(body.get())) {
HTTP_REQUEST_ERROR("get body failed");
return;
}
if (JSI::ValueIsString(body.get())) {
size_t size = 0;
std::unique_ptr<char, decltype(&JSI::ReleaseString)> bodyStr(JSI::ValueToString(body.get(), size),
JSI::ReleaseString);
if (bodyStr == nullptr) {
HTTP_REQUEST_ERROR("get body str failed");
return;
}
std::string str(bodyStr.get(), size);
requestData->SetBody(str);
HTTP_REQUEST_INFO("body is string, size %zu", str.size());
return;
}
if (JSI::ValueIsObject(body.get())) {
std::unique_ptr<char, decltype(&JSI::ReleaseString)> jsonString(JSI::JsonStringify(body.get()),
JSI::ReleaseString);
if (jsonString == nullptr) {
return;
}
requestData->SetBody(jsonString.get());
HTTP_REQUEST_INFO("body is object, stringify size %zu", requestData->GetBody().size());
requestData->SetHeader(HttpConstant::HTTP_HEADER_KEY_CONTENT_TYPE, HttpConstant::HTTP_CONTENT_TYPE_JSON);
return;
}
HTTP_REQUEST_ERROR("body should be string or object");
}
void FetchModule::ParseExtraData(JSIValue options, RequestData *requestData)
{
if (MethodForGet(requestData->GetMethod())) {
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> extraData(
JSI::GetNamedProperty(options, HttpConstant::KEY_HTTP_REQUEST_DATA), JSI::ReleaseValue);
if (extraData == nullptr || JSI::ValueIsUndefined(extraData.get())) {
return;
}
std::string url = requestData->GetUrl();
std::string param;
std::size_t index = url.find(HttpConstant::HTTP_URL_PARAM_SEPARATOR);
if (index != std::string::npos) {
param = url.substr(index + 1);
url = url.substr(0, index);
}
if (JSI::ValueIsString(extraData.get())) {
std::unique_ptr<char, decltype(&JSI::ReleaseString)> dataStr(JSI::ValueToString(extraData.get()),
JSI::ReleaseString);
if (dataStr == nullptr) {
return;
}
std::string extraParam(dataStr.get());
requestData->SetUrl(MakeUrl(url, param, extraParam));
return;
}
if (!JSI::ValueIsObject(extraData.get())) {
return;
}
std::map<std::string, std::string> urlPara;
GetNameValue(extraData.get(), urlPara);
std::string extraParam;
for (const auto &p : urlPara) {
extraParam += p.first + "=" + p.second + HttpConstant::HTTP_URL_PARAM_DELIMITER;
}
if (!extraParam.empty()) {
extraParam = extraParam.substr(0, extraParam.size() - 1); // delete the last &
}
requestData->SetUrl(MakeUrl(url, param, extraParam));
return;
}
if (MethodForPost(requestData->GetMethod())) {
GetRequestBody(options, requestData);
}
}
std::string FetchModule::GetMethodFromOptions(JSIValue options)
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> value(
JSI::GetNamedProperty(options, HttpConstant::KEY_HTTP_REQUEST_METHOD), JSI::ReleaseValue);
if (value == nullptr || JSI::ValueIsUndefined(value.get()) || !JSI::ValueIsString(value.get())) {
return HttpConstant::HTTP_METHOD_GET;
}
std::unique_ptr<char, decltype(&JSI::ReleaseString)> methodStr(JSI::ValueToString(value.get()), JSI::ReleaseString);
return methodStr == nullptr ? HttpConstant::HTTP_METHOD_GET : methodStr.get();
}
JSIValue FetchModule::StringToArrayBuffer(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
(void)thisVal;
if (argsNum < 1 || args[0] == nullptr || JSI::ValueIsUndefined(args[0]) || !JSI::ValueIsString(args[0])) {
return JSI::CreateUndefined();
}
size_t size = 0;
std::unique_ptr<char, decltype(&JSI::ReleaseString)> str(JSI::ValueToString(args[0], size), JSI::ReleaseString);
if (str == nullptr || size == 0) {
return JSI::CreateUndefined();
}
uint8_t *buffer = nullptr;
JSIValue arrayBuffer = JSI::CreateArrayBuffer(size, buffer);
if (buffer == nullptr || arrayBuffer == nullptr) {
return JSI::CreateUndefined();
}
(void)memcpy_s(buffer, size, str.get(), size);
return arrayBuffer;
}
std::string FetchModule::GetResponseTypeFromOptions(JSIValue options)
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> value(
JSI::GetNamedProperty(options, HttpConstant::KEY_HTTP_REQUEST_RESPONSE_TYPE), JSI::ReleaseValue);
if (value == nullptr || JSI::ValueIsUndefined(value.get()) || !JSI::ValueIsString(value.get())) {
return "";
}
std::unique_ptr<char, decltype(&JSI::ReleaseString)> responseType(JSI::ValueToString(value.get()),
JSI::ReleaseString);
return responseType == nullptr ? "" : responseType.get();
}
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_FETCH_MODULE_H
#define OHOS_ACELITE_FETCH_MODULE_H
#include "http_request/http_request.h"
#include "jsi.h"
#include "non_copyable.h"
#include <map>
namespace OHOS {
namespace ACELite {
class FetchModule final : public MemoryHeap {
public:
ACE_DISALLOW_COPY_AND_MOVE(FetchModule);
FetchModule() = default;
~FetchModule() = default;
static JSIValue StringToArrayBuffer(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum);
static JSIValue Fetch(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum);
public:
static const char *const HTTP_API_KEY_FETCH;
static const char *const HTTP_API_KEY_STRING_TO_ARRAY_BUFFER;
private:
static JSIValue MakeCallback(JSIValue options);
static bool JsObjectToRequestData(JSIValue options, RequestData *req);
static void GetNameValue(JSIValue nv, std::map<std::string, std::string> &map);
static void GetRequestBody(JSIValue options, RequestData *requestData);
static void ParseExtraData(JSIValue options, RequestData *requestData);
static std::string GetMethodFromOptions(JSIValue options);
static std::string GetResponseTypeFromOptions(JSIValue options);
};
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_FETCH_MODULE_H */

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "http_async_callback.h"
#include "http_request.h"
#include "http_request_utils.h"
#include "securec.h"
#include <algorithm>
#include <memory>
template <typename T> void DefaultDelete(T *ptr)
{
HTTP_REQUEST_INFO("delete %s", typeid(ptr).name());
delete ptr;
}
namespace OHOS {
namespace ACELite {
HttpAsyncCallback::HttpAsyncCallback(const RequestData *&requestData, JSIValue responseCallback, JSIValue thisVal)
{
this->requestData = const_cast<RequestData *>(requestData);
this->responseCallback = responseCallback;
this->thisVal = thisVal;
}
void HttpAsyncCallback::AsyncExecHttpRequest(void *data)
{
std::unique_ptr<HttpAsyncCallback, decltype(&DefaultDelete<HttpAsyncCallback>)> asyncCallback(
static_cast<HttpAsyncCallback *>(data), DefaultDelete<HttpAsyncCallback>);
if (asyncCallback == nullptr) {
return;
}
std::unique_ptr<RequestData, decltype(&DefaultDelete<RequestData>)> requestData(asyncCallback->requestData,
DefaultDelete<RequestData>);
if (requestData == nullptr) {
return;
}
ResponseData responseData;
bool success = HttpRequest::Request(requestData.get(), &responseData);
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> responseCallback(asyncCallback->responseCallback,
JSI::ReleaseValue);
if (responseCallback == nullptr || JSI::ValueIsUndefined(responseCallback.get()) ||
!JSI::ValueIsObject(responseCallback.get())) {
if (success) {
HTTP_REQUEST_INFO("http status line: %s", responseData.GetStatusLine().c_str());
}
return;
}
if (success) {
asyncCallback->OnSuccess(responseData);
} else {
asyncCallback->OnFail(responseData.GetErrString().c_str(), responseData.GetCode());
}
asyncCallback->OnComplete();
}
JSIValue HttpAsyncCallback::ResponseDataToJsValue(const ResponseData &responseData)
{
JSIValue object = JSI::CreateObject();
if (object == nullptr) {
return nullptr;
}
JSI::SetNumberProperty(object, HttpConstant::KEY_HTTP_RESPONSE_CODE, responseData.GetCode());
HTTP_REQUEST_INFO("response body size = %zu", responseData.GetData().size());
std::string responseType = requestData->GetResponseType();
std::transform(responseType.begin(), responseType.end(), responseType.begin(), tolower);
if (responseType == HttpConstant::HTTP_RESPONSE_TYPE_JSON) {
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> jsonObj(JSI::JsonParse(responseData.GetData().c_str()),
JSI::ReleaseValue);
if (jsonObj != nullptr && !JSI::ValueIsUndefined(jsonObj.get()) && JSI::ValueIsObject(jsonObj.get())) {
JSI::SetNamedProperty(object, HttpConstant::KEY_HTTP_RESPONSE_DATA, jsonObj.get());
}
} else {
JSI::SetStringProperty(object, HttpConstant::KEY_HTTP_RESPONSE_DATA, responseData.GetData().c_str(),
responseData.GetData().size());
}
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> headers(JSI::CreateObject(), JSI::ReleaseValue);
if (headers == nullptr) {
JSI::ReleaseValue(object);
}
for (const auto &p : responseData.GetHeaders()) {
JSI::SetStringProperty(headers.get(), p.first.c_str(), p.second.c_str());
}
JSI::SetNamedProperty(object, HttpConstant::KEY_HTTP_RESPONSE_HEADERS, headers.get());
return object;
}
void HttpAsyncCallback::OnSuccess(const ResponseData &responseData)
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> success(JSI::GetNamedProperty(responseCallback, CB_SUCCESS),
JSI::ReleaseValue);
if (success == nullptr || JSI::ValueIsUndefined(success.get()) || !JSI::ValueIsFunction(success.get())) {
return;
}
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> obj(ResponseDataToJsValue(responseData), JSI::ReleaseValue);
if (obj == nullptr || JSI::ValueIsUndefined(obj.get()) || !JSI::ValueIsObject(obj.get())) {
return;
}
JSIValue arg[ARGC_ONE] = {obj.get()};
JSI::CallFunction(success.get(), thisVal, arg, ARGC_ONE);
}
void HttpAsyncCallback::OnFail(const char *errData, int32_t errCode)
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> fail(JSI::GetNamedProperty(responseCallback, CB_FAIL),
JSI::ReleaseValue);
if (fail == nullptr || JSI::ValueIsUndefined(fail.get()) || !JSI::ValueIsFunction(fail.get())) {
return;
}
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> errInfo(JSI::CreateString(errData), JSI::ReleaseValue);
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> retCode(JSI::CreateNumber(errCode), JSI::ReleaseValue);
JSIValue argv[ARGC_TWO] = {errInfo.get(), retCode.get()};
JSI::CallFunction(fail.get(), thisVal, argv, ARGC_TWO);
}
void HttpAsyncCallback::OnComplete()
{
std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> complete(JSI::GetNamedProperty(responseCallback, CB_COMPLETE),
JSI::ReleaseValue);
if (complete == nullptr || JSI::ValueIsUndefined(complete.get()) || !JSI::ValueIsFunction(complete.get())) {
return;
}
JSI::CallFunction(complete.get(), thisVal, nullptr, 0);
}
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_HTTP_ASYNC_CALLBACK_H
#define OHOS_ACELITE_HTTP_ASYNC_CALLBACK_H
#include "jsi.h"
#include "non_copyable.h"
#include "request_data.h"
#include "response_data.h"
namespace OHOS {
namespace ACELite {
class HttpAsyncCallback : public MemoryHeap {
public:
ACE_DISALLOW_COPY_AND_MOVE(HttpAsyncCallback);
HttpAsyncCallback(const RequestData *&requestData, JSIValue responseCallback, JSIValue thisVal);
public:
static void AsyncExecHttpRequest(void *data);
private:
RequestData *requestData;
JSIValue responseCallback;
JSIValue thisVal;
private:
JSIValue ResponseDataToJsValue(const ResponseData &responseData);
void OnSuccess(const ResponseData &responseData);
void OnFail(const char *errData, int32_t errCode);
void OnComplete();
};
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_HTTP_ASYNC_CALLBACK_H */

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace OHOS {
namespace ACELite {
namespace HttpConstant {
int HTTP_RESPONSE_CODE_INVALID = -1;
const char *HTTP_RESPONSE_TYPE_JSON = "json";
const char *HTTP_HEADER_SEPARATOR = ":";
const char *HTTP_DEFAULT_USER_AGENT = "libcurl-agent/1.0";
const char *HTTP_DEFAULT_CONTENT_TYPE = "text/plain";
const char *HTTP_HEADER_KEY_CONTENT_TYPE = "content-type";
const char *HTTP_CONTENT_TYPE_URL_ENCODE = "application/x-www-form-urlencoded";
const char *HTTP_CONTENT_TYPE_JSON = "application/json";
const char *HTTP_URL_PARAM_SEPARATOR = "?";
const char *HTTP_URL_PARAM_DELIMITER = "&";
const char *HTTP_METHOD_GET = "GET";
const char *HTTP_METHOD_HEAD = "HEAD";
const char *HTTP_METHOD_OPTIONS = "OPTIONS";
const char *HTTP_METHOD_TRACE = "TRACE";
const char *HTTP_METHOD_DELETE = "DELETE";
const char *HTTP_METHOD_POST = "POST";
const char *HTTP_METHOD_PUT = "PUT";
const char *KEY_HTTP_RESPONSE_CODE = "code";
const char *KEY_HTTP_RESPONSE_DATA = "data";
const char *KEY_HTTP_RESPONSE_HEADERS = "headers";
const char *KEY_HTTP_REQUEST_URL = "url";
const char *KEY_HTTP_REQUEST_DATA = "data";
const char *KEY_HTTP_REQUEST_HEADER = "header";
const char *KEY_HTTP_REQUEST_METHOD = "method";
const char *KEY_HTTP_REQUEST_RESPONSE_TYPE = "responseType";
} // namespace HttpConstant
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_HTTP_CONSTANT_H
#define OHOS_ACELITE_HTTP_CONSTANT_H
namespace OHOS {
namespace ACELite {
namespace HttpConstant {
extern const int HTTP_RESPONSE_CODE_INVALID;
extern const char *const HTTP_RESPONSE_TYPE_JSON;
extern const char *const HTTP_HEADER_SEPARATOR;
extern const char *const HTTP_DEFAULT_USER_AGENT;
extern const char *const HTTP_DEFAULT_CONTENT_TYPE;
extern const char *const HTTP_HEADER_KEY_CONTENT_TYPE;
extern const char *const HTTP_CONTENT_TYPE_URL_ENCODE;
extern const char *const HTTP_CONTENT_TYPE_JSON;
extern const char *const HTTP_URL_PARAM_SEPARATOR;
extern const char *const HTTP_URL_PARAM_DELIMITER;
extern const char *const HTTP_METHOD_GET;
extern const char *const HTTP_METHOD_HEAD;
extern const char *const HTTP_METHOD_OPTIONS;
extern const char *const HTTP_METHOD_TRACE;
extern const char *const HTTP_METHOD_DELETE;
extern const char *const HTTP_METHOD_POST;
extern const char *const HTTP_METHOD_PUT;
extern const char *const KEY_HTTP_RESPONSE_CODE;
extern const char *const KEY_HTTP_RESPONSE_DATA;
extern const char *const KEY_HTTP_RESPONSE_HEADERS;
extern const char *const KEY_HTTP_REQUEST_URL;
extern const char *const KEY_HTTP_REQUEST_DATA;
extern const char *const KEY_HTTP_REQUEST_HEADER;
extern const char *const KEY_HTTP_REQUEST_METHOD;
extern const char *const KEY_HTTP_REQUEST_RESPONSE_TYPE;
} // namespace HttpConstant
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_HTTP_CONSTANT_H */

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "http_request.h"
#include "http_request_utils.h"
#include <cstring>
#define ACE_CURL_EASY_SET_OPTION(handle, opt, data, respData) \
do { \
CURLcode result = curl_easy_setopt(handle, opt, data); \
if (result != CURLE_OK) { \
const char *err = curl_easy_strerror(result); \
HTTP_REQUEST_ERROR("Failed to set option: %s, %s", #opt, err); \
respData->SetErrString(err); \
respData->SetCode(result); \
return false; \
} \
} while (0)
#define ACE_CURL_EASY_PERFORM(handle, reqData, respData) \
do { \
CURLcode result = curl_easy_perform(handle); \
if (result != CURLE_OK) { \
const char *err = curl_easy_strerror(result); \
HTTP_REQUEST_ERROR("Failed to fetch, url:%s, %s", reqData->GetUrl().c_str(), err); \
respData->SetErrString(err); \
respData->SetCode(result); \
return false; \
} \
} while (0)
#define ACE_CURL_EASY_GET_INFO(handle, opt, data, respData) \
do { \
CURLcode result = curl_easy_getinfo(handle, opt, data); \
if (result != CURLE_OK) { \
const char *err = curl_easy_strerror(result); \
HTTP_REQUEST_ERROR("Failed to get info: %s, %s", #opt, err); \
respData->SetErrString(err); \
respData->SetCode(result); \
return false; \
} \
} while (0)
namespace OHOS {
namespace ACELite {
std::mutex HttpRequest::mutex;
bool HttpRequest::initialized = false;
bool HttpRequest::Initialize()
{
std::lock_guard<std::mutex> lock(mutex);
if (initialized) {
return true;
}
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
HTTP_REQUEST_ERROR("Failed to initialize 'curl'");
return false;
}
initialized = true;
return true;
}
bool HttpRequest::Request(RequestData *requestData, ResponseData *responseData)
{
if (!Initialize()) {
return false;
}
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> handle(curl_easy_init(), curl_easy_cleanup);
if (!handle) {
HTTP_REQUEST_ERROR("Failed to create fetch task");
return false;
}
#if NO_SSL_CERTIFICATION
// in real life, you should buy a ssl certification and rename it to /etc/ssl/cert.pem
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_SSL_VERIFYPEER, 0L, responseData);
#endif // NO_SSL_CERTIFICATION
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_WRITEFUNCTION, OnWritingMemoryBody, responseData);
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_WRITEDATA, responseData, responseData);
std::string responseHeader;
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_HEADERFUNCTION, OnWritingMemoryHeader, responseData);
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_HEADERDATA, &responseHeader, responseData);
// Some servers don't like requests that are made without a user-agent field, so we provide one
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_USERAGENT, HttpConstant::HTTP_DEFAULT_USER_AGENT, responseData);
if (!SetOption(requestData, handle.get(), responseData)) {
HTTP_REQUEST_ERROR("set option failed");
return false;
}
std::vector<std::string> vec(responseData->GetHeaders().size());
for (const auto &p : requestData->GetHeader()) {
vec.emplace_back(p.first + HttpConstant::HTTP_HEADER_SEPARATOR + p.second);
}
std::unique_ptr<struct curl_slist, decltype(&curl_slist_free_all)> header(MakeHeaders(vec), curl_slist_free_all);
if (header != nullptr) {
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_HTTPHEADER, header.get(), responseData);
}
ACE_CURL_EASY_PERFORM(handle.get(), requestData, responseData);
int32_t responseCode;
ACE_CURL_EASY_GET_INFO(handle.get(), CURLINFO_RESPONSE_CODE, &responseCode, responseData);
responseData->SetCode(responseCode);
responseData->ParseHeaders(responseHeader);
return true;
}
bool HttpRequest::SetOption(RequestData *requestData, CURL *curl, ResponseData *responseData)
{
const std::string &method = requestData->GetMethod();
if (!MethodForGet(method) && !MethodForPost(method)) {
HTTP_REQUEST_ERROR("method %s not supported", method.c_str());
return false;
}
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_CUSTOMREQUEST, method.c_str(), responseData);
if (MethodForPost(method)) {
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_POST, 1L, responseData);
}
if (!requestData->GetBody().empty()) {
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_POSTFIELDS, requestData->GetBody().c_str(), responseData);
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_POSTFIELDSIZE, requestData->GetBody().size(), responseData);
}
if (EncodeUrlParam(curl, const_cast<std::string &>(requestData->GetUrl())) && MethodForGet(method)) {
requestData->SetHeader(HttpConstant::HTTP_HEADER_KEY_CONTENT_TYPE, HttpConstant::HTTP_CONTENT_TYPE_URL_ENCODE);
}
HTTP_REQUEST_INFO("final url: %s", requestData->GetUrl().c_str());
ACE_CURL_EASY_SET_OPTION(curl, CURLOPT_URL, requestData->GetUrl().c_str(), responseData);
return true;
}
size_t HttpRequest::OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData)
{
static_cast<ResponseData *>(userData)->AppendData(static_cast<const char *>(data), size * memBytes);
return size * memBytes;
}
size_t HttpRequest::OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData)
{
static_cast<std::string *>(userData)->append(static_cast<const char *>(data), size * memBytes);
return size * memBytes;
}
struct curl_slist *HttpRequest::MakeHeaders(const std::vector<std::string> &vec)
{
struct curl_slist *header = nullptr;
for (const auto &s : vec) {
header = curl_slist_append(header, s.c_str());
}
return header;
}
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_HTTP_REQUEST_H
#define OHOS_ACELITE_HTTP_REQUEST_H
#include "curl/curl.h"
#include "http_constant.h"
#include "non_copyable.h"
#include "request_data.h"
#include "response_data.h"
#include "securec.h"
#include <memory>
#include <mutex>
#include <string>
namespace OHOS {
namespace ACELite {
class HttpRequest final {
public:
ACE_DISALLOW_COPY_AND_MOVE(HttpRequest);
HttpRequest() = default;
~HttpRequest() = default;
static bool Request(RequestData *requestData, ResponseData *responseData);
private:
static bool Initialize();
static bool SetOption(RequestData *requestData, CURL *curl, ResponseData *responseData);
static size_t OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData);
static size_t OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData);
static struct curl_slist *MakeHeaders(const std::vector<std::string> &vec);
private:
static std::mutex mutex;
static bool initialized;
};
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_HTTP_REQUEST_H */

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "http_request_utils.h"
#include "http_constant.h"
#include <cstring>
#include <memory>
#include <vector>
namespace OHOS {
namespace ACELite {
std::vector<std::string> Split(const std::string &str, const std::string &sep)
{
std::string s = str;
std::vector<std::string> res;
while (!s.empty()) {
size_t pos = s.find(sep);
if (pos == std::string::npos) {
res.emplace_back(s);
break;
}
res.emplace_back(s.substr(0, pos));
s = s.substr(pos + sep.size());
}
return res;
}
std::string Strip(const std::string &str, char ch)
{
int64_t i = 0;
while (i < str.size() && str[i] == ch) {
++i;
}
int64_t j = static_cast<int64_t>(str.size()) - 1;
while (j > 0 && str[j] == ch) {
--j;
}
if (i >= 0 && i < str.size() && j >= 0 && j < str.size() && j - i + 1 > 0) {
return str.substr(i, j - i + 1);
}
return "";
}
bool MethodForGet(const std::string &method)
{
return (method == HttpConstant::HTTP_METHOD_HEAD || method == HttpConstant::HTTP_METHOD_OPTIONS ||
method == HttpConstant::HTTP_METHOD_DELETE || method == HttpConstant::HTTP_METHOD_TRACE ||
method == HttpConstant::HTTP_METHOD_GET);
}
bool MethodForPost(const std::string &method)
{
return (method == HttpConstant::HTTP_METHOD_POST || method == HttpConstant::HTTP_METHOD_PUT);
}
std::string MakeUrl(const std::string &url, std::string param, const std::string &extraParam)
{
if (param.empty()) {
param += extraParam;
} else {
param += HttpConstant::HTTP_URL_PARAM_DELIMITER;
param += extraParam;
}
if (param.empty()) {
return url;
}
return url + HttpConstant::HTTP_URL_PARAM_SEPARATOR + param;
}
bool EncodeUrlParam(CURL *curl, std::string &url)
{
size_t index = url.find(HttpConstant::HTTP_URL_PARAM_SEPARATOR);
if (index == std::string::npos) {
return false;
}
std::string param = url.substr(index + 1);
if (param.empty()) {
return false;
}
std::unique_ptr<char, decltype(&curl_free)> encodeOut(
curl_easy_escape(curl, param.c_str(), static_cast<int>(strlen(param.c_str()))), curl_free);
if (encodeOut == nullptr || strlen(encodeOut.get()) == 0) {
return false;
}
url = url.substr(0, index) + HttpConstant::HTTP_URL_PARAM_SEPARATOR + encodeOut.get();
return true;
}
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_HTTP_REQUEST_UTILS_H
#define OHOS_ACELITE_HTTP_REQUEST_UTILS_H
#include "curl/curl.h"
#include "securec.h"
#include <string>
#include <vector>
#define HTTP_PRINT_TIME() \
do { \
struct timeval now = {0}; \
gettimeofday(&now, NULL); \
struct tm *tmp_time = localtime(&now.tv_sec); \
char timeString[100] = {0}; \
strftime(timeString, sizeof(timeString), "%04Y/%02m/%02d %H:%M:%S", tmp_time); \
long double uSec = now.tv_usec; \
printf("[%s%.3Lf] ", timeString, uSec / 1000.0L / 1000.0L); \
fflush(stdout); \
} while (0)
#define HTTP_REQUEST_INFO(...) \
do { \
HTTP_PRINT_TIME(); \
printf("[HTTP][INFO] " __VA_ARGS__); \
fflush(stdout); \
puts(""); \
fflush(stdout); \
} while (0)
#define HTTP_REQUEST_ERROR(...) \
do { \
HTTP_PRINT_TIME(); \
printf("[HTTP][ERROR] " __VA_ARGS__); \
fflush(stdout); \
puts(""); \
fflush(stdout); \
} while (0)
namespace OHOS {
namespace ACELite {
std::vector<std::string> Split(const std::string &str, const std::string &sep);
std::string Strip(const std::string &str, char ch = ' ');
bool MethodForGet(const std::string &method);
bool MethodForPost(const std::string &method);
std::string MakeUrl(const std::string &url, std::string param, const std::string &extraParam);
bool EncodeUrlParam(CURL *curl, std::string &url);
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_HTTP_REQUEST_UTILS_H */

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "request_data.h"
#include "http_constant.h"
namespace OHOS {
namespace ACELite {
RequestData::RequestData()
{
method = HttpConstant::HTTP_METHOD_GET; // default
header[HttpConstant::HTTP_HEADER_KEY_CONTENT_TYPE] = HttpConstant::HTTP_DEFAULT_CONTENT_TYPE; // default
}
void RequestData::SetUrl(const std::string &urlPara)
{
url = urlPara;
}
void RequestData::SetMethod(const std::string &methodPara)
{
method = methodPara;
}
void RequestData::SetHeader(const std::string &key, const std::string &val)
{
header[key] = val;
}
void RequestData::SetBody(const std::string &bodyPara)
{
body = bodyPara;
}
void RequestData::SetResponseType(const std::string &respType)
{
responseType = respType;
}
const std::string &RequestData::GetUrl() const
{
return url;
}
const std::map<std::string, std::string> &RequestData::GetHeader() const
{
return header;
}
const std::string &RequestData::GetMethod() const
{
return method;
}
const std::string &RequestData::GetBody() const
{
return body;
}
const std::string &RequestData::GetResponseType() const
{
return responseType;
}
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_REQUEST_DATA_H
#define OHOS_ACELITE_REQUEST_DATA_H
#include <array>
#include <map>
#include <string>
namespace OHOS {
namespace ACELite {
class RequestData {
public:
RequestData();
void SetUrl(const std::string &url);
void SetMethod(const std::string &method);
void SetHeader(const std::string &key, const std::string &val);
void SetBody(const std::string &body);
void SetResponseType(const std::string &respType);
[[nodiscard]] const std::string &GetUrl() const;
[[nodiscard]] const std::map<std::string, std::string> &GetHeader() const;
[[nodiscard]] const std::string &GetMethod() const;
[[nodiscard]] const std::string &GetBody() const;
[[nodiscard]] const std::string &GetResponseType() const;
private:
std::string url;
std::map<std::string, std::string> header;
std::string method;
std::string body;
std::string responseType;
};
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_REQUEST_DATA_H */

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "response_data.h"
#include "http_request_utils.h"
namespace OHOS {
namespace ACELite {
ResponseData::ResponseData()
{
code = HttpConstant::HTTP_RESPONSE_CODE_INVALID;
}
void ResponseData::SetCode(int32_t codePara)
{
code = codePara;
}
void ResponseData::SetErrString(const std::string &err)
{
errString = err;
}
void ResponseData::ParseHeaders(const std::string &headersStr)
{
std::vector<std::string> vec = Split(headersStr, "\n");
for (auto header : vec) {
header = Strip(Strip(header), '\r');
if (header.empty()) {
continue;
}
size_t posColon = header.find(HttpConstant::HTTP_HEADER_SEPARATOR);
if (posColon == std::string::npos) {
statusLine = Strip(header);
continue;
}
std::vector<std::string> temp = Split(header, HttpConstant::HTTP_HEADER_SEPARATOR);
headers[Strip(temp[0])] = Strip(temp[1]);
}
}
int32_t ResponseData::GetCode() const
{
return code;
}
const std::string &ResponseData::GetErrString() const
{
return errString;
}
void ResponseData::AppendData(const char *dataPara, size_t size)
{
data.append(dataPara, size);
}
const std::string &ResponseData::GetData() const
{
return data;
}
const std::string &ResponseData::GetStatusLine() const
{
return statusLine;
}
const std::map<std::string, std::string> &ResponseData::GetHeaders() const
{
return headers;
}
} // namespace ACELite
} // namespace OHOS

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ACELITE_RESPONSE_DATA_H
#define OHOS_ACELITE_RESPONSE_DATA_H
#include "http_constant.h"
#include <map>
#include <string>
#include <vector>
namespace OHOS {
namespace ACELite {
class ResponseData {
public:
ResponseData();
void SetCode(int32_t code);
void SetErrString(const std::string &err);
void ParseHeaders(const std::string &headersStr);
void AppendData(const char *data, size_t size);
[[nodiscard]] int32_t GetCode() const;
[[nodiscard]] const std::string &GetErrString() const;
[[nodiscard]] const std::string &GetData() const;
[[nodiscard]] const std::string &GetStatusLine() const;
[[nodiscard]] const std::map<std::string, std::string> &GetHeaders() const;
private:
int32_t code;
std::string data;
std::string statusLine;
std::string errString;
std::map<std::string, std::string> headers;
};
} // namespace ACELite
} // namespace OHOS
#endif /* OHOS_ACELITE_RESPONSE_DATA_H */

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fetch_module.h"
#include "http_request/http_async_callback.h"
#include "http_request/http_request_utils.h"
#include "jerryscript-core.h"
#include "js_async_work.h"
#include "message_queue_utils.h"
#define FUNC_BEGIN() \
do { \
HTTP_REQUEST_INFO("%s BEGIN ##########", __FUNCTION__); \
} while (0)
#define FUNC_END_NO_NEW_LINE() \
do { \
HTTP_REQUEST_INFO("%s END ##########", __FUNCTION__); \
} while (0)
#define FUNC_END() \
do { \
HTTP_REQUEST_INFO("%s END ##########\n\n\n", __FUNCTION__); \
} while (0)
namespace OHOS {
namespace ACELite {
void InitFetchModule(JSIValue exports);
class JerryInitializer {
private:
int *temp;
JSIValue exports;
public:
JerryInitializer()
{
temp = new int;
jerry_init(JERRY_INIT_EMPTY);
JsAsyncWork::SetAppQueueHandler(temp);
exports = JSI::CreateObject();
InitFetchModule(exports);
}
~JerryInitializer()
{
jerry_cleanup();
delete temp;
JSI::ReleaseValue(exports);
}
};
void TestPutMessage(void *data)
{
auto msg = static_cast<AbilityInnerMsg *>(data);
auto asyncWork = static_cast<AsyncWork *>(msg->data);
asyncWork->workHandler(asyncWork->data);
}
JSIValue TestCallbackOnSuccess(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
FUNC_BEGIN();
(void)thisVal;
(void)argsNum;
JSIValue para = args[0];
HTTP_REQUEST_INFO("code = %d",
static_cast<int>(JSI::GetNumberProperty(para, HttpConstant::KEY_HTTP_RESPONSE_CODE)));
size_t size = 0;
char *data = JSI::GetStringProperty(para, HttpConstant::KEY_HTTP_RESPONSE_DATA, size);
std::string body;
for (uint32_t index = 0; index < size; ++index) {
if (data[index] != 0) {
body += data[index];
} else {
body += "0";
}
}
HTTP_REQUEST_INFO("%s", body.c_str());
JSIValue head = JSI::GetNamedProperty(para, HttpConstant::KEY_HTTP_RESPONSE_HEADERS);
JSIValue keys = JSI::GetObjectKeys(head);
uint32_t length = JSI::GetArrayLength(keys);
for (uint32_t i = 0; i < length; ++i) {
JSIValue k = JSI::GetPropertyByIndex(keys, i);
char *s = JSI::ValueToString(k);
char *v = JSI::GetStringProperty(head, s);
HTTP_REQUEST_INFO("%s ---------------- %s", s, v);
}
FUNC_END_NO_NEW_LINE();
return JSI::CreateUndefined();
}
JSIValue TestCallbackOnFail(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
FUNC_BEGIN();
(void)thisVal;
(void)argsNum;
HTTP_REQUEST_INFO("err = %s", JSI::ValueToString(args[0]));
HTTP_REQUEST_INFO("code = %d", static_cast<int>(JSI::ValueToNumber(args[1])));
FUNC_END_NO_NEW_LINE();
return JSI::CreateUndefined();
}
JSIValue TestCallbackOnComplete(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
FUNC_BEGIN();
(void)thisVal;
(void)args;
(void)argsNum;
HTTP_REQUEST_INFO("request complete");
FUNC_END_NO_NEW_LINE();
return JSI::CreateUndefined();
}
void TestHttpModuleMethodAndHeaderByDefault()
{
FUNC_BEGIN();
JSIValue object = JSI::CreateObject();
if (object == nullptr) {
return;
}
JSIValue header = JSI::CreateObject();
JSI::SetStringProperty(header, "no-use", "test value");
JSI::SetNamedProperty(object, HttpConstant::KEY_HTTP_REQUEST_HEADER, header);
JSIValue url = JSI::CreateString("https://www.zhihu.com");
JSI::SetNamedProperty(object, HttpConstant::KEY_HTTP_REQUEST_URL, url);
JSI::SetNamedProperty(object, CB_SUCCESS, JSI::CreateFunction(TestCallbackOnSuccess));
JSI::SetNamedProperty(object, CB_FAIL, JSI::CreateFunction(TestCallbackOnFail));
JSI::SetNamedProperty(object, CB_COMPLETE, JSI::CreateFunction(TestCallbackOnComplete));
JSIValue arg[1] = {object};
FetchModule::Fetch(nullptr, arg, 1);
FUNC_END();
}
} // namespace ACELite
} // namespace OHOS
int main()
{
OHOS::ACELite::JerryInitializer jerryInitializer;
OHOS::ACELite::TestHttpModuleMethodAndHeaderByDefault();
return 0;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TEST_HEADERS_ACE_LOG_H
#define TEST_HEADERS_ACE_LOG_H
#include <cstring>
#define __LITEOS__
#define HILOG_ERROR(...) \
do { \
} while (0)
#define HILOG_WARN(num, s, ...) \
do { \
if (strcmp(s, "todo call linux putmsg interface here!") == 0) { \
OHOS::ACELite::TestPutMessage(const_cast<void *>(msgPtr)); \
return MSGQ_OK; \
} \
} while (0)
static void *msgPtr;
namespace OHOS {
namespace ACELite {
void TestPutMessage(void *data);
} // namespace ACELite
} // namespace OHOS
#endif /* TEST_HEADERS_ACE_LOG_H */

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TEST_HEADERS_ACE_MEM_BASE_H
#define TEST_HEADERS_ACE_MEM_BASE_H
#include <cstdlib>
#define ace_malloc malloc
#define ace_free free
#endif /* TEST_HEADERS_ACE_MEM_BASE_H */

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TEST_HEADERS_GRAPHIC_CONFIG_H
#define TEST_HEADERS_GRAPHIC_CONFIG_H
#endif /* TEST_HEADERS_GRAPHIC_CONFIG_H */

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../../../../../../../ace/ace_engine_lite/interfaces/innerkits/builtin/base/memory_heap.h"

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export interface FetchResponse {
/**
* Server status code.
* @since 3
*/
code: number;
/**
* Data returned by the success function.
* @since 3
*/
data: string | object;
/**
* All headers in the response from the server.
* @since 3
*/
headers: Object;
}
/**
* @Syscap SysCap.ACE.UIEngine
*/
export default class Fetch {
/**
* Obtains data through the network.
* @param options
*/
static fetch(options: {
/**
* Resource URL.
* @since 3
*/
url: string;
/**
* Request parameter, which can be of the string type or a JSON object.
* @since 3
*/
data?: string | object;
/**
* Request header, which accommodates all attributes of the request.
* @since 3
*/
header?: Object;
/**
* Request methods available: OPTIONS, GET, HEAD, POST, PUT, DELETE and TRACE. The default value is GET.
* @since 3
*/
method?: string;
/**
* The return type can be text, or JSON. By default, the return type is determined based on Content-Type in the header returned by the server.
* @since 3
*/
responseType?: string;
/**
* Called when the network data is obtained successfully.
* @since 3
*/
success?: (data: FetchResponse) => void;
/**
* Called when the network data fails to be obtained.
* @since 3
*/
fail?: (data: any, code: number) => void;
/**
* Called when the execution is completed.
* @since 3
*/
complete?: () => void;
}): void;
}