• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "net_http_request_context.h"
17 
18 #include <algorithm>
19 
20 #include "constant.h"
21 #include "net_http_client_exec.h"
22 #include "netstack_common_utils.h"
23 #include "netstack_log.h"
24 #include "net_http_utils.h"
25 
26 static constexpr const int32_t RESPONSE_MAX_SIZE = 1024 * 1024 * 1024;
27 static constexpr const uint32_t DNS_SERVER_SIZE = 3;
28 static constexpr const int32_t PROP_UNSET = -1;
29 static constexpr size_t PERMISSION_DENIED_CODE = 201;
30 static constexpr const char *PERMISSION_DENIED_MSG = "Permission denied";
31 namespace OHOS::NetStack::Http {
32 static const std::map<int32_t, const char *> HTTP_ERR_MAP = {
33     {static_cast<int32_t>(HttpErrorCode::HTTP_UNSUPPORTED_PROTOCOL), "Unsupported protocol."},
34     {static_cast<int32_t>(HttpErrorCode::HTTP_URL_MALFORMAT), "URL using bad/illegal format or missing URL."},
35     {static_cast<int32_t>(HttpErrorCode::HTTP_COULDNT_RESOLVE_PROXY), "Couldn't resolve proxy name."},
36     {static_cast<int32_t>(HttpErrorCode::HTTP_COULDNT_RESOLVE_HOST), "Couldn't resolve host name."},
37     {static_cast<int32_t>(HttpErrorCode::HTTP_COULDNT_CONNECT), "Couldn't connect to server."},
38     {static_cast<int32_t>(HttpErrorCode::HTTP_WEIRD_SERVER_REPLY), "Weird server reply."},
39     {static_cast<int32_t>(HttpErrorCode::HTTP_REMOTE_ACCESS_DENIED), "Access denied to remote resource."},
40     {static_cast<int32_t>(HttpErrorCode::HTTP_HTTP2_ERROR), "Error in the HTTP2 framing layer."},
41     {static_cast<int32_t>(HttpErrorCode::HTTP_PARTIAL_FILE), "Transferred a partial file."},
42     {static_cast<int32_t>(HttpErrorCode::HTTP_WRITE_ERROR), "Failed writing received data to disk/application."},
43     {static_cast<int32_t>(HttpErrorCode::HTTP_UPLOAD_FAILED), "Upload failed."},
44     {static_cast<int32_t>(HttpErrorCode::HTTP_READ_ERROR), "Failed to open/read local data from file/application."},
45     {static_cast<int32_t>(HttpErrorCode::HTTP_OUT_OF_MEMORY), "Out of memory."},
46     {static_cast<int32_t>(HttpErrorCode::HTTP_OPERATION_TIMEDOUT), "Timeout was reached."},
47     {static_cast<int32_t>(HttpErrorCode::HTTP_TOO_MANY_REDIRECTS), "Number of redirects hit maximum amount."},
48     {static_cast<int32_t>(HttpErrorCode::HTTP_GOT_NOTHING), "Server returned nothing (no headers, no data)."},
49     {static_cast<int32_t>(HttpErrorCode::HTTP_SEND_ERROR), "Failed sending data to the peer."},
50     {static_cast<int32_t>(HttpErrorCode::HTTP_RECV_ERROR), "Failure when receiving data from the peer."},
51     {static_cast<int32_t>(HttpErrorCode::HTTP_SSL_CERTPROBLEM), "Problem with the local SSL certificate."},
52     {static_cast<int32_t>(HttpErrorCode::HTTP_SSL_CIPHER), "Couldn't use specified SSL cipher."},
53     {static_cast<int32_t>(HttpErrorCode::HTTP_PEER_FAILED_VERIFICATION),
54         "SSL peer certificate or SSH remote key was not OK."},
55     {static_cast<int32_t>(HttpErrorCode::HTTP_BAD_CONTENT_ENCODING),
56         "Unrecognized or bad HTTP Content or Transfer-Encoding."},
57     {static_cast<int32_t>(HttpErrorCode::HTTP_FILESIZE_EXCEEDED), "Maximum file size exceeded."},
58     {static_cast<int32_t>(HttpErrorCode::HTTP_REMOTE_DISK_FULL), "Disk full or allocation exceeded."},
59     {static_cast<int32_t>(HttpErrorCode::HTTP_REMOTE_FILE_EXISTS), "Remote file already exists."},
60     {static_cast<int32_t>(HttpErrorCode::HTTP_SSL_CACERT_BADFILE),
61         "Problem with the SSL CA cert (path? access rights?)."},
62     {static_cast<int32_t>(HttpErrorCode::HTTP_REMOTE_FILE_NOT_FOUND), "Remote file not found."},
63     {static_cast<int32_t>(HttpErrorCode::HTTP_AUTH_ERROR), "An authentication function returned an error."},
64     {static_cast<int32_t>(HttpErrorCode::HTTP_UNKNOWN_OTHER_ERROR), "Unknown Other Error."},
65 };
RequestContext()66 RequestContext::RequestContext()
67 {
68     StartTiming();
69 }
70 
StartTiming()71 void RequestContext::StartTiming()
72 {
73     time_t startTime = TimeUtils::GetNowTimeMicroseconds();
74     timerMap_.RecieveTimer(RESPONSE_HEADER_TIMING).Start(startTime);
75     timerMap_.RecieveTimer(RESPONSE_BODY_TIMING).Start(startTime);
76     timerMap_.RecieveTimer(RESPONSE_TOTAL_TIMING).Start(startTime);
77 }
78 
HandleMethodForGet(CArrUI8 extraData)79 void RequestContext::HandleMethodForGet(CArrUI8 extraData)
80 {
81     if (extraData.head == nullptr) {
82         return;
83     }
84     std::string url = options.GetUrl();
85     std::string param;
86     auto index = url.find(HTTP_URL_PARAM_START);
87     if (index != std::string::npos) {
88         param = url.substr(index + 1);
89         url.resize(index);
90     }
91     std::string extraParam{extraData.head, extraData.head + extraData.size};
92 
93     options.SetUrl(NetHttpClientExec::MakeUrl(url, param, extraParam));
94     return;
95 }
96 
GetRequestBody(CArrUI8 extraData)97 bool RequestContext::GetRequestBody(CArrUI8 extraData)
98 {
99     /* if body is empty, return false, or curl will wait for body */
100 
101     if (extraData.head == nullptr) {
102         return false;
103     }
104     options.SetBody(extraData.head, extraData.size);
105     return true;
106 }
107 
IsUsingCache() const108 bool RequestContext::IsUsingCache() const
109 {
110     return usingCache_;
111 }
112 
SetCurlHeaderList(struct curl_slist * curlHeaderList)113 void RequestContext::SetCurlHeaderList(struct curl_slist *curlHeaderList)
114 {
115     curlHeaderList_ = curlHeaderList;
116 }
117 
GetCurlHeaderList()118 struct curl_slist *RequestContext::GetCurlHeaderList()
119 {
120     return curlHeaderList_;
121 }
~RequestContext()122 RequestContext::~RequestContext()
123 {
124     if (curlHeaderList_ != nullptr) {
125         curl_slist_free_all(curlHeaderList_);
126     }
127     if (multipart_ != nullptr) {
128         curl_mime_free(multipart_);
129         multipart_ = nullptr;
130     }
131     NETSTACK_LOGI("RequestContext is destructed by the destructor");
132 }
133 
SetCacheResponse(const HttpResponse & cacheResponse)134 void RequestContext::SetCacheResponse(const HttpResponse &cacheResponse)
135 {
136     cacheResponse_ = cacheResponse;
137 }
SetResponseByCache()138 void RequestContext::SetResponseByCache()
139 {
140     response = cacheResponse_;
141 }
142 
GetErrorCode() const143 int32_t RequestContext::GetErrorCode() const
144 {
145     if (IsPermissionDenied()) {
146         return PERMISSION_DENIED_CODE;
147     }
148 
149     if (HTTP_ERR_MAP.find(errCode_ + static_cast<int32_t>(HttpErrorCode::HTTP_ERROR_CODE_BASE))
150             != HTTP_ERR_MAP.end()) {
151         return errCode_ + static_cast<int32_t>(HttpErrorCode::HTTP_ERROR_CODE_BASE);
152     }
153     return static_cast<int32_t>(HttpErrorCode::HTTP_UNKNOWN_OTHER_ERROR);
154 }
155 
GetErrorMessage() const156 std::string RequestContext::GetErrorMessage() const
157 {
158     if (IsPermissionDenied()) {
159         return PERMISSION_DENIED_MSG;
160     }
161 
162     auto pos = HTTP_ERR_MAP.find(errCode_ + static_cast<int32_t>(HttpErrorCode::HTTP_ERROR_CODE_BASE));
163     if (pos != HTTP_ERR_MAP.end()) {
164         return pos->second;
165     }
166     return HTTP_ERR_MAP.at(static_cast<int32_t>(HttpErrorCode::HTTP_UNKNOWN_OTHER_ERROR));
167 }
168 
SetErrorCode(int32_t code)169 void RequestContext::SetErrorCode(int32_t code)
170 {
171     errCode_ = code;
172 }
173 
EnableRequestInStream()174 void RequestContext::EnableRequestInStream()
175 {
176     requestInStream_ = true;
177 }
178 
IsRequestInStream() const179 bool RequestContext::IsRequestInStream() const
180 {
181     return requestInStream_;
182 }
183 
SetDlLen(curl_off_t nowLen,curl_off_t totalLen)184 void RequestContext::SetDlLen(curl_off_t nowLen, curl_off_t totalLen)
185 {
186     std::lock_guard<std::mutex> lock(dlLenLock_);
187     LoadBytes dlBytes{nowLen, totalLen};
188     dlBytes_.push(dlBytes);
189 }
190 
SetUlLen(curl_off_t nowLen,curl_off_t totalLen)191 void RequestContext::SetUlLen(curl_off_t nowLen, curl_off_t totalLen)
192 {
193     std::lock_guard<std::mutex> lock(ulLenLock_);
194     if (!ulBytes_.empty()) {
195         ulBytes_.pop();
196     }
197     LoadBytes ulBytes{nowLen, totalLen};
198     ulBytes_.push(ulBytes);
199 }
200 
GetDlLen()201 LoadBytes RequestContext::GetDlLen()
202 {
203     std::lock_guard<std::mutex> lock(dlLenLock_);
204     LoadBytes dlBytes;
205     if (!dlBytes_.empty()) {
206         dlBytes.nLen = dlBytes_.front().nLen;
207         dlBytes.tLen = dlBytes_.front().tLen;
208         dlBytes_.pop();
209     }
210     return dlBytes;
211 }
212 
GetUlLen()213 LoadBytes RequestContext::GetUlLen()
214 {
215     std::lock_guard<std::mutex> lock(ulLenLock_);
216     LoadBytes ulBytes;
217     if (!ulBytes_.empty()) {
218         ulBytes.nLen = ulBytes_.back().nLen;
219         ulBytes.tLen = ulBytes_.back().tLen;
220     }
221     return ulBytes;
222 }
223 
CompareWithLastElement(curl_off_t nowLen,curl_off_t totalLen)224 bool RequestContext::CompareWithLastElement(curl_off_t nowLen, curl_off_t totalLen)
225 {
226     std::lock_guard<std::mutex> lock(ulLenLock_);
227     if (ulBytes_.empty()) {
228         return false;
229     }
230     const LoadBytes &lastElement = ulBytes_.back();
231     return nowLen == lastElement.nLen && totalLen == lastElement.tLen;
232 }
233 
SetTempData(const void * data,size_t size)234 void RequestContext::SetTempData(const void *data, size_t size)
235 {
236     std::lock_guard<std::mutex> lock(tempDataLock_);
237     std::string tempString;
238     tempString.append(reinterpret_cast<const char *>(data), size);
239     tempData_.push(tempString);
240 }
241 
GetTempData()242 std::string RequestContext::GetTempData()
243 {
244     std::lock_guard<std::mutex> lock(tempDataLock_);
245     if (!tempData_.empty()) {
246         return tempData_.front();
247     }
248     return {};
249 }
250 
PopTempData()251 void RequestContext::PopTempData()
252 {
253     std::lock_guard<std::mutex> lock(tempDataLock_);
254     if (!tempData_.empty()) {
255         tempData_.pop();
256     }
257 }
258 
CachePerformanceTimingItem(const std::string & key,double value)259 void RequestContext::CachePerformanceTimingItem(const std::string &key, double value)
260 {
261     performanceTimingMap_[key] = value;
262 }
263 
StopAndCachePerformanceTiming(const char * key)264 void RequestContext::StopAndCachePerformanceTiming(const char *key)
265 {
266     Timer &timer = timerMap_.RecieveTimer(key);
267     timer.Stop();
268     CachePerformanceTimingItem(key, timer.Elapsed());
269 }
270 
SetPerformanceTimingToResult(CHttpResponse & resp)271 void RequestContext::SetPerformanceTimingToResult(CHttpResponse &resp)
272 {
273     if (performanceTimingMap_.empty()) {
274         NETSTACK_LOGI("Get performanceTiming data is empty.");
275         return;
276     }
277 
278     CPerformanceTiming timing{
279         .dnsTiming = performanceTimingMap_[RESPONSE_DNS_TIMING],
280         .tcpTiming = performanceTimingMap_[RESPONSE_TCP_TIMING],
281         .tlsTiming = performanceTimingMap_[RESPONSE_TLS_TIMING],
282         .firstSendTiming = performanceTimingMap_[RESPONSE_FIRST_SEND_TIMING],
283         .firstReceiveTiming = performanceTimingMap_[RESPONSE_FIRST_RECEIVE_TIMING],
284         .totalFinishTiming = performanceTimingMap_[RESPONSE_TOTAL_FINISH_TIMING],
285         .redirectTiming = performanceTimingMap_[RESPONSE_REDIRECT_TIMING],
286         .responseHeaderTiming = performanceTimingMap_[RESPONSE_HEADER_TIMING],
287         .responseBodyTiming = performanceTimingMap_[RESPONSE_BODY_TIMING],
288         .totalTiming = performanceTimingMap_[RESPONSE_TOTAL_TIMING]
289     };
290     resp.performanceTiming = timing;
291 }
292 
SetMultipart(curl_mime * multipart)293 void RequestContext::SetMultipart(curl_mime *multipart)
294 {
295     multipart_ = multipart;
296 }
297 
SetParseOK()298 void RequestContext::SetParseOK()
299 {
300     parseok_ = true;
301 }
302 
IsParseOK() const303 bool RequestContext::IsParseOK() const
304 {
305     return parseok_;
306 }
307 
SetExecOK(bool ok)308 void RequestContext::SetExecOK(bool ok)
309 {
310     requestOK_ = ok;
311 }
312 
IsExecOK() const313 bool RequestContext::IsExecOK() const
314 {
315     return requestOK_;
316 }
317 
SetPermissionDenied(bool deny)318 void RequestContext::SetPermissionDenied(bool deny)
319 {
320     permissionDenied_ = deny;
321 }
322 
IsPermissionDenied() const323 bool RequestContext::IsPermissionDenied() const
324 {
325     return permissionDenied_;
326 }
327 
Destroy()328 void RequestContext::Destroy()
329 {
330     isDestroyed_ = true;
331 }
332 
IsDestroyed() const333 bool RequestContext::IsDestroyed() const
334 {
335     return isDestroyed_;
336 }
337 
IsRootCaVerified() const338 bool RequestContext::IsRootCaVerified() const
339 {
340     return isRootCaVerified_;
341 }
342 
SetRootCaVerified()343 void RequestContext::SetRootCaVerified()
344 {
345     isRootCaVerified_ = true;
346 }
347 
IsRootCaVerifiedOk() const348 bool RequestContext::IsRootCaVerifiedOk() const
349 {
350     return isRootCaVerifiedOk_;
351 }
352 
SetRootCaVerifiedOk(bool ok)353 void RequestContext::SetRootCaVerifiedOk(bool ok)
354 {
355     isRootCaVerifiedOk_ = ok;
356 }
357 
SetPinnedPubkey(std::string & pubkey)358 void RequestContext::SetPinnedPubkey(std::string &pubkey)
359 {
360     pinnedPubkey_ = pubkey;
361 }
362 
GetPinnedPubkey() const363 std::string RequestContext::GetPinnedPubkey() const
364 {
365     return pinnedPubkey_;
366 }
367 
SetCertsPath(std::vector<std::string> && certPathList,const std::string & certFile)368 void RequestContext::SetCertsPath(std::vector<std::string> &&certPathList, const std::string &certFile)
369 {
370     certsPath_.certPathList = std::move(certPathList);
371     certsPath_.certFile = certFile;
372 }
373 
GetCertsPath()374 const CertsPath &RequestContext::GetCertsPath()
375 {
376     return certsPath_;
377 }
378 
ParseParams(std::string url,CHttpRequestOptions * ops)379 void RequestContext::ParseParams(std::string url, CHttpRequestOptions *ops)
380 {
381     options.SetUrl(url);
382     if (ops != nullptr) {
383         options.SetMethod(std::string(ops->method));
384         options.SetReadTimeout(ops->readTimeout);
385         options.SetMaxLimit(ops->maxLimit);
386         options.SetConnectTimeout(ops->connectTimeout);
387         usingCache_ = ops->usingCache;
388         if (ops->usingProtocol == static_cast<int32_t>(HttpProtocol::HTTP1_1) ||
389             ops->usingProtocol == static_cast<int32_t>(HttpProtocol::HTTP2)) {
390                 options.SetUsingProtocol(static_cast<HttpProtocol>(ops->usingProtocol));
391             }
392         if (ops->expectDataType != PROP_UNSET) {
393             options.SetHttpDataType(static_cast<HttpDataType>(ops->expectDataType));
394         }
395         options.SetPriority(ops->priority);
396         ParseUsingHttpProxy(ops->usingProxy, ops->usingDefaultProxy);
397         if (ops->clientCert != nullptr) {
398             std::string certPath{ops->clientCert->certPath};
399             std::string certType{ops->clientCert->certType};
400             std::string keyPath{ops->clientCert->keyPath};
401             SecureChar keyPasswd;
402             if (ops->clientCert->keyPassword != nullptr) {
403                 keyPasswd = SecureChar(ops->clientCert->keyPassword);
404             } else {
405                 keyPasswd = SecureChar("");
406             }
407             options.SetClientCert(certPath, certType, keyPath, keyPasswd);
408         }
409         if (!ParseExtraData(ops->extraData)) {
410             return;
411         }
412         ParseHeader(ops->header);
413         if (ops->caPath != nullptr) {
414             options.SetCaPath(std::string{ops->caPath});
415         }
416         if (ops->dnsOverHttps != nullptr) {
417             options.SetDohUrl(std::string{ops->dnsOverHttps});
418         }
419         options.SetRangeNumber(ops->resumeFrom, ops->resumeTo);
420         ParseDnsServers(ops->dnsServer);
421         ParseMultiFormData(ops->multiFormDataList);
422     }
423     SetParseOK();
424 }
425 
ParseUsingHttpProxy(CHttpProxy * proxy,bool useDefault)426 void RequestContext::ParseUsingHttpProxy(CHttpProxy* proxy, bool useDefault)
427 {
428     if (proxy != nullptr) {
429         options.SetUsingHttpProxyType(UsingHttpProxyType::USE_SPECIFIED);
430         std::string host{proxy->host};
431         std::string exclusionList;
432         for (int i = 0; i < proxy->exclusionListSize; i++) {
433             if (i != 0) {
434                 exclusionList = exclusionList + HTTP_PROXY_EXCLUSIONS_SEPARATOR;
435             }
436             exclusionList += std::string{proxy->exclusionList[i]};
437         }
438         options.SetSpecifiedHttpProxy(host, proxy->port, exclusionList);
439     } else {
440         UsingHttpProxyType usingType = useDefault ? UsingHttpProxyType::USE_DEFAULT : UsingHttpProxyType::NOT_USE;
441         options.SetUsingHttpProxyType(usingType);
442     }
443 }
444 
ParseHeader(CArrString header)445 void RequestContext::ParseHeader(CArrString header)
446 {
447     if (header.head == nullptr || header.size == 0) {
448         return;
449     }
450     if (NetHttpClientExec::MethodForPost(options.GetMethod())) {
451         options.SetHeader(CommonUtils::ToLower(HTTP_CONTENT_TYPE), HTTP_CONTENT_TYPE_JSON); // default
452     }
453     for (int i = 0; i < header.size; i += MAP_TUPLE_SIZE) {
454         std::string key{header.head[i]};
455         std::string value{header.head[i + 1]};
456         options.SetHeader(CommonUtils::ToLower(key), value);
457     }
458 }
459 
ParseDnsServers(CArrString dns)460 void RequestContext::ParseDnsServers(CArrString dns)
461 {
462     if (dns.size == 0) {
463         return;
464     }
465     std::vector<std::string> dnsServers;
466     uint32_t dnsSize = 0;
467     for (uint32_t i = 0; i < dns.size && dnsSize < DNS_SERVER_SIZE; i++) {
468         std::string dnsServer{dns.head[i]};
469         if (dnsServer.empty()) {
470             continue;
471         }
472         if (!CommonUtils::IsValidIPV4(dnsServer) && !CommonUtils::IsValidIPV6(dnsServer)) {
473             continue;
474         }
475         dnsServers.push_back(dnsServer);
476         dnsSize++;
477     }
478     options.SetDnsServers(dnsServers);
479 }
480 
ParseExtraData(CArrUI8 data)481 bool RequestContext::ParseExtraData(CArrUI8 data)
482 {
483     if (data.size == 0) {
484         return true;
485     }
486     if (NetHttpClientExec::MethodForGet(options.GetMethod())) {
487         HandleMethodForGet(data);
488         return true;
489     }
490 
491     if (NetHttpClientExec::MethodForPost(options.GetMethod())) {
492         return GetRequestBody(data);
493     }
494     return false;
495 }
496 
ParseMultiFormData(CArrMultiFormData multi)497 void RequestContext::ParseMultiFormData(CArrMultiFormData multi)
498 {
499     if (multi.size == 0) {
500         return;
501     }
502 
503     for (int i = 0; i < multi.size; i++) {
504         CMultiFormData from = multi.data[i];
505         MultiFormData multiFormData;
506         multiFormData.name = std::string{from.name};
507         multiFormData.contentType = std::string{from.contentType};
508         if (from.remoteFileName != nullptr) {
509             multiFormData.remoteFileName = std::string{from.remoteFileName};
510         }
511         if (from.filePath != nullptr) {
512             multiFormData.filePath = std::string{from.filePath};
513         }
514         if (from.data.size > 0) {
515             std::string data{from.data.head, from.data.head + from.data.size};
516             multiFormData.data = data;
517         }
518         options.AddMultiFormData(multiFormData);
519     }
520 }
521 
ParseSetCookie(CArrString & setCookie,HttpResponse & response)522 void ParseSetCookie(CArrString &setCookie, HttpResponse &response)
523 {
524     auto setCookieSize = response.GetsetCookie().size();
525     if (setCookieSize > 0 && setCookieSize < RESPONSE_MAX_SIZE) {
526         setCookie.head = static_cast<char**>(malloc(sizeof(char*) * setCookieSize));
527         if (setCookie.head == nullptr) {
528             return;
529         }
530         setCookie.size = static_cast<int64_t>(setCookieSize);
531         int i = 0;
532         for (const auto &cookie : response.GetsetCookie()) {
533             setCookie.head[i] = MallocCString(cookie);
534             i++;
535         }
536     }
537 }
538 
SendResponse()539 void RequestContext::SendResponse()
540 {
541     CHttpResponse resp = { .errCode = 0,
542         .errMsg = nullptr,
543         .result = { .head = nullptr, .size = 0},
544         .resultType = 2,
545         .responseCode = 0,
546         .header = CArrString{ .head = nullptr, .size = 0 },
547         .cookies = nullptr,
548         .setCookie = CArrString{ .head = nullptr, .size = 0 },
549         .performanceTiming = CPerformanceTiming{}};
550     if (IsExecOK()) {
551         resp.responseCode = response.GetResponseCode();
552         if (!IsRequestInStream()) {
553             auto headerSize = response.GetHeader().size();
554             resp.cookies = MallocCString(response.GetCookies());
555             if (headerSize > 0) {
556                 resp.header = g_map2CArrString(response.GetHeader());
557             }
558             ParseSetCookie(resp.setCookie, response);
559             StopAndCachePerformanceTiming(RESPONSE_TOTAL_TIMING);
560             SetPerformanceTimingToResult(resp);
561             resp.result.head = reinterpret_cast<uint8_t*>(MallocCString(response.GetResult()));
562             resp.result.size = static_cast<int64_t>(response.GetResult().length());
563             resp.resultType = static_cast<int32_t>(options.GetHttpDataType());
564         }
565     } else {
566         resp.errCode = GetErrorCode();
567         resp.errMsg = MallocCString(GetErrorMessage());
568     }
569     respCallback(resp);
570 }
571 
Request(std::string url,CHttpRequestOptions * ops,bool isInStream)572 RequestContext* HttpRequestProxy::Request(std::string url, CHttpRequestOptions *ops, bool isInStream)
573 {
574     if (!NetHttpClientExec::Initialize()) {
575         return nullptr;
576     }
577 
578     RequestContext* context = new RequestContext();
579     if (context == nullptr) {
580         return nullptr;
581     }
582     if (!CommonUtils::HasInternetPermission()) {
583         context->SetPermissionDenied(true);
584         return context;
585     }
586     context->options.SetRequestTime(GetNowTimeGMT());
587     if (isInStream) {
588         context->EnableRequestInStream();
589     }
590     context->ParseParams(url, ops);
591 
592     if (!context->IsParseOK()) {
593         // context.setxxx
594         return context;
595     }
596     NetHttpClientExec::ExecRequest(context);
597     return context;
598 }
599 
Destroy()600 void HttpRequestProxy::Destroy()
601 {
602     isDestroyed = true;
603 
604     // clear funcs
605     callbacks->headersReceive.clear();
606     callbacks->headersReceiveOnce.clear();
607     callbacks->dataReceive.clear();
608     callbacks->dataEnd.clear();
609     callbacks->dataReceiveProgress.clear();
610     callbacks->dataSendProgress.clear();
611 }
612 
613 } // namespace OHOS::NetStack::Http
614