mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
add concurrency; add server header
This commit is contained in:
parent
aaf3e52503
commit
9ee37ce4bf
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
all: covtest example
|
||||
example: example.cpp flask.h http_server.h http_connection.h parser.h http_response.h routing.h common.h utility.h
|
||||
g++ -Wall -g -O2 -std=c++11 -o example example.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/
|
||||
g++ -Wall -g -O3 -std=c++11 -o example example.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/
|
||||
|
||||
test: covtest
|
||||
|
||||
|
12
example.cpp
12
example.cpp
@ -7,11 +7,16 @@ int main()
|
||||
flask::Flask app;
|
||||
|
||||
FLASK_ROUTE(app, "/")
|
||||
.name("hello")
|
||||
.name("hello")
|
||||
([]{
|
||||
return "Hello World!";
|
||||
});
|
||||
|
||||
FLASK_ROUTE(app, "/json")
|
||||
([]{
|
||||
return "{\"message\":\"Hello, World!\"}";
|
||||
});
|
||||
|
||||
FLASK_ROUTE(app, "/about")
|
||||
([](){
|
||||
return "About Flask example.";
|
||||
@ -32,6 +37,7 @@ int main()
|
||||
//return flask::response(500);
|
||||
//});
|
||||
|
||||
app.port(8080)
|
||||
.run();
|
||||
app.port(18080)
|
||||
.multithreaded()
|
||||
.run();
|
||||
}
|
||||
|
17
flask.h
17
flask.h
@ -5,6 +5,7 @@
|
||||
#include <future>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
#include <thread>
|
||||
|
||||
#include "http_server.h"
|
||||
#include "utility.h"
|
||||
@ -48,6 +49,19 @@ namespace flask
|
||||
return *this;
|
||||
}
|
||||
|
||||
Flask& multithreaded()
|
||||
{
|
||||
return concurrency(std::thread::hardware_concurrency());
|
||||
}
|
||||
|
||||
Flask& concurrency(std::uint16_t concurrency)
|
||||
{
|
||||
if (concurrency < 1)
|
||||
concurrency = 1;
|
||||
concurrency_ = concurrency;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void validate()
|
||||
{
|
||||
router_.validate();
|
||||
@ -56,7 +70,7 @@ namespace flask
|
||||
void run()
|
||||
{
|
||||
validate();
|
||||
Server<Flask> server(this, port_);
|
||||
Server<Flask> server(this, port_, concurrency_);
|
||||
server.run();
|
||||
}
|
||||
void debug_print()
|
||||
@ -67,6 +81,7 @@ namespace flask
|
||||
|
||||
private:
|
||||
uint16_t port_ = 80;
|
||||
uint16_t concurrency_ = 1;
|
||||
|
||||
Router router_;
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "parser.h"
|
||||
#include "http_response.h"
|
||||
@ -17,7 +18,7 @@ namespace flask
|
||||
class Connection
|
||||
{
|
||||
public:
|
||||
Connection(tcp::socket&& socket, Handler* handler) : socket_(std::move(socket)), handler_(handler), parser_(this)
|
||||
Connection(tcp::socket&& socket, Handler* handler, const std::string& server_name) : socket_(std::move(socket)), handler_(handler), parser_(this), server_name_(server_name)
|
||||
{
|
||||
}
|
||||
|
||||
@ -34,32 +35,62 @@ namespace flask
|
||||
static std::string seperator = ": ";
|
||||
static std::string crlf = "\r\n";
|
||||
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers_.clear();
|
||||
buffers_.reserve(4*(res.headers.size()+4)+3);
|
||||
|
||||
buffers.push_back(boost::asio::buffer(statusCodes[res.code]));
|
||||
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);
|
||||
|
||||
bool has_content_length = false;
|
||||
bool has_date = false;
|
||||
bool has_server = false;
|
||||
|
||||
for(auto& kv : res.headers)
|
||||
{
|
||||
buffers.push_back(boost::asio::buffer(kv.first));
|
||||
buffers.push_back(boost::asio::buffer(seperator));
|
||||
buffers.push_back(boost::asio::buffer(kv.second));
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
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 (boost::iequals(kv.first, "content-length"))
|
||||
has_content_length = true;
|
||||
if (boost::iequals(kv.first, "date"))
|
||||
has_date = true;
|
||||
if (boost::iequals(kv.first, "server"))
|
||||
has_server = true;
|
||||
}
|
||||
|
||||
if (!has_content_length)
|
||||
close_connection_ = true;
|
||||
{
|
||||
auto ret = res.headers.emplace("Content-Length", boost::lexical_cast<std::string>(res.body.size()));
|
||||
buffers_.emplace_back(ret.first->first.data(), ret.first->first.size());
|
||||
buffers_.emplace_back(seperator.data(), seperator.size());
|
||||
buffers_.emplace_back(ret.first->second.data(), ret.first->second.size());
|
||||
buffers_.emplace_back(crlf.data(), crlf.size());
|
||||
}
|
||||
if (!has_server)
|
||||
{
|
||||
auto ret = res.headers.emplace("Server", server_name_);
|
||||
buffers_.emplace_back(ret.first->first.data(), ret.first->first.size());
|
||||
buffers_.emplace_back(seperator.data(), seperator.size());
|
||||
buffers_.emplace_back(ret.first->second.data(), ret.first->second.size());
|
||||
buffers_.emplace_back(crlf.data(), crlf.size());
|
||||
}
|
||||
if (!has_date)
|
||||
{
|
||||
}
|
||||
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
buffers.push_back(boost::asio::buffer(res.body));
|
||||
buffers_.emplace_back(crlf.data(), crlf.size());
|
||||
buffers_.emplace_back(res.body.data(), res.body.size());
|
||||
|
||||
do_write(buffers);
|
||||
do_write();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -99,10 +130,10 @@ namespace flask
|
||||
});
|
||||
}
|
||||
|
||||
void do_write(const std::vector<boost::asio::const_buffer>& buffers)
|
||||
void do_write()
|
||||
{
|
||||
life_++;
|
||||
boost::asio::async_write(socket_, buffers,
|
||||
boost::asio::async_write(socket_, buffers_,
|
||||
[this](const boost::system::error_code& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
bool should_close = false;
|
||||
@ -140,5 +171,8 @@ namespace flask
|
||||
|
||||
std::atomic<int> life_;
|
||||
bool close_connection_ = false;
|
||||
|
||||
const std::string& server_name_;
|
||||
std::vector<boost::asio::const_buffer> buffers_;
|
||||
};
|
||||
}
|
||||
|
@ -16,15 +16,19 @@ namespace flask
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
Server(Handler* handler, uint16_t port)
|
||||
: acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)), socket_(io_service_), handler_(handler)
|
||||
Server(Handler* handler, uint16_t port, uint16_t concurrency = 1)
|
||||
: acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)), socket_(io_service_), handler_(handler), concurrency_(concurrency)
|
||||
{
|
||||
do_accept();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
auto _ = std::async(std::launch::async, [this]{io_service_.run();});
|
||||
std::vector<std::future<void>> v;
|
||||
for(uint16_t i = 0; i < concurrency_; i ++)
|
||||
v.push_back(
|
||||
std::async(std::launch::async, [this]{io_service_.run();})
|
||||
);
|
||||
}
|
||||
|
||||
void stop()
|
||||
@ -39,7 +43,7 @@ namespace flask
|
||||
[this](boost::system::error_code ec)
|
||||
{
|
||||
if (!ec)
|
||||
(new Connection<Handler>(std::move(socket_), handler_))->start();
|
||||
(new Connection<Handler>(std::move(socket_), handler_, server_name_))->start();
|
||||
do_accept();
|
||||
});
|
||||
}
|
||||
@ -49,5 +53,7 @@ namespace flask
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
Handler* handler_;
|
||||
uint16_t concurrency_ = 1;
|
||||
std::string server_name_ = "Flask++/0.1";
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user