| 347 | } |
| 348 | |
| 349 | void ProcessHttpResponse(InputMessageBase* msg) { |
| 350 | const int64_t start_parse_us = butil::cpuwide_time_us(); |
| 351 | DestroyingPtr<HttpContext> imsg_guard(static_cast<HttpContext*>(msg)); |
| 352 | Socket* socket = imsg_guard->socket(); |
| 353 | uint64_t cid_value; |
| 354 | const bool is_http2 = imsg_guard->header().is_http2(); |
| 355 | if (is_http2) { |
| 356 | H2StreamContext* h2_sctx = static_cast<H2StreamContext*>(msg); |
| 357 | cid_value = h2_sctx->correlation_id(); |
| 358 | } else { |
| 359 | cid_value = socket->correlation_id(); |
| 360 | } |
| 361 | if (cid_value == 0) { |
| 362 | LOG(WARNING) << "Fail to find correlation_id from " << *socket; |
| 363 | return; |
| 364 | } |
| 365 | const bthread_id_t cid = { cid_value }; |
| 366 | Controller* cntl = NULL; |
| 367 | const int rc = bthread_id_lock(cid, (void**)&cntl); |
| 368 | if (rc != 0) { |
| 369 | LOG_IF(ERROR, rc != EINVAL && rc != EPERM) |
| 370 | << "Fail to lock correlation_id=" << cid << ": " << berror(rc); |
| 371 | return; |
| 372 | } |
| 373 | |
| 374 | ControllerPrivateAccessor accessor(cntl); |
| 375 | |
| 376 | if (auto span = accessor.span()) { |
| 377 | span->set_base_real_us(msg->base_real_us()); |
| 378 | span->set_received_us(msg->received_us()); |
| 379 | // TODO: changing when imsg_guard->read_body_progressively() is true |
| 380 | span->set_response_size(imsg_guard->parsed_length()); |
| 381 | span->set_start_parse_us(start_parse_us); |
| 382 | } |
| 383 | |
| 384 | HttpHeader* res_header = &cntl->http_response(); |
| 385 | res_header->Swap(imsg_guard->header()); |
| 386 | butil::IOBuf& res_body = imsg_guard->body(); |
| 387 | CHECK(cntl->response_attachment().empty()); |
| 388 | const int saved_error = cntl->ErrorCode(); |
| 389 | |
| 390 | bool is_grpc_ct = false; |
| 391 | const HttpContentType content_type = |
| 392 | ParseContentType(res_header->content_type(), &is_grpc_ct); |
| 393 | const bool is_grpc = (is_http2 && is_grpc_ct); |
| 394 | bool grpc_compressed = false; // only valid when is_grpc is true. |
| 395 | |
| 396 | do { |
| 397 | if (!is_http2) { |
| 398 | // If header has "Connection: close", close the connection. |
| 399 | const std::string* conn_cmd = res_header->GetHeader(common->CONNECTION); |
| 400 | if (conn_cmd != NULL && 0 == strcasecmp(conn_cmd->c_str(), "close")) { |
| 401 | // Server asked to close the connection. |
| 402 | if (imsg_guard->read_body_progressively()) { |
| 403 | // Close the socket when reading completes. |
| 404 | socket->read_will_be_progressive(CONNECTION_TYPE_SHORT); |
| 405 | } else { |
| 406 | socket->SetFailed(); |
no test coverage detected