|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <fmt/format.h> |
|
|
#include <fmt/format.h> |
|
|
#include <fmt/ostream.h> |
|
|
#include <fmt/ostream.h> |
|
|
|
|
|
#include <neo/event.hpp> |
|
|
#include <neo/http/parse/chunked.hpp> |
|
|
#include <neo/http/parse/chunked.hpp> |
|
|
#include <neo/http/request.hpp> |
|
|
#include <neo/http/request.hpp> |
|
|
#include <neo/http/response.hpp> |
|
|
#include <neo/http/response.hpp> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace |
|
|
} // namespace |
|
|
|
|
|
|
|
|
|
|
|
http_session http_session::connect_for(const neo::url& url) { |
|
|
|
|
|
if (!url.host) { |
|
|
|
|
|
throw_user_error< |
|
|
|
|
|
errc::invalid_remote_url>("URL is invalid for network connection [{}]: No host segment", |
|
|
|
|
|
url.to_string()); |
|
|
|
|
|
} |
|
|
|
|
|
auto sub = neo::subscribe( |
|
|
|
|
|
[&](neo::address::ev_resolve ev) { |
|
|
|
|
|
dds_log(trace, "Resolving '{}:{}'", ev.host, ev.service); |
|
|
|
|
|
neo::bubble_event(ev); |
|
|
|
|
|
}, |
|
|
|
|
|
[&](neo::socket::ev_connect ev) { |
|
|
|
|
|
dds_log(trace, "Connecting {}", *url.host); |
|
|
|
|
|
neo::bubble_event(ev); |
|
|
|
|
|
}, |
|
|
|
|
|
[&](neo::ssl::ev_handshake ev) { |
|
|
|
|
|
dds_log(trace, "TLS handshake..."); |
|
|
|
|
|
neo::bubble_event(ev); |
|
|
|
|
|
}); |
|
|
|
|
|
if (url.scheme == "http") { |
|
|
|
|
|
return connect(*url.host, url.port_or_default_port_or(80)); |
|
|
|
|
|
} else if (url.scheme == "https") { |
|
|
|
|
|
return connect_ssl(*url.host, url.port_or_default_port_or(443)); |
|
|
|
|
|
} else { |
|
|
|
|
|
throw_user_error<errc::invalid_remote_url>("URL is invalid [{}]", url.to_string()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
http_session http_session::connect(const std::string& host, int port) { |
|
|
http_session http_session::connect(const std::string& host, int port) { |
|
|
DDS_E_SCOPE(e_http_connect{host, port}); |
|
|
DDS_E_SCOPE(e_http_connect{host, port}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
params.method, |
|
|
params.method, |
|
|
params.path, |
|
|
params.path, |
|
|
params.query); |
|
|
params.query); |
|
|
|
|
|
neo::emit(ev_http_request{params}); |
|
|
neo::http::request_line start_line{ |
|
|
neo::http::request_line start_line{ |
|
|
.method_view = params.method, |
|
|
.method_view = params.method, |
|
|
.target = neo::http::origin_form_target{ |
|
|
.target = neo::http::origin_form_target{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto cl_str = std::to_string(params.content_length); |
|
|
auto cl_str = std::to_string(params.content_length); |
|
|
|
|
|
|
|
|
|
|
|
// TODO: GZip downloads |
|
|
std::pair<std::string_view, std::string_view> headers[] = { |
|
|
std::pair<std::string_view, std::string_view> headers[] = { |
|
|
{"Host", host_string()}, |
|
|
{"Host", host_string()}, |
|
|
{"Accept", "*/*"}, |
|
|
{"Accept", "*/*"}, |
|
|
|
|
|
|
|
|
= _do_io([&](auto&& io) { return neo::http::read_response_head<http_response_info>(io); }); |
|
|
= _do_io([&](auto&& io) { return neo::http::read_response_head<http_response_info>(io); }); |
|
|
dds_log(trace, "Recv: HTTP {} {}", r.status, r.status_message); |
|
|
dds_log(trace, "Recv: HTTP {} {}", r.status, r.status_message); |
|
|
_state = _state_t::recvd_head; |
|
|
_state = _state_t::recvd_head; |
|
|
|
|
|
neo::emit(ev_http_response_begin{r}); |
|
|
return r; |
|
|
return r; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
neo::string_dynbuf_io resp_body; |
|
|
neo::string_dynbuf_io resp_body; |
|
|
_do_io([&](auto&& io) { download_into(resp_body, io, resp_head); }); |
|
|
_do_io([&](auto&& io) { download_into(resp_body, io, resp_head); }); |
|
|
|
|
|
neo::emit(ev_http_response_end{resp_head}); |
|
|
auto body_size = resp_body.available(); |
|
|
auto body_size = resp_body.available(); |
|
|
auto str = std::move(resp_body.string()); |
|
|
auto str = std::move(resp_body.string()); |
|
|
str.resize(body_size); |
|
|
str.resize(body_size); |
|
|
|
|
|
_state = _state_t::ready; |
|
|
return str; |
|
|
return str; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto ofile = neo::file_stream::open(dest, neo::open_mode::write | neo::open_mode::create); |
|
|
auto ofile = neo::file_stream::open(dest, neo::open_mode::write | neo::open_mode::create); |
|
|
neo::stream_io_buffers file_out{ofile}; |
|
|
neo::stream_io_buffers file_out{ofile}; |
|
|
_do_io([&](auto&& io) { download_into(file_out, io, resp_head); }); |
|
|
_do_io([&](auto&& io) { download_into(file_out, io, resp_head); }); |
|
|
|
|
|
neo::emit(ev_http_response_end{resp_head}); |
|
|
_state = _state_t::ready; |
|
|
_state = _state_t::ready; |
|
|
} |
|
|
} |
|
|
|
|
|
|