• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "fetch_context.h"
17 
18 #include "constant.h"
19 #include "fetch_exec.h"
20 #include "netstack_common_utils.h"
21 #include "netstack_log.h"
22 #include "napi_utils.h"
23 
24 namespace OHOS::NetStack {
FetchContext(napi_env env,EventManager * manager)25 FetchContext::FetchContext(napi_env env, EventManager *manager)
26     : BaseContext(env, manager), successCallback_(nullptr), failCallback_(nullptr), completeCallback_(nullptr)
27 {
28 }
29 
ParseParams(napi_value * params,size_t paramsCount)30 void FetchContext::ParseParams(napi_value *params, size_t paramsCount)
31 {
32     SetNeedPromise(false);
33 
34     bool valid = CheckParamsType(params, paramsCount);
35     if (!valid) {
36         NETSTACK_LOGE("fetch CheckParamsType failed");
37         return;
38     }
39 
40     request.SetUrl(NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], FetchConstant::PARAM_KEY_URL));
41     request.SetMethod(NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], FetchConstant::PARAM_KEY_METHOD));
42     if (request.GetMethod().empty()) {
43         request.SetMethod(FetchConstant::HTTP_METHOD_GET);
44     }
45     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], FetchConstant::PARAM_KEY_RESPONSE_TYPE)) {
46         responseType_ = NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], FetchConstant::PARAM_KEY_RESPONSE_TYPE);
47     }
48     ParseHeader(params[0]);
49     ParseData(params[0]);
50 
51     napi_value success = NapiUtils::GetNamedProperty(GetEnv(), params[0], FetchConstant::PARAM_KEY_SUCCESS);
52     if (NapiUtils::GetValueType(GetEnv(), success) == napi_function) {
53         if (SetSuccessCallback(success) != napi_ok) {
54             NETSTACK_LOGE("SetSuccessCallback failed");
55             return;
56         }
57     }
58     napi_value fail = NapiUtils::GetNamedProperty(GetEnv(), params[0], FetchConstant::PARAM_KEY_FAIL);
59     if (NapiUtils::GetValueType(GetEnv(), fail) == napi_function) {
60         if (SetFailCallback(fail) != napi_ok) {
61             NETSTACK_LOGE("SetFailCallback failed");
62             return;
63         }
64     }
65     napi_value complete = NapiUtils::GetNamedProperty(GetEnv(), params[0], FetchConstant::PARAM_KEY_COMPLETE);
66     if (NapiUtils::GetValueType(GetEnv(), complete) == napi_function) {
67         if (SetCompleteCallback(complete) != napi_ok) {
68             NETSTACK_LOGE("SetCompleteCallback failed");
69             return;
70         }
71     }
72     NETSTACK_LOGI("fetch parse OK");
73     SetParseOK(true);
74 }
75 
CheckParamsType(napi_value * params,size_t paramsCount)76 bool FetchContext::CheckParamsType(napi_value *params, size_t paramsCount)
77 {
78     if (paramsCount == 1) {
79         return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object;
80     }
81     return false;
82 }
83 
ParseHeader(napi_value optionsValue)84 void FetchContext::ParseHeader(napi_value optionsValue)
85 {
86     if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, FetchConstant::PARAM_KEY_HEADER)) {
87         return;
88     }
89     napi_value header = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, FetchConstant::PARAM_KEY_HEADER);
90     if (NapiUtils::GetValueType(GetEnv(), header) != napi_object) {
91         return;
92     }
93     auto names = NapiUtils::GetPropertyNames(GetEnv(), header);
94     std::for_each(names.begin(), names.end(), [header, this](const std::string &name) {
95         auto value = NapiUtils::GetStringPropertyUtf8(GetEnv(), header, name);
96         if (!value.empty()) {
97             request.SetHeader(CommonUtils::ToLower(name), value);
98         }
99     });
100 }
101 
ParseData(napi_value optionsValue)102 bool FetchContext::ParseData(napi_value optionsValue)
103 {
104     if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, FetchConstant::PARAM_KEY_DATA)) {
105         NETSTACK_LOGI("no extraData");
106         return true;
107     }
108     napi_value data = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, FetchConstant::PARAM_KEY_DATA);
109 
110     if (FetchExec::MethodForGet(request.GetMethod())) {
111         return GetUrlParam(data);
112     }
113     if (FetchExec::MethodForPost(request.GetMethod())) {
114         return GetRequestBody(data);
115     }
116 
117     NETSTACK_LOGE("ParseData failed, method is not supported %{public}s", request.GetMethod().c_str());
118     return false;
119 }
120 
GetRequestBody(napi_value data)121 bool FetchContext::GetRequestBody(napi_value data)
122 {
123     /* if body is empty, return false, or curl will wait for body */
124 
125     napi_valuetype type = NapiUtils::GetValueType(GetEnv(), data);
126     if (type == napi_string) {
127         auto body = NapiUtils::GetStringFromValueUtf8(GetEnv(), data);
128         if (body.empty()) {
129             NETSTACK_LOGE("body napi_string is empty");
130             return false;
131         }
132         request.SetBody(body.c_str(), body.size());
133         return true;
134     }
135     if (type == napi_object) {
136         std::string body = NapiUtils::GetStringFromValueUtf8(GetEnv(), NapiUtils::JsonStringify(GetEnv(), data));
137         if (body.empty()) {
138             NETSTACK_LOGE("body napi_object is empty");
139             return false;
140         }
141         request.SetBody(body.c_str(), body.size());
142         return true;
143     }
144 
145     NETSTACK_LOGE("Body just support string and object");
146     return false;
147 }
148 
GetUrlParam(napi_value data)149 bool FetchContext::GetUrlParam(napi_value data)
150 {
151     std::string url = request.GetUrl();
152     if (url.empty()) {
153         NETSTACK_LOGE("url is empty!");
154         return false;
155     }
156 
157     std::string param;
158     auto index = url.find(FetchConstant::HTTP_URL_PARAM_START);
159     if (index != std::string::npos) {
160         param = url.substr(index + 1);
161         url = url.substr(0, index);
162     }
163 
164     napi_valuetype type = NapiUtils::GetValueType(GetEnv(), data);
165     if (type == napi_string) {
166         std::string extraParam = NapiUtils::GetStringFromValueUtf8(GetEnv(), data);
167 
168         request.SetUrl(FetchExec::MakeUrl(url, param, extraParam));
169         return true;
170     }
171     if (type != napi_object) {
172         return true;
173     }
174 
175     std::string extraParam;
176     auto names = NapiUtils::GetPropertyNames(GetEnv(), data);
177     std::for_each(names.begin(), names.end(), [this, data, &extraParam](std::string name) {
178         auto value = NapiUtils::GetStringPropertyUtf8(GetEnv(), data, name);
179         NETSTACK_LOGI("url param name = %{public}s, value = %{public}s", name.c_str(), value.c_str());
180         if (!name.empty() && !value.empty()) {
181             bool encodeName = FetchExec::EncodeUrlParam(name);
182             bool encodeValue = FetchExec::EncodeUrlParam(value);
183             if (encodeName || encodeValue) {
184                 request.SetHeader(CommonUtils::ToLower(FetchConstant::HTTP_CONTENT_TYPE),
185                                   FetchConstant::HTTP_CONTENT_TYPE_URL_ENCODE);
186             }
187             extraParam +=
188                 name + FetchConstant::HTTP_URL_NAME_VALUE_SEPARATOR + value + FetchConstant::HTTP_URL_PARAM_SEPARATOR;
189         }
190     });
191     if (!extraParam.empty()) {
192         extraParam.pop_back(); // remove the last &
193     }
194 
195     request.SetUrl(FetchExec::MakeUrl(url, param, extraParam));
196     return true;
197 }
198 
SetSuccessCallback(napi_value callback)199 napi_status FetchContext::SetSuccessCallback(napi_value callback)
200 {
201     if (successCallback_ != nullptr) {
202         (void)napi_delete_reference(GetEnv(), successCallback_);
203     }
204     return napi_create_reference(GetEnv(), callback, 1, &successCallback_);
205 }
206 
SetFailCallback(napi_value callback)207 napi_status FetchContext::SetFailCallback(napi_value callback)
208 {
209     if (failCallback_ != nullptr) {
210         (void)napi_delete_reference(GetEnv(), failCallback_);
211     }
212     return napi_create_reference(GetEnv(), callback, 1, &failCallback_);
213 }
214 
SetCompleteCallback(napi_value callback)215 napi_status FetchContext::SetCompleteCallback(napi_value callback)
216 {
217     if (completeCallback_ != nullptr) {
218         (void)napi_delete_reference(GetEnv(), completeCallback_);
219     }
220     return napi_create_reference(GetEnv(), callback, 1, &completeCallback_);
221 }
222 
GetSuccessCallback() const223 napi_value FetchContext::GetSuccessCallback() const
224 {
225     if (successCallback_ == nullptr) {
226         return nullptr;
227     }
228     napi_value callback = nullptr;
229     NAPI_CALL(GetEnv(), napi_get_reference_value(GetEnv(), successCallback_, &callback));
230     return callback;
231 }
232 
GetFailCallback() const233 napi_value FetchContext::GetFailCallback() const
234 {
235     if (failCallback_ == nullptr) {
236         return nullptr;
237     }
238     napi_value callback = nullptr;
239     NAPI_CALL(GetEnv(), napi_get_reference_value(GetEnv(), failCallback_, &callback));
240     return callback;
241 }
242 
GetCompleteCallback() const243 napi_value FetchContext::GetCompleteCallback() const
244 {
245     if (completeCallback_ == nullptr) {
246         return nullptr;
247     }
248     napi_value callback = nullptr;
249     NAPI_CALL(GetEnv(), napi_get_reference_value(GetEnv(), completeCallback_, &callback));
250     return callback;
251 }
252 
GetResponseType() const253 std::string FetchContext::GetResponseType() const
254 {
255     return responseType_;
256 }
257 } // namespace OHOS::NetStack
258