1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <algorithm>
17 #include <memory>
18
19 #include "http_constant.h"
20 #include "http_request.h"
21 #include "http_request_utils.h"
22
23 #include "http_async_callback.h"
24
25 namespace OHOS {
26 namespace ACELite {
27
HttpAsyncCallback(JSIValue thisValue)28 HttpAsyncCallback::HttpAsyncCallback(JSIValue thisValue) : thisVal(thisValue) {}
29
AsyncExecHttpRequest(void * data)30 void HttpAsyncCallback::AsyncExecHttpRequest(void *data)
31 {
32 std::unique_ptr<HttpAsyncCallback, decltype(&HttpAsyncCallback::AsyncCallbackDeleter)> asyncCallback(
33 static_cast<HttpAsyncCallback *>(data), HttpAsyncCallback::AsyncCallbackDeleter);
34 if (asyncCallback == nullptr) {
35 return;
36 }
37
38 ResponseData responseData;
39 bool success = HttpRequest::Request(&asyncCallback->requestData, &responseData);
40 if (success) {
41 HTTP_REQUEST_INFO("http status line: %s", responseData.GetStatusLine().c_str());
42 asyncCallback->OnSuccess(responseData);
43 } else {
44 asyncCallback->OnFail(responseData.GetErrString().c_str(), responseData.GetCode());
45 }
46 asyncCallback->OnComplete();
47 }
48
AsyncCallbackDeleter(HttpAsyncCallback * asyncCallback)49 void HttpAsyncCallback::AsyncCallbackDeleter(HttpAsyncCallback *asyncCallback)
50 {
51 if (asyncCallback->responseCallback[CB_SUCCESS]) {
52 JSI::ReleaseValue(asyncCallback->responseCallback[CB_SUCCESS]);
53 }
54 if (asyncCallback->responseCallback[CB_FAIL]) {
55 JSI::ReleaseValue(asyncCallback->responseCallback[CB_FAIL]);
56 }
57 if (asyncCallback->responseCallback[CB_COMPLETE]) {
58 JSI::ReleaseValue(asyncCallback->responseCallback[CB_COMPLETE]);
59 }
60 delete asyncCallback;
61 }
62
ResponseDataToJsValue(const ResponseData & responseData)63 JSIValue HttpAsyncCallback::ResponseDataToJsValue(const ResponseData &responseData)
64 {
65 JSIValue object = JSI::CreateObject();
66 if (object == nullptr) {
67 return nullptr;
68 }
69
70 JSI::SetNumberProperty(object, HttpConstant::KEY_HTTP_RESPONSE_CODE, responseData.GetCode());
71
72 HTTP_REQUEST_INFO("response body size = %zu", responseData.GetData().size());
73 std::string responseType = requestData.GetResponseType();
74 std::transform(responseType.begin(), responseType.end(), responseType.begin(), tolower);
75
76 if (responseType == HttpConstant::HTTP_RESPONSE_TYPE_JSON) {
77 std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> jsonObj(JSI::JsonParse(responseData.GetData().c_str()),
78 JSI::ReleaseValue);
79 if (jsonObj != nullptr && !JSI::ValueIsUndefined(jsonObj.get()) && JSI::ValueIsObject(jsonObj.get())) {
80 JSI::SetNamedProperty(object, HttpConstant::KEY_HTTP_RESPONSE_DATA, jsonObj.get());
81 }
82 } else {
83 JSI::SetStringPropertyWithBufferSize(object, HttpConstant::KEY_HTTP_RESPONSE_DATA,
84 responseData.GetData().c_str(), responseData.GetData().size());
85 }
86
87 std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> headers(JSI::CreateObject(), JSI::ReleaseValue);
88 if (headers == nullptr) {
89 JSI::ReleaseValue(object);
90 return JSI::CreateUndefined();
91 }
92 for (const auto &p : responseData.GetHeaders()) {
93 JSI::SetStringProperty(headers.get(), p.first.c_str(), p.second.c_str());
94 }
95 JSI::SetNamedProperty(object, HttpConstant::KEY_HTTP_RESPONSE_HEADERS, headers.get());
96
97 return object;
98 }
99
OnSuccess(const ResponseData & responseData)100 void HttpAsyncCallback::OnSuccess(const ResponseData &responseData)
101 {
102 JSIValue success = responseCallback[CB_SUCCESS];
103 if (success == nullptr || JSI::ValueIsUndefined(success) || !JSI::ValueIsFunction(success)) {
104 return;
105 }
106
107 std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> obj(ResponseDataToJsValue(responseData), JSI::ReleaseValue);
108 if (obj == nullptr || JSI::ValueIsUndefined(obj.get()) || !JSI::ValueIsObject(obj.get())) {
109 return;
110 }
111
112 JSIValue arg[ARGC_ONE] = {obj.get()};
113 JSI::CallFunction(success, thisVal, arg, ARGC_ONE);
114 }
115
OnFail(const char * errData,int32_t errCode)116 void HttpAsyncCallback::OnFail(const char *errData, int32_t errCode)
117 {
118 JSIValue fail = responseCallback[CB_FAIL];
119 if (fail == nullptr || JSI::ValueIsUndefined(fail) || !JSI::ValueIsFunction(fail)) {
120 return;
121 }
122 std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> errInfo(JSI::CreateString(errData), JSI::ReleaseValue);
123 std::unique_ptr<JSIVal, decltype(&JSI::ReleaseValue)> retCode(JSI::CreateNumber(errCode), JSI::ReleaseValue);
124
125 JSIValue argv[ARGC_TWO] = {errInfo.get(), retCode.get()};
126 JSI::CallFunction(fail, thisVal, argv, ARGC_TWO);
127 }
128
OnComplete()129 void HttpAsyncCallback::OnComplete()
130 {
131 JSIValue complete = responseCallback[CB_COMPLETE];
132 if (complete == nullptr || JSI::ValueIsUndefined(complete) || !JSI::ValueIsFunction(complete)) {
133 return;
134 }
135 JSI::CallFunction(complete, thisVal, nullptr, 0);
136 }
137
138 } // namespace ACELite
139 } // namespace OHOS
140