/* */ #include "HttpConnection.h" #include #include "util.h" #include "message.h" #include "prefs.h" #include "LogFactory.h" #include "DlRetryEx.h" #include "DlAbortEx.h" #include "Request.h" #include "Segment.h" #include "HttpRequest.h" #include "HttpResponse.h" #include "HttpHeaderProcessor.h" #include "HttpHeader.h" #include "Logger.h" #include "SocketCore.h" #include "Option.h" #include "CookieStorage.h" #include "AuthConfigFactory.h" #include "AuthConfig.h" #include "a2functional.h" #include "fmt.h" #include "SocketRecvBuffer.h" #include "array_fun.h" namespace aria2 { HttpRequestEntry::HttpRequestEntry(std::unique_ptr httpRequest) : httpRequest_{std::move(httpRequest)}, proc_{ make_unique(HttpHeaderProcessor::CLIENT_PARSER)} { } void HttpRequestEntry::resetHttpHeaderProcessor() { proc_ = make_unique(HttpHeaderProcessor::CLIENT_PARSER); } std::unique_ptr HttpRequestEntry::popHttpRequest() { return std::move(httpRequest_); } const std::unique_ptr& HttpRequestEntry::getHttpHeaderProcessor() const { return proc_; } HttpConnection::HttpConnection( cuid_t cuid, const std::shared_ptr& socket, const std::shared_ptr& socketRecvBuffer) : cuid_(cuid), socket_(socket), socketRecvBuffer_(socketRecvBuffer), socketBuffer_(socket) { } HttpConnection::~HttpConnection() = default; std::string HttpConnection::eraseConfidentialInfo(const std::string& request) { std::istringstream istr(request); std::string result; std::string line; while (getline(istr, line)) { if (util::startsWith(line, "Authorization: Basic")) { result += "Authorization: Basic ********\n"; } else if (util::startsWith(line, "Proxy-Authorization: Basic")) { result += "Proxy-Authorization: Basic ********\n"; } else { result += line; result += "\n"; } } return result; } void HttpConnection::sendRequest(std::unique_ptr httpRequest, std::string request) { A2_LOG_INFO( fmt(MSG_SENDING_REQUEST, cuid_, eraseConfidentialInfo(request).c_str())); socketBuffer_.pushStr(std::move(request)); socketBuffer_.send(); outstandingHttpRequests_.push_back( make_unique(std::move(httpRequest))); } void HttpConnection::sendRequest(std::unique_ptr httpRequest) { auto req = httpRequest->createRequest(); sendRequest(std::move(httpRequest), std::move(req)); } void HttpConnection::sendProxyRequest(std::unique_ptr httpRequest) { auto req = httpRequest->createProxyRequest(); sendRequest(std::move(httpRequest), std::move(req)); } std::unique_ptr HttpConnection::receiveResponse() { if (outstandingHttpRequests_.empty()) { throw DL_ABORT_EX(EX_NO_HTTP_REQUEST_ENTRY_FOUND); } if (socketRecvBuffer_->bufferEmpty()) { if (socketRecvBuffer_->recv() == 0 && !socket_->wantRead() && !socket_->wantWrite()) { throw DL_RETRY_EX(EX_GOT_EOF); } } const auto& proc = outstandingHttpRequests_.front()->getHttpHeaderProcessor(); if (proc->parse(socketRecvBuffer_->getBuffer(), socketRecvBuffer_->getBufferLength())) { A2_LOG_INFO( fmt(MSG_RECEIVE_RESPONSE, cuid_, proc->getHeaderString().c_str())); auto result = proc->getResult(); if (result->getStatusCode() / 100 == 1) { socketRecvBuffer_->drain(proc->getLastBytesProcessed()); outstandingHttpRequests_.front()->resetHttpHeaderProcessor(); return nullptr; } auto httpResponse = make_unique(); httpResponse->setCuid(cuid_); httpResponse->setHttpHeader(std::move(result)); httpResponse->setHttpRequest( outstandingHttpRequests_.front()->popHttpRequest()); socketRecvBuffer_->drain(proc->getLastBytesProcessed()); outstandingHttpRequests_.pop_front(); return httpResponse; } socketRecvBuffer_->drain(proc->getLastBytesProcessed()); return nullptr; } bool HttpConnection::isIssued(const std::shared_ptr& segment) const { for (const auto& entry : outstandingHttpRequests_) { if (*entry->getHttpRequest()->getSegment() == *segment) { return true; } } return false; } bool HttpConnection::sendBufferIsEmpty() const { return socketBuffer_.sendBufferIsEmpty(); } void HttpConnection::sendPendingData() { socketBuffer_.send(); } } // namespace aria2