Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[coro_http_server][feat]update coro_http server #578

Merged
merged 3 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions include/ylt/thirdparty/cinatra/cookie.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#pragma once

#include <chrono>
#include <ctime>
#include <string>

#include "time_util.hpp"

namespace cinatra {

class cookie {
public:
cookie() = default;
cookie(const std::string &name, const std::string &value)
: name_(name), value_(value) {}

void set_version(int version) { version_ = version; }

void set_name(const std::string &name) { name_ = name; }

std::string get_name() const { return name_; }

void set_value(const std::string &value) { value_ = value; }

std::string get_value() const { return value_; }

void set_comment(const std::string &comment) { comment_ = comment; }

void set_domain(const std::string &domain) { domain_ = domain; }

void set_path(const std::string &path) { path_ = path; }

void set_priority(const std::string &priority) { priority_ = priority; }

void set_secure(bool secure) { secure_ = secure; }

void set_max_age(std::time_t seconds) { max_age_ = seconds; }

void set_http_only(bool http_only) { http_only_ = http_only; }

std::string to_string() const {
std::string result;
result.reserve(256);
result.append(name_);
result.append("=");
if (version_ == 0) {
// Netscape cookie
result.append(value_);
if (!domain_.empty()) {
result.append("; domain=");
result.append(domain_);
}
if (!path_.empty()) {
result.append("; path=");
result.append(path_);
}
if (!priority_.empty()) {
result.append("; Priority=");
result.append(priority_);
}
if (max_age_ != -1) {
result.append("; expires=");
result.append(get_gmt_time_str(std::chrono::system_clock::from_time_t(
max_age_ + std::time(nullptr))));
}
if (secure_) {
result.append("; secure");
}
if (http_only_) {
result.append("; HttpOnly");
}
}
else {
// RFC 2109 cookie
result.append("\"");
result.append(value_);
result.append("\"");
if (!comment_.empty()) {
result.append("; Comment=\"");
result.append(comment_);
result.append("\"");
}
if (!domain_.empty()) {
result.append("; Domain=\"");
result.append(domain_);
result.append("\"");
}
if (!path_.empty()) {
result.append("; Path=\"");
result.append(path_);
result.append("\"");
}
if (!priority_.empty()) {
result.append("; Priority=\"");
result.append(priority_);
result.append("\"");
}

if (max_age_ != -1) {
result.append("; Max-Age=\"");
result.append(std::to_string(max_age_));
result.append("\"");
}
if (secure_) {
result.append("; secure");
}
if (http_only_) {
result.append("; HttpOnly");
}
result.append("; Version=\"1\"");
}
return result;
}

private:
std::string name_ = "";
std::string value_ = "";
std::string comment_ = "";
std::string domain_ = "";
std::string priority_ = "";
std::string path_ = "";
std::time_t max_age_ = -1;
int version_ = 0;
bool secure_ = false;
bool http_only_ = false;
};

} // namespace cinatra
81 changes: 78 additions & 3 deletions include/ylt/thirdparty/cinatra/coro_http_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
#include "async_simple/coro/Lazy.h"
#include "cinatra/cinatra_log_wrapper.hpp"
#include "cinatra/response_cv.hpp"
#include "cookie.hpp"
#include "coro_http_request.hpp"
#include "coro_http_router.hpp"
#include "define.h"
#include "http_parser.hpp"
#include "multipart.hpp"
#include "session_manager.hpp"
#include "sha1.hpp"
#include "string_resize.hpp"
#include "websocket.hpp"
Expand Down Expand Up @@ -218,7 +220,7 @@ class coro_http_connection

if (is_coro_exist) {
if (coro_handler) {
co_await (coro_handler)(request_, response_);
co_await coro_handler(request_, response_);
}
else {
response_.set_status(status_type::not_found);
Expand All @@ -236,7 +238,7 @@ class coro_http_connection
std::get<0>(pair))) {
auto coro_handler = std::get<1>(pair);
if (coro_handler) {
co_await (coro_handler)(request_, response_);
co_await coro_handler(request_, response_);
is_matched_regex_router = true;
}
}
Expand Down Expand Up @@ -268,12 +270,73 @@ class coro_http_connection
}

if (!response_.get_delay()) {
co_await reply();
if (head_buf_.size()) {
// handle pipeling, only support GET and HEAD method now.
if (parser_.method()[0] != 'G' && parser_.method()[0] != 'H') {
response_.set_status_and_content(status_type::method_not_allowed,
"method not allowed");
co_await reply();
}
else {
resp_str_.reserve(512);
response_.build_resp_str(resp_str_);

while (true) {
size_t left_size = head_buf_.size();
auto data_ptr = asio::buffer_cast<const char *>(head_buf_.data());
std::string_view left_content{data_ptr, left_size};
size_t pos = left_content.find(TWO_CRCF);
if (pos == std::string_view::npos) {
break;
}
http_parser parser;
int head_len = parser.parse_request(data_ptr, size, 0);
if (head_len <= 0) {
CINATRA_LOG_ERROR << "parse http header error";
close();
break;
}

head_buf_.consume(pos + TWO_CRCF.length());

std::string_view key = {
parser_.method().data(),
parser_.method().length() + 1 + parser_.url().length()};

coro_http_request req(parser, this);
coro_http_response resp(this);
resp.need_date_head(response_.need_date());
if (auto handler = router_.get_handler(key); handler) {
router_.route(handler, req, resp, key);
}
else {
if (auto coro_handler = router_.get_coro_handler(key);
coro_handler) {
co_await router_.route_coro(coro_handler, req, resp, key);
}
}

resp.build_resp_str(resp_str_);
}

auto [write_ec, _] = co_await async_write(asio::buffer(resp_str_));
if (write_ec) {
CINATRA_LOG_ERROR << "async_write error: " << write_ec.message();
close();
co_return;
}
}
}
else {
handle_session_for_response();
co_await reply();
}
}

response_.clear();
buffers_.clear();
body_.clear();
resp_str_.clear();
if (need_shrink_every_time_) {
body_.shrink_to_fit();
}
Expand Down Expand Up @@ -684,6 +747,17 @@ class coro_http_connection

void set_check_timeout(bool r) { checkout_timeout_ = r; }

void handle_session_for_response() {
if (request_.has_session()) {
auto session =
session_manager::get().get_session(request_.get_cached_session_id());
if (session != nullptr && session->get_need_set_to_client()) {
response_.add_cookie(session->get_session_cookie());
session->set_need_set_to_client(false);
}
}
}

private:
bool check_keep_alive() {
bool keep_alive = true;
Expand Down Expand Up @@ -739,6 +813,7 @@ class coro_http_connection
bool checkout_timeout_ = false;
std::atomic<std::chrono::system_clock::time_point> last_rwtime_;
uint64_t max_part_size_ = 8 * 1024 * 1024;
std::string resp_str_;

websocket ws_;
#ifdef CINATRA_ENABLE_SSL
Expand Down
37 changes: 37 additions & 0 deletions include/ylt/thirdparty/cinatra/coro_http_request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "async_simple/coro/Lazy.h"
#include "define.h"
#include "http_parser.hpp"
#include "session.hpp"
#include "session_manager.hpp"
#include "utils.hpp"
#include "ws_define.h"

Expand Down Expand Up @@ -224,6 +226,40 @@ class coro_http_request {
}
}

std::unordered_map<std::string_view, std::string_view> get_cookies(
std::string_view cookie_str) const {
auto cookies = get_cookies_map(cookie_str);
return cookies;
}

std::shared_ptr<session> get_session(bool create = true) {
auto &session_manager = session_manager::get();

auto cookies = get_cookies(get_header_value("Cookie"));
std::string session_id;
auto iter = cookies.find(CSESSIONID);
if (iter == cookies.end() && !create) {
return nullptr;
}
else if (iter == cookies.end()) {
session_id = session_manager.generate_session_id();
}
else {
session_id = iter->second;
}

cached_session_id_ = session_id;
return session_manager.get_session(session_id);
}

std::string get_cached_session_id() {
std::string temp_session_id = "";
cached_session_id_.swap(temp_session_id);
return temp_session_id;
}

bool has_session() { return !cached_session_id_.empty(); }

std::unordered_map<std::string, std::string> params_;
std::smatch matches_;

Expand All @@ -233,5 +269,6 @@ class coro_http_request {
coro_http_connection *conn_;
bool is_websocket_;
std::unordered_map<std::string, std::any> aspect_data_;
std::string cached_session_id_;
};
} // namespace cinatra
Loading
Loading