• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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