| 189 | } |
| 190 | |
| 191 | void WorkerRunningRequest::send_answer(td::int32 status_code, std::vector<std::pair<std::string, std::string>> headers, |
| 192 | std::string orig_payload, bool payload_is_completed) { |
| 193 | if (completed_) { |
| 194 | return; |
| 195 | } |
| 196 | LOG(DEBUG) << "worker request " << proxy_request_id_.to_hex() << ": starting sending answer"; |
| 197 | |
| 198 | auto payload_to_send = postprocessor_->add_next_answer_slice(orig_payload); |
| 199 | if (payload_is_completed) { |
| 200 | payload_to_send = payload_to_send + postprocessor_->finalize(); |
| 201 | } |
| 202 | |
| 203 | stats()->answer_bytes_sent += (double)payload_to_send.size(); |
| 204 | if (payload_to_send.size() > 0) { |
| 205 | payload_parts_++; |
| 206 | payload_bytes_ += payload_to_send.size(); |
| 207 | } |
| 208 | |
| 209 | //http.response http_version:string status_code:int reason:string headers:(vector http.header) payload:bytes = http.Response; |
| 210 | auto res = cocoon::cocoon_api::make_object<cocoon_api::http_response>( |
| 211 | "HTTP/1.1", status_code, "", std::vector<ton::tl_object_ptr<cocoon_api::http_header>>{}, |
| 212 | td::BufferSlice(payload_to_send)); |
| 213 | |
| 214 | for (auto &h : headers) { |
| 215 | auto name = h.first; |
| 216 | std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) { return std::tolower(c); }); |
| 217 | if (name == "content-length" || name == "transfer-encoding" || name == "connection") { |
| 218 | continue; |
| 219 | } |
| 220 | res->headers_.push_back(cocoon::cocoon_api::make_object<cocoon_api::http_header>(h.first, h.second)); |
| 221 | } |
| 222 | |
| 223 | // Add debug timing headers using Unix timestamps |
| 224 | res->headers_.push_back(cocoon::cocoon_api::make_object<cocoon_api::http_header>( |
| 225 | "X-Cocoon-Worker-Start", PSTRING() << td::StringBuilder::FixedDouble(started_at_unix_, 6))); |
| 226 | res->headers_.push_back(cocoon::cocoon_api::make_object<cocoon_api::http_header>( |
| 227 | "X-Cocoon-Worker-End", PSTRING() << td::StringBuilder::FixedDouble(td::Clocks::system(), 6))); |
| 228 | |
| 229 | if (payload_is_completed) { |
| 230 | res->headers_.push_back( |
| 231 | cocoon::cocoon_api::make_object<cocoon_api::http_header>("Content-Length", PSTRING() << res->payload_.size())); |
| 232 | } else { |
| 233 | res->headers_.push_back(cocoon::cocoon_api::make_object<cocoon_api::http_header>("Transfer-Encoding", "chunked")); |
| 234 | } |
| 235 | |
| 236 | auto serialized_res = cocoon::serialize_tl_object(res, true); |
| 237 | td::BufferSlice ans; |
| 238 | auto final_info = payload_is_completed ? create_final_info() : nullptr; |
| 239 | ans = cocoon::create_serialize_tl_object<cocoon_api::proxy_queryAnswerEx>( |
| 240 | proxy_request_id_, std::move(serialized_res), payload_is_completed ? 1 : 0, std::move(final_info)); |
| 241 | td::actor::send_closure(runner_, &WorkerRunner::send_message_to_connection, proxy_connection_id_, std::move(ans)); |
| 242 | sent_answer_ = true; |
| 243 | |
| 244 | if (payload_is_completed) { |
| 245 | finish_request(true); |
| 246 | } |
| 247 | } |
| 248 |
nothing calls this directly
no test coverage detected