ipv6 support
This commit is contained in:
@@ -34,7 +34,7 @@ int main(int argc, char* argv[]) {
|
|||||||
std::cout << "Book photos will be saved to: " << photo_dir << std::endl;
|
std::cout << "Book photos will be saved to: " << photo_dir << std::endl;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webcc::Server server{ port }; // No doc root
|
webcc::Server server{ asio::ip::tcp::v4(), port };
|
||||||
|
|
||||||
server.Route("/books",
|
server.Route("/books",
|
||||||
std::make_shared<BookListView>(),
|
std::make_shared<BookListView>(),
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ int main(int argc, char* argv[]) {
|
|||||||
std::uint16_t port = static_cast<std::uint16_t>(std::atoi(argv[1]));
|
std::uint16_t port = static_cast<std::uint16_t>(std::atoi(argv[1]));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webcc::Server server(port);
|
webcc::Server server{ asio::ip::tcp::v4(), port };
|
||||||
|
|
||||||
server.Route("/upload", std::make_shared<FileUploadView>(), { "POST" });
|
server.Route("/upload", std::make_shared<FileUploadView>(), { "POST" });
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
LOG_USER("Sleep seconds: %d", sleep_seconds);
|
LOG_USER("Sleep seconds: %d", sleep_seconds);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webcc::Server server{ 8080 };
|
webcc::Server server{ asio::ip::tcp::v4(), 8080 };
|
||||||
|
|
||||||
auto view = std::make_shared<HelloView>(sleep_seconds);
|
auto view = std::make_shared<HelloView>(sleep_seconds);
|
||||||
server.Route("/", view);
|
server.Route("/", view);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ int main() {
|
|||||||
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webcc::Server server{ 8080 };
|
webcc::Server server{ asio::ip::tcp::v4(), 8080 };
|
||||||
|
|
||||||
server.Route("/", std::make_shared<HelloView>());
|
server.Route("/", std::make_shared<HelloView>());
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ int main(int argc, char* argv[]) {
|
|||||||
std::string doc_root = argv[2];
|
std::string doc_root = argv[2];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webcc::Server server{ port, doc_root };
|
webcc::Server server{ asio::ip::tcp::v4(), port, doc_root };
|
||||||
|
|
||||||
if (argc == 4) {
|
if (argc == 4) {
|
||||||
server.set_file_chunk_size(std::atoi(argv[3]));
|
server.set_file_chunk_size(std::atoi(argv[3]));
|
||||||
|
|||||||
@@ -81,3 +81,14 @@ TEST(UrlTest, Full) {
|
|||||||
EXPECT_EQ("/path/to", url.path());
|
EXPECT_EQ("/path/to", url.path());
|
||||||
EXPECT_EQ("key=value", url.query());
|
EXPECT_EQ("key=value", url.query());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(UrlTest, IPv6) {
|
||||||
|
webcc::Url url("http://[::1]:8080");
|
||||||
|
|
||||||
|
EXPECT_EQ("http", url.scheme());
|
||||||
|
EXPECT_EQ("[::1]", url.host());
|
||||||
|
EXPECT_EQ("8080", url.port());
|
||||||
|
EXPECT_EQ("", url.path());
|
||||||
|
EXPECT_EQ("", url.query());
|
||||||
|
}
|
||||||
|
|||||||
+3
-1
@@ -102,7 +102,9 @@ void Client::DoConnect(RequestPtr request, const std::string& default_port) {
|
|||||||
LOG_VERB("Resolve host (%s)...", request->host().c_str());
|
LOG_VERB("Resolve host (%s)...", request->host().c_str());
|
||||||
|
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
auto endpoints = resolver.resolve(tcp::v4(), request->host(), port, ec);
|
|
||||||
|
// The protocol depends on the `host`, both V4 and V6 are supported.
|
||||||
|
auto endpoints = resolver.resolve(request->host(), port, ec);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Host resolve error (%s): %s, %s.", ec.message().c_str(),
|
LOG_ERRO("Host resolve error (%s): %s, %s.", ec.message().c_str(),
|
||||||
|
|||||||
+12
-6
@@ -16,9 +16,15 @@ using tcp = asio::ip::tcp;
|
|||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
Server::Server(std::uint16_t port, const std::filesystem::path& doc_root)
|
Server::Server(asio::ip::tcp protocol, std::uint16_t port,
|
||||||
: port_(port), doc_root_(doc_root), file_chunk_size_(1024), running_(false),
|
const sfs::path& doc_root)
|
||||||
acceptor_(io_context_), signals_(io_context_) {
|
: protocol_(protocol),
|
||||||
|
port_(port),
|
||||||
|
doc_root_(doc_root),
|
||||||
|
file_chunk_size_(1024),
|
||||||
|
running_(false),
|
||||||
|
acceptor_(io_context_),
|
||||||
|
signals_(io_context_) {
|
||||||
AddSignals();
|
AddSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +118,7 @@ void Server::AsyncWaitSignals() {
|
|||||||
bool Server::Listen(std::uint16_t port) {
|
bool Server::Listen(std::uint16_t port) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
|
||||||
tcp::endpoint endpoint(tcp::v4(), port);
|
tcp::endpoint endpoint(protocol_, port);
|
||||||
|
|
||||||
// Open the acceptor.
|
// Open the acceptor.
|
||||||
acceptor_.open(endpoint.protocol(), ec);
|
acceptor_.open(endpoint.protocol(), ec);
|
||||||
@@ -296,7 +302,7 @@ bool Server::MatchViewOrStatic(const std::string& method,
|
|||||||
|
|
||||||
// Try to match a static file.
|
// Try to match a static file.
|
||||||
if (method == methods::kGet && !doc_root_.empty()) {
|
if (method == methods::kGet && !doc_root_.empty()) {
|
||||||
std::filesystem::path path = doc_root_ / url;
|
sfs::path path = doc_root_ / url;
|
||||||
if (!sfs::is_directory(path) && sfs::exists(path)) {
|
if (!sfs::is_directory(path) && sfs::exists(path)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -313,7 +319,7 @@ ResponsePtr Server::ServeStatic(RequestPtr request) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path path = doc_root_ / request->url().path();
|
sfs::path path = doc_root_ / request->url().path();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// NOTE: FileBody might throw Error::kFileError.
|
// NOTE: FileBody might throw Error::kFileError.
|
||||||
|
|||||||
+4
-1
@@ -20,7 +20,7 @@ namespace webcc {
|
|||||||
|
|
||||||
class Server : public Router {
|
class Server : public Router {
|
||||||
public:
|
public:
|
||||||
explicit Server(std::uint16_t port,
|
Server(asio::ip::tcp protocol, std::uint16_t port,
|
||||||
const std::filesystem::path& doc_root = {});
|
const std::filesystem::path& doc_root = {});
|
||||||
|
|
||||||
~Server() = default;
|
~Server() = default;
|
||||||
@@ -94,6 +94,9 @@ private:
|
|||||||
ResponsePtr ServeStatic(RequestPtr request);
|
ResponsePtr ServeStatic(RequestPtr request);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// tcp::v4() or tcp::v6()
|
||||||
|
asio::ip::tcp protocol_;
|
||||||
|
|
||||||
// Port number.
|
// Port number.
|
||||||
std::uint16_t port_;
|
std::uint16_t port_;
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -274,13 +274,18 @@ void Url::Parse(const std::string& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!host_.empty()) {
|
if (!host_.empty()) {
|
||||||
p = host_.find(':');
|
// Check if there's a port.
|
||||||
|
p = host_.find_last_of(':');
|
||||||
if (p != std::string::npos) {
|
if (p != std::string::npos) {
|
||||||
|
// For IPv6: [::1]:8080
|
||||||
|
std::size_t bracket = host_.find_last_of(']');
|
||||||
|
if (bracket == std::string::npos || p > bracket) {
|
||||||
port_ = host_.substr(p + 1);
|
port_ = host_.substr(p + 1);
|
||||||
host_ = host_.substr(0, p);
|
host_ = host_.substr(0, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Url::Clear() {
|
void Url::Clear() {
|
||||||
scheme_.clear();
|
scheme_.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user