1 /*
2 * Copyright (c) 2023-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 <iostream>
17 #include <memory>
18
19 #include "http_client_task.h"
20 #include "http_client.h"
21 #include "http_client_constant.h"
22 #include "http_client_time.h"
23 #include "netstack_common_utils.h"
24 #include "netstack_log.h"
25 #include "net_conn_client.h"
26
27 #define NETSTACK_CURL_EASY_SET_OPTION(handle, opt, data) \
28 do { \
29 CURLcode result = curl_easy_setopt(handle, opt, data); \
30 if (result != CURLE_OK) { \
31 const char *err = curl_easy_strerror(result); \
32 error_.SetCURLResult(result); \
33 NETSTACK_LOGE("Failed to set option: %{public}s, %{public}s %{public}d", #opt, err, result); \
34 return false; \
35 } \
36 } while (0)
37
38 namespace OHOS {
39 namespace NetStack {
40 namespace HttpClient {
41
42 static constexpr size_t MAX_LIMIT = 100 * 1024 * 1024;
43 std::atomic<uint32_t> HttpClientTask::nextTaskId_(0);
44
CheckFilePath(const std::string & fileName,std::string & realPath)45 bool CheckFilePath(const std::string &fileName, std::string &realPath)
46 {
47 char tmpPath[PATH_MAX] = {0};
48 if (!realpath(static_cast<const char *>(fileName.c_str()), tmpPath)) {
49 NETSTACK_LOGE("file name is error");
50 return false;
51 }
52
53 realPath = tmpPath;
54 return true;
55 }
56
HttpClientTask(const HttpClientRequest & request)57 HttpClientTask::HttpClientTask(const HttpClientRequest &request)
58 : request_(request),
59 type_(DEFAULT),
60 status_(IDLE),
61 taskId_(nextTaskId_++),
62 curlHeaderList_(nullptr),
63 canceled_(false),
64 file_(nullptr)
65 {
66 NETSTACK_LOGI("taskId_=%{public}d", taskId_);
67
68 curlHandle_ = curl_easy_init();
69 if (!curlHandle_) {
70 NETSTACK_LOGE("Failed to create task!");
71 return;
72 }
73
74 SetCurlOptions();
75 }
76
HttpClientTask(const HttpClientRequest & request,TaskType type,const std::string & filePath)77 HttpClientTask::HttpClientTask(const HttpClientRequest &request, TaskType type, const std::string &filePath)
78 : request_(request),
79 type_(type),
80 status_(IDLE),
81 taskId_(nextTaskId_++),
82 curlHeaderList_(nullptr),
83 canceled_(false),
84 filePath_(filePath),
85 file_(nullptr)
86 {
87 NETSTACK_LOGI(
88 "taskId_=%{public}d type=%{public}d filePath=%{public}s",
89 taskId_, type_, filePath_.c_str());
90
91 curlHandle_ = curl_easy_init();
92 if (!curlHandle_) {
93 NETSTACK_LOGE("Failed to create task!");
94 return;
95 }
96
97 SetCurlOptions();
98 }
99
~HttpClientTask()100 HttpClientTask::~HttpClientTask()
101 {
102 NETSTACK_LOGD("Destroy: taskId_=%{public}d", taskId_);
103 if (curlHeaderList_ != nullptr) {
104 curl_slist_free_all(curlHeaderList_);
105 curlHeaderList_ = nullptr;
106 }
107
108 if (curlHandle_) {
109 curl_easy_cleanup(curlHandle_);
110 curlHandle_ = nullptr;
111 }
112
113 if (file_ != nullptr) {
114 fclose(file_);
115 file_ = nullptr;
116 }
117 }
118
GetHttpVersion(HttpProtocol ptcl) const119 uint32_t HttpClientTask::GetHttpVersion(HttpProtocol ptcl) const
120 {
121 if (ptcl == HttpProtocol::HTTP1_1) {
122 NETSTACK_LOGD("CURL_HTTP_VERSION_1_1");
123 return CURL_HTTP_VERSION_1_1;
124 } else if (ptcl == HttpProtocol::HTTP2) {
125 NETSTACK_LOGD("CURL_HTTP_VERSION_2_0");
126 return CURL_HTTP_VERSION_2_0;
127 } else if (ptcl == HttpProtocol::HTTP3) {
128 NETSTACK_LOGD("CURL_HTTP_VERSION_3");
129 return CURL_HTTP_VERSION_3;
130 }
131 return CURL_HTTP_VERSION_NONE;
132 }
133
GetHttpProxyInfo(std::string & host,int32_t & port,std::string & exclusions,bool & tunnel)134 void HttpClientTask::GetHttpProxyInfo(std::string &host, int32_t &port, std::string &exclusions,
135 bool &tunnel)
136 {
137 if (request_.GetHttpProxyType() == HttpProxyType::USE_SPECIFIED) {
138 HttpProxy proxy = request_.GetHttpProxy();
139 host = proxy.host;
140 port = proxy.port;
141 exclusions = proxy.exclusions;
142 tunnel = proxy.tunnel;
143 } else {
144 using namespace NetManagerStandard;
145 NetManagerStandard::HttpProxy httpProxy;
146 NetConnClient::GetInstance().GetDefaultHttpProxy(httpProxy);
147 host = httpProxy.GetHost();
148 port = httpProxy.GetPort();
149 exclusions = CommonUtils::ToString(httpProxy.GetExclusionList());
150 }
151 }
152
SetOtherCurlOption(CURL * handle)153 bool HttpClientTask::SetOtherCurlOption(CURL *handle)
154 {
155 // set proxy
156 std::string host;
157 std::string exclusions;
158 int32_t port = 0;
159 bool tunnel = false;
160 std::string url = request_.GetURL();
161 GetHttpProxyInfo(host, port, exclusions, tunnel);
162 if (!host.empty() && !CommonUtils::IsHostNameExcluded(url, exclusions, ",")) {
163 NETSTACK_LOGD("Set CURLOPT_PROXY: %{public}s:%{public}d, %{public}s", host.c_str(), port, exclusions.c_str());
164 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_PROXY, host.c_str());
165 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_PROXYPORT, port);
166 auto curlTunnelValue = (url.find("https://") != std::string::npos) ? 1L : 0L;
167 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_HTTPPROXYTUNNEL, curlTunnelValue);
168 auto proxyType = (host.find("https://") != std::string::npos) ? CURLPROXY_HTTPS : CURLPROXY_HTTP;
169 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_PROXYTYPE, proxyType);
170 }
171
172 #ifdef NO_SSL_CERTIFICATION
173 // in real life, you should buy a ssl certification and rename it to /etc/ssl/cert.pem
174 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_SSL_VERIFYHOST, 0L);
175 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_SSL_VERIFYPEER, 0L);
176 #else
177 #ifndef WINDOWS_PLATFORM
178 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_CAINFO, request_.GetCaPath().c_str());
179 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_CAPATH, HttpConstant::HTTP_PREPARE_CA_PATH);
180 #endif // WINDOWS_PLATFORM
181 SetServerSSLCertOption(handle);
182 #endif // NO_SSL_CERTIFICATION
183
184 #ifdef HTTP_CURL_PRINT_VERBOSE
185 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_VERBOSE, 1L);
186 #endif
187
188 #ifndef WINDOWS_PLATFORM
189 NETSTACK_CURL_EASY_SET_OPTION(handle, CURLOPT_ACCEPT_ENCODING, "");
190 #endif
191
192 return true;
193 }
194
SetServerSSLCertOption(CURL * curl)195 bool HttpClientTask::SetServerSSLCertOption(CURL *curl)
196 {
197 std::string pins;
198 auto hostname = CommonUtils::GetHostnameFromURL(request_.GetURL());
199 auto ret = NetManagerStandard::NetConnClient::GetInstance().GetPinSetForHostName(hostname, pins);
200 if (ret != 0 || pins.empty()) {
201 NETSTACK_LOGD("Get no pin set by host name[%{public}s]", hostname.c_str());
202 } else {
203 NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PINNEDPUBLICKEY, pins.c_str());
204 }
205
206 return true;
207 }
208
SetUploadOptions(CURL * handle)209 bool HttpClientTask::SetUploadOptions(CURL *handle)
210 {
211 if (filePath_.empty()) {
212 NETSTACK_LOGE("HttpClientTask::SetUploadOptions() filePath_ is empty");
213 error_.SetErrorCode(HttpErrorCode::HTTP_UPLOAD_FAILED);
214 return false;
215 }
216
217 std::string realPath;
218 if (!CheckFilePath(filePath_, realPath)) {
219 NETSTACK_LOGE("filePath_ does not exist! ");
220 error_.SetErrorCode(HttpErrorCode::HTTP_UPLOAD_FAILED);
221 return false;
222 }
223
224 file_ = fopen(realPath.c_str(), "rb");
225 if (file_ == nullptr) {
226 NETSTACK_LOGE("HttpClientTask::SetUploadOptions() Failed to open file %{public}s", realPath.c_str());
227 error_.SetErrorCode(HttpErrorCode::HTTP_UPLOAD_FAILED);
228 return false;
229 }
230
231 NETSTACK_LOGD("filePath_=%{public}s", realPath.c_str());
232 fseek(file_, 0, SEEK_END);
233 long size = ftell(file_);
234 rewind(file_);
235
236 // Set the file data and file size to upload
237 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_READDATA, file_);
238 NETSTACK_LOGD("CURLOPT_INFILESIZE=%{public}ld", size);
239 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_INFILESIZE, size);
240 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_UPLOAD, 1L);
241
242 return true;
243 }
244
SetCurlOptions()245 bool HttpClientTask::SetCurlOptions()
246 {
247 auto method = request_.GetMethod();
248 if (method == HttpConstant::HTTP_METHOD_HEAD) {
249 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_NOBODY, 1L);
250 }
251
252 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_URL, request_.GetURL().c_str());
253
254 if (type_ == TaskType::UPLOAD) {
255 if (!SetUploadOptions(curlHandle_)) {
256 return false;
257 }
258 } else {
259 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_CUSTOMREQUEST, request_.GetMethod().c_str());
260
261 if ((method == HttpConstant::HTTP_METHOD_POST || method == HttpConstant::HTTP_METHOD_PUT) &&
262 !request_.GetBody().empty()) {
263 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_POST, 1L);
264 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_POSTFIELDS, request_.GetBody().c_str());
265 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_POSTFIELDSIZE, request_.GetBody().size());
266 }
267 }
268
269 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_XFERINFOFUNCTION, ProgressCallback);
270 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_XFERINFODATA, &taskId_);
271 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_NOPROGRESS, 0L);
272
273 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_WRITEFUNCTION, DataReceiveCallback);
274 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_WRITEDATA, &taskId_);
275
276 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_HEADERFUNCTION, HeaderReceiveCallback);
277 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_HEADERDATA, &taskId_);
278
279 if (curlHeaderList_ != nullptr) {
280 curl_slist_free_all(curlHeaderList_);
281 curlHeaderList_ = nullptr;
282 }
283 for (const auto &header : request_.GetHeaders()) {
284 std::string headerStr = header.first + HttpConstant::HTTP_HEADER_SEPARATOR + header.second;
285 curlHeaderList_ = curl_slist_append(curlHeaderList_, headerStr.c_str());
286 }
287 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_HTTPHEADER, curlHeaderList_);
288
289 // Some servers don't like requests that are made without a user-agent field, so we provide one
290 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_USERAGENT, HttpConstant::HTTP_DEFAULT_USER_AGENT);
291
292 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_FOLLOWLOCATION, 1L);
293
294 /* first #undef CURL_DISABLE_COOKIES in curl config */
295 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_COOKIEFILE, "");
296
297 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_NOSIGNAL, 1L);
298
299 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_TIMEOUT_MS, request_.GetTimeout());
300 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_CONNECTTIMEOUT_MS, request_.GetConnectTimeout());
301
302 NETSTACK_CURL_EASY_SET_OPTION(curlHandle_, CURLOPT_HTTP_VERSION, GetHttpVersion(request_.GetHttpProtocol()));
303
304 if (!SetOtherCurlOption(curlHandle_)) {
305 return false;
306 }
307
308 return true;
309 }
310
Start()311 bool HttpClientTask::Start()
312 {
313 auto task = shared_from_this();
314 if (task->GetStatus() != TaskStatus::IDLE) {
315 NETSTACK_LOGD("task is running, taskId_=%{public}d", task->GetTaskId());
316 return false;
317 }
318
319 if (!CommonUtils::HasInternetPermission()) {
320 NETSTACK_LOGE("Don't Has Internet Permission()");
321 error_.SetErrorCode(HttpErrorCode::HTTP_PERMISSION_DENIED_CODE);
322 return false;
323 }
324
325 if (error_.GetErrorCode() != HttpErrorCode::HTTP_NONE_ERR) {
326 NETSTACK_LOGE("error_.GetErrorCode()=%{public}d", error_.GetErrorCode());
327 return false;
328 }
329
330 request_.SetRequestTime(HttpTime::GetNowTimeGMT());
331
332 HttpSession &session = HttpSession::GetInstance();
333 NETSTACK_LOGD("taskId_=%{public}d", taskId_);
334 task->canceled_ = false;
335
336 response_.SetRequestTime(HttpTime::GetNowTimeGMT());
337 session.StartTask(task);
338
339 return true;
340 }
341
Cancel()342 void HttpClientTask::Cancel()
343 {
344 canceled_ = true;
345 }
346
SetStatus(TaskStatus status)347 void HttpClientTask::SetStatus(TaskStatus status)
348 {
349 status_ = status;
350 }
351
GetStatus()352 TaskStatus HttpClientTask::GetStatus()
353 {
354 return status_;
355 }
356
GetType()357 TaskType HttpClientTask::GetType()
358 {
359 return type_;
360 }
361
GetFilePath()362 const std::string &HttpClientTask::GetFilePath()
363 {
364 return filePath_;
365 }
366
GetTaskId()367 unsigned int HttpClientTask::GetTaskId()
368 {
369 return taskId_;
370 }
371
OnSuccess(const std::function<void (const HttpClientRequest & request,const HttpClientResponse & response)> & onSucceeded)372 void HttpClientTask::OnSuccess(
373 const std::function<void(const HttpClientRequest &request, const HttpClientResponse &response)> &onSucceeded)
374 {
375 onSucceeded_ = onSucceeded;
376 }
377
OnCancel(const std::function<void (const HttpClientRequest & request,const HttpClientResponse & response)> & onCanceled)378 void HttpClientTask::OnCancel(
379 const std::function<void(const HttpClientRequest &request, const HttpClientResponse &response)> &onCanceled)
380 {
381 onCanceled_ = onCanceled;
382 }
383
OnFail(const std::function<void (const HttpClientRequest & request,const HttpClientResponse & response,const HttpClientError & error)> & onFailed)384 void HttpClientTask::OnFail(
385 const std::function<void(const HttpClientRequest &request, const HttpClientResponse &response,
386 const HttpClientError &error)> &onFailed)
387 {
388 onFailed_ = onFailed;
389 }
390
OnDataReceive(const std::function<void (const HttpClientRequest & request,const uint8_t * data,size_t length)> & onDataReceive)391 void HttpClientTask::OnDataReceive(
392 const std::function<void(const HttpClientRequest &request, const uint8_t *data, size_t length)> &onDataReceive)
393 {
394 onDataReceive_ = onDataReceive;
395 }
396
OnProgress(const std::function<void (const HttpClientRequest & request,u_long dlTotal,u_long dlNow,u_long ulTotal,u_long ulNow)> & onProgress)397 void HttpClientTask::OnProgress(const std::function<void(const HttpClientRequest &request, u_long dlTotal, u_long dlNow,
398 u_long ulTotal, u_long ulNow)> &onProgress)
399 {
400 onProgress_ = onProgress;
401 }
402
DataReceiveCallback(const void * data,size_t size,size_t memBytes,void * userData)403 size_t HttpClientTask::DataReceiveCallback(const void *data, size_t size, size_t memBytes, void *userData)
404 {
405 unsigned int taskId = *reinterpret_cast<unsigned int *>(userData);
406 NETSTACK_LOGD("taskId=%{public}d size=%{public}zu memBytes=%{public}zu",
407 taskId, size, memBytes);
408
409 auto task = HttpSession::GetInstance().GetTaskById(taskId);
410 if (task == nullptr) {
411 NETSTACK_LOGE("task == nullptr");
412 return 0;
413 }
414
415 if (task->canceled_) {
416 NETSTACK_LOGD("canceled");
417 return 0;
418 }
419
420 if (task->onDataReceive_) {
421 HttpClientRequest request = task->request_;
422 task->onDataReceive_(request, static_cast<const uint8_t *>(data), size * memBytes);
423 }
424
425 if (task->response_.GetResult().size() < MAX_LIMIT) {
426 task->response_.AppendResult(data, size * memBytes);
427 }
428
429 return size * memBytes;
430 }
431
ProgressCallback(void * userData,curl_off_t dltotal,curl_off_t dlnow,curl_off_t ultotal,curl_off_t ulnow)432 int HttpClientTask::ProgressCallback(void *userData, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal,
433 curl_off_t ulnow)
434 {
435 unsigned int taskId = *reinterpret_cast<unsigned int *>(userData);
436 NETSTACK_LOGD("taskId=%{public}d dltotal=%{public}" CURL_FORMAT_CURL_OFF_T
437 " dlnow=%{public}" CURL_FORMAT_CURL_OFF_T " ultotal=%{public}" CURL_FORMAT_CURL_OFF_T
438 " ulnow=%{public}" CURL_FORMAT_CURL_OFF_T,
439 taskId, dltotal, dlnow, ultotal, ulnow);
440
441 auto task = HttpSession::GetInstance().GetTaskById(taskId);
442 if (task == nullptr) {
443 NETSTACK_LOGE("HttpClientTask::ProgressCallback() task == nullptr");
444 return 0;
445 }
446
447 if (task->canceled_) {
448 NETSTACK_LOGD("canceled");
449 return CURLE_ABORTED_BY_CALLBACK;
450 }
451
452 if (task->onProgress_) {
453 task->onProgress_(task->request_, dltotal, dlnow, ultotal, ulnow);
454 }
455
456 return 0;
457 }
458
HeaderReceiveCallback(const void * data,size_t size,size_t memBytes,void * userData)459 size_t HttpClientTask::HeaderReceiveCallback(const void *data, size_t size, size_t memBytes, void *userData)
460 {
461 unsigned int taskId = *reinterpret_cast<unsigned int *>(userData);
462 NETSTACK_LOGD("taskId=%{public}d size=%{public}zu memBytes=%{public}zu",
463 taskId, size, memBytes);
464
465 if (size * memBytes > MAX_LIMIT) {
466 NETSTACK_LOGE("size * memBytes(%{public}zu) > MAX_LIMIT(%{public}zu)",
467 size * memBytes, MAX_LIMIT);
468 return 0;
469 }
470
471 auto task = HttpSession::GetInstance().GetTaskById(taskId);
472 if (task == nullptr) {
473 NETSTACK_LOGE("HttpClientTask::HeaderReceiveCallback() task == nullptr");
474 return 0;
475 }
476
477 task->response_.AppendHeader(static_cast<const char *>(data), size * memBytes);
478
479 return size * memBytes;
480 }
481
ProcessCookie(CURL * handle)482 void HttpClientTask::ProcessCookie(CURL *handle)
483 {
484 struct curl_slist *cookies = nullptr;
485 if (handle == nullptr) {
486 NETSTACK_LOGE("HttpClientTask::ProcessCookie() handle == nullptr");
487 return;
488 }
489
490 CURLcode res = curl_easy_getinfo(handle, CURLINFO_COOKIELIST, &cookies);
491 if (res != CURLE_OK) {
492 NETSTACK_LOGE("HttpClientTask::ProcessCookie() curl_easy_getinfo() error! res = %{public}d", res);
493 return;
494 }
495
496 while (cookies) {
497 response_.AppendCookies(cookies->data, strlen(cookies->data));
498 if (cookies->next != nullptr) {
499 response_.AppendCookies(HttpConstant::HTTP_LINE_SEPARATOR, strlen(HttpConstant::HTTP_LINE_SEPARATOR));
500 }
501 cookies = cookies->next;
502 }
503
504 NETSTACK_LOGD("ProcessCookie() GetCookies() = %{public}s", response_.GetCookies().c_str());
505 NETSTACK_LOGD("ProcessCookie() GetHeader() = %{public}s", response_.GetHeader().c_str());
506 }
507
ProcessResponseCode()508 bool HttpClientTask::ProcessResponseCode()
509 {
510 int64_t result = 0;
511 CURLcode code = curl_easy_getinfo(curlHandle_, CURLINFO_RESPONSE_CODE, &result);
512 if (code != CURLE_OK) {
513 error_.SetCURLResult(code);
514 return false;
515 }
516 ResponseCode resultCode = static_cast<ResponseCode>(result);
517 NETSTACK_LOGI("taskid=%{public}d, responseCode=%{public}d", taskId_, resultCode);
518 response_.SetResponseCode(resultCode);
519
520 return true;
521 }
522
GetTimingFromCurl(CURL * handle,CURLINFO info)523 double HttpClientTask::GetTimingFromCurl(CURL *handle, CURLINFO info)
524 {
525 time_t timing;
526 CURLcode result = curl_easy_getinfo(handle, info, &timing);
527 if (result != CURLE_OK) {
528 NETSTACK_LOGE("Failed to get timing: %{public}d, %{public}s", info, curl_easy_strerror(result));
529 return 0;
530 }
531 return static_cast<double>(timing);
532 }
533
ProcessResponse(CURLMsg * msg)534 void HttpClientTask::ProcessResponse(CURLMsg *msg)
535 {
536 CURLcode code = msg->data.result;
537 NETSTACK_LOGD("taskid=%{public}d code=%{public}d", taskId_, code);
538 error_.SetCURLResult(code);
539 response_.SetResponseTime(HttpTime::GetNowTimeGMT());
540
541 NETSTACK_LOGD("dnsTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_NAMELOOKUP_TIME_T));
542 NETSTACK_LOGD("connectTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_CONNECT_TIME_T));
543 NETSTACK_LOGD("tlsTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_APPCONNECT_TIME_T));
544 NETSTACK_LOGD("firstSendTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_PRETRANSFER_TIME_T));
545 NETSTACK_LOGD("firstRecvTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_STARTTRANSFER_TIME_T));
546 NETSTACK_LOGD("totalTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_TOTAL_TIME_T));
547 NETSTACK_LOGD("redirectTiming: %{public}lf", GetTimingFromCurl(curlHandle_, CURLINFO_REDIRECT_TIME_T));
548
549 if (CURLE_ABORTED_BY_CALLBACK == code) {
550 (void)ProcessResponseCode();
551 if (onCanceled_) {
552 onCanceled_(request_, response_);
553 }
554 return;
555 }
556
557 if (code != CURLE_OK) {
558 if (onFailed_) {
559 onFailed_(request_, response_, error_);
560 }
561 return;
562 }
563
564 ProcessCookie(curlHandle_);
565 response_.ParseHeaders();
566
567 if (ProcessResponseCode()) {
568 if (onSucceeded_) {
569 onSucceeded_(request_, response_);
570 }
571 } else if (onFailed_) {
572 onFailed_(request_, response_, error_);
573 }
574 }
575
SetResponse(const HttpClientResponse & response)576 void HttpClientTask::SetResponse(const HttpClientResponse &response)
577 {
578 response_ = response;
579 }
580 } // namespace HttpClient
581 } // namespace NetStack
582 } // namespace OHOS
583