выкинул зависимость boost::url
This commit is contained in:
parent
5c348ace87
commit
839198820e
@ -36,7 +36,7 @@ add_executable(terminal-web-server
|
||||
src/server/resource.h
|
||||
)
|
||||
|
||||
find_package(Boost 1.53.0 COMPONENTS system thread filesystem url log log_setup REQUIRED)
|
||||
find_package(Boost 1.53.0 COMPONENTS system thread filesystem log log_setup REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(terminal-web-server ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES})
|
||||
target_include_directories(terminal-web-server PRIVATE ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR})
|
||||
|
@ -13,7 +13,7 @@ namespace http::server {
|
||||
}
|
||||
|
||||
void Connection::start() {
|
||||
do_read();
|
||||
doRead();
|
||||
}
|
||||
|
||||
void Connection::stop() {
|
||||
@ -22,11 +22,14 @@ namespace http::server {
|
||||
|
||||
Connection::~Connection() = default;
|
||||
|
||||
void Connection::do_read() {
|
||||
void Connection::doRead() {
|
||||
request_parser_.reset();
|
||||
request_.headers.clear();
|
||||
request_.method.clear();
|
||||
request_.uri.clear();
|
||||
request_.queryUri.clear();
|
||||
if (request_.url != nullptr) {
|
||||
request_.url.reset(nullptr);
|
||||
}
|
||||
|
||||
auto self(shared_from_this());
|
||||
socket_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) {
|
||||
@ -37,12 +40,12 @@ namespace http::server {
|
||||
|
||||
if (result == RequestParser::good) {
|
||||
request_handler_(request_, reply_);
|
||||
do_write();
|
||||
doWrite();
|
||||
} else if (result == RequestParser::bad) {
|
||||
stockReply(bad_request, reply_);
|
||||
do_write();
|
||||
doWrite();
|
||||
} else {
|
||||
do_read();
|
||||
doRead();
|
||||
}
|
||||
} else {
|
||||
connection_manager_.stop(shared_from_this());
|
||||
@ -50,7 +53,7 @@ namespace http::server {
|
||||
});
|
||||
}
|
||||
|
||||
void Connection::do_write() {
|
||||
void Connection::doWrite() {
|
||||
reply_.headers.push_back({.name = "Server", .value = SERVER_HEADER_VALUE});
|
||||
if (!reply_.content.empty()) {
|
||||
reply_.headers.push_back({.name = "Content-Length", .value = std::to_string(reply_.content.size())});
|
||||
@ -59,13 +62,13 @@ namespace http::server {
|
||||
reply_.headers.push_back({.name = "Connection", .value = "keep-alive"});
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "HTTP query " << reply_.status << " " << request_.method << " " << request_.uri;
|
||||
BOOST_LOG_TRIVIAL(info) << "HTTP query " << reply_.status << " " << request_.method << " " << request_.queryUri;
|
||||
|
||||
auto self(shared_from_this());
|
||||
async_write(socket_, reply_.to_buffers(), [this, self](boost::system::error_code ec, std::size_t) {
|
||||
if (!ec) {
|
||||
// keep alive Connection
|
||||
do_read();
|
||||
doRead();
|
||||
} else {
|
||||
connection_manager_.stop(shared_from_this());
|
||||
}
|
||||
@ -97,7 +100,7 @@ namespace http::server {
|
||||
request_parser_.reset();
|
||||
request_.headers.clear();
|
||||
request_.method.clear();
|
||||
request_.uri.clear();
|
||||
request_.queryUri.clear();
|
||||
|
||||
auto self(shared_from_this());
|
||||
stream_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) {
|
||||
@ -130,7 +133,7 @@ namespace http::server {
|
||||
reply_.headers.push_back({.name = "Connection", .value = "keep-alive"});
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "HTTP query " << reply_.status << " " << request_.method << " " << request_.uri;
|
||||
BOOST_LOG_TRIVIAL(info) << "HTTPS query " << reply_.status << " " << request_.method << " " << request_.queryUri;
|
||||
|
||||
auto self(shared_from_this());
|
||||
async_write(stream_, reply_.to_buffers(), [this, self](boost::system::error_code ec, std::size_t) {
|
||||
|
@ -47,10 +47,10 @@ namespace http::server {
|
||||
~Connection() override;
|
||||
private:
|
||||
/// Perform an asynchronous read operation.
|
||||
void do_read();
|
||||
void doRead();
|
||||
|
||||
/// Perform an asynchronous write operation.
|
||||
void do_write();
|
||||
void doWrite();
|
||||
|
||||
/// Socket for the Connection.
|
||||
boost::asio::ip::tcp::socket socket_;
|
||||
|
@ -3,14 +3,26 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "header.hpp"
|
||||
|
||||
|
||||
namespace http::server {
|
||||
class Url {
|
||||
public:
|
||||
explicit Url(const std::string& url);
|
||||
|
||||
std::string path;
|
||||
std::map<std::string, std::string> params;
|
||||
|
||||
~Url();
|
||||
};
|
||||
|
||||
/// A request received from a client.
|
||||
struct Request {
|
||||
std::string method;
|
||||
std::string uri;
|
||||
std::string queryUri;
|
||||
std::unique_ptr<Url> url;
|
||||
bool is_keep_alive;
|
||||
int http_version_major;
|
||||
int http_version_minor;
|
||||
|
@ -1,8 +1,38 @@
|
||||
#include "request_parser.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "request.hpp"
|
||||
|
||||
|
||||
namespace http::server {
|
||||
static void parseParams(Url& u, const std::string& query) {
|
||||
std::istringstream iss(query);
|
||||
std::string param;
|
||||
while (std::getline(iss, param, '&')) {
|
||||
size_t equal_pos = param.find('=');
|
||||
if (equal_pos != std::string::npos) {
|
||||
const std::string key = param.substr(0, equal_pos);
|
||||
const std::string value = param.substr(equal_pos + 1);
|
||||
u.params[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Url::Url(const std::string &url) {
|
||||
size_t question_mark_pos = url.find('?');
|
||||
if (question_mark_pos != std::string::npos) {
|
||||
path = url.substr(0, question_mark_pos);
|
||||
const std::string query = url.substr(question_mark_pos + 1);
|
||||
parseParams(*this, query);
|
||||
} else {
|
||||
path = url;
|
||||
}
|
||||
}
|
||||
|
||||
Url::~Url() = default;
|
||||
|
||||
|
||||
RequestParser::RequestParser()
|
||||
: state_(method_start) {
|
||||
}
|
||||
@ -38,7 +68,7 @@ namespace http::server {
|
||||
} else if (is_ctl(input)) {
|
||||
return bad;
|
||||
} else {
|
||||
req.uri.push_back(input);
|
||||
req.queryUri.push_back(input);
|
||||
return indeterminate;
|
||||
}
|
||||
case http_version_h:
|
||||
@ -131,7 +161,7 @@ namespace http::server {
|
||||
} else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
|
||||
return bad;
|
||||
} else {
|
||||
req.headers.push_back(header());
|
||||
req.headers.emplace_back();
|
||||
req.headers.back().name.push_back(input);
|
||||
state_ = header_name;
|
||||
return indeterminate;
|
||||
@ -184,7 +214,11 @@ namespace http::server {
|
||||
return bad;
|
||||
}
|
||||
case expecting_newline_3:
|
||||
return (input == '\n') ? good : bad;
|
||||
if (input == '\n') {
|
||||
req.url = std::make_unique<Url>(req.queryUri);
|
||||
return good;
|
||||
}
|
||||
return bad;
|
||||
default:
|
||||
return bad;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "server.hpp"
|
||||
#include <utility>
|
||||
#include <boost/beast/core/basic_stream.hpp>
|
||||
#include <boost/url/url_view.hpp>
|
||||
|
||||
|
||||
namespace http::server {
|
||||
@ -113,12 +112,8 @@ namespace http::server {
|
||||
}
|
||||
|
||||
void Server::requestHandler(const Request &req, reply &rep) {
|
||||
boost::urls::url_view url(req.uri);
|
||||
|
||||
const auto path = url.path();
|
||||
|
||||
// Request path must be absolute and not contain "..".
|
||||
if (path.empty() || path[0] != '/' || path.find("..") != std::string::npos) {
|
||||
if (req.url->path.empty() || req.url->path[0] != '/' || req.url->path.find("..") != std::string::npos) {
|
||||
stockReply(bad_request, rep);
|
||||
return;
|
||||
}
|
||||
@ -128,7 +123,7 @@ namespace http::server {
|
||||
rep.content.clear();
|
||||
|
||||
for (auto& res: resources) {
|
||||
if (res->path != path) {
|
||||
if (res->path != req.url->path) {
|
||||
continue;
|
||||
}
|
||||
res->handle(req, rep);
|
||||
|
Loading…
x
Reference in New Issue
Block a user