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
SetCertsPath(std::vector<std::string> && certPathList,const std::string & certFile)338 void RequestContext::SetCertsPath(std::vector<std::string> &&certPathList, const std::string &certFile)
339 {
340 certsPath_.certPathList = std::move(certPathList);
341 certsPath_.certFile = certFile;
342 }
343
GetCertsPath()344 const CertsPath &RequestContext::GetCertsPath()
345 {
346 return certsPath_;
347 }
348
ParseParams(std::string url,CHttpRequestOptions * ops)349 void RequestContext::ParseParams(std::string url, CHttpRequestOptions *ops)
350 {
351 options.SetUrl(url);
352 if (ops != nullptr) {
353 options.SetMethod(std::string(ops->method));
354 options.SetReadTimeout(ops->readTimeout);
355 options.SetMaxLimit(ops->maxLimit);
356 options.SetConnectTimeout(ops->connectTimeout);
357 usingCache_ = ops->usingCache;
358 if (ops->usingProtocol == static_cast<int32_t>(HttpProtocol::HTTP1_1) ||
359 ops->usingProtocol == static_cast<int32_t>(HttpProtocol::HTTP2)) {
360 options.SetUsingProtocol(static_cast<HttpProtocol>(ops->usingProtocol));
361 }
362 if (ops->expectDataType != PROP_UNSET) {
363 options.SetHttpDataType(static_cast<HttpDataType>(ops->expectDataType));
364 }
365 options.SetPriority(ops->priority);
366 ParseUsingHttpProxy(ops->usingProxy, ops->usingDefaultProxy);
367 if (ops->clientCert != nullptr) {
368 std::string certPath{ops->clientCert->certPath};
369 std::string certType{ops->clientCert->certType};
370 std::string keyPath{ops->clientCert->keyPath};
371 SecureChar keyPasswd;
372 if (ops->clientCert->keyPassword != nullptr) {
373 keyPasswd = SecureChar(ops->clientCert->keyPassword);
374 } else {
375 keyPasswd = SecureChar("");
376 }
377 options.SetClientCert(certPath, certType, keyPath, keyPasswd);
378 }
379 if (!ParseExtraData(ops->extraData)) {
380 return;
381 }
382 ParseHeader(ops->header);
383 if (ops->caPath != nullptr) {
384 options.SetCaPath(std::string{ops->caPath});
385 }
386 if (ops->dnsOverHttps != nullptr) {
387 options.SetDohUrl(std::string{ops->dnsOverHttps});
388 }
389 options.SetRangeNumber(ops->resumeFrom, ops->resumeTo);
390 ParseDnsServers(ops->dnsServer);
391 ParseMultiFormData(ops->multiFormDataList);
392 }
393 SetParseOK();
394 }
395
ParseUsingHttpProxy(CHttpProxy * proxy,bool useDefault)396 void RequestContext::ParseUsingHttpProxy(CHttpProxy* proxy, bool useDefault)
397 {
398 if (proxy != nullptr) {
399 options.SetUsingHttpProxyType(UsingHttpProxyType::USE_SPECIFIED);
400 std::string host{proxy->host};
401 std::string exclusionList;
402 for (int i = 0; i < proxy->exclusionListSize; i++) {
403 if (i != 0) {
404 exclusionList = exclusionList + HTTP_PROXY_EXCLUSIONS_SEPARATOR;
405 }
406 exclusionList += std::string{proxy->exclusionList[i]};
407 }
408 options.SetSpecifiedHttpProxy(host, proxy->port, exclusionList);
409 } else {
410 UsingHttpProxyType usingType = useDefault ? UsingHttpProxyType::USE_DEFAULT : UsingHttpProxyType::NOT_USE;
411 options.SetUsingHttpProxyType(usingType);
412 }
413 }
414
ParseHeader(CArrString header)415 void RequestContext::ParseHeader(CArrString header)
416 {
417 if (header.head == nullptr || header.size == 0) {
418 return;
419 }
420 if (NetHttpClientExec::MethodForPost(options.GetMethod())) {
421 options.SetHeader(CommonUtils::ToLower(HTTP_CONTENT_TYPE), HTTP_CONTENT_TYPE_JSON); // default
422 }
423 for (int i = 0; i < header.size; i += MAP_TUPLE_SIZE) {
424 std::string key{header.head[i]};
425 std::string value{header.head[i + 1]};
426 options.SetHeader(CommonUtils::ToLower(key), value);
427 }
428 }
429
ParseDnsServers(CArrString dns)430 void RequestContext::ParseDnsServers(CArrString dns)
431 {
432 if (dns.size == 0) {
433 return;
434 }
435 std::vector<std::string> dnsServers;
436 uint32_t dnsSize = 0;
437 for (uint32_t i = 0; i < dns.size && dnsSize < DNS_SERVER_SIZE; i++) {
438 std::string dnsServer{dns.head[i]};
439 if (dnsServer.empty()) {
440 continue;
441 }
442 if (!CommonUtils::IsValidIPV4(dnsServer) && !CommonUtils::IsValidIPV6(dnsServer)) {
443 continue;
444 }
445 dnsServers.push_back(dnsServer);
446 dnsSize++;
447 }
448 options.SetDnsServers(dnsServers);
449 }
450
ParseExtraData(CArrUI8 data)451 bool RequestContext::ParseExtraData(CArrUI8 data)
452 {
453 if (data.size == 0) {
454 return true;
455 }
456 if (NetHttpClientExec::MethodForGet(options.GetMethod())) {
457 HandleMethodForGet(data);
458 return true;
459 }
460
461 if (NetHttpClientExec::MethodForPost(options.GetMethod())) {
462 return GetRequestBody(data);
463 }
464 return false;
465 }
466
ParseMultiFormData(CArrMultiFormData multi)467 void RequestContext::ParseMultiFormData(CArrMultiFormData multi)
468 {
469 if (multi.size == 0) {
470 return;
471 }
472
473 for (int i = 0; i < multi.size; i++) {
474 CMultiFormData from = multi.data[i];
475 MultiFormData multiFormData;
476 multiFormData.name = std::string{from.name};
477 multiFormData.contentType = std::string{from.contentType};
478 if (from.remoteFileName != nullptr) {
479 multiFormData.remoteFileName = std::string{from.remoteFileName};
480 }
481 if (from.filePath != nullptr) {
482 multiFormData.filePath = std::string{from.filePath};
483 }
484 if (from.data.size > 0) {
485 std::string data{from.data.head, from.data.head + from.data.size};
486 multiFormData.data = data;
487 }
488 options.AddMultiFormData(multiFormData);
489 }
490 }
491
ParseSetCookie(CArrString & setCookie,HttpResponse & response)492 void ParseSetCookie(CArrString &setCookie, HttpResponse &response)
493 {
494 auto setCookieSize = response.GetsetCookie().size();
495 if (setCookieSize > 0 && setCookieSize < RESPONSE_MAX_SIZE) {
496 setCookie.head = static_cast<char**>(malloc(sizeof(char*) * setCookieSize));
497 if (setCookie.head == nullptr) {
498 return;
499 }
500 setCookie.size = static_cast<int64_t>(setCookieSize);
501 int i = 0;
502 for (const auto &cookie : response.GetsetCookie()) {
503 setCookie.head[i] = MallocCString(cookie);
504 i++;
505 }
506 }
507 }
508
SendResponse()509 void RequestContext::SendResponse()
510 {
511 CHttpResponse resp = { .errCode = 0,
512 .errMsg = nullptr,
513 .result = { .head = nullptr, .size = 0},
514 .resultType = 2,
515 .responseCode = 0,
516 .header = CArrString{ .head = nullptr, .size = 0 },
517 .cookies = nullptr,
518 .setCookie = CArrString{ .head = nullptr, .size = 0 },
519 .performanceTiming = CPerformanceTiming{}};
520 if (IsExecOK()) {
521 resp.responseCode = response.GetResponseCode();
522 if (!IsRequestInStream()) {
523 auto headerSize = response.GetHeader().size();
524 resp.cookies = MallocCString(response.GetCookies());
525 if (headerSize > 0) {
526 resp.header = g_map2CArrString(response.GetHeader());
527 }
528 ParseSetCookie(resp.setCookie, response);
529 StopAndCachePerformanceTiming(RESPONSE_TOTAL_TIMING);
530 SetPerformanceTimingToResult(resp);
531 resp.result.head = reinterpret_cast<uint8_t*>(MallocCString(response.GetResult()));
532 resp.result.size = static_cast<int64_t>(response.GetResult().length());
533 resp.resultType = static_cast<int32_t>(options.GetHttpDataType());
534 }
535 } else {
536 resp.errCode = GetErrorCode();
537 resp.errMsg = MallocCString(GetErrorMessage());
538 }
539 respCallback(resp);
540 }
541
Request(std::string url,CHttpRequestOptions * ops,bool isInStream)542 RequestContext* HttpRequestProxy::Request(std::string url, CHttpRequestOptions *ops, bool isInStream)
543 {
544 if (!NetHttpClientExec::Initialize()) {
545 return nullptr;
546 }
547
548 RequestContext* context = new RequestContext();
549 if (context == nullptr) {
550 return nullptr;
551 }
552 if (!CommonUtils::HasInternetPermission()) {
553 context->SetPermissionDenied(true);
554 return context;
555 }
556 context->options.SetRequestTime(GetNowTimeGMT());
557 if (isInStream) {
558 context->EnableRequestInStream();
559 }
560 context->ParseParams(url, ops);
561
562 if (!context->IsParseOK()) {
563 // context.setxxx
564 return context;
565 }
566 NetHttpClientExec::ExecRequest(context);
567 return context;
568 }
569
Destroy()570 void HttpRequestProxy::Destroy()
571 {
572 isDestroyed = true;
573
574 // clear funcs
575 callbacks->headersReceive.clear();
576 callbacks->headersReceiveOnce.clear();
577 callbacks->dataReceive.clear();
578 callbacks->dataEnd.clear();
579 callbacks->dataReceiveProgress.clear();
580 callbacks->dataSendProgress.clear();
581 }
582
583 } // namespace OHOS::NetStack::Http
584