avoid copy headers (#663)

This commit is contained in:
qicosmos 2024-04-23 14:02:01 +08:00 committed by GitHub
parent 0f05b4fb35
commit cc271bddf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 24 deletions

View File

@ -15,6 +15,7 @@
#ifdef CINATRA_ENABLE_GZIP #ifdef CINATRA_ENABLE_GZIP
#include "gzip.hpp" #include "gzip.hpp"
#endif #endif
#include "picohttpparser.h"
#include "response_cv.hpp" #include "response_cv.hpp"
#include "time_util.hpp" #include "time_util.hpp"
#include "utils.hpp" #include "utils.hpp"
@ -52,11 +53,12 @@ class coro_http_response {
void set_status_and_content( void set_status_and_content(
status_type status, std::string content = "", status_type status, std::string content = "",
content_encoding encoding = content_encoding::none) { content_encoding encoding = content_encoding::none) {
set_status_and_content_view(status, content, encoding, false); set_status_and_content_view(status, std::move(content), encoding, false);
} }
template <typename String>
void set_status_and_content_view( void set_status_and_content_view(
status_type status, std::string_view content = "", status_type status, String content = "",
content_encoding encoding = content_encoding::none, bool is_view = true) { content_encoding encoding = content_encoding::none, bool is_view = true) {
status_ = status; status_ = status;
#ifdef CINATRA_ENABLE_GZIP #ifdef CINATRA_ENABLE_GZIP
@ -100,6 +102,10 @@ class coro_http_response {
resp_headers_.emplace_back(resp_header{std::move(k), std::move(v)}); resp_headers_.emplace_back(resp_header{std::move(k), std::move(v)});
} }
void add_header_span(std::span<http_header> resp_headers) {
resp_header_span_ = resp_headers;
}
void set_keepalive(bool r) { keepalive_ = r; } void set_keepalive(bool r) { keepalive_ = r; }
void need_date_head(bool r) { need_date_ = r; } void need_date_head(bool r) { need_date_ = r; }
@ -125,13 +131,9 @@ class coro_http_response {
resp_str.append(to_http_status_string(status_)); resp_str.append(to_http_status_string(status_));
bool has_len = false; bool has_len = false;
bool has_host = false; bool has_host = false;
for (auto &[k, v] : resp_headers_) { check_header(resp_headers_, has_len, has_host);
if (k == "Server") { if (!resp_header_span_.empty()) {
has_host = true; check_header(resp_header_span_, has_len, has_host);
}
if (k == "Content-Length") {
has_len = true;
}
} }
if (!has_host) { if (!has_host) {
@ -175,21 +177,27 @@ class coro_http_response {
resp_str.append(content_type_); resp_str.append(content_type_);
} }
for (auto &[k, v] : resp_headers_) { append_header_str(resp_str, resp_headers_);
resp_str.append(k);
resp_str.append(COLON_SV); if (!resp_header_span_.empty()) {
resp_str.append(v); append_header_str(resp_str, resp_header_span_);
resp_str.append(CRCF);
} }
resp_str.append(CRCF); resp_str.append(CRCF);
resp_str.append(content_); resp_str.append(content_);
} }
void build_resp_head(std::vector<asio::const_buffer> &buffers) { void append_header_str(auto &resp_str, auto &resp_headers) {
bool has_len = false; for (auto &[k, v] : resp_headers) {
bool has_host = false; resp_str.append(k);
for (auto &[k, v] : resp_headers_) { resp_str.append(COLON_SV);
resp_str.append(v);
resp_str.append(CRCF);
}
}
void check_header(auto &resp_headers, bool &has_len, bool &has_host) {
for (auto &[k, v] : resp_headers) {
if (k == "Server") { if (k == "Server") {
has_host = true; has_host = true;
} }
@ -200,6 +208,15 @@ class coro_http_response {
need_date_ = false; need_date_ = false;
} }
} }
}
void build_resp_head(std::vector<asio::const_buffer> &buffers) {
bool has_len = false;
bool has_host = false;
check_header(resp_headers_, has_len, has_host);
if (!resp_header_span_.empty()) {
check_header(resp_header_span_, has_len, has_host);
}
if (!has_host) { if (!has_host) {
buffers.emplace_back(asio::buffer(CINATRA_HOST_SV)); buffers.emplace_back(asio::buffer(CINATRA_HOST_SV));
@ -251,14 +268,22 @@ class coro_http_response {
buffers.emplace_back(asio::buffer(content_type_)); buffers.emplace_back(asio::buffer(content_type_));
} }
for (auto &[k, v] : resp_headers_) { append_header(buffers, resp_headers_);
if (!resp_header_span_.empty()) {
append_header(buffers, resp_header_span_);
}
buffers.emplace_back(asio::buffer(CRCF));
}
void append_header(auto &buffers, auto &resp_headers) {
for (auto &[k, v] : resp_headers) {
buffers.emplace_back(asio::buffer(k)); buffers.emplace_back(asio::buffer(k));
buffers.emplace_back(asio::buffer(COLON_SV)); buffers.emplace_back(asio::buffer(COLON_SV));
buffers.emplace_back(asio::buffer(v)); buffers.emplace_back(asio::buffer(v));
buffers.emplace_back(asio::buffer(CRCF)); buffers.emplace_back(asio::buffer(CRCF));
} }
buffers.emplace_back(asio::buffer(CRCF));
} }
coro_http_connection *get_conn() { return conn_; } coro_http_connection *get_conn() { return conn_; }
@ -319,6 +344,7 @@ class coro_http_response {
bool delay_; bool delay_;
char buf_[32]; char buf_[32];
std::vector<resp_header> resp_headers_; std::vector<resp_header> resp_headers_;
std::span<http_header> resp_header_span_;
coro_http_connection *conn_; coro_http_connection *conn_;
std::string boundary_; std::string boundary_;
bool has_set_content_ = false; bool has_set_content_ = false;

View File

@ -854,9 +854,7 @@ class coro_http_server {
req.full_url(), method_type(req.get_method()), std::move(ctx), req.full_url(), method_type(req.get_method()), std::move(ctx),
std::move(req_headers)); std::move(req_headers));
for (auto &[k, v] : result.resp_headers) { response.add_header_span(result.resp_headers);
response.add_header(std::string(k), std::string(v));
}
response.set_status_and_content_view( response.set_status_and_content_view(
static_cast<status_type>(result.status), result.resp_body); static_cast<status_type>(result.status), result.resp_body);