1 /*
2 * Copyright (c) 2021-2024 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 "request_context.h"
17
18 #include <algorithm>
19 #include <atomic>
20 #include <limits>
21 #include <string>
22 #include <utility>
23 #include <sstream>
24
25 #include "constant.h"
26 #include "http_exec.h"
27 #include "http_tls_config.h"
28 #include "napi_utils.h"
29 #include "netstack_common_utils.h"
30 #include "netstack_log.h"
31 #include "request_tracer.h"
32 #include "secure_char.h"
33 #include "timing.h"
34 #if HAS_NETMANAGER_BASE
35 #include "http_network_message.h"
36 #endif
37 #ifdef HTTP_HANDOVER_FEATURE
38 #include "http_handover_handler.h"
39 #endif
40
41 static constexpr const int PARAM_JUST_URL = 1;
42
43 static constexpr const int PARAM_JUST_URL_OR_CALLBACK = 1;
44
45 static constexpr const int PARAM_URL_AND_OPTIONS_OR_CALLBACK = 2;
46
47 static constexpr const int PARAM_URL_AND_OPTIONS_AND_CALLBACK = 3;
48
49 static constexpr const uint32_t DNS_SERVER_SIZE = 3;
50
51 static constexpr size_t CADATA_STRING_MAX_LENGTH = 8000;
52 namespace OHOS::NetStack::Http {
53 static const std::map<int32_t, const char *> HTTP_ERR_MAP = {
54 {HTTP_UNSUPPORTED_PROTOCOL, "Unsupported protocol"},
55 {HTTP_URL_MALFORMAT, "URL using bad/illegal format or missing URL"},
56 {HTTP_COULDNT_RESOLVE_PROXY, "Couldn't resolve proxy name"},
57 {HTTP_COULDNT_RESOLVE_HOST, "Couldn't resolve host name"},
58 {HTTP_COULDNT_CONNECT, "Couldn't connect to server"},
59 {HTTP_WEIRD_SERVER_REPLY, "Weird server reply"},
60 {HTTP_REMOTE_ACCESS_DENIED, "Access denied to remote resource"},
61 {HTTP_HTTP2_ERROR, "Error in the HTTP2 framing layer"},
62 {HTTP_PARTIAL_FILE, "Transferred a partial file"},
63 {HTTP_WRITE_ERROR, "Failed writing received data to disk/application"},
64 {HTTP_UPLOAD_FAILED, "Upload failed"},
65 {HTTP_READ_ERROR, "Failed to open/read local data from file/application"},
66 {HTTP_OUT_OF_MEMORY, "Out of memory"},
67 {HTTP_OPERATION_TIMEDOUT, "Timeout was reached"},
68 {HTTP_TOO_MANY_REDIRECTS, "Number of redirects hit maximum amount"},
69 {HTTP_GOT_NOTHING, "Server returned nothing (no headers, no data)"},
70 {HTTP_SEND_ERROR, "Failed sending data to the peer"},
71 {HTTP_RECV_ERROR, "Failure when receiving data from the peer"},
72 {HTTP_SSL_CERTPROBLEM, "Problem with the local SSL certificate"},
73 {HTTP_SSL_CIPHER, "Couldn't use specified SSL cipher"},
74 {HTTP_PEER_FAILED_VERIFICATION, "SSL peer certificate or SSH remote key was not OK"},
75 {HTTP_BAD_CONTENT_ENCODING, "Unrecognized or bad HTTP Content or Transfer-Encoding"},
76 {HTTP_FILESIZE_EXCEEDED, "Maximum file size exceeded"},
77 {HTTP_REMOTE_DISK_FULL, "Disk full or allocation exceeded"},
78 {HTTP_REMOTE_FILE_EXISTS, "Remote file already exists"},
79 {HTTP_SSL_CACERT_BADFILE, "Problem with the SSL CA cert (path? access rights?)"},
80 {HTTP_REMOTE_FILE_NOT_FOUND, "Remote file not found"},
81 {HTTP_AUTH_ERROR, "An authentication function returned an error"},
82 {HTTP_SSL_PINNEDPUBKEYNOTMATCH, "Specified pinned public key did not match"},
83 {HTTP_CLEARTEXT_NOT_PERMITTED, "Cleartext traffic is not permitted"},
84 {HTTP_NOT_ALLOWED_HOST, "It is not allowed to access this domain"},
85 {HTTP_UNKNOWN_OTHER_ERROR, "Unknown Other Error"},
86 };
87 static std::atomic<int32_t> g_currentTaskId = std::numeric_limits<int32_t>::min();
RequestContext(napi_env env,const std::shared_ptr<EventManager> & manager)88 RequestContext::RequestContext(napi_env env, const std::shared_ptr<EventManager> &manager)
89 : BaseContext(env, manager),
90 taskId_(g_currentTaskId++),
91 usingCache_(true),
92 requestInStream_(false),
93 curlHeaderList_(nullptr),
94 multipart_(nullptr),
95 curlHostList_(nullptr),
96 isAtomicService_(false),
97 bundleName_(""),
98 trace_("HttpRequest_" + std::to_string(taskId_))
99 {
100 StartTiming();
101 #if HAS_NETMANAGER_BASE
102 networkProfilerUtils_ = std::make_unique<NetworkProfilerUtils>();
103 #endif
104 }
105
StartTiming()106 void RequestContext::StartTiming()
107 {
108 time_t startTime = Timing::TimeUtils::GetNowTimeMicroseconds();
109 timerMap_.RecieveTimer(HttpConstant::RESPONSE_HEADER_TIMING).Start(startTime);
110 timerMap_.RecieveTimer(HttpConstant::RESPONSE_BODY_TIMING).Start(startTime);
111 timerMap_.RecieveTimer(HttpConstant::RESPONSE_TOTAL_TIMING).Start(startTime);
112
113 // init RESPONSE_HEADER_TIMING and RESPONSE_BODY_TIMING
114 performanceTimingMap_[HttpConstant::RESPONSE_HEADER_TIMING] = 0.0;
115 performanceTimingMap_[HttpConstant::RESPONSE_BODY_TIMING] = 0.0;
116 }
117
ParseParams(napi_value * params,size_t paramsCount)118 void RequestContext::ParseParams(napi_value *params, size_t paramsCount)
119 {
120 bool valid = CheckParamsType(params, paramsCount);
121 if (!valid) {
122 if (paramsCount == PARAM_JUST_URL_OR_CALLBACK) {
123 if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_function) {
124 SetCallback(params[0]);
125 }
126 return;
127 }
128 if (paramsCount == PARAM_URL_AND_OPTIONS_OR_CALLBACK) {
129 if (NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function) {
130 SetCallback(params[1]);
131 }
132 return;
133 }
134 if (paramsCount == PARAM_URL_AND_OPTIONS_AND_CALLBACK) {
135 if (NapiUtils::GetValueType(GetEnv(), params[PARAM_URL_AND_OPTIONS_AND_CALLBACK - 1]) == napi_function) {
136 SetCallback(params[PARAM_URL_AND_OPTIONS_AND_CALLBACK - 1]);
137 }
138 return;
139 }
140 return;
141 }
142
143 if (paramsCount == PARAM_JUST_URL) {
144 options.SetUrl(NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0]));
145 SetParseOK(true);
146 return;
147 }
148
149 if (paramsCount == PARAM_URL_AND_OPTIONS_OR_CALLBACK) {
150 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), params[1]);
151 if (type == napi_function) {
152 options.SetUrl(NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0]));
153 SetParseOK(SetCallback(params[1]) == napi_ok);
154 return;
155 }
156 if (type == napi_object) {
157 UrlAndOptions(params[0], params[1]);
158 return;
159 }
160 return;
161 }
162
163 if (paramsCount == PARAM_URL_AND_OPTIONS_AND_CALLBACK) {
164 if (SetCallback(params[PARAM_URL_AND_OPTIONS_AND_CALLBACK - 1]) != napi_ok) {
165 return;
166 }
167 UrlAndOptions(params[0], params[1]);
168 }
169 }
170
CheckParamsType(napi_value * params,size_t paramsCount)171 bool RequestContext::CheckParamsType(napi_value *params, size_t paramsCount)
172 {
173 if (paramsCount == PARAM_JUST_URL) {
174 // just url
175 return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string;
176 }
177 if (paramsCount == PARAM_URL_AND_OPTIONS_OR_CALLBACK) {
178 // should be url, callback or url, options
179 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), params[1]);
180 return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string &&
181 (type == napi_function || type == napi_object);
182 }
183 if (paramsCount == PARAM_URL_AND_OPTIONS_AND_CALLBACK) {
184 // should be url options and callback
185 return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string &&
186 NapiUtils::GetValueType(GetEnv(), params[1]) == napi_object &&
187 NapiUtils::GetValueType(GetEnv(), params[PARAM_URL_AND_OPTIONS_AND_CALLBACK - 1]) == napi_function;
188 }
189 return false;
190 }
191
ParseNumberOptions(napi_value optionsValue)192 void RequestContext::ParseNumberOptions(napi_value optionsValue)
193 {
194 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_READ_TIMEOUT)) {
195 options.SetReadTimeout(
196 NapiUtils::GetUint32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_READ_TIMEOUT));
197 }
198
199 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_MAX_LIMIT)) {
200 options.SetMaxLimit(NapiUtils::GetUint32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_MAX_LIMIT));
201 }
202
203 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CONNECT_TIMEOUT)) {
204 options.SetConnectTimeout(
205 NapiUtils::GetUint32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CONNECT_TIMEOUT));
206 }
207
208 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_CACHE)) {
209 napi_value value = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_CACHE);
210 if (NapiUtils::GetValueType(GetEnv(), value) == napi_boolean) {
211 usingCache_ = NapiUtils::GetBooleanFromValue(GetEnv(), value);
212 }
213 }
214
215 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_PROTOCOL)) {
216 napi_value value = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_PROTOCOL);
217 if (NapiUtils::GetValueType(GetEnv(), value) == napi_number) {
218 uint32_t number = NapiUtils::GetUint32FromValue(GetEnv(), value);
219 if (number == static_cast<uint32_t>(HttpProtocol::HTTP1_1) ||
220 number == static_cast<uint32_t>(HttpProtocol::HTTP2) ||
221 number == static_cast<uint32_t>(HttpProtocol::HTTP3)) {
222 options.SetUsingProtocol(static_cast<HttpProtocol>(number));
223 }
224 }
225 }
226 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_EXPECT_DATA_TYPE)) {
227 napi_value value =
228 NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_EXPECT_DATA_TYPE);
229 if (NapiUtils::GetValueType(GetEnv(), value) == napi_number) {
230 uint32_t type = NapiUtils::GetUint32FromValue(GetEnv(), value);
231 options.SetHttpDataType(static_cast<HttpDataType>(type));
232 }
233 }
234
235 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_PRIORITY)) {
236 napi_value value = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_PRIORITY);
237 if (NapiUtils::GetValueType(GetEnv(), value) == napi_number) {
238 uint32_t priority = NapiUtils::GetUint32FromValue(GetEnv(), value);
239 options.SetPriority(priority);
240 }
241 }
242 }
243
ParseRemoteValidationMode(napi_value optionsValue)244 void RequestContext::ParseRemoteValidationMode(napi_value optionsValue)
245 {
246 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_REMOTE_VALIDATION)) {
247 NETSTACK_LOGD("no remote validation mode config");
248 return;
249 }
250 napi_value value = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_REMOTE_VALIDATION);
251 if (NapiUtils::GetValueType(GetEnv(), value) == napi_string) {
252 auto remoteValidationMode = NapiUtils::GetStringFromValueUtf8(GetEnv(), value);
253 if (remoteValidationMode == "skip") {
254 NETSTACK_LOGI("ParseRemoteValidationMode remoteValidationMode skip");
255 options.SetCanSkipCertVerifyFlag(true);
256 } else if (remoteValidationMode != "system") {
257 NETSTACK_LOGE("RemoteValidationMode config error");
258 }
259 }
260 }
261
ParseTlsOption(napi_value optionsValue)262 void RequestContext::ParseTlsOption(napi_value optionsValue)
263 {
264 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_TLS_OPTION)) {
265 NETSTACK_LOGD("no tls config");
266 return;
267 }
268 napi_value tlsVersionValue = NapiUtils::GetNamedProperty(
269 GetEnv(), optionsValue, HttpConstant::PARAM_KEY_TLS_OPTION);
270 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), tlsVersionValue);
271 if (type != napi_object && type != napi_string) {
272 NETSTACK_LOGE("tlsVersionValue type error");
273 return;
274 }
275 uint32_t tlsVersionMin = NapiUtils::GetUint32Property(GetEnv(), tlsVersionValue, "tlsVersionMin");
276 uint32_t tlsVersionMax = NapiUtils::GetUint32Property(GetEnv(), tlsVersionValue, "tlsVersionMax");
277 NETSTACK_LOGD("tlsVersionMin = %{public}d, tlsVersionMax = %{public}d", tlsVersionMin, tlsVersionMax);
278 TlsOption tlsOption;
279 tlsOption.tlsVersionMin = static_cast<TlsVersion>(tlsVersionMin);
280 tlsOption.tlsVersionMax = static_cast<TlsVersion>(tlsVersionMax);
281 if (!NapiUtils::HasNamedProperty(GetEnv(), tlsVersionValue, "cipherSuites")) {
282 NETSTACK_LOGD("no cipherSuites");
283 options.SetTlsOption(tlsOption);
284 return;
285 }
286 auto cipherSuiteNapi = NapiUtils::GetNamedProperty(GetEnv(), tlsVersionValue, "cipherSuites");
287 if (!NapiUtils::IsArray(GetEnv(), cipherSuiteNapi)) {
288 options.SetTlsOption(tlsOption);
289 return;
290 }
291 auto length = NapiUtils::GetArrayLength(GetEnv(), cipherSuiteNapi);
292 for (uint32_t i = 0; i < length; ++i) {
293 auto standardNameNapi = NapiUtils::GetArrayElement(GetEnv(), cipherSuiteNapi, i);
294 auto cipherSuite = GetTlsCipherSuiteFromStandardName(
295 NapiUtils::GetStringFromValueUtf8(GetEnv(), standardNameNapi));
296 if (cipherSuite != CipherSuite::INVALID) {
297 tlsOption.cipherSuite.emplace(cipherSuite);
298 }
299 }
300
301 options.SetTlsOption(tlsOption);
302 }
303
ParseServerAuthentication(napi_value optionsValue)304 void RequestContext::ParseServerAuthentication(napi_value optionsValue)
305 {
306 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_SERVER_AUTH)) {
307 NETSTACK_LOGD("no server authentication config");
308 return;
309 }
310 napi_value serverAuthenticationValue = NapiUtils::GetNamedProperty(
311 GetEnv(), optionsValue, HttpConstant::PARAM_KEY_SERVER_AUTH);
312 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), serverAuthenticationValue);
313 if (type != napi_object) {
314 NETSTACK_LOGE("server authentication type error");
315 return;
316 }
317 ServerAuthentication serverAuthentication;
318 auto credentialNapi = NapiUtils::GetNamedProperty(GetEnv(), serverAuthenticationValue, "credential");
319 NapiUtils::GetSecureDataPropertyUtf8(GetEnv(),
320 credentialNapi, "username", serverAuthentication.credential.username);
321 NapiUtils::GetSecureDataPropertyUtf8(GetEnv(),
322 credentialNapi, "password", serverAuthentication.credential.password);
323 auto authenticationType = NapiUtils::GetStringPropertyUtf8(GetEnv(),
324 serverAuthenticationValue, "authenticationType");
325 if (authenticationType == "basic") {
326 serverAuthentication.authenticationType = AuthenticationType::BASIC;
327 } else if (authenticationType == "ntlm") {
328 serverAuthentication.authenticationType = AuthenticationType::NTLM;
329 } else if (authenticationType == "digest") {
330 serverAuthentication.authenticationType = AuthenticationType::DIGEST;
331 }
332 options.SetServerAuthentication(serverAuthentication);
333 }
334
ParseHeader(napi_value optionsValue)335 void RequestContext::ParseHeader(napi_value optionsValue)
336 {
337 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_HEADER)) {
338 return;
339 }
340 napi_value header = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_HEADER);
341 if (NapiUtils::GetValueType(GetEnv(), header) != napi_object) {
342 return;
343 }
344 if (HttpExec::MethodForPost(options.GetMethod())) {
345 options.SetHeader(CommonUtils::ToLower(HttpConstant::HTTP_CONTENT_TYPE),
346 HttpConstant::HTTP_CONTENT_TYPE_JSON); // default
347 }
348 auto names = NapiUtils::GetPropertyNames(GetEnv(), header);
349 std::for_each(names.begin(), names.end(), [header, this](const std::string &name) {
350 napi_value value = NapiUtils::GetNamedProperty(GetEnv(), header, name);
351 std::string valueStr = NapiUtils::NapiValueToString(GetEnv(), value);
352 options.SetHeader(CommonUtils::ToLower(name), valueStr);
353 });
354 }
355
HandleMethodForGet(napi_value extraData)356 bool RequestContext::HandleMethodForGet(napi_value extraData)
357 {
358 std::string url = options.GetUrl();
359 std::string param;
360 auto index = url.find(HttpConstant::HTTP_URL_PARAM_START);
361 if (index != std::string::npos) {
362 param = url.substr(index + 1);
363 url.resize(index);
364 }
365
366 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), extraData);
367 if (type == napi_string) {
368 std::string extraParam = NapiUtils::GetStringFromValueUtf8(GetEnv(), extraData);
369
370 options.SetUrl(HttpExec::MakeUrl(url, param, extraParam));
371 return true;
372 }
373 if (type != napi_object) {
374 return true;
375 }
376
377 std::string extraParam;
378 auto names = NapiUtils::GetPropertyNames(GetEnv(), extraData);
379 std::for_each(names.begin(), names.end(), [this, extraData, &extraParam](std::string name) {
380 auto value = NapiUtils::GetStringPropertyUtf8(GetEnv(), extraData, name);
381 if (!name.empty() && !value.empty()) {
382 bool encodeName = HttpExec::EncodeUrlParam(name);
383 bool encodeValue = HttpExec::EncodeUrlParam(value);
384 if (encodeName || encodeValue) {
385 options.SetHeader(CommonUtils::ToLower(HttpConstant::HTTP_CONTENT_TYPE),
386 HttpConstant::HTTP_CONTENT_TYPE_URL_ENCODE);
387 }
388 extraParam +=
389 name + HttpConstant::HTTP_URL_NAME_VALUE_SEPARATOR + value + HttpConstant::HTTP_URL_PARAM_SEPARATOR;
390 }
391 });
392 if (!extraParam.empty()) {
393 extraParam.pop_back(); // remove the last &
394 }
395
396 options.SetUrl(HttpExec::MakeUrl(url, param, extraParam));
397 return true;
398 }
399
ParseExtraData(napi_value optionsValue)400 bool RequestContext::ParseExtraData(napi_value optionsValue)
401 {
402 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_EXTRA_DATA)) {
403 NETSTACK_LOGD("no extraData");
404 return true;
405 }
406
407 napi_value extraData = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_EXTRA_DATA);
408 if (NapiUtils::GetValueType(GetEnv(), extraData) == napi_undefined ||
409 NapiUtils::GetValueType(GetEnv(), extraData) == napi_null) {
410 NETSTACK_LOGD("extraData is undefined or null");
411 return true;
412 }
413
414 if (HttpExec::MethodForGet(options.GetMethod())) {
415 return HandleMethodForGet(extraData);
416 }
417
418 if (HttpExec::MethodForPost(options.GetMethod())) {
419 return GetRequestBody(extraData);
420 }
421 return false;
422 }
423
ParseUsingHttpProxy(napi_value optionsValue)424 void RequestContext::ParseUsingHttpProxy(napi_value optionsValue)
425 {
426 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_HTTP_PROXY)) {
427 NETSTACK_LOGD("Use default proxy");
428 return;
429 }
430 napi_value httpProxyValue =
431 NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_USING_HTTP_PROXY);
432 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), httpProxyValue);
433 if (type == napi_boolean) {
434 bool usingProxy = NapiUtils::GetBooleanFromValue(GetEnv(), httpProxyValue);
435 UsingHttpProxyType usingType = usingProxy ? UsingHttpProxyType::USE_DEFAULT : UsingHttpProxyType::NOT_USE;
436 options.SetUsingHttpProxyType(usingType);
437 return;
438 }
439 if (type != napi_object) {
440 return;
441 }
442 std::string host = NapiUtils::GetStringPropertyUtf8(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_HOST);
443 int32_t port = NapiUtils::GetInt32Property(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_PORT);
444 std::string exclusionList;
445 if (NapiUtils::HasNamedProperty(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_EXCLUSION_LIST)) {
446 napi_value exclusionListValue =
447 NapiUtils::GetNamedProperty(GetEnv(), httpProxyValue, HttpConstant::HTTP_PROXY_KEY_EXCLUSION_LIST);
448 uint32_t listLength = NapiUtils::GetArrayLength(GetEnv(), exclusionListValue);
449 for (uint32_t index = 0; index < listLength; ++index) {
450 napi_value exclusionValue = NapiUtils::GetArrayElement(GetEnv(), exclusionListValue, index);
451 std::string exclusion = NapiUtils::GetStringFromValueUtf8(GetEnv(), exclusionValue);
452 if (index != 0) {
453 exclusionList = exclusionList + HttpConstant::HTTP_PROXY_EXCLUSIONS_SEPARATOR;
454 }
455 exclusionList += exclusion;
456 }
457 }
458 options.SetSpecifiedHttpProxy(host, port, exclusionList);
459 options.SetUsingHttpProxyType(UsingHttpProxyType::USE_SPECIFIED);
460 }
461
GetRequestBody(napi_value extraData)462 bool RequestContext::GetRequestBody(napi_value extraData)
463 {
464 /* if body is empty, return false, or curl will wait for body */
465
466 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), extraData);
467 if (type == napi_string) {
468 auto body = NapiUtils::GetStringFromValueUtf8(GetEnv(), extraData);
469 if (body.empty()) {
470 return false;
471 }
472 options.SetBody(body.c_str(), body.size());
473 return true;
474 }
475
476 if (NapiUtils::ValueIsArrayBuffer(GetEnv(), extraData)) {
477 size_t length = 0;
478 void *data = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), extraData, &length);
479 if (data == nullptr) {
480 return false;
481 }
482 options.SetBody(data, length);
483 return true;
484 }
485
486 if (type == napi_object) {
487 std::string body = NapiUtils::GetStringFromValueUtf8(GetEnv(), NapiUtils::JsonStringify(GetEnv(), extraData));
488 if (body.empty()) {
489 return false;
490 }
491 options.SetBody(body.c_str(), body.length());
492 return true;
493 }
494
495 NETSTACK_LOGE("only support string arraybuffer and object");
496 return false;
497 }
498
ParseCaPath(napi_value optionsValue)499 void RequestContext::ParseCaPath(napi_value optionsValue)
500 {
501 std::string caPath = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CA_PATH);
502 if (!caPath.empty()) {
503 options.SetCaPath(caPath);
504 }
505 }
506
ParseCaData(napi_value optionsValue)507 void RequestContext::ParseCaData(napi_value optionsValue)
508 {
509 std::string caPath = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CA_PATH);
510 std::string caData = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CA_DATA);
511 if (caPath.empty() && !caData.empty() && caData.size() < CADATA_STRING_MAX_LENGTH) {
512 options.SetCaData(caData);
513 }
514 }
515
ParseDohUrl(napi_value optionsValue)516 void RequestContext::ParseDohUrl(napi_value optionsValue)
517 {
518 std::string dohUrl = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_DOH_URL);
519 if (!dohUrl.empty()) {
520 options.SetDohUrl(dohUrl);
521 }
522 }
523
ParseResumeFromToNumber(napi_value optionsValue)524 void RequestContext::ParseResumeFromToNumber(napi_value optionsValue)
525 {
526 napi_env env = GetEnv();
527 int64_t from = NapiUtils::GetInt64Property(env, optionsValue, HttpConstant::PARAM_KEY_RESUME_FROM);
528 int64_t to = NapiUtils::GetInt64Property(env, optionsValue, HttpConstant::PARAM_KEY_RESUME_TO);
529 options.SetRangeNumber(from, to);
530 }
531
UrlAndOptions(napi_value urlValue,napi_value optionsValue)532 void RequestContext::UrlAndOptions(napi_value urlValue, napi_value optionsValue)
533 {
534 options.SetUrl(NapiUtils::GetStringFromValueUtf8(GetEnv(), urlValue));
535
536 if (NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_METHOD)) {
537 napi_value requestMethod = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_METHOD);
538 if (NapiUtils::GetValueType(GetEnv(), requestMethod) == napi_string) {
539 options.SetMethod(NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_METHOD));
540 }
541 }
542
543 ParseNumberOptions(optionsValue);
544 ParseUsingHttpProxy(optionsValue);
545 ParseClientCert(optionsValue);
546
547 /* parse extra data here to recover header */
548 if (!ParseExtraData(optionsValue)) {
549 return;
550 }
551
552 ParseHeader(optionsValue);
553 ParseCaPath(optionsValue);
554 ParseCaData(optionsValue);
555 ParseDohUrl(optionsValue);
556 ParseResumeFromToNumber(optionsValue);
557 ParseDnsServers(optionsValue);
558 ParseMultiFormData(optionsValue);
559 ParseCertificatePinning(optionsValue);
560 ParseRemoteValidationMode(optionsValue);
561 ParseTlsOption(optionsValue);
562 ParseServerAuthentication(optionsValue);
563 SetParseOK(true);
564 ParseAddressFamily(optionsValue);
565 }
566
IsUsingCache() const567 bool RequestContext::IsUsingCache() const
568 {
569 return usingCache_;
570 }
571
SetCurlHeaderList(curl_slist * curlHeaderList)572 void RequestContext::SetCurlHeaderList(curl_slist *curlHeaderList)
573 {
574 curlHeaderList_ = curlHeaderList;
575 }
576
GetCurlHeaderList()577 curl_slist *RequestContext::GetCurlHeaderList()
578 {
579 return curlHeaderList_;
580 }
581
SetCurlHostList(curl_slist * curlHostList)582 void RequestContext::SetCurlHostList(curl_slist *curlHostList)
583 {
584 curlHostList_ = curlHostList;
585 }
586
GetCurlHostList()587 curl_slist *RequestContext::GetCurlHostList()
588 {
589 return curlHostList_;
590 }
591
~RequestContext()592 RequestContext::~RequestContext()
593 {
594 trace_.Finish();
595 if (curlHeaderList_ != nullptr) {
596 curl_slist_free_all(curlHeaderList_);
597 }
598 if (curlHostList_ != nullptr) {
599 curl_slist_free_all(curlHostList_);
600 }
601 if (multipart_ != nullptr) {
602 curl_mime_free(multipart_);
603 multipart_ = nullptr;
604 }
605 NETSTACK_LOGD("the destructor of request context is invoked");
606 }
607
SetCacheResponse(const HttpResponse & cacheResponse)608 void RequestContext::SetCacheResponse(const HttpResponse &cacheResponse)
609 {
610 cacheResponse_ = cacheResponse;
611 }
SetResponseByCache()612 void RequestContext::SetResponseByCache()
613 {
614 response = cacheResponse_;
615 }
616
GetErrorCode() const617 int32_t RequestContext::GetErrorCode() const
618 {
619 auto err = BaseContext::GetErrorCode();
620 if (err == PARSE_ERROR_CODE) {
621 return PARSE_ERROR_CODE;
622 }
623
624 if (BaseContext::IsPermissionDenied()) {
625 return PERMISSION_DENIED_CODE;
626 }
627
628 if (BaseContext::IsNoAllowedHost()) {
629 return HTTP_NOT_ALLOWED_HOST;
630 }
631
632 if (BaseContext::IsCleartextNotPermitted()) {
633 return HTTP_CLEARTEXT_NOT_PERMITTED;
634 }
635
636 if (HTTP_ERR_MAP.find(err + HTTP_ERROR_CODE_BASE) != HTTP_ERR_MAP.end()) {
637 return err + HTTP_ERROR_CODE_BASE;
638 }
639 return HTTP_UNKNOWN_OTHER_ERROR;
640 }
641
GetErrorMessage() const642 std::string RequestContext::GetErrorMessage() const
643 {
644 auto err = BaseContext::GetErrorCode();
645 if (err == PARSE_ERROR_CODE) {
646 return PARSE_ERROR_MSG;
647 }
648
649 if (BaseContext::IsPermissionDenied()) {
650 return PERMISSION_DENIED_MSG;
651 }
652
653 if (BaseContext::IsNoAllowedHost()) {
654 return HTTP_ERR_MAP.at(HTTP_NOT_ALLOWED_HOST);
655 }
656
657 if (BaseContext::IsCleartextNotPermitted()) {
658 return HTTP_ERR_MAP.at(HTTP_CLEARTEXT_NOT_PERMITTED);
659 }
660
661 auto pos = HTTP_ERR_MAP.find(err + HTTP_ERROR_CODE_BASE);
662 if (pos != HTTP_ERR_MAP.end()) {
663 return pos->second;
664 }
665 return HTTP_ERR_MAP.at(HTTP_UNKNOWN_OTHER_ERROR);
666 }
667
EnableRequestInStream()668 void RequestContext::EnableRequestInStream()
669 {
670 requestInStream_ = true;
671 }
672
IsRequestInStream() const673 bool RequestContext::IsRequestInStream() const
674 {
675 return requestInStream_;
676 }
677
SetDlLen(curl_off_t nowLen,curl_off_t totalLen)678 void RequestContext::SetDlLen(curl_off_t nowLen, curl_off_t totalLen)
679 {
680 std::lock_guard<std::mutex> lock(dlLenLock_);
681 LoadBytes dlBytes{nowLen, totalLen};
682 dlBytes_.push(dlBytes);
683 }
684
SetCertsPath(std::vector<std::string> && certPathList,const std::string & certFile)685 void RequestContext::SetCertsPath(std::vector<std::string> &&certPathList, const std::string &certFile)
686 {
687 certsPath_.certPathList = std::move(certPathList);
688 certsPath_.certFile = certFile;
689 }
690
GetCertsPath()691 const CertsPath &RequestContext::GetCertsPath()
692 {
693 return certsPath_;
694 }
695
GetDlLen()696 LoadBytes RequestContext::GetDlLen()
697 {
698 std::lock_guard<std::mutex> lock(dlLenLock_);
699 LoadBytes dlBytes;
700 if (!dlBytes_.empty()) {
701 dlBytes.nLen = dlBytes_.front().nLen;
702 dlBytes.tLen = dlBytes_.front().tLen;
703 dlBytes_.pop();
704 }
705 return dlBytes;
706 }
707
SetUlLen(curl_off_t nowLen,curl_off_t totalLen)708 void RequestContext::SetUlLen(curl_off_t nowLen, curl_off_t totalLen)
709 {
710 std::lock_guard<std::mutex> lock(ulLenLock_);
711 if (!ulBytes_.empty()) {
712 ulBytes_.pop();
713 }
714 LoadBytes ulBytes{nowLen, totalLen};
715 ulBytes_.push(ulBytes);
716 }
717
GetUlLen()718 LoadBytes RequestContext::GetUlLen()
719 {
720 std::lock_guard<std::mutex> lock(ulLenLock_);
721 LoadBytes ulBytes;
722 if (!ulBytes_.empty()) {
723 ulBytes.nLen = ulBytes_.back().nLen;
724 ulBytes.tLen = ulBytes_.back().tLen;
725 }
726 return ulBytes;
727 }
728
CompareWithLastElement(curl_off_t nowLen,curl_off_t totalLen)729 bool RequestContext::CompareWithLastElement(curl_off_t nowLen, curl_off_t totalLen)
730 {
731 std::lock_guard<std::mutex> lock(ulLenLock_);
732 if (ulBytes_.empty()) {
733 return false;
734 }
735 const LoadBytes &lastElement = ulBytes_.back();
736 return nowLen == lastElement.nLen && totalLen == lastElement.tLen;
737 }
738
SetTempData(const void * data,size_t size)739 void RequestContext::SetTempData(const void *data, size_t size)
740 {
741 std::lock_guard<std::mutex> lock(tempDataLock_);
742 std::string tempString;
743 tempString.append(reinterpret_cast<const char *>(data), size);
744 tempData_.push(tempString);
745 }
746
GetTempData()747 std::string RequestContext::GetTempData()
748 {
749 std::lock_guard<std::mutex> lock(tempDataLock_);
750 if (!tempData_.empty()) {
751 return tempData_.front();
752 }
753 return {};
754 }
755
PopTempData()756 void RequestContext::PopTempData()
757 {
758 std::lock_guard<std::mutex> lock(tempDataLock_);
759 if (!tempData_.empty()) {
760 tempData_.pop();
761 }
762 }
763
ParseDnsServers(napi_value optionsValue)764 void RequestContext::ParseDnsServers(napi_value optionsValue)
765 {
766 napi_env env = GetEnv();
767 if (!NapiUtils::HasNamedProperty(env, optionsValue, HttpConstant::PARAM_KEY_DNS_SERVERS)) {
768 NETSTACK_LOGD("ParseDnsServers no data");
769 return;
770 }
771 napi_value dnsServerValue = NapiUtils::GetNamedProperty(env, optionsValue, HttpConstant::PARAM_KEY_DNS_SERVERS);
772 if (NapiUtils::GetValueType(env, dnsServerValue) != napi_object) {
773 return;
774 }
775 uint32_t dnsLength = NapiUtils::GetArrayLength(env, dnsServerValue);
776 if (dnsLength == 0) {
777 return;
778 }
779 std::vector<std::string> dnsServers;
780 uint32_t dnsSize = 0;
781 for (uint32_t i = 0; i < dnsLength && dnsSize < DNS_SERVER_SIZE; i++) {
782 napi_value element = NapiUtils::GetArrayElement(env, dnsServerValue, i);
783 std::string dnsServer = NapiUtils::GetStringFromValueUtf8(env, element);
784 if (dnsServer.length() == 0) {
785 continue;
786 }
787 if (!CommonUtils::IsValidIPV4(dnsServer) && !CommonUtils::IsValidIPV6(dnsServer)) {
788 continue;
789 }
790 dnsServers.push_back(dnsServer);
791 dnsSize++;
792 }
793 if (dnsSize == 0 || dnsServers.data() == nullptr || dnsServers.empty()) {
794 NETSTACK_LOGD("dnsServersArray is empty.");
795 return;
796 }
797 options.SetDnsServers(dnsServers);
798 NETSTACK_LOGD("SetDnsServers success");
799 }
800
CachePerformanceTimingItem(const std::string & key,double value)801 void RequestContext::CachePerformanceTimingItem(const std::string &key, double value)
802 {
803 performanceTimingMap_[key] = value;
804 }
805
StopAndCacheNapiPerformanceTiming(const char * key)806 void RequestContext::StopAndCacheNapiPerformanceTiming(const char *key)
807 {
808 Timing::Timer &timer = timerMap_.RecieveTimer(key);
809 timer.Stop();
810 CachePerformanceTimingItem(key, timer.Elapsed());
811 }
812
SetPerformanceTimingToResult(napi_value result)813 void RequestContext::SetPerformanceTimingToResult(napi_value result)
814 {
815 if (performanceTimingMap_.empty()) {
816 NETSTACK_LOGD("Get performanceTiming data is empty.");
817 return;
818 }
819 napi_value performanceTimingValue;
820 napi_env env = GetEnv();
821 napi_create_object(env, &performanceTimingValue);
822 for (const auto &pair : performanceTimingMap_) {
823 NapiUtils::SetDoubleProperty(env, performanceTimingValue, pair.first, pair.second);
824 }
825 NapiUtils::SetNamedProperty(env, result, HttpConstant::RESPONSE_PERFORMANCE_TIMING, performanceTimingValue);
826 }
827
ParseClientCert(napi_value optionsValue)828 void RequestContext::ParseClientCert(napi_value optionsValue)
829 {
830 if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CLIENT_CERT)) {
831 return;
832 }
833 napi_value clientCertValue =
834 NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CLIENT_CERT);
835 napi_valuetype type = NapiUtils::GetValueType(GetEnv(), clientCertValue);
836 if (type != napi_object) {
837 return;
838 }
839 std::string cert = NapiUtils::GetStringPropertyUtf8(GetEnv(), clientCertValue, HttpConstant::HTTP_CLIENT_CERT);
840 std::string certType =
841 NapiUtils::GetStringPropertyUtf8(GetEnv(), clientCertValue, HttpConstant::HTTP_CLIENT_CERT_TYPE);
842 std::string key = NapiUtils::GetStringPropertyUtf8(GetEnv(), clientCertValue, HttpConstant::HTTP_CLIENT_KEY);
843 Secure::SecureChar keyPasswd = Secure::SecureChar(
844 NapiUtils::GetStringPropertyUtf8(GetEnv(), clientCertValue, HttpConstant::HTTP_CLIENT_KEY_PASSWD));
845 options.SetClientCert(cert, certType, key, keyPasswd);
846 }
847
ParseMultiFormData(napi_value optionsValue)848 void RequestContext::ParseMultiFormData(napi_value optionsValue)
849 {
850 napi_env env = GetEnv();
851 if (!NapiUtils::HasNamedProperty(env, optionsValue, HttpConstant::PARAM_KEY_MULTI_FORM_DATA_LIST)) {
852 NETSTACK_LOGD("ParseMultiFormData multiFormDataList is null.");
853 return;
854 }
855 napi_value multiFormDataListValue =
856 NapiUtils::GetNamedProperty(env, optionsValue, HttpConstant::PARAM_KEY_MULTI_FORM_DATA_LIST);
857 if (NapiUtils::GetValueType(env, multiFormDataListValue) != napi_object) {
858 NETSTACK_LOGE("ParseMultiFormData multiFormDataList type is not object.");
859 return;
860 }
861 uint32_t dataLength = NapiUtils::GetArrayLength(env, multiFormDataListValue);
862 if (dataLength == 0) {
863 NETSTACK_LOGD("ParseMultiFormData multiFormDataList length is 0.");
864 return;
865 }
866 for (uint32_t i = 0; i < dataLength; i++) {
867 napi_value formDataValue = NapiUtils::GetArrayElement(env, multiFormDataListValue, i);
868 MultiFormData multiFormData = NapiValue2FormData(formDataValue);
869 options.AddMultiFormData(multiFormData);
870 }
871 }
872
NapiValue2FormData(napi_value formDataValue)873 MultiFormData RequestContext::NapiValue2FormData(napi_value formDataValue)
874 {
875 napi_env env = GetEnv();
876 MultiFormData multiFormData;
877 multiFormData.name = NapiUtils::GetStringPropertyUtf8(env, formDataValue, HttpConstant::HTTP_MULTI_FORM_DATA_NAME);
878 multiFormData.contentType =
879 NapiUtils::GetStringPropertyUtf8(env, formDataValue, HttpConstant::HTTP_MULTI_FORM_DATA_CONTENT_TYPE);
880 multiFormData.remoteFileName =
881 NapiUtils::GetStringPropertyUtf8(env, formDataValue, HttpConstant::HTTP_MULTI_FORM_DATA_REMOTE_FILE_NAME);
882 RequestContext::SaveFormData(
883 env, NapiUtils::GetNamedProperty(env, formDataValue, HttpConstant::HTTP_MULTI_FORM_DATA_DATA), multiFormData);
884 multiFormData.filePath =
885 NapiUtils::GetStringPropertyUtf8(env, formDataValue, HttpConstant::HTTP_MULTI_FORM_DATA_FILE_PATH);
886 return multiFormData;
887 }
888
NapiValue2CertPinning(napi_value certPIN)889 CertificatePinning RequestContext::NapiValue2CertPinning(napi_value certPIN)
890 {
891 napi_env env = GetEnv();
892 CertificatePinning singleCertPIN;
893 auto algorithm = NapiUtils::GetStringPropertyUtf8(env, certPIN, HttpConstant::HTTP_HASH_ALGORITHM);
894 if (algorithm == "SHA-256") {
895 singleCertPIN.hashAlgorithm = HashAlgorithm::SHA256;
896 } else {
897 singleCertPIN.hashAlgorithm = HashAlgorithm::INVALID;
898 }
899
900 singleCertPIN.publicKeyHash = NapiUtils::GetStringPropertyUtf8(env, certPIN, HttpConstant::HTTP_PUBLIC_KEY_HASH);
901 return singleCertPIN;
902 }
903
SaveFormData(napi_env env,napi_value dataValue,MultiFormData & multiFormData)904 void RequestContext::SaveFormData(napi_env env, napi_value dataValue, MultiFormData &multiFormData)
905 {
906 napi_valuetype type = NapiUtils::GetValueType(env, dataValue);
907 if (type == napi_string) {
908 multiFormData.data = NapiUtils::GetStringFromValueUtf8(GetEnv(), dataValue);
909 NETSTACK_LOGD("SaveFormData string");
910 } else if (NapiUtils::ValueIsArrayBuffer(GetEnv(), dataValue)) {
911 size_t length = 0;
912 void *data = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), dataValue, &length);
913 if (data == nullptr) {
914 return;
915 }
916 multiFormData.data = std::string(static_cast<const char *>(data), length);
917 NETSTACK_LOGD("SaveFormData ArrayBuffer");
918 } else if (type == napi_object) {
919 multiFormData.data = NapiUtils::GetStringFromValueUtf8(GetEnv(), NapiUtils::JsonStringify(GetEnv(), dataValue));
920 NETSTACK_LOGD("SaveFormData Object");
921 } else {
922 NETSTACK_LOGD("only support string, ArrayBuffer and Object");
923 }
924 }
925
ParseCertificatePinning(napi_value optionsValue)926 void RequestContext::ParseCertificatePinning(napi_value optionsValue)
927 {
928 auto env = GetEnv();
929 if (!NapiUtils::HasNamedProperty(env, optionsValue, HttpConstant::PARAM_KEY_CERTIFICATE_PINNING)) {
930 NETSTACK_LOGD("NO CertificatePinning option");
931 return;
932 }
933 napi_value certificatePin =
934 NapiUtils::GetNamedProperty(env, optionsValue, HttpConstant::PARAM_KEY_CERTIFICATE_PINNING);
935 std::stringstream certPinBuilder;
936
937 if (NapiUtils::IsArray(env, certificatePin)) {
938 auto arrayLen = NapiUtils::GetArrayLength(env, certificatePin);
939 for (uint32_t i = 0; i < arrayLen; i++) {
940 napi_value certPIN = NapiUtils::GetArrayElement(env, certificatePin, i);
941 CertificatePinning singleCertPIN = NapiValue2CertPinning(certPIN);
942 if (singleCertPIN.hashAlgorithm == HashAlgorithm::SHA256) {
943 certPinBuilder << "sha256//" << singleCertPIN.publicKeyHash << ';';
944 }
945 }
946 } else {
947 CertificatePinning singleCertPIN = NapiValue2CertPinning(certificatePin);
948 if (singleCertPIN.hashAlgorithm == HashAlgorithm::SHA256) {
949 certPinBuilder << "sha256//" << singleCertPIN.publicKeyHash << ';';
950 }
951 }
952
953 std::string pinRes = certPinBuilder.str();
954 if (!pinRes.empty()) {
955 pinRes.pop_back();
956 options.SetCertificatePinning(pinRes);
957 }
958 }
959
SetMultipart(curl_mime * multipart)960 void RequestContext::SetMultipart(curl_mime *multipart)
961 {
962 multipart_ = multipart;
963 }
964
GetTaskId() const965 int32_t RequestContext::GetTaskId() const
966 {
967 return taskId_;
968 }
969
SetModuleId(uint64_t moduleId)970 void RequestContext::SetModuleId(uint64_t moduleId)
971 {
972 moduleId_ = moduleId;
973 }
974
GetModuleId() const975 uint64_t RequestContext::GetModuleId() const
976 {
977 return moduleId_;
978 }
979
IsAtomicService() const980 bool RequestContext::IsAtomicService() const
981 {
982 return isAtomicService_;
983 }
984
SetAtomicService(bool isAtomicService)985 void RequestContext::SetAtomicService(bool isAtomicService)
986 {
987 isAtomicService_ = isAtomicService;
988 }
989
SetBundleName(const std::string & bundleName)990 void RequestContext::SetBundleName(const std::string &bundleName)
991 {
992 bundleName_ = bundleName;
993 }
994
GetBundleName() const995 std::string RequestContext::GetBundleName() const
996 {
997 return bundleName_;
998 }
999
SetCurlHandle(CURL * handle)1000 void RequestContext::SetCurlHandle(CURL *handle)
1001 {
1002 curlHandle_ = handle;
1003 }
1004
SendNetworkProfiler()1005 void RequestContext::SendNetworkProfiler()
1006 {
1007 #if HAS_NETMANAGER_BASE
1008 HttpNetworkMessage networkMessage(std::to_string(GetTaskId()), options, response, curlHandle_);
1009 networkProfilerUtils_->NetworkProfiling(networkMessage);
1010 #endif
1011 }
1012
GetTrace()1013 RequestTracer::Trace &RequestContext::GetTrace()
1014 {
1015 return trace_;
1016 }
1017
IsRootCaVerified() const1018 bool RequestContext::IsRootCaVerified() const
1019 {
1020 return isRootCaVerified_;
1021 }
1022
SetRootCaVerified()1023 void RequestContext::SetRootCaVerified()
1024 {
1025 isRootCaVerified_ = true;
1026 }
1027
IsRootCaVerifiedOk() const1028 bool RequestContext::IsRootCaVerifiedOk() const
1029 {
1030 return isRootCaVerifiedOk_;
1031 }
1032
SetRootCaVerifiedOk(bool ok)1033 void RequestContext::SetRootCaVerifiedOk(bool ok)
1034 {
1035 isRootCaVerifiedOk_ = ok;
1036 }
1037
SetPinnedPubkey(std::string & pubkey)1038 void RequestContext::SetPinnedPubkey(std::string &pubkey)
1039 {
1040 pinnedPubkey_ = pubkey;
1041 }
1042
GetPinnedPubkey() const1043 std::string RequestContext::GetPinnedPubkey() const
1044 {
1045 return pinnedPubkey_;
1046 }
1047
1048 #ifdef HTTP_HANDOVER_FEATURE
SetRequestHandoverInfo(int32_t handoverNum,int32_t handoverReason,double flowControlTime,int32_t readFlag)1049 void RequestContext::SetRequestHandoverInfo(int32_t handoverNum, int32_t handoverReason, double flowControlTime,
1050 int32_t readFlag)
1051 {
1052 requestHandoverInfo_.handoverNum = handoverNum;
1053 requestHandoverInfo_.handoverReason = handoverReason;
1054 requestHandoverInfo_.flowControlTime = flowControlTime;
1055 requestHandoverInfo_.readFlag = readFlag;
1056 }
1057
GetRequestHandoverInfo()1058 std::string RequestContext::GetRequestHandoverInfo()
1059 {
1060 std::string requestHandoverInfo;
1061 if (requestHandoverInfo_.handoverNum <= 0) {
1062 requestHandoverInfo = "no handover";
1063 return requestHandoverInfo;
1064 }
1065 int32_t readFlag = requestHandoverInfo_.readFlag;
1066 requestHandoverInfo += "HandoverNum:";
1067 requestHandoverInfo += std::to_string(requestHandoverInfo_.handoverNum);
1068 requestHandoverInfo += ", handoverReason:";
1069 switch (requestHandoverInfo_.handoverReason) {
1070 case HandoverRequestType::INCOMING:
1071 requestHandoverInfo += "flowControl, flowControlTime:";
1072 break;
1073 case HandoverRequestType::NETWORKERROR:
1074 requestHandoverInfo += "netErr, retransTime:";
1075 break;
1076 case HandoverRequestType::UNDONE:
1077 requestHandoverInfo += "undone, retransTime:";
1078 break;
1079 default:
1080 requestHandoverInfo += "unkown type";
1081 break;
1082 }
1083 requestHandoverInfo += std::to_string(requestHandoverInfo_.flowControlTime);
1084 requestHandoverInfo += ", isRead:";
1085 requestHandoverInfo += readFlag == 1 ? "true" : (readFlag == 0 ? "false" : "error");
1086 requestHandoverInfo += ", isStream:";
1087 requestHandoverInfo += this->IsRequestInStream() ? "true" : "false";
1088 return requestHandoverInfo;
1089 }
1090 #endif
1091
ParseAddressFamily(napi_value optionsValue)1092 void RequestContext::ParseAddressFamily(napi_value optionsValue)
1093 {
1094 std::string addressFamily = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue,
1095 HttpConstant::PARAM_KEY_ADDRESS_FAMILY);
1096 if (!addressFamily.empty()) {
1097 options.SetAddressFamily(addressFamily);
1098 }
1099 }
1100 } // namespace OHOS::NetStack::Http
1101