From 3081e4e1a82a4efd8feff68850c4cc04af230cd7 Mon Sep 17 00:00:00 2001 From: ipknHama Date: Wed, 21 Sep 2016 23:11:06 +0900 Subject: Cleanup include folder into crow subfolder - only crow.h is exposed now --- include/http_connection.h | 599 ---------------------------------------------- 1 file changed, 599 deletions(-) delete mode 100644 include/http_connection.h (limited to 'include/http_connection.h') diff --git a/include/http_connection.h b/include/http_connection.h deleted file mode 100644 index e8eb4b1..0000000 --- a/include/http_connection.h +++ /dev/null @@ -1,599 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#include "http_parser_merged.h" - -#include "parser.h" -#include "http_response.h" -#include "logging.h" -#include "settings.h" -#include "dumb_timer_queue.h" -#include "middleware_context.h" -#include "socket_adaptors.h" - -namespace crow -{ - using namespace boost; - using tcp = asio::ip::tcp; - - namespace detail - { - template - struct check_before_handle_arity_3_const - { - template - struct get - { }; - }; - - template - struct check_before_handle_arity_3 - { - template - struct get - { }; - }; - - template - struct check_after_handle_arity_3_const - { - template - struct get - { }; - }; - - template - struct check_after_handle_arity_3 - { - template - struct get - { }; - }; - - template - struct is_before_handle_arity_3_impl - { - template - static std::true_type f(typename check_before_handle_arity_3_const::template get*); - - template - static std::true_type f(typename check_before_handle_arity_3::template get*); - - template - static std::false_type f(...); - - public: - static const bool value = decltype(f(nullptr))::value; - }; - - template - struct is_after_handle_arity_3_impl - { - template - static std::true_type f(typename check_after_handle_arity_3_const::template get*); - - template - static std::true_type f(typename check_after_handle_arity_3::template get*); - - template - static std::false_type f(...); - - public: - static const bool value = decltype(f(nullptr))::value; - }; - - template - typename std::enable_if::value>::type - before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/) - { - mw.before_handle(req, res, ctx.template get(), ctx); - } - - template - typename std::enable_if::value>::type - before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/) - { - mw.before_handle(req, res, ctx.template get()); - } - - template - typename std::enable_if::value>::type - after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/) - { - mw.after_handle(req, res, ctx.template get(), ctx); - } - - template - typename std::enable_if::value>::type - after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/) - { - mw.after_handle(req, res, ctx.template get()); - } - - template - bool middleware_call_helper(Container& middlewares, request& req, response& res, Context& ctx) - { - using parent_context_t = typename Context::template partial; - before_handler_call(std::get(middlewares), req, res, ctx, static_cast(ctx)); - - if (res.is_completed()) - { - after_handler_call(std::get(middlewares), req, res, ctx, static_cast(ctx)); - return true; - } - - if (middleware_call_helper(middlewares, req, res, ctx)) - { - after_handler_call(std::get(middlewares), req, res, ctx, static_cast(ctx)); - return true; - } - - return false; - } - - template - bool middleware_call_helper(Container& /*middlewares*/, request& /*req*/, response& /*res*/, Context& /*ctx*/) - { - return false; - } - - template - typename std::enable_if<(N<0)>::type - after_handlers_call_helper(Container& /*middlewares*/, Context& /*context*/, request& /*req*/, response& /*res*/) - { - } - - template - typename std::enable_if<(N==0)>::type after_handlers_call_helper(Container& middlewares, Context& ctx, request& req, response& res) - { - using parent_context_t = typename Context::template partial; - using CurrentMW = typename std::tuple_element::type>::type; - after_handler_call(std::get(middlewares), req, res, ctx, static_cast(ctx)); - } - - template - typename std::enable_if<(N>0)>::type after_handlers_call_helper(Container& middlewares, Context& ctx, request& req, response& res) - { - using parent_context_t = typename Context::template partial; - using CurrentMW = typename std::tuple_element::type>::type; - after_handler_call(std::get(middlewares), req, res, ctx, static_cast(ctx)); - after_handlers_call_helper(middlewares, ctx, req, res); - } - } - -#ifdef CROW_ENABLE_DEBUG - static int connectionCount; -#endif - template - class Connection - { - public: - Connection( - boost::asio::io_service& io_service, - Handler* handler, - const std::string& server_name, - std::tuple* middlewares, - std::function& get_cached_date_str_f, - detail::dumb_timer_queue& timer_queue, - typename Adaptor::context* adaptor_ctx_ - ) - : adaptor_(io_service, adaptor_ctx_), - handler_(handler), - parser_(this), - server_name_(server_name), - middlewares_(middlewares), - get_cached_date_str(get_cached_date_str_f), - timer_queue(timer_queue) - { -#ifdef CROW_ENABLE_DEBUG - connectionCount ++; - CROW_LOG_DEBUG << "Connection open, total " << connectionCount << ", " << this; -#endif - } - - ~Connection() - { - res.complete_request_handler_ = nullptr; - cancel_deadline_timer(); -#ifdef CROW_ENABLE_DEBUG - connectionCount --; - CROW_LOG_DEBUG << "Connection closed, total " << connectionCount << ", " << this; -#endif - } - - decltype(std::declval().raw_socket())& socket() - { - return adaptor_.raw_socket(); - } - - void start() - { - adaptor_.start([this](const boost::system::error_code& ec) { - if (!ec) - { - start_deadline(); - - do_read(); - } - else - { - check_destroy(); - } - }); - } - - void handle_header() - { - // HTTP 1.1 Expect: 100-continue - if (parser_.check_version(1, 1) && parser_.headers.count("expect") && get_header_value(parser_.headers, "expect") == "100-continue") - { - buffers_.clear(); - static std::string expect_100_continue = "HTTP/1.1 100 Continue\r\n\r\n"; - buffers_.emplace_back(expect_100_continue.data(), expect_100_continue.size()); - do_write(); - } - } - - void handle() - { - cancel_deadline_timer(); - bool is_invalid_request = false; - add_keep_alive_ = false; - - req_ = std::move(parser_.to_request()); - request& req = req_; - - if (parser_.check_version(1, 0)) - { - // HTTP/1.0 - if (req.headers.count("connection")) - { - if (boost::iequals(req.get_header_value("connection"),"Keep-Alive")) - add_keep_alive_ = true; - } - else - close_connection_ = true; - } - else if (parser_.check_version(1, 1)) - { - // HTTP/1.1 - if (req.headers.count("connection")) - { - if (req.get_header_value("connection") == "close") - close_connection_ = true; - else if (boost::iequals(req.get_header_value("connection"),"Keep-Alive")) - add_keep_alive_ = true; - } - if (!req.headers.count("host")) - { - is_invalid_request = true; - res = response(400); - } - if (parser_.is_upgrade()) - { - if (req.get_header_value("upgrade") == "h2c") - { - // TODO HTTP/2 - // currently, ignore upgrade header - } - else - { - close_connection_ = true; - handler_->handle_upgrade(req, res, std::move(adaptor_)); - return; - } - } - } - - CROW_LOG_INFO << "Request: " << boost::lexical_cast(adaptor_.remote_endpoint()) << " " << this << " HTTP/" << parser_.http_major << "." << parser_.http_minor << ' ' - << method_name(req.method) << " " << req.url; - - - need_to_call_after_handlers_ = false; - if (!is_invalid_request) - { - res.complete_request_handler_ = []{}; - res.is_alive_helper_ = [this]()->bool{ return adaptor_.is_open(); }; - - ctx_ = detail::context(); - req.middleware_context = (void*)&ctx_; - req.io_service = &adaptor_.get_io_service(); - detail::middleware_call_helper<0, decltype(ctx_), decltype(*middlewares_), Middlewares...>(*middlewares_, req, res, ctx_); - - if (!res.completed_) - { - res.complete_request_handler_ = [this]{ this->complete_request(); }; - need_to_call_after_handlers_ = true; - handler_->handle(req, res); - if (add_keep_alive_) - res.set_header("connection", "Keep-Alive"); - } - else - { - complete_request(); - } - } - else - { - complete_request(); - } - } - - void complete_request() - { - CROW_LOG_INFO << "Response: " << this << ' ' << req_.raw_url << ' ' << res.code << ' ' << close_connection_; - - if (need_to_call_after_handlers_) - { - need_to_call_after_handlers_ = false; - - // call all after_handler of middlewares - detail::after_handlers_call_helper< - ((int)sizeof...(Middlewares)-1), - decltype(ctx_), - decltype(*middlewares_)> - (*middlewares_, ctx_, req_, res); - } - - //auto self = this->shared_from_this(); - res.complete_request_handler_ = nullptr; - - if (!adaptor_.is_open()) - { - //CROW_LOG_DEBUG << this << " delete (socket is closed) " << is_reading << ' ' << is_writing; - //delete this; - return; - } - - static std::unordered_map statusCodes = { - {200, "HTTP/1.1 200 OK\r\n"}, - {201, "HTTP/1.1 201 Created\r\n"}, - {202, "HTTP/1.1 202 Accepted\r\n"}, - {204, "HTTP/1.1 204 No Content\r\n"}, - - {300, "HTTP/1.1 300 Multiple Choices\r\n"}, - {301, "HTTP/1.1 301 Moved Permanently\r\n"}, - {302, "HTTP/1.1 302 Moved Temporarily\r\n"}, - {304, "HTTP/1.1 304 Not Modified\r\n"}, - - {400, "HTTP/1.1 400 Bad Request\r\n"}, - {401, "HTTP/1.1 401 Unauthorized\r\n"}, - {403, "HTTP/1.1 403 Forbidden\r\n"}, - {404, "HTTP/1.1 404 Not Found\r\n"}, - - {500, "HTTP/1.1 500 Internal Server Error\r\n"}, - {501, "HTTP/1.1 501 Not Implemented\r\n"}, - {502, "HTTP/1.1 502 Bad Gateway\r\n"}, - {503, "HTTP/1.1 503 Service Unavailable\r\n"}, - }; - - static std::string seperator = ": "; - static std::string crlf = "\r\n"; - - buffers_.clear(); - buffers_.reserve(4*(res.headers.size()+5)+3); - - if (res.body.empty() && res.json_value.t() == json::type::Object) - { - res.body = json::dump(res.json_value); - } - - if (!statusCodes.count(res.code)) - res.code = 500; - { - auto& status = statusCodes.find(res.code)->second; - buffers_.emplace_back(status.data(), status.size()); - } - - if (res.code >= 400 && res.body.empty()) - res.body = statusCodes[res.code].substr(9); - - for(auto& kv : res.headers) - { - buffers_.emplace_back(kv.first.data(), kv.first.size()); - buffers_.emplace_back(seperator.data(), seperator.size()); - buffers_.emplace_back(kv.second.data(), kv.second.size()); - buffers_.emplace_back(crlf.data(), crlf.size()); - - } - - if (!res.headers.count("content-length")) - { - content_length_ = std::to_string(res.body.size()); - static std::string content_length_tag = "Content-Length: "; - buffers_.emplace_back(content_length_tag.data(), content_length_tag.size()); - buffers_.emplace_back(content_length_.data(), content_length_.size()); - buffers_.emplace_back(crlf.data(), crlf.size()); - } - if (!res.headers.count("server")) - { - static std::string server_tag = "Server: "; - buffers_.emplace_back(server_tag.data(), server_tag.size()); - buffers_.emplace_back(server_name_.data(), server_name_.size()); - buffers_.emplace_back(crlf.data(), crlf.size()); - } - if (!res.headers.count("date")) - { - static std::string date_tag = "Date: "; - date_str_ = get_cached_date_str(); - buffers_.emplace_back(date_tag.data(), date_tag.size()); - buffers_.emplace_back(date_str_.data(), date_str_.size()); - buffers_.emplace_back(crlf.data(), crlf.size()); - } - if (add_keep_alive_) - { - static std::string keep_alive_tag = "Connection: Keep-Alive"; - buffers_.emplace_back(keep_alive_tag.data(), keep_alive_tag.size()); - buffers_.emplace_back(crlf.data(), crlf.size()); - } - - buffers_.emplace_back(crlf.data(), crlf.size()); - res_body_copy_.swap(res.body); - buffers_.emplace_back(res_body_copy_.data(), res_body_copy_.size()); - - do_write(); - - if (need_to_start_read_after_complete_) - { - need_to_start_read_after_complete_ = false; - start_deadline(); - do_read(); - } - } - - private: - void do_read() - { - //auto self = this->shared_from_this(); - is_reading = true; - adaptor_.socket().async_read_some(boost::asio::buffer(buffer_), - [this](const boost::system::error_code& ec, std::size_t bytes_transferred) - { - bool error_while_reading = true; - if (!ec) - { - bool ret = parser_.feed(buffer_.data(), bytes_transferred); - if (ret && adaptor_.is_open()) - { - error_while_reading = false; - } - } - - if (error_while_reading) - { - cancel_deadline_timer(); - parser_.done(); - adaptor_.close(); - is_reading = false; - CROW_LOG_DEBUG << this << " from read(1)"; - check_destroy(); - } - else if (close_connection_) - { - cancel_deadline_timer(); - parser_.done(); - is_reading = false; - check_destroy(); - // adaptor will close after write - } - else if (!need_to_call_after_handlers_) - { - start_deadline(); - do_read(); - } - else - { - // res will be completed later by user - need_to_start_read_after_complete_ = true; - } - }); - } - - void do_write() - { - //auto self = this->shared_from_this(); - is_writing = true; - boost::asio::async_write(adaptor_.socket(), buffers_, - [&](const boost::system::error_code& ec, std::size_t /*bytes_transferred*/) - { - is_writing = false; - res.clear(); - res_body_copy_.clear(); - if (!ec) - { - if (close_connection_) - { - adaptor_.close(); - CROW_LOG_DEBUG << this << " from write(1)"; - check_destroy(); - } - } - else - { - CROW_LOG_DEBUG << this << " from write(2)"; - check_destroy(); - } - }); - } - - void check_destroy() - { - CROW_LOG_DEBUG << this << " is_reading " << is_reading << " is_writing " << is_writing; - if (!is_reading && !is_writing) - { - CROW_LOG_DEBUG << this << " delete (idle) "; - delete this; - } - } - - void cancel_deadline_timer() - { - CROW_LOG_DEBUG << this << " timer cancelled: " << timer_cancel_key_.first << ' ' << timer_cancel_key_.second; - timer_queue.cancel(timer_cancel_key_); - } - - void start_deadline(/*int timeout = 5*/) - { - cancel_deadline_timer(); - - timer_cancel_key_ = timer_queue.add([this] - { - if (!adaptor_.is_open()) - { - return; - } - adaptor_.close(); - }); - CROW_LOG_DEBUG << this << " timer added: " << timer_cancel_key_.first << ' ' << timer_cancel_key_.second; - } - - private: - Adaptor adaptor_; - Handler* handler_; - - boost::array buffer_; - - HTTPParser parser_; - request req_; - response res; - - bool close_connection_ = false; - - const std::string& server_name_; - std::vector buffers_; - - std::string content_length_; - std::string date_str_; - std::string res_body_copy_; - - //boost::asio::deadline_timer deadline_; - detail::dumb_timer_queue::key timer_cancel_key_; - - bool is_reading{}; - bool is_writing{}; - bool need_to_call_after_handlers_{}; - bool need_to_start_read_after_complete_{}; - bool add_keep_alive_{}; - - std::tuple* middlewares_; - detail::context ctx_; - - std::function& get_cached_date_str; - detail::dumb_timer_queue& timer_queue; - }; - -} -- cgit v1.2.3-54-g00ecf