From 22a8df854f567e368cabe57c2bb2d9b88fc87045 Mon Sep 17 00:00:00 2001 From: Thomas Sanchez Date: Thu, 13 Jul 2023 18:41:04 +0200 Subject: [PATCH] feat: rework interface and reading - remove the body_buffer_ - add a read_whole function to ready the whole body within the current buffer - It means that the request can point on the old header, so any change in capacity must trigger a parsing of the header - remove char* for string_view and update accordingly ragel parser --- CMakeLists.txt | 4 +- include/httpp/http/Connection.hpp | 128 +- include/httpp/http/Protocol.hpp | 8 +- include/httpp/http/Response.hpp | 102 +- include/httpp/http/client/Request.hpp | 2 +- src/httpp/http/Connection.cpp | 62 +- src/httpp/http/Protocol.cpp | 47 +- src/httpp/http/Response.cpp | 19 +- src/httpp/http/client/Connection.cpp | 2 +- src/httpp/http/client/Request.cpp | 4 +- src/httpp/http/parser.rl | 12 +- src/httpp/http/parser_ragel.cpp | 2857 ++++++++----------------- tests/request_parser/headers.cpp | 4 +- tests/request_parser/query.cpp | 7 +- tests/server/chunked_encoding.cpp | 14 +- tests/server/pipeline.cpp | 64 +- 16 files changed, 1239 insertions(+), 2097 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b090530..c78c690 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,8 +54,8 @@ option(BUILD_SHARED_LIBS "Build shared lib instead of static ones") # Setting vars ################################################################# set(HTTPP_VERSION_MAJOR "0") -set(HTTPP_VERSION_MINOR "8") -set(HTTPP_VERSION_PATCH "0") +set(HTTPP_VERSION_MINOR "9") +set(HTTPP_VERSION_PATCH "0~pre-alpha") set(CPACK_PACKAGE_VERSION_MAJOR ${HTTPP_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${HTTPP_VERSION_MINOR}) diff --git a/include/httpp/http/Connection.hpp b/include/httpp/http/Connection.hpp index fe29af7..10a3ade 100644 --- a/include/httpp/http/Connection.hpp +++ b/include/httpp/http/Connection.hpp @@ -90,29 +90,31 @@ class Connection throw std::logic_error("Invalid connection state"); } - size_t offset = 0; - - if (not body_buffer_.empty()) + auto already_read = request_buffer_.size() - offset_body_start_; + if (already_read) { - if (size <= body_buffer_.size()) + if (size <= already_read) { - std::copy(begin(body_buffer_), begin(body_buffer_) + size, buffer); - body_buffer_.erase(begin(body_buffer_), begin(body_buffer_) + size); + offset_body_end_ = offset_body_start_ + size; + std::copy( + request_buffer_.begin() + offset_body_start_, + request_buffer_.begin() + offset_body_end_, + buffer + ); disown(); callable(boost::system::error_code()); return; } - else - { - std::copy(begin(body_buffer_), end(body_buffer_), buffer); - size -= body_buffer_.size(); - offset += body_buffer_.size(); - body_buffer_.clear(); - } + std::copy( + request_buffer_.begin() + offset_body_start_, request_buffer_.end(), buffer + ); + size -= already_read; + request_buffer_.resize(offset_body_start_); } + offset_body_end_ = offset_body_start_; async_read( - boost::asio::buffer(buffer + offset, size), + boost::asio::buffer(buffer + already_read, size), [callable = std::move(callable), this](const boost::system::error_code& ec, size_t) mutable { disown(); @@ -138,23 +140,20 @@ class Connection throw std::logic_error("Invalid connection state"); } - if (not body_buffer_.empty()) + auto already_read = request_buffer_.size() - offset_body_start_; + if (already_read) { - if (body_size <= body_buffer_.size()) + auto body_start = request_buffer_.data() + offset_body_start_; + if (body_size <= already_read) { - callable(boost::system::error_code(), body_buffer_.data(), body_size); - body_buffer_.erase(begin(body_buffer_), begin(body_buffer_) + body_size); + offset_body_end_ = offset_body_start_ + body_size; + callable(boost::system::error_code(), body_start, already_read); body_size = 0; } else { - callable( - boost::system::error_code(), - body_buffer_.data(), - body_buffer_.size() - ); - body_size -= body_buffer_.size(); - body_buffer_.clear(); + callable(boost::system::error_code(), body_start, already_read); + body_size -= already_read; } } @@ -165,12 +164,19 @@ class Connection return; } + offset_body_end_ = offset_body_start_; auto buf_size = std::min(BUFFER_SIZE, body_size); - body_buffer_.resize(buf_size); + auto capacity = request_buffer_.capacity() - offset_body_start_; + if (capacity < buf_size) + { + request_buffer_.reserve(offset_body_start_ + buf_size + 1); + reparse(); + } + request_buffer_.resize(offset_body_start_ + buf_size); async_read_some( - boost::asio::buffer(body_buffer_), + boost::asio::buffer(request_buffer_.data() + offset_body_start_, buf_size), [body_size, callable = std::move(callable), this](const boost::system::error_code& ec, size_t size) mutable @@ -185,14 +191,77 @@ class Connection return; } - body_buffer_.resize(size); + request_buffer_.resize(offset_body_start_ + size); read(body_size, std::move(callable)); } ); } + template + void read_whole(size_t body_size, Callable callable) + { + if (!own()) + { + throw std::logic_error("Invalid connection state"); + } + + auto already_read = request_buffer_.size() - offset_body_start_; + offset_body_end_ = offset_body_start_ + body_size; + if (already_read) + { + if (body_size <= already_read) + { + callable(boost::system::error_code()); + return; + } + } + + if (!body_size) + { + disown(); + callable(boost::system::error_code()); + return; + } + + auto missing = body_size - already_read; + + // +1 for an hypothetical \0 + auto capacity = offset_body_end_ + 1; + if (request_buffer_.capacity() < capacity) + { + request_buffer_.reserve(capacity); + // pointer might have changed, so we need to reconstruct header, + // path, etc. + reparse(); + } + + request_buffer_.resize(offset_body_end_); + async_read( + boost::asio::buffer(request_buffer_.data() + offset_body_end_ - missing, missing), + [callable = std::move(callable), + this](const boost::system::error_code& ec, size_t size) mutable + { + disown(); + + if (ec) + { + LOG(connection_detail::conn_logger_, error) + << "Error detected while reading the body"; + callable(ec); + return; + } + + callable(boost::system::error_code()); + } + ); + } + void sendResponse(); void sendContinue(Callback&& cb); + std::pair mutable_body(); + +private: + void reparse(); private: static void release(Connection* connection); @@ -246,8 +315,9 @@ class Connection std::atomic_bool is_owned_ = {false}; bool should_be_deleted_ = {false}; std::vector request_buffer_; - std::vector body_buffer_; size_t size_ = 0; + size_t offset_body_start_ = 0; + size_t offset_body_end_ = 0; std::mutex mutex_; diff --git a/include/httpp/http/Protocol.hpp b/include/httpp/http/Protocol.hpp index d9fdfb5..771327b 100644 --- a/include/httpp/http/Protocol.hpp +++ b/include/httpp/http/Protocol.hpp @@ -12,6 +12,7 @@ #define HTTPP_HTTP_PROTOCOL_HPP_ #include +#include #include @@ -48,9 +49,8 @@ enum class Method CONNECT }; -std::string to_string(Method method); -Method method_from(const std::string& str); -Method method_from(const char* str); +std::string_view to_string(Method method); +Method method_from(std::string_view str); enum class HttpCode : unsigned int { @@ -106,7 +106,7 @@ enum class HttpCode : unsigned int HttpVersionNotSupported = 505 }; -const char* getDefaultMessage(HttpCode code); +std::string_view getDefaultMessage(HttpCode code); } // namespace HTTP } // namespace HTTPP diff --git a/include/httpp/http/Response.hpp b/include/httpp/http/Response.hpp index 3457bff..fa5402f 100644 --- a/include/httpp/http/Response.hpp +++ b/include/httpp/http/Response.hpp @@ -11,8 +11,10 @@ #ifndef _HTTPP_HTPP_RESPONSE_HPP_ #define _HTTPP_HTPP_RESPONSE_HPP_ +#include #include #include +#include #include #include @@ -37,11 +39,11 @@ class Response // "chunks" of a response. Each call to the ChunkedResponseCallback should // return a string representing the content for an individual chunk. An // empty string signifying the end of the response. - using ChunkedResponseCallback = std::function; + using ChunkedResponseCallback = std::function; Response() = default; Response(HttpCode code); - Response(HttpCode code, const std::string_view& body); + Response(HttpCode code, std::string_view body); Response(HttpCode code, ChunkedResponseCallback&& callback); Response& setCode(HttpCode code) @@ -58,73 +60,75 @@ class Response void clear(); Response& addHeader(std::string k, std::string v); - Response& setBody(const std::string_view& body); - Response& setBody(ChunkedResponseCallback&& callback); + Response& setBody(std::string_view body); + Response& setBody(ChunkedResponseCallback callback); template void sendResponse(Writer& writer, WriteHandler&& writeHandler) { - std::vector buffers; - buffers.reserve(5 + 1 + 4 * (headers_.size() + 1) + 1); + using namespace std::string_view_literals; + buffers_.clear(); + buffers_.reserve(5 + 1 + 4 * (headers_.size() + 1) + 1); { // HTTP/1.1 - buffers.emplace_back(boost::asio::buffer(HTTP_START)); - snprintf(code_str_, 4, "%i", int(code_)); - buffers.emplace_back(boost::asio::buffer(code_str_, strlen(code_str_))); - buffers.emplace_back(boost::asio::buffer(SPACE)); + buffers_.emplace_back(boost::asio::buffer(HTTP_START)); + auto n = std::snprintf(code_str_, 4, "%i", int(code_)); + buffers_.emplace_back(boost::asio::buffer(code_str_, n)); + buffers_.emplace_back(boost::asio::buffer(SPACE)); auto message = getDefaultMessage(code_); - buffers.emplace_back(boost::asio::buffer(message, ::strlen(message))); + buffers_.emplace_back(boost::asio::buffer(message)); } - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); for (const auto& header : headers_) { - buffers.emplace_back(boost::asio::buffer(header.first)); - buffers.emplace_back(boost::asio::buffer(HEADER_SEPARATOR)); - buffers.emplace_back(boost::asio::buffer(header.second)); - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + buffers_.emplace_back(boost::asio::buffer(header.first)); + buffers_.emplace_back(boost::asio::buffer(HEADER_SEPARATOR)); + buffers_.emplace_back(boost::asio::buffer(header.second)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); } { if (is_chunked_enconding()) { - static const std::string te = "Transfer-Encoding"; - static const std::string chunked = "chunked"; - buffers.emplace_back(boost::asio::buffer(te)); - buffers.emplace_back(boost::asio::buffer(HEADER_SEPARATOR)); - buffers.emplace_back(boost::asio::buffer(chunked)); - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + static const std::string_view te = "Transfer-Encoding"sv; + static const std::string_view chunked = "chunked"sv; + buffers_.emplace_back(boost::asio::buffer(te)); + buffers_.emplace_back(boost::asio::buffer(HEADER_SEPARATOR)); + buffers_.emplace_back(boost::asio::buffer(chunked)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); } else { - static const std::string cl = "Content-Length"; - buffers.emplace_back(boost::asio::buffer(cl)); - buffers.emplace_back(boost::asio::buffer(HEADER_SEPARATOR)); - - snprintf(body_size_, 16, "%lu", body_.size()); - buffers.emplace_back(boost::asio::buffer(body_size_, strlen(body_size_))); - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + static const std::string_view cl = "Content-Length"sv; + buffers_.emplace_back(boost::asio::buffer(cl)); + buffers_.emplace_back(boost::asio::buffer(HEADER_SEPARATOR)); + + auto n = + std::snprintf(body_size_, sizeof(body_size_), "%zu", body_.size()); + buffers_.emplace_back(boost::asio::buffer(body_size_, n)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); } } - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); if (!is_chunked_enconding()) { // response is non-chunked, send everything at once. if (!body_.empty()) { - buffers.emplace_back(boost::asio::buffer(body_)); + buffers_.emplace_back(boost::asio::buffer(body_)); } - boost::asio::async_write(writer, buffers, writeHandler); + boost::asio::async_write(writer, buffers_, writeHandler); } else { // send headers, then each chunks individually. boost::asio::async_write( writer, - buffers, + buffers_, [this, &writer, writeHandler](const boost::system::error_code& ec, size_t size) { // if there was an error sending the headers, notify the @@ -188,19 +192,24 @@ class Response if (!current_chunk_.empty()) { // Format the chunk header and chunk body. - std::vector buffers; - buffers.reserve(4); - std::stringstream header; - header << std::hex << current_chunk_.size(); - current_chunk_header_ = header.str(); - buffers.emplace_back(boost::asio::buffer(current_chunk_header_)); - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); - buffers.emplace_back(boost::asio::buffer(current_chunk_)); - buffers.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + buffers_.clear(); + buffers_.reserve(4); + + std::snprintf( + current_chunk_header_, + sizeof(current_chunk_header_), + "%zx", + current_chunk_.size() + ); + + buffers_.emplace_back(boost::asio::buffer(current_chunk_header_)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); + buffers_.emplace_back(boost::asio::buffer(current_chunk_)); + buffers_.emplace_back(boost::asio::buffer(HTTP_DELIMITER)); boost::asio::async_write( writer, - buffers, + buffers_, [this, &writer, writeHandler](const boost::system::error_code& ec, size_t size) { if (ec) @@ -232,14 +241,15 @@ class Response } private: + std::vector buffers_; HttpCode code_ = HttpCode::Ok; char code_str_[4]; std::vector body_; char body_size_[16]; - std::function chunkedBodyCallback_; - std::string current_chunk_header_; - std::string current_chunk_; + ChunkedResponseCallback chunkedBodyCallback_; + char current_chunk_header_[16]; + std::string_view current_chunk_; std::vector
headers_; bool should_be_closed_ = false; std::string status_string_; diff --git a/include/httpp/http/client/Request.hpp b/include/httpp/http/client/Request.hpp index e803a53..92c8816 100644 --- a/include/httpp/http/client/Request.hpp +++ b/include/httpp/http/client/Request.hpp @@ -46,7 +46,7 @@ class Request }; public: - Request& url(std::string url); + Request& url(std::string_view url); // unsafe, catenate current url + path Request& addToUrl(const std::string& path); diff --git a/src/httpp/http/Connection.cpp b/src/httpp/http/Connection.cpp index d85897b..00b90d2 100644 --- a/src/httpp/http/Connection.cpp +++ b/src/httpp/http/Connection.cpp @@ -144,22 +144,12 @@ void Connection::start() } // Maybe we have the beginning of the next request in the - // body_buffer_ - if (not body_buffer_.empty()) + // request_buffer_ + if (!request_buffer_.empty()) { - request_buffer_.swap(body_buffer_); + request_buffer_.erase(request_buffer_.begin(), request_buffer_.begin() + offset_body_end_); size_ = request_buffer_.size(); } - else - { - size_ = 0; - } - - request_buffer_.resize(BUF_SIZE, 0); - - body_buffer_.clear(); - body_buffer_.reserve(BUF_SIZE); - request_.clear(); response_.clear(); @@ -195,7 +185,7 @@ void Connection::read_request() return; } - if (Parser::isComplete(request_buffer_.data(), size_)) + if (Parser::isComplete(request_buffer_.data(), request_buffer_.size())) { request_.setDate(); #if HTTPP_PARSER_BACKEND_IS_STREAM @@ -221,16 +211,7 @@ void Connection::read_request() DLOG(conn_logger_, trace) << "Received a request from: " << source() << ": " << request_; - if (consumed != size_) - { - body_buffer_.insert( - body_buffer_.begin(), - request_buffer_.begin() + consumed, - request_buffer_.begin() + size_ - ); - request_buffer_.resize(consumed); - } - + offset_body_end_ = offset_body_start_ = consumed; disown(); handler_.connection_notify_request(this); } @@ -241,19 +222,19 @@ void Connection::read_request() << "Invalid request received from: " << source() << "\n" << std::string(request_buffer_.data(), size_); - response_ = Response( - HttpCode::BadRequest, - std::string("An error occured in the request " - "parsing indicating an error") - ); - response_.connectionShouldBeClosed(true); - + response_.setCode(HttpCode::BadRequest) + .setBody( + "An error occured in the request parsing indicating an " + "error" + ) + .connectionShouldBeClosed(true); disown(); sendResponse(); } } else { + request_buffer_.resize(request_buffer_.capacity()); if (size_ == request_buffer_.size()) { request_buffer_.resize(request_buffer_.size() + BUF_SIZE); @@ -263,7 +244,7 @@ void Connection::read_request() data += size_; async_read_some( - boost::asio::buffer(data, request_buffer_.capacity() - size_), + boost::asio::buffer(data, BUF_SIZE), [this](const boost::system::error_code& ec, size_t size) { if (ec) @@ -273,13 +254,23 @@ void Connection::read_request() return; } - this->size_ += size; + size_ += size; + request_buffer_.resize(size_); read_request(); } ); } } +void Connection::reparse() +{ + request_.clear(); + const char* begin = request_buffer_.data(); + const char* end = begin + offset_body_start_; + size_t consumed = 0; + Parser::parse(begin, end, consumed, request_); +} + void Connection::sendResponse(Callback&& cb) { if (shouldBeDeleted()) @@ -373,5 +364,10 @@ void Connection::recycle() } } +std::pair Connection::mutable_body() +{ + return {request_buffer_.data() + offset_body_start_, offset_body_end_ - offset_body_start_}; +} + } // namespace HTTP } // namespace HTTPP diff --git a/src/httpp/http/Protocol.cpp b/src/httpp/http/Protocol.cpp index 20f27a1..5c39039 100644 --- a/src/httpp/http/Protocol.cpp +++ b/src/httpp/http/Protocol.cpp @@ -18,29 +18,30 @@ namespace HTTPP { namespace HTTP { +using namespace std::string_view_literals; -std::string to_string(Method method) +std::string_view to_string(Method method) { switch (method) { default: - return "UNKNOWN"; + return "UNKNOWN"sv; case Method::GET: - return "GET"; + return "GET"sv; case Method::POST: - return "POST"; + return "POST"sv; case Method::PUT: - return "PUT"; + return "PUT"sv; case Method::HEAD: - return "HEAD"; + return "HEAD"sv; case Method::CONNECT: - return "CONNECT"; + return "CONNECT"sv; case Method::TRACE: - return "TRACE"; + return "TRACE"sv; case Method::OPTIONS: - return "OPTIONS"; + return "OPTIONS"sv; case Method::DELETE_: - return "DELETE"; + return "DELETE"sv; } } @@ -54,27 +55,17 @@ std::string to_string(Method method) FN(TRACE, TRACE) \ FN(CONNECT, CONNECT) -Method method_from(const std::string& str) +Method method_from(std::string_view str) { #define fn(name, e) \ - if (str == #name) return Method::e; - APPLY_ON_METHOD(fn) -#undef fn - - throw std::runtime_error("Unknown method"); -} - -Method method_from(const char* str) -{ -#define my_strlen(str) \ - (__extension__(__builtin_constant_p(str) ? __builtin_strlen(str) : ::strlen(str))) - -#define fn(name, e) \ - if (::strncmp(#name, str, my_strlen(#name)) == 0) return Method::e; + if (str == #name##sv) \ + { \ + return Method::e; \ + } APPLY_ON_METHOD(fn) #undef fn - throw std::runtime_error("Unknown method"); + throw std::runtime_error("Unknown method: " + std::string(str)); } #define APPLY_ON_HTTP_CODE(FN) \ @@ -120,7 +111,7 @@ Method method_from(const char* str) FN(GatewayTimeout) \ FN(HttpVersionNotSupported) -const char* getDefaultMessage(HttpCode code) +std::string_view getDefaultMessage(HttpCode code) { switch (code) { @@ -129,7 +120,7 @@ const char* getDefaultMessage(HttpCode code) #define FN(code) \ case HttpCode::code: \ - return #code; + return #code##sv; APPLY_ON_HTTP_CODE(FN) #undef FN } diff --git a/src/httpp/http/Response.cpp b/src/httpp/http/Response.cpp index ae69707..7fe5f3c 100644 --- a/src/httpp/http/Response.cpp +++ b/src/httpp/http/Response.cpp @@ -53,7 +53,7 @@ Response::Response(HttpCode code) setBody(getDefaultMessage(code_)); } -Response::Response(HttpCode code, const std::string_view& body) +Response::Response(HttpCode code, std::string_view body) { setCode(code); setBody(body); @@ -72,8 +72,8 @@ void Response::clear() should_be_closed_ = false; chunkedBodyCallback_ = nullptr; - current_chunk_.clear(); - current_chunk_header_.clear(); + current_chunk_ = ""; + current_chunk_header_[0] = 0; status_string_.clear(); headers_.clear(); } @@ -103,7 +103,7 @@ Response& Response::addHeader(std::string k, std::string v) return *this; } -Response& Response::setBody(const std::string_view& body) +Response& Response::setBody(std::string_view body) { chunkedBodyCallback_ = nullptr; body_.reserve(body.size()); @@ -111,7 +111,7 @@ Response& Response::setBody(const std::string_view& body) return *this; } -Response& Response::setBody(ChunkedResponseCallback&& callback) +Response& Response::setBody(ChunkedResponseCallback callback) { if (callback) { @@ -119,12 +119,9 @@ Response& Response::setBody(ChunkedResponseCallback&& callback) chunkedBodyCallback_ = std::move(callback); return *this; } - else - { - throw std::invalid_argument( - "Setting chunked response body to an empty callback" - ); - } + throw std::invalid_argument( + "Setting chunked response body to an empty callback" + ); } } // namespace HTTP diff --git a/src/httpp/http/client/Connection.cpp b/src/httpp/http/client/Connection.cpp index c1c466b..5173ded 100644 --- a/src/httpp/http/client/Connection.cpp +++ b/src/httpp/http/client/Connection.cpp @@ -254,7 +254,7 @@ void Connection::configureRequest(HTTPP::HTTP::Method method) case HTTPP::HTTP::Method::OPTIONS: case HTTPP::HTTP::Method::TRACE: case HTTPP::HTTP::Method::CONNECT: - std::string method_str = to_string(method); + auto method_str = to_string(method); conn_setopt(CURLOPT_CUSTOMREQUEST, method_str.data()); break; } diff --git a/src/httpp/http/client/Request.cpp b/src/httpp/http/client/Request.cpp index 18a0d47..4dd36ed 100644 --- a/src/httpp/http/client/Request.cpp +++ b/src/httpp/http/client/Request.cpp @@ -22,9 +22,9 @@ namespace HTTP namespace client { -Request& Request::url(std::string u) +Request& Request::url(std::string_view u) { - url_ = std::move(u); + url_.assign(u.begin(), u.end()); return *this; } diff --git a/src/httpp/http/parser.rl b/src/httpp/http/parser.rl index 362ceb0..5b79dc0 100644 --- a/src/httpp/http/parser.rl +++ b/src/httpp/http/parser.rl @@ -45,7 +45,7 @@ action start_key { action end_key { token_end = fpc; - request.headers.emplace_back(std::make_pair(TOKEN_REF, "")); + request.headers.emplace_back(TOKEN_REF, ""); token_begin = token_end = nullptr; } @@ -65,7 +65,7 @@ action start_qkey { action end_qkey { token_end = fpc; - request.query_params.emplace_back(std::make_pair({UTILS::url_decode(token_begin, token_end)}, "")); + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); token_begin = token_end = nullptr; } @@ -84,16 +84,16 @@ action start_method { } action end_method { + token_end = fpc; try { - request.method = method_from(token_begin); + request.method = method_from(TOKEN_REF); } catch(...) { fbreak; } - - token_begin = nullptr; + token_begin = token_end = nullptr; } }%% @@ -124,7 +124,7 @@ bool Parser::parse(const char* start, major = digit >{ request.major = fc - '0';}; minor = digit >{request.minor = fc - '0';}; - status_line = (method >start_method @end_method) space query space "HTTP/" major "." minor "\r\n"; + status_line = (method >start_method %end_method) space query space "HTTP/" major "." minor "\r\n"; key = identifier >start_key %end_key; value = (any+ -- "\r\n") >start_value %end_value; diff --git a/src/httpp/http/parser_ragel.cpp b/src/httpp/http/parser_ragel.cpp index 9f6f9d4..84f03b2 100644 --- a/src/httpp/http/parser_ragel.cpp +++ b/src/httpp/http/parser_ragel.cpp @@ -10,1947 +10,979 @@ * */ -#include #include +#include #include #include "httpp/http/Parser.hpp" #include "httpp/http/Request.hpp" -#include "httpp/utils/LazyDecodedValue.hpp" #include "httpp/utils/URL.hpp" +#include "httpp/utils/LazyDecodedValue.hpp" #if HTTPP_PARSER_BACKEND_IS_RAGEL -# define TOKEN_LEN size_t(token_end - token_begin) -# define TOKEN_REF std::string_view(token_begin, TOKEN_LEN) +#define TOKEN_LEN size_t(token_end - token_begin) +#define TOKEN_REF std::string_view(token_begin, TOKEN_LEN) -# line 30 "parser_ragel.cpp" + +#line 27 "parser.c" static const int http_start = 1; static const int http_first_final = 61; static const int http_error = 0; static const int http_en_main = 1; -# line 29 "parser.rl" -# line 99 "parser.rl" +#line 29 "parser.rl" -namespace HTTPP -{ -namespace HTTP -{ -bool Parser::parse(const char* start, const char* end, size_t& consumed, Request& request) + + +#line 99 "parser.rl" + + +namespace HTTPP { namespace HTTP { +bool Parser::parse(const char* start, + const char* end, + size_t& consumed, + Request& request) { - const char* p = start; + const char *p = start; int cs; const char *token_begin, *token_end; -# line 57 "parser_ragel.cpp" + +#line 48 "parser.c" + { + cs = http_start; + } + +#line 51 "parser.c" + { + switch ( cs ) + { +case 1: + switch( (*p) ) { + case 67: goto tr0; + case 68: goto tr2; + case 71: goto tr3; + case 72: goto tr4; + case 79: goto tr5; + case 80: goto tr6; + case 84: goto tr7; + } + goto st0; +st0: +cs = 0; + goto _out; +tr0: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st2; +st2: + p += 1; +case 2: +#line 76 "parser.c" + if ( (*p) == 79 ) + goto st3; + goto st0; +st3: + p += 1; +case 3: + if ( (*p) == 78 ) + goto st4; + goto st0; +st4: + p += 1; +case 4: + if ( (*p) == 78 ) + goto st5; + goto st0; +st5: + p += 1; +case 5: + if ( (*p) == 69 ) + goto st6; + goto st0; +st6: + p += 1; +case 6: + if ( (*p) == 67 ) + goto st7; + goto st0; +st7: + p += 1; +case 7: + if ( (*p) == 84 ) + goto st8; + goto st0; +st8: + p += 1; +case 8: + if ( (*p) == 32 ) + goto tr14; + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr14; + goto st0; +tr14: +#line 86 "parser.rl" + { + token_end = p; + try { - cs = http_start; + request.method = method_from(TOKEN_REF); } - -# line 62 "parser_ragel.cpp" + catch(...) { - switch (cs) - { - case 1: - switch ((*p)) - { - case 67: - { - goto ctr0; - } - case 68: - { - goto ctr2; - } - case 71: - { - goto ctr3; - } - case 72: - { - goto ctr4; - } - case 79: - { - goto ctr5; - } - case 80: - { - goto ctr6; - } - case 84: - { - goto ctr7; - } - } - { - goto st0; - } - st0: - cs = 0; - goto _out; - ctr0: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st2; - st2: - p += 1; - case 2: -# line 105 "parser_ragel.cpp" - if ((*p) == 79) - { - goto st3; - } - { - goto st0; - } - st3: - p += 1; - case 3: - if ((*p) == 78) - { - goto st4; - } - { - goto st0; - } - st4: - p += 1; - case 4: - if ((*p) == 78) - { - goto st5; - } - { - goto st0; - } - st5: - p += 1; - case 5: - if ((*p) == 69) - { - goto st6; - } - { - goto st0; - } - st6: - p += 1; - case 6: - if ((*p) == 67) - { - goto st7; - } - { - goto st0; - } - st7: - p += 1; - case 7: - if ((*p) == 84) - { - goto ctr13; - } - { - goto st0; - } - ctr13: -# line 86 "parser.rl" - { - try - { - request.method = method_from(token_begin); - } - catch (...) - { - { - p++; - cs = 8; - goto _out; - } - } + {p++; cs = 9; goto _out;} + } + token_begin = token_end = nullptr; +} + goto st9; +st9: + p += 1; +case 9: +#line 134 "parser.c" + switch( (*p) ) { + case 32: goto st0; + case 63: goto st0; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto st0; + goto tr15; +tr15: +#line 32 "parser.rl" + { + token_begin = p; +} + goto st10; +st10: + p += 1; +case 10: +#line 149 "parser.c" + switch( (*p) ) { + case 32: goto tr17; + case 63: goto tr18; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr17; + goto st10; +tr17: +#line 36 "parser.rl" + { + token_end = p; + request.uri = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st11; +tr58: +#line 62 "parser.rl" + { + token_begin = p; +} +#line 66 "parser.rl" + { + token_end = p; + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); + token_begin = token_end = nullptr; +} + goto st11; +tr62: +#line 66 "parser.rl" + { + token_end = p; + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); + token_begin = token_end = nullptr; +} + goto st11; +tr66: +#line 72 "parser.rl" + { + token_begin = p; +} +#line 76 "parser.rl" + { + token_end = p; + request.query_params.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st11; +tr69: +#line 76 "parser.rl" + { + token_end = p; + request.query_params.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st11; +st11: + p += 1; +case 11: +#line 200 "parser.c" + if ( (*p) == 72 ) + goto st12; + goto st0; +st12: + p += 1; +case 12: + if ( (*p) == 84 ) + goto st13; + goto st0; +st13: + p += 1; +case 13: + if ( (*p) == 84 ) + goto st14; + goto st0; +st14: + p += 1; +case 14: + if ( (*p) == 80 ) + goto st15; + goto st0; +st15: + p += 1; +case 15: + if ( (*p) == 47 ) + goto st16; + goto st0; +st16: + p += 1; +case 16: + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr24; + goto st0; +tr24: +#line 125 "parser.rl" + { request.major = (*p) - '0';} + goto st17; +st17: + p += 1; +case 17: +#line 239 "parser.c" + if ( (*p) == 46 ) + goto st18; + goto st0; +st18: + p += 1; +case 18: + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr26; + goto st0; +tr26: +#line 126 "parser.rl" + {request.minor = (*p) - '0';} + goto st19; +st19: + p += 1; +case 19: +#line 254 "parser.c" + if ( (*p) == 13 ) + goto st20; + goto st0; +st20: + p += 1; +case 20: + if ( (*p) == 10 ) + goto st21; + goto st0; +st21: + p += 1; +case 21: + switch( (*p) ) { + case 13: goto st22; + case 45: goto tr30; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr30; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr30; + } else + goto tr30; + goto st0; +st22: + p += 1; +case 22: + if ( (*p) == 10 ) + goto st61; + goto st0; +st61: +#line 134 "parser.rl" + { + {p++; cs = 61; goto _out;} + } + p += 1; +case 61: +#line 291 "parser.c" + goto st0; +tr30: +#line 42 "parser.rl" + { + token_begin = p; +} + goto st23; +st23: + p += 1; +case 23: +#line 300 "parser.c" + switch( (*p) ) { + case 32: goto tr32; + case 45: goto st23; + case 58: goto tr34; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr32; + } else if ( (*p) > 57 ) { + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st23; + } else if ( (*p) >= 65 ) + goto st23; + } else + goto st23; + goto st0; +tr32: +#line 46 "parser.rl" + { + token_end = p; + request.headers.emplace_back(TOKEN_REF, ""); + token_begin = token_end = nullptr; +} + goto st24; +st24: + p += 1; +case 24: +#line 327 "parser.c" + switch( (*p) ) { + case 32: goto st24; + case 58: goto st25; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto st24; + goto st0; +tr34: +#line 46 "parser.rl" + { + token_end = p; + request.headers.emplace_back(TOKEN_REF, ""); + token_begin = token_end = nullptr; +} + goto st25; +st25: + p += 1; +case 25: +#line 344 "parser.c" + switch( (*p) ) { + case 13: goto tr39; + case 32: goto tr38; + } + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr38; + goto tr37; +tr37: +#line 52 "parser.rl" + { + token_begin = p; +} + goto st26; +st26: + p += 1; +case 26: +#line 359 "parser.c" + if ( (*p) == 13 ) + goto tr41; + goto st26; +tr41: +#line 56 "parser.rl" + { + token_end = p; + request.headers.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st27; +st27: + p += 1; +case 27: +#line 372 "parser.c" + switch( (*p) ) { + case 10: goto st21; + case 13: goto tr41; + } + goto st26; +tr50: +#line 46 "parser.rl" + { + token_end = p; + request.headers.emplace_back(TOKEN_REF, ""); + token_begin = token_end = nullptr; +} + goto st28; +tr38: +#line 52 "parser.rl" + { + token_begin = p; +} + goto st28; +st28: + p += 1; +case 28: +#line 392 "parser.c" + switch( (*p) ) { + case 13: goto tr42; + case 32: goto tr38; + } + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr38; + goto tr37; +tr39: +#line 52 "parser.rl" + { + token_begin = p; +} + goto st29; +tr42: +#line 52 "parser.rl" + { + token_begin = p; +} +#line 56 "parser.rl" + { + token_end = p; + request.headers.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st29; +st29: + p += 1; +case 29: +#line 417 "parser.c" + switch( (*p) ) { + case 10: goto tr43; + case 13: goto tr42; + case 32: goto tr38; + } + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr38; + goto tr37; +tr43: +#line 52 "parser.rl" + { + token_begin = p; +} + goto st30; +st30: + p += 1; +case 30: +#line 433 "parser.c" + switch( (*p) ) { + case 13: goto tr44; + case 32: goto tr38; + case 45: goto tr45; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr38; + } else if ( (*p) > 57 ) { + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr45; + } else if ( (*p) >= 65 ) + goto tr45; + } else + goto tr45; + goto tr37; +tr44: +#line 52 "parser.rl" + { + token_begin = p; +} +#line 56 "parser.rl" + { + token_end = p; + request.headers.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st31; +st31: + p += 1; +case 31: +#line 463 "parser.c" + switch( (*p) ) { + case 10: goto tr46; + case 13: goto tr42; + case 32: goto tr38; + } + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr38; + goto tr37; +tr46: +#line 52 "parser.rl" + { + token_begin = p; +} + goto st62; +st62: +#line 134 "parser.rl" + { + {p++; cs = 62; goto _out;} + } + p += 1; +case 62: +#line 482 "parser.c" + switch( (*p) ) { + case 13: goto tr44; + case 32: goto tr38; + case 45: goto tr45; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr38; + } else if ( (*p) > 57 ) { + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr45; + } else if ( (*p) >= 65 ) + goto tr45; + } else + goto tr45; + goto tr37; +tr45: +#line 52 "parser.rl" + { + token_begin = p; +} +#line 42 "parser.rl" + { + token_begin = p; +} + goto st32; +st32: + p += 1; +case 32: +#line 510 "parser.c" + switch( (*p) ) { + case 13: goto tr48; + case 32: goto tr47; + case 45: goto st32; + case 58: goto tr50; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 12 ) + goto tr47; + } else if ( (*p) > 57 ) { + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st32; + } else if ( (*p) >= 65 ) + goto st32; + } else + goto st32; + goto st26; +tr47: +#line 46 "parser.rl" + { + token_end = p; + request.headers.emplace_back(TOKEN_REF, ""); + token_begin = token_end = nullptr; +} + goto st33; +st33: + p += 1; +case 33: +#line 538 "parser.c" + switch( (*p) ) { + case 13: goto tr52; + case 32: goto st33; + case 58: goto st28; + } + if ( 9 <= (*p) && (*p) <= 12 ) + goto st33; + goto st26; +tr52: +#line 56 "parser.rl" + { + token_end = p; + request.headers.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st34; +tr48: +#line 46 "parser.rl" + { + token_end = p; + request.headers.emplace_back(TOKEN_REF, ""); + token_begin = token_end = nullptr; +} +#line 56 "parser.rl" + { + token_end = p; + request.headers.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st34; +st34: + p += 1; +case 34: +#line 568 "parser.c" + switch( (*p) ) { + case 10: goto st35; + case 13: goto tr52; + case 32: goto st33; + case 58: goto st28; + } + if ( 9 <= (*p) && (*p) <= 12 ) + goto st33; + goto st26; +st35: + p += 1; +case 35: + switch( (*p) ) { + case 13: goto st36; + case 32: goto st24; + case 45: goto tr30; + case 58: goto st25; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 12 ) + goto st24; + } else if ( (*p) > 57 ) { + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr30; + } else if ( (*p) >= 65 ) + goto tr30; + } else + goto tr30; + goto st0; +st36: + p += 1; +case 36: + switch( (*p) ) { + case 10: goto st63; + case 32: goto st24; + case 58: goto st25; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto st24; + goto st0; +st63: +#line 134 "parser.rl" + { + {p++; cs = 63; goto _out;} + } + p += 1; +case 63: +#line 615 "parser.c" + switch( (*p) ) { + case 32: goto st24; + case 58: goto st25; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto st24; + goto st0; +tr18: +#line 36 "parser.rl" + { + token_end = p; + request.uri = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st37; +tr59: +#line 62 "parser.rl" + { + token_begin = p; +} +#line 66 "parser.rl" + { + token_end = p; + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); + token_begin = token_end = nullptr; +} + goto st37; +tr63: +#line 66 "parser.rl" + { + token_end = p; + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); + token_begin = token_end = nullptr; +} + goto st37; +tr67: +#line 72 "parser.rl" + { + token_begin = p; +} +#line 76 "parser.rl" + { + token_end = p; + request.query_params.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st37; +tr70: +#line 76 "parser.rl" + { + token_end = p; + request.query_params.back().second = TOKEN_REF; + token_begin = token_end = nullptr; +} + goto st37; +st37: + p += 1; +case 37: +#line 666 "parser.c" + switch( (*p) ) { + case 32: goto tr58; + case 38: goto tr59; + case 61: goto tr60; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr58; + goto tr57; +tr57: +#line 62 "parser.rl" + { + token_begin = p; +} + goto st38; +st38: + p += 1; +case 38: +#line 682 "parser.c" + switch( (*p) ) { + case 32: goto tr62; + case 38: goto tr63; + case 61: goto tr64; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr62; + goto st38; +tr60: +#line 62 "parser.rl" + { + token_begin = p; +} +#line 66 "parser.rl" + { + token_end = p; + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); + token_begin = token_end = nullptr; +} + goto st39; +tr64: +#line 66 "parser.rl" + { + token_end = p; + request.query_params.emplace_back(UTILS::url_decode(token_begin, token_end), ""); + token_begin = token_end = nullptr; +} + goto st39; +st39: + p += 1; +case 39: +#line 710 "parser.c" + switch( (*p) ) { + case 32: goto tr66; + case 38: goto tr67; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr66; + goto tr65; +tr65: +#line 72 "parser.rl" + { + token_begin = p; +} + goto st40; +st40: + p += 1; +case 40: +#line 725 "parser.c" + switch( (*p) ) { + case 32: goto tr69; + case 38: goto tr70; + } + if ( 9 <= (*p) && (*p) <= 13 ) + goto tr69; + goto st40; +tr2: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st41; +st41: + p += 1; +case 41: +#line 740 "parser.c" + if ( (*p) == 69 ) + goto st42; + goto st0; +st42: + p += 1; +case 42: + if ( (*p) == 76 ) + goto st43; + goto st0; +st43: + p += 1; +case 43: + if ( (*p) == 69 ) + goto st44; + goto st0; +st44: + p += 1; +case 44: + if ( (*p) == 84 ) + goto st45; + goto st0; +st45: + p += 1; +case 45: + if ( (*p) == 69 ) + goto st8; + goto st0; +tr3: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st46; +st46: + p += 1; +case 46: +#line 775 "parser.c" + if ( (*p) == 69 ) + goto st7; + goto st0; +tr4: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st47; +st47: + p += 1; +case 47: +#line 786 "parser.c" + if ( (*p) == 69 ) + goto st48; + goto st0; +st48: + p += 1; +case 48: + if ( (*p) == 65 ) + goto st49; + goto st0; +st49: + p += 1; +case 49: + if ( (*p) == 68 ) + goto st8; + goto st0; +tr5: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st50; +st50: + p += 1; +case 50: +#line 809 "parser.c" + if ( (*p) == 80 ) + goto st51; + goto st0; +st51: + p += 1; +case 51: + if ( (*p) == 84 ) + goto st52; + goto st0; +st52: + p += 1; +case 52: + if ( (*p) == 73 ) + goto st53; + goto st0; +st53: + p += 1; +case 53: + if ( (*p) == 79 ) + goto st54; + goto st0; +st54: + p += 1; +case 54: + if ( (*p) == 78 ) + goto st55; + goto st0; +st55: + p += 1; +case 55: + if ( (*p) == 83 ) + goto st8; + goto st0; +tr6: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st56; +st56: + p += 1; +case 56: +#line 850 "parser.c" + switch( (*p) ) { + case 79: goto st57; + case 85: goto st7; + } + goto st0; +st57: + p += 1; +case 57: + if ( (*p) == 83 ) + goto st7; + goto st0; +tr7: +#line 82 "parser.rl" + { + token_begin = p; +} + goto st58; +st58: + p += 1; +case 58: +#line 869 "parser.c" + if ( (*p) == 82 ) + goto st59; + goto st0; +st59: + p += 1; +case 59: + if ( (*p) == 65 ) + goto st60; + goto st0; +st60: + p += 1; +case 60: + if ( (*p) == 67 ) + goto st45; + goto st0; + } - token_begin = nullptr; - } - goto st8; - st8: - p += 1; - case 8: -# line 175 "parser_ragel.cpp" - if ((*p) == 32) - { - goto st9; - } - if (9 <= (*p) && (*p) <= 13) - { - goto st9; - } - { - goto st0; - } - st9: - p += 1; - case 9: - switch ((*p)) - { - case 32: - { - goto st0; - } - case 63: - { - goto st0; - } - } - if ((*p) < 14) - { - if (9 <= (*p)) - { - goto st0; - } - } - else if ((*p) > 31) - { - if ((*p) > 62) - { - if (64 <= (*p)) - { - goto ctr15; - } - } - else if ((*p) >= 33) - { - goto ctr15; - } - } - else - { - goto ctr15; - } - { - goto ctr15; - } - ctr15: -# line 32 "parser.rl" - { - token_begin = p; - } - goto st10; - st10: - p += 1; - case 10: -# line 223 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto ctr17; - } - case 63: - { - goto ctr18; - } - } - if ((*p) < 14) - { - if (9 <= (*p)) - { - goto ctr17; - } - } - else if ((*p) > 31) - { - if ((*p) > 62) - { - if (64 <= (*p)) - { - goto st10; - } - } - else if ((*p) >= 33) - { - goto st10; - } - } - else - { - goto st10; - } - { - goto st10; - } - ctr17: -# line 36 "parser.rl" - { - token_end = p; - request.uri = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st11; - ctr58: -# line 62 "parser.rl" - { - token_begin = p; - } -# line 66 "parser.rl" - { - token_end = p; - request.query_params.emplace_back(std::make_pair( - {UTILS::url_decode(token_begin, token_end)}, "" - )); - token_begin = token_end = nullptr; - } - goto st11; - ctr62: -# line 66 "parser.rl" - { - token_end = p; - request.query_params.emplace_back(std::make_pair( - {UTILS::url_decode(token_begin, token_end)}, "" - )); - token_begin = token_end = nullptr; - } - goto st11; - ctr66: -# line 72 "parser.rl" - { - token_begin = p; - } -# line 76 "parser.rl" - { - token_end = p; - request.query_params.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st11; - ctr69: -# line 76 "parser.rl" - { - token_end = p; - request.query_params.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st11; - st11: - p += 1; - case 11: -# line 301 "parser_ragel.cpp" - if ((*p) == 72) - { - goto st12; - } - { - goto st0; - } - st12: - p += 1; - case 12: - if ((*p) == 84) - { - goto st13; - } - { - goto st0; - } - st13: - p += 1; - case 13: - if ((*p) == 84) - { - goto st14; - } - { - goto st0; - } - st14: - p += 1; - case 14: - if ((*p) == 80) - { - goto st15; - } - { - goto st0; - } - st15: - p += 1; - case 15: - if ((*p) == 47) - { - goto st16; - } - { - goto st0; - } - st16: - p += 1; - case 16: - if (48 <= (*p) && (*p) <= 57) - { - goto ctr24; - } - { - goto st0; - } - ctr24: -# line 125 "parser.rl" - { - request.major = (*p) - '0'; - } - goto st17; - st17: - p += 1; - case 17: -# line 360 "parser_ragel.cpp" - if ((*p) == 46) - { - goto st18; - } - { - goto st0; - } - st18: - p += 1; - case 18: - if (48 <= (*p) && (*p) <= 57) - { - goto ctr26; - } - { - goto st0; - } - ctr26: -# line 126 "parser.rl" - { - request.minor = (*p) - '0'; - } - goto st19; - st19: - p += 1; - case 19: -# line 383 "parser_ragel.cpp" - if ((*p) == 13) - { - goto st20; - } - { - goto st0; - } - st20: - p += 1; - case 20: - if ((*p) == 10) - { - goto st21; - } - { - goto st0; - } - st21: - p += 1; - case 21: - switch ((*p)) - { - case 13: - { - goto st22; - } - case 45: - { - goto ctr30; - } - } - if ((*p) < 65) - { - if (48 <= (*p) && (*p) <= 57) - { - goto ctr30; - } - } - else if ((*p) > 90) - { - if (97 <= (*p) && (*p) <= 122) - { - goto ctr30; - } - } - else - { - goto ctr30; - } - { - goto st0; - } - st22: - p += 1; - case 22: - if ((*p) == 10) - { - goto st61; - } - { - goto st0; - } - st61: -# line 134 "parser.rl" - { - { - p++; - cs = 61; - goto _out; - } - } - p += 1; - case 61: -# line 440 "parser_ragel.cpp" - { - goto st0; - } - ctr30: -# line 42 "parser.rl" - { - token_begin = p; - } - goto st23; - st23: - p += 1; - case 23: -# line 453 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto ctr32; - } - case 45: - { - goto st23; - } - case 58: - { - goto ctr34; - } - } - if ((*p) < 48) - { - if (9 <= (*p) && (*p) <= 13) - { - goto ctr32; - } - } - else if ((*p) > 57) - { - if ((*p) > 90) - { - if (97 <= (*p) && (*p) <= 122) - { - goto st23; - } - } - else if ((*p) >= 65) - { - goto st23; - } - } - else - { - goto st23; - } - { - goto st0; - } - ctr32: -# line 46 "parser.rl" - { - token_end = p; - request.headers.emplace_back( - std::make_pair(TOKEN_REF, "") - ); - token_begin = token_end = nullptr; - } - goto st24; - st24: - p += 1; - case 24: -# line 494 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto st24; - } - case 58: - { - goto st25; - } - } - if (9 <= (*p) && (*p) <= 13) - { - goto st24; - } - { - goto st0; - } - ctr34: -# line 46 "parser.rl" - { - token_end = p; - request.headers.emplace_back( - std::make_pair(TOKEN_REF, "") - ); - token_begin = token_end = nullptr; - } - goto st25; - st25: - p += 1; - case 25: -# line 520 "parser_ragel.cpp" - switch ((*p)) - { - case 13: - { - goto ctr39; - } - case 32: - { - goto ctr38; - } - } - if ((*p) < 14) - { - if (9 <= (*p) && (*p) <= 12) - { - goto ctr38; - } - } - else if ((*p) > 31) - { - if (33 <= (*p)) - { - goto ctr37; - } - } - else - { - goto ctr37; - } - { - goto ctr37; - } - ctr37: -# line 52 "parser.rl" - { - token_begin = p; - } - goto st26; - st26: - p += 1; - case 26: -# line 552 "parser_ragel.cpp" - if ((*p) == 13) - { - goto ctr41; - } - if (14 <= (*p)) - { - goto st26; - } - { - goto st26; - } - ctr41: -# line 56 "parser.rl" - { - token_end = p; - request.headers.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st27; - st27: - p += 1; - case 27: -# line 573 "parser_ragel.cpp" - switch ((*p)) - { - case 10: - { - goto st21; - } - case 13: - { - goto ctr41; - } - } - if ((*p) > 12) - { - if (14 <= (*p)) - { - goto st26; - } - } - else if ((*p) >= 11) - { - goto st26; - } - { - goto st26; - } - ctr50: -# line 46 "parser.rl" - { - token_end = p; - request.headers.emplace_back( - std::make_pair(TOKEN_REF, "") - ); - token_begin = token_end = nullptr; - } - goto st28; - ctr38: -# line 52 "parser.rl" - { - token_begin = p; - } - goto st28; - st28: - p += 1; - case 28: -# line 609 "parser_ragel.cpp" - switch ((*p)) - { - case 13: - { - goto ctr42; - } - case 32: - { - goto ctr38; - } - } - if ((*p) < 14) - { - if (9 <= (*p) && (*p) <= 12) - { - goto ctr38; - } - } - else if ((*p) > 31) - { - if (33 <= (*p)) - { - goto ctr37; - } - } - else - { - goto ctr37; - } - { - goto ctr37; - } - ctr39: -# line 52 "parser.rl" - { - token_begin = p; - } - goto st29; - ctr42: -# line 52 "parser.rl" - { - token_begin = p; - } -# line 56 "parser.rl" - { - token_end = p; - request.headers.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st29; - st29: - p += 1; - case 29: -# line 653 "parser_ragel.cpp" - switch ((*p)) - { - case 9: - { - goto ctr38; - } - case 10: - { - goto ctr43; - } - case 13: - { - goto ctr42; - } - case 32: - { - goto ctr38; - } - } - if ((*p) < 14) - { - if (11 <= (*p) && (*p) <= 12) - { - goto ctr38; - } - } - else if ((*p) > 31) - { - if (33 <= (*p)) - { - goto ctr37; - } - } - else - { - goto ctr37; - } - { - goto ctr37; - } - ctr43: -# line 52 "parser.rl" - { - token_begin = p; - } - goto st30; - st30: - p += 1; - case 30: -# line 691 "parser_ragel.cpp" - switch ((*p)) - { - case 13: - { - goto ctr44; - } - case 32: - { - goto ctr38; - } - case 45: - { - goto ctr45; - } - } - if ((*p) < 48) - { - if ((*p) < 14) - { - if (9 <= (*p) && (*p) <= 12) - { - goto ctr38; - } - } - else if ((*p) > 31) - { - if ((*p) > 44) - { - if (46 <= (*p)) - { - goto ctr37; - } - } - else if ((*p) >= 33) - { - goto ctr37; - } - } - else - { - goto ctr37; - } - } - else if ((*p) > 57) - { - if ((*p) < 91) - { - if ((*p) > 64) - { - { - goto ctr45; - } - } - else - { - goto ctr37; - } - } - else if ((*p) > 96) - { - if ((*p) > 122) - { - { - goto ctr37; - } - } - else - { - goto ctr45; - } - } - else - { - goto ctr37; - } - } - else - { - goto ctr45; - } - { - goto ctr37; - } - ctr44: -# line 52 "parser.rl" - { - token_begin = p; - } -# line 56 "parser.rl" - { - token_end = p; - request.headers.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st31; - st31: - p += 1; - case 31: -# line 760 "parser_ragel.cpp" - switch ((*p)) - { - case 9: - { - goto ctr38; - } - case 10: - { - goto ctr46; - } - case 13: - { - goto ctr42; - } - case 32: - { - goto ctr38; - } - } - if ((*p) < 14) - { - if (11 <= (*p) && (*p) <= 12) - { - goto ctr38; - } - } - else if ((*p) > 31) - { - if (33 <= (*p)) - { - goto ctr37; - } - } - else - { - goto ctr37; - } - { - goto ctr37; - } - ctr46: -# line 52 "parser.rl" - { - token_begin = p; - } - goto st62; - st62: -# line 134 "parser.rl" - { - { - p++; - cs = 62; - goto _out; - } - } - p += 1; - case 62: -# line 802 "parser_ragel.cpp" - switch ((*p)) - { - case 13: - { - goto ctr44; - } - case 32: - { - goto ctr38; - } - case 45: - { - goto ctr45; - } - } - if ((*p) < 48) - { - if ((*p) < 14) - { - if (9 <= (*p) && (*p) <= 12) - { - goto ctr38; - } - } - else if ((*p) > 31) - { - if ((*p) > 44) - { - if (46 <= (*p)) - { - goto ctr37; - } - } - else if ((*p) >= 33) - { - goto ctr37; - } - } - else - { - goto ctr37; - } - } - else if ((*p) > 57) - { - if ((*p) < 91) - { - if ((*p) > 64) - { - { - goto ctr45; - } - } - else - { - goto ctr37; - } - } - else if ((*p) > 96) - { - if ((*p) > 122) - { - { - goto ctr37; - } - } - else - { - goto ctr45; - } - } - else - { - goto ctr37; - } - } - else - { - goto ctr45; - } - { - goto ctr37; - } - ctr45: -# line 52 "parser.rl" - { - token_begin = p; - } -# line 42 "parser.rl" - { - token_begin = p; - } - goto st32; - st32: - p += 1; - case 32: -# line 869 "parser_ragel.cpp" - switch ((*p)) - { - case 13: - { - goto ctr48; - } - case 32: - { - goto ctr47; - } - case 45: - { - goto st32; - } - case 58: - { - goto ctr50; - } - } - if ((*p) < 48) - { - if ((*p) < 14) - { - if (9 <= (*p) && (*p) <= 12) - { - goto ctr47; - } - } - else if ((*p) > 31) - { - if ((*p) > 44) - { - if (46 <= (*p)) - { - goto st26; - } - } - else if ((*p) >= 33) - { - goto st26; - } - } - else - { - goto st26; - } - } - else if ((*p) > 57) - { - if ((*p) < 91) - { - if ((*p) > 64) - { - { - goto st32; - } - } - else if ((*p) >= 59) - { - goto st26; - } - } - else if ((*p) > 96) - { - if ((*p) > 122) - { - { - goto st26; - } - } - else - { - goto st32; - } - } - else - { - goto st26; - } - } - else - { - goto st32; - } - { - goto st26; - } - ctr47: -# line 46 "parser.rl" - { - token_end = p; - request.headers.emplace_back( - std::make_pair(TOKEN_REF, "") - ); - token_begin = token_end = nullptr; - } - goto st33; - st33: - p += 1; - case 33: -# line 937 "parser_ragel.cpp" - switch ((*p)) - { - case 13: - { - goto ctr52; - } - case 32: - { - goto st33; - } - case 58: - { - goto st28; - } - } - if ((*p) < 14) - { - if (9 <= (*p) && (*p) <= 12) - { - goto st33; - } - } - else if ((*p) > 31) - { - if ((*p) > 57) - { - if (59 <= (*p)) - { - goto st26; - } - } - else if ((*p) >= 33) - { - goto st26; - } - } - else - { - goto st26; - } - { - goto st26; - } - ctr52: -# line 56 "parser.rl" - { - token_end = p; - request.headers.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st34; - ctr48: -# line 46 "parser.rl" - { - token_end = p; - request.headers.emplace_back( - std::make_pair(TOKEN_REF, "") - ); - token_begin = token_end = nullptr; - } -# line 56 "parser.rl" - { - token_end = p; - request.headers.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st34; - st34: - p += 1; - case 34: -# line 992 "parser_ragel.cpp" - switch ((*p)) - { - case 9: - { - goto st33; - } - case 10: - { - goto st35; - } - case 13: - { - goto ctr52; - } - case 32: - { - goto st33; - } - case 58: - { - goto st28; - } - } - if ((*p) < 14) - { - if (11 <= (*p) && (*p) <= 12) - { - goto st33; - } - } - else if ((*p) > 31) - { - if ((*p) > 57) - { - if (59 <= (*p)) - { - goto st26; - } - } - else if ((*p) >= 33) - { - goto st26; - } - } - else - { - goto st26; - } - { - goto st26; - } - st35: - p += 1; - case 35: - switch ((*p)) - { - case 13: - { - goto st36; - } - case 32: - { - goto st24; - } - case 45: - { - goto ctr30; - } - case 58: - { - goto st25; - } - } - if ((*p) < 48) - { - if (9 <= (*p) && (*p) <= 12) - { - goto st24; - } - } - else if ((*p) > 57) - { - if ((*p) > 90) - { - if (97 <= (*p) && (*p) <= 122) - { - goto ctr30; - } - } - else if ((*p) >= 65) - { - goto ctr30; - } - } - else - { - goto ctr30; - } - { - goto st0; - } - st36: - p += 1; - case 36: - switch ((*p)) - { - case 9: - { - goto st24; - } - case 10: - { - goto st63; - } - case 32: - { - goto st24; - } - case 58: - { - goto st25; - } - } - if (11 <= (*p) && (*p) <= 13) - { - goto st24; - } - { - goto st0; - } - st63: -# line 134 "parser.rl" - { - { - p++; - cs = 63; - goto _out; - } - } - p += 1; - case 63: -# line 1093 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto st24; - } - case 58: - { - goto st25; - } - } - if (9 <= (*p) && (*p) <= 13) - { - goto st24; - } - { - goto st0; - } - ctr18: -# line 36 "parser.rl" - { - token_end = p; - request.uri = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st37; - ctr59: -# line 62 "parser.rl" - { - token_begin = p; - } -# line 66 "parser.rl" - { - token_end = p; - request.query_params.emplace_back(std::make_pair( - {UTILS::url_decode(token_begin, token_end)}, "" - )); - token_begin = token_end = nullptr; - } - goto st37; - ctr63: -# line 66 "parser.rl" - { - token_end = p; - request.query_params.emplace_back(std::make_pair( - {UTILS::url_decode(token_begin, token_end)}, "" - )); - token_begin = token_end = nullptr; - } - goto st37; - ctr67: -# line 72 "parser.rl" - { - token_begin = p; - } -# line 76 "parser.rl" - { - token_end = p; - request.query_params.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st37; - ctr70: -# line 76 "parser.rl" - { - token_end = p; - request.query_params.back().second = TOKEN_REF; - token_begin = token_end = nullptr; - } - goto st37; - st37: - p += 1; - case 37: -# line 1159 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto ctr58; - } - case 38: - { - goto ctr59; - } - case 61: - { - goto ctr60; - } - } - if ((*p) < 33) - { - if ((*p) > 13) - { - if ((*p) <= 31) - { - goto ctr57; - } - } - else if ((*p) >= 9) - { - goto ctr58; - } - } - else if ((*p) > 37) - { - if ((*p) > 60) - { - if (62 <= (*p)) - { - goto ctr57; - } - } - else if ((*p) >= 39) - { - goto ctr57; - } - } - else - { - goto ctr57; - } - { - goto ctr57; - } - ctr57: -# line 62 "parser.rl" - { - token_begin = p; - } - goto st38; - st38: - p += 1; - case 38: -# line 1202 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto ctr62; - } - case 38: - { - goto ctr63; - } - case 61: - { - goto ctr64; - } - } - if ((*p) < 33) - { - if ((*p) > 13) - { - if ((*p) <= 31) - { - goto st38; - } - } - else if ((*p) >= 9) - { - goto ctr62; - } - } - else if ((*p) > 37) - { - if ((*p) > 60) - { - if (62 <= (*p)) - { - goto st38; - } - } - else if ((*p) >= 39) - { - goto st38; - } - } - else - { - goto st38; - } - { - goto st38; - } - ctr60: -# line 62 "parser.rl" - { - token_begin = p; - } -# line 66 "parser.rl" - { - token_end = p; - request.query_params.emplace_back(std::make_pair( - {UTILS::url_decode(token_begin, token_end)}, "" - )); - token_begin = token_end = nullptr; - } - goto st39; - ctr64: -# line 66 "parser.rl" - { - token_end = p; - request.query_params.emplace_back(std::make_pair( - {UTILS::url_decode(token_begin, token_end)}, "" - )); - token_begin = token_end = nullptr; - } - goto st39; - st39: - p += 1; - case 39: -# line 1259 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto ctr66; - } - case 38: - { - goto ctr67; - } - } - if ((*p) < 14) - { - if (9 <= (*p)) - { - goto ctr66; - } - } - else if ((*p) > 31) - { - if ((*p) > 37) - { - if (39 <= (*p)) - { - goto ctr65; - } - } - else if ((*p) >= 33) - { - goto ctr65; - } - } - else - { - goto ctr65; - } - { - goto ctr65; - } - ctr65: -# line 72 "parser.rl" - { - token_begin = p; - } - goto st40; - st40: - p += 1; - case 40: -# line 1295 "parser_ragel.cpp" - switch ((*p)) - { - case 32: - { - goto ctr69; - } - case 38: - { - goto ctr70; - } - } - if ((*p) < 14) - { - if (9 <= (*p)) - { - goto ctr69; - } - } - else if ((*p) > 31) - { - if ((*p) > 37) - { - if (39 <= (*p)) - { - goto st40; - } - } - else if ((*p) >= 33) - { - goto st40; - } - } - else - { - goto st40; - } - { - goto st40; - } - ctr2: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st41; - st41: - p += 1; - case 41: -# line 1331 "parser_ragel.cpp" - if ((*p) == 69) - { - goto st42; - } - { - goto st0; - } - st42: - p += 1; - case 42: - if ((*p) == 76) - { - goto st43; - } - { - goto st0; - } - st43: - p += 1; - case 43: - if ((*p) == 69) - { - goto st44; - } - { - goto st0; - } - st44: - p += 1; - case 44: - if ((*p) == 84) - { - goto st45; - } - { - goto st0; - } - st45: - p += 1; - case 45: - if ((*p) == 69) - { - goto ctr13; - } - { - goto st0; - } - ctr3: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st46; - st46: - p += 1; - case 46: -# line 1383 "parser_ragel.cpp" - if ((*p) == 69) - { - goto st7; - } - { - goto st0; - } - ctr4: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st47; - st47: - p += 1; - case 47: -# line 1399 "parser_ragel.cpp" - if ((*p) == 69) - { - goto st48; - } - { - goto st0; - } - st48: - p += 1; - case 48: - if ((*p) == 65) - { - goto st49; - } - { - goto st0; - } - st49: - p += 1; - case 49: - if ((*p) == 68) - { - goto ctr13; - } - { - goto st0; - } - ctr5: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st50; - st50: - p += 1; - case 50: -# line 1433 "parser_ragel.cpp" - if ((*p) == 80) - { - goto st51; - } - { - goto st0; - } - st51: - p += 1; - case 51: - if ((*p) == 84) - { - goto st52; - } - { - goto st0; - } - st52: - p += 1; - case 52: - if ((*p) == 73) - { - goto st53; - } - { - goto st0; - } - st53: - p += 1; - case 53: - if ((*p) == 79) - { - goto st54; - } - { - goto st0; - } - st54: - p += 1; - case 54: - if ((*p) == 78) - { - goto st55; - } - { - goto st0; - } - st55: - p += 1; - case 55: - if ((*p) == 83) - { - goto ctr13; - } - { - goto st0; - } - ctr6: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st56; - st56: - p += 1; - case 56: -# line 1494 "parser_ragel.cpp" - switch ((*p)) - { - case 79: - { - goto st57; - } - case 85: - { - goto st7; - } - } - { - goto st0; - } - st57: - p += 1; - case 57: - if ((*p) == 83) - { - goto st7; - } - { - goto st0; - } - ctr7: -# line 82 "parser.rl" - { - token_begin = p; - } - goto st58; - st58: - p += 1; - case 58: -# line 1524 "parser_ragel.cpp" - if ((*p) == 82) - { - goto st59; - } - { - goto st0; - } - st59: - p += 1; - case 59: - if ((*p) == 65) - { - goto st60; - } - { - goto st0; - } - st60: - p += 1; - case 60: - if ((*p) == 67) - { - goto st45; - } - { - goto st0; - } - } + _out: {} + } - _out: - { - } - } +#line 140 "parser.rl" -# line 140 "parser.rl" if (cs < http_first_final) { @@ -1962,6 +994,5 @@ bool Parser::parse(const char* start, const char* end, size_t& consumed, Request return true; } -} // namespace HTTP -} // namespace HTTPP +} } #endif diff --git a/tests/request_parser/headers.cpp b/tests/request_parser/headers.cpp index ee6a18e..6de219d 100644 --- a/tests/request_parser/headers.cpp +++ b/tests/request_parser/headers.cpp @@ -76,9 +76,9 @@ BOOST_AUTO_TEST_CASE(parser_ragel) std::vector vect(std::begin(query), std::end(query)); Request request; - size_t consumed; + size_t consumed = 0; bool b = Parser::parse(query.data(), query.data() + query.size(), consumed, request); - BOOST_CHECK(b); + BOOST_REQUIRE(b); vect.erase(vect.begin(), vect.begin() + consumed); std::string remaining(vect.data(), vect.size()); diff --git a/tests/request_parser/query.cpp b/tests/request_parser/query.cpp index 7a2201f..4e41715 100644 --- a/tests/request_parser/query.cpp +++ b/tests/request_parser/query.cpp @@ -41,12 +41,13 @@ Request parse(const std::string& req) #elif HTTPP_PARSER_BACKEND_IS_RAGEL Request parse(const std::string& req) { - const std::string query = "GET " + req + " HTTP/1.1\r\n\r\n"; + // leak all the things! + auto query = new std::string("GET " + req + " HTTP/1.1\r\n\r\n"); Request request; size_t consumed; - bool b = Parser::parse(query.data(), query.data() + query.size(), consumed, request); - BOOST_CHECK(b); + bool b = Parser::parse(query->data(), query->data() + query->size(), consumed, request); + BOOST_REQUIRE(b); return request; } #endif diff --git a/tests/server/chunked_encoding.cpp b/tests/server/chunked_encoding.cpp index df900fb..23dbb59 100644 --- a/tests/server/chunked_encoding.cpp +++ b/tests/server/chunked_encoding.cpp @@ -36,21 +36,21 @@ const int DEFAULT_CHUNK_SIZE = 100; // Helper that constructs a stream functor for the specified number of chunks, // each chunk being 'chunkSize' bytes. // -std::function make_stream(int numChunks, int chunkSize) +std::function make_stream(int numChunks, int chunkSize) { auto stream = [numChunks, chunkSize]() mutable -> std::string { + static std::string s; if (numChunks > 0) { GLOG(debug) << __FUNCTION__ << ":Sending Chunk "; numChunks--; - return std::string(chunkSize, 'X'); - } - else - { - GLOG(debug) << __FUNCTION__ << ":End of Stream "; - return ""; + s = std::string(chunkSize, 'X'); + return s; } + + GLOG(debug) << __FUNCTION__ << ":End of Stream "; + return ""; }; return stream; } diff --git a/tests/server/pipeline.cpp b/tests/server/pipeline.cpp index 19545cf..c68e3ec 100644 --- a/tests/server/pipeline.cpp +++ b/tests/server/pipeline.cpp @@ -33,7 +33,22 @@ static const std::string REQUEST = "GET / HTTP/1.1\r\n\r\n" "GET / HTTP/1.1\r\n\r\n"; -static const std::string BODY(8192, 'a'); +static const std::string BODY = [] +{ + std::string s; + s.reserve(8192); + for (char a = 'a'; a < 'z'; a++) + { + s.append(256, a); + } + + for (char a = 'A'; a < 'Z' && s.size() != 8192; a++) + { + s.append(256, a); + } + + return s; +}(); static const std::string REQUEST_BODY_ = "GET / HTTP/1.1\r\n" @@ -86,21 +101,50 @@ BOOST_AUTO_TEST_CASE(pipeline) } size_t total_size = 0; +std::atomic_int r = 0; void handler_w_body(Connection* connection) { - read_whole_request( - connection, - [](std::unique_ptr hndl, - const boost::system::error_code& ec) + if (r++ == 0) + { + read_whole_request( + connection, + [](std::unique_ptr hndl, + const boost::system::error_code& ec) + { + if (ec) + { + throw UTILS::convert_boost_ec_to_std_ec(ec); + } + BOOST_REQUIRE_EQUAL( + std::string_view(hndl->body.data(), hndl->body.size()), BODY + ); + total_size += hndl->body.size(); + hndl->connection->response() + .setCode(HTTP::HttpCode::Ok) + .setBody(""); + hndl->connection->sendResponse(); + } + ); + return; + } + + connection->read_whole( + BODY.size(), + [connection](const boost::system::error_code& ec) { if (ec) { throw UTILS::convert_boost_ec_to_std_ec(ec); } - total_size += hndl->body.size(); - hndl->connection->response().setCode(HTTP::HttpCode::Ok).setBody(""); - hndl->connection->sendResponse(); + + auto [ptr, sz] = connection->mutable_body(); + BOOST_REQUIRE_EQUAL(sz, BODY.size()); + BOOST_REQUIRE_EQUAL(std::string_view(ptr, sz), BODY); + + total_size += sz; + connection->response().setCode(HTTP::HttpCode::Ok).setBody(""); + connection->sendResponse(); } ); } @@ -117,7 +161,9 @@ BOOST_AUTO_TEST_CASE(pipeline_with_body) tcp::socket s(io_service); tcp::resolver resolver(io_service); boost::asio::connect(s, resolver.resolve({"localhost", "8000"})); - boost::asio::write(s, boost::asio::buffer(REQUEST_BODY)); + auto n = boost::asio::write(s, boost::asio::buffer(REQUEST_BODY)); + BOOST_REQUIRE_EQUAL(n, REQUEST_BODY.size()); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); int i = 0;