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