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