소스 검색

connect_for() for opening connections based on URLs

default_compile_flags
vector-of-bool 4 년 전
부모
커밋
850d02e379
3개의 변경된 파일51개의 추가작업 그리고 3개의 파일을 삭제
  1. +1
    -3
      src/dds/catalog/remote/http.cpp
  2. +35
    -0
      src/dds/http/session.cpp
  3. +15
    -0
      src/dds/http/session.hpp

+ 1
- 3
src/dds/catalog/remote/http.cpp 파일 보기

@@ -15,9 +15,7 @@ namespace {

void http_download_with_redir(neo::url url, path_ref dest) {
for (auto redir_count = 0;; ++redir_count) {
auto sess = url.scheme == "https"
? http_session::connect_ssl(*url.host, url.port_or_default_port_or(443))
: http_session::connect(*url.host, url.port_or_default_port_or(80));
auto sess = http_session::connect_for(url);

sess.send_head({.method = "GET", .path = url.path});


+ 35
- 0
src/dds/http/session.cpp 파일 보기

@@ -7,6 +7,7 @@

#include <fmt/format.h>
#include <fmt/ostream.h>
#include <neo/event.hpp>
#include <neo/http/parse/chunked.hpp>
#include <neo/http/request.hpp>
#include <neo/http/response.hpp>
@@ -46,6 +47,34 @@ void download_into(Out&& out, In&& in, http_response_info resp) {

} // 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) {
DDS_E_SCOPE(e_http_connect{host, port});

@@ -79,6 +108,7 @@ void http_session::send_head(http_request_params params) {
params.method,
params.path,
params.query);
neo::emit(ev_http_request{params});
neo::http::request_line start_line{
.method_view = params.method,
.target = neo::http::origin_form_target{
@@ -95,6 +125,7 @@ void http_session::send_head(http_request_params params) {

auto cl_str = std::to_string(params.content_length);

// TODO: GZip downloads
std::pair<std::string_view, std::string_view> headers[] = {
{"Host", host_string()},
{"Accept", "*/*"},
@@ -115,6 +146,7 @@ http_response_info http_session::recv_head() {
= _do_io([&](auto&& io) { return neo::http::read_response_head<http_response_info>(io); });
dds_log(trace, "Recv: HTTP {} {}", r.status, r.status_message);
_state = _state_t::recvd_head;
neo::emit(ev_http_response_begin{r});
return r;
}

@@ -125,9 +157,11 @@ std::string http_session::request(http_request_params params) {

neo::string_dynbuf_io resp_body;
_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 str = std::move(resp_body.string());
str.resize(body_size);
_state = _state_t::ready;
return str;
}

@@ -141,6 +175,7 @@ void http_session::recv_body_to_file(http_response_info const& resp_head,
auto ofile = neo::file_stream::open(dest, neo::open_mode::write | neo::open_mode::create);
neo::stream_io_buffers file_out{ofile};
_do_io([&](auto&& io) { download_into(file_out, io, resp_head); });
neo::emit(ev_http_response_end{resp_head});
_state = _state_t::ready;
}


+ 15
- 0
src/dds/http/session.hpp 파일 보기

@@ -6,6 +6,7 @@
#include <neo/io/stream/buffers.hpp>
#include <neo/io/stream/socket.hpp>
#include <neo/string_io.hpp>
#include <neo/url.hpp>

#include <filesystem>
#include <string>
@@ -28,6 +29,10 @@ struct http_request_params {
std::size_t content_length = 0;
};

struct ev_http_request {
const http_request_params& request;
};

struct http_response_info {
int status;
std::string status_message;
@@ -44,6 +49,14 @@ struct http_response_info {
bool is_redirect() const noexcept { return status >= 300 && status < 400; }
};

struct ev_http_response_begin {
const http_response_info& response;
};

struct ev_http_response_end {
const http_response_info& response;
};

enum class http_kind {
plain,
ssl,
@@ -118,6 +131,8 @@ public:
static http_session connect(const std::string& host, int port);
static http_session connect_ssl(const std::string& host, int port);

static http_session connect_for(const neo::url& url);

std::string request(http_request_params);

std::string request_get(std::string_view path) {

Loading…
취소
저장