srctree

Robin Linden parent 13619b08 30f654d6
protocol: Support providing a user agent to use in http/s requests

protocol/handler_factory.cpp added: 58, removed: 30, total 28
@@ -8,12 +8,14 @@
#include "protocol/http_handler.h"
#include "protocol/https_handler.h"
 
#include <utility>
 
namespace protocol {
 
std::unique_ptr<MultiProtocolHandler> HandlerFactory::create() {
std::unique_ptr<MultiProtocolHandler> HandlerFactory::create(std::optional<std::string> user_agent) {
auto handler = std::make_unique<MultiProtocolHandler>();
handler->add("http", std::make_unique<HttpHandler>());
handler->add("https", std::make_unique<HttpsHandler>());
handler->add("http", std::make_unique<HttpHandler>(user_agent));
handler->add("https", std::make_unique<HttpsHandler>(std::move(user_agent)));
handler->add("file", std::make_unique<FileHandler>());
return handler;
}
 
protocol/handler_factory.h added: 58, removed: 30, total 28
@@ -8,12 +8,15 @@
#include "protocol/multi_protocol_handler.h"
 
#include <memory>
#include <optional>
#include <string>
 
namespace protocol {
 
class HandlerFactory {
public:
[[nodiscard]] static std::unique_ptr<MultiProtocolHandler> create();
[[nodiscard]] static std::unique_ptr<MultiProtocolHandler> create(
std::optional<std::string> user_agent = std::nullopt);
};
 
} // namespace protocol
 
protocol/http.cpp added: 58, removed: 30, total 28
@@ -30,7 +30,7 @@ bool Http::use_port(uri::Uri const &uri) {
return false;
}
 
std::string Http::create_get_request(uri::Uri const &uri) {
std::string Http::create_get_request(uri::Uri const &uri, std::optional<std::string_view> user_agent) {
std::stringstream ss;
ss << fmt::format("GET {} HTTP/1.1\r\n", uri.path);
if (Http::use_port(uri)) {
@@ -39,7 +39,12 @@ std::string Http::create_get_request(uri::Uri const &uri) {
ss << fmt::format("Host: {}\r\n", uri.authority.host);
}
ss << "Accept: text/html\r\n";
ss << "Connection: close\r\n\r\n";
ss << "Connection: close\r\n";
if (user_agent) {
ss << fmt::format("User-Agent: {}\r\n", *user_agent);
}
 
ss << "\r\n";
 
return std::move(ss).str();
}
 
protocol/http.h added: 58, removed: 30, total 28
@@ -21,11 +21,11 @@ namespace protocol {
 
class Http {
public:
static Response get(auto &&socket, uri::Uri const &uri) {
static Response get(auto &&socket, uri::Uri const &uri, std::optional<std::string_view> user_agent) {
using namespace std::string_view_literals;
 
if (socket.connect(uri.authority.host, Http::use_port(uri) ? uri.authority.port : uri.scheme)) {
socket.write(Http::create_get_request(uri));
socket.write(Http::create_get_request(uri, std::move(user_agent)));
auto data = socket.read_until("\r\n"sv);
if (data.empty()) {
return {Error::Unresolved};
@@ -106,7 +106,7 @@ private:
}
 
static bool use_port(uri::Uri const &uri);
static std::string create_get_request(uri::Uri const &uri);
static std::string create_get_request(uri::Uri const &uri, std::optional<std::string_view> user_agent);
static std::optional<StatusLine> parse_status_line(std::string_view status_line);
static Headers parse_headers(std::string_view header);
};
 
protocol/http_handler.cpp added: 58, removed: 30, total 28
@@ -11,7 +11,7 @@
namespace protocol {
 
Response HttpHandler::handle(uri::Uri const &uri) {
return Http::get(net::Socket{}, uri);
return Http::get(net::Socket{}, uri, user_agent_);
}
 
} // namespace protocol
 
protocol/http_handler.h added: 58, removed: 30, total 28
@@ -7,11 +7,20 @@
 
#include "protocol/iprotocol_handler.h"
 
#include <optional>
#include <string>
#include <utility>
 
namespace protocol {
 
class HttpHandler final : public IProtocolHandler {
public:
explicit HttpHandler(std::optional<std::string> user_agent) : user_agent_{std::move(user_agent)} {}
 
[[nodiscard]] Response handle(uri::Uri const &) override;
 
private:
std::optional<std::string> user_agent_;
};
 
} // namespace protocol
 
protocol/http_test.cpp added: 58, removed: 30, total 28
@@ -96,7 +96,7 @@ int main() {
"</head>\n"
"</html>\n";
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
require(response.headers.size() == 13);
expect_eq(socket.host, "example.com");
@@ -145,7 +145,7 @@ int main() {
"<A HREF=\"http://www.google.com/\">here</A>.\r\n"
"</BODY></HTML>\r\n";
 
auto response = protocol::Http::get(socket, create_uri("http://google.com"));
auto response = protocol::Http::get(socket, create_uri("http://google.com"), std::nullopt);
 
require(response.headers.size() == 7);
expect_eq(socket.host, "google.com");
@@ -177,7 +177,7 @@ int main() {
"0\r\n"
"\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.body,
"<!DOCTYPE html>\r\n"
@@ -196,7 +196,7 @@ int main() {
" 5\r\nhello\r\n"
" 0\r\n\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.body, "hello");
});
@@ -206,7 +206,7 @@ int main() {
"5 \r\nhello\r\n"
"0 \r\n\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.body, "hello");
});
@@ -216,7 +216,7 @@ int main() {
"8684838388283847263674\r\nhello\r\n"
"0\r\n\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.err, protocol::Error::InvalidResponse);
});
@@ -226,7 +226,7 @@ int main() {
"5\r\nhello"
"0\r\n\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.err, protocol::Error::InvalidResponse);
});
@@ -236,7 +236,7 @@ int main() {
"6\r\nhello\r\n"
"0\r\n\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.err, protocol::Error::InvalidResponse);
});
@@ -246,7 +246,7 @@ int main() {
"3\r\nhello\r\n"
"0\r\n\r\n");
 
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
expect_eq(response.err, protocol::Error::InvalidResponse);
});
@@ -254,7 +254,7 @@ int main() {
etest::test("404 no headers no body", [] {
FakeSocket socket;
socket.read_data = "HTTP/1.1 404 Not Found\r\n\r\n";
auto response = protocol::Http::get(socket, create_uri());
auto response = protocol::Http::get(socket, create_uri(), std::nullopt);
 
require(response.headers.size() == 0);
expect_eq(response.status_line.version, "HTTP/1.1"sv);
 
protocol/https_handler.cpp added: 58, removed: 30, total 28
@@ -11,7 +11,7 @@
namespace protocol {
 
Response HttpsHandler::handle(uri::Uri const &uri) {
return Http::get(net::SecureSocket{}, uri);
return Http::get(net::SecureSocket{}, uri, user_agent_);
}
 
} // namespace protocol
 
protocol/https_handler.h added: 58, removed: 30, total 28
@@ -7,11 +7,20 @@
 
#include "protocol/iprotocol_handler.h"
 
#include <optional>
#include <string>
#include <utility>
 
namespace protocol {
 
class HttpsHandler final : public IProtocolHandler {
public:
explicit HttpsHandler(std::optional<std::string> user_agent) : user_agent_{std::move(user_agent)} {}
 
[[nodiscard]] Response handle(uri::Uri const &) override;
 
private:
std::optional<std::string> user_agent_;
};
 
} // namespace protocol