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