rename flask to crow

This commit is contained in:
ipknHama 2014-04-27 02:19:59 +09:00
parent 8eceb3f7cc
commit f8893eb138
14 changed files with 131 additions and 131 deletions

View File

@ -1,5 +1,5 @@
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 json.h
example: example.cpp crow.h http_server.h http_connection.h parser.h http_response.h routing.h common.h utility.h json.h
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
@ -14,7 +14,7 @@ unittest: unittest.cpp routing.h
g++ -Wall -g -std=c++11 -o unittest unittest.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/
./unittest
covtest: unittest.cpp routing.h utility.h flask.h http_server.h http_connection.h parser.h http_response.h common.h json.h
covtest: unittest.cpp routing.h utility.h crow.h http_server.h http_connection.h parser.h http_response.h common.h json.h
g++ -Wall -g -std=c++11 -o covtest --coverage unittest.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/
./covtest
gcov -r unittest.cpp

View File

@ -4,7 +4,7 @@
#include <stdexcept>
#include "utility.h"
namespace flask
namespace crow
{
enum class HTTPMethod
{
@ -107,17 +107,17 @@ namespace flask
}
}
constexpr flask::HTTPMethod operator "" _method(const char* str, size_t len)
constexpr crow::HTTPMethod operator "" _method(const char* str, size_t len)
{
return
flask::black_magic::is_equ_p(str, "GET", 3) ? flask::HTTPMethod::GET :
flask::black_magic::is_equ_p(str, "DELETE", 6) ? flask::HTTPMethod::DELETE :
flask::black_magic::is_equ_p(str, "HEAD", 4) ? flask::HTTPMethod::HEAD :
flask::black_magic::is_equ_p(str, "POST", 4) ? flask::HTTPMethod::POST :
flask::black_magic::is_equ_p(str, "PUT", 3) ? flask::HTTPMethod::PUT :
flask::black_magic::is_equ_p(str, "OPTIONS", 7) ? flask::HTTPMethod::OPTIONS :
flask::black_magic::is_equ_p(str, "CONNECT", 7) ? flask::HTTPMethod::CONNECT :
flask::black_magic::is_equ_p(str, "TRACE", 5) ? flask::HTTPMethod::TRACE :
crow::black_magic::is_equ_p(str, "GET", 3) ? crow::HTTPMethod::GET :
crow::black_magic::is_equ_p(str, "DELETE", 6) ? crow::HTTPMethod::DELETE :
crow::black_magic::is_equ_p(str, "HEAD", 4) ? crow::HTTPMethod::HEAD :
crow::black_magic::is_equ_p(str, "POST", 4) ? crow::HTTPMethod::POST :
crow::black_magic::is_equ_p(str, "PUT", 3) ? crow::HTTPMethod::PUT :
crow::black_magic::is_equ_p(str, "OPTIONS", 7) ? crow::HTTPMethod::OPTIONS :
crow::black_magic::is_equ_p(str, "CONNECT", 7) ? crow::HTTPMethod::CONNECT :
crow::black_magic::is_equ_p(str, "TRACE", 5) ? crow::HTTPMethod::TRACE :
throw std::runtime_error("invalid http method");
};

View File

@ -7,7 +7,7 @@
#include <type_traits>
#include <thread>
//#define FLASK_ENABLE_LOGGING
//#define CROW_ENABLE_LOGGING
#include "http_server.h"
#include "utility.h"
@ -16,14 +16,15 @@
// TEST
#include <iostream>
#define FLASK_ROUTE(app, url) app.route<flask::black_magic::get_parameter_tag(url)>(url)
#define CROW_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url)
namespace flask
namespace crow
{
class Flask
class Crow
{
public:
Flask()
using self_t = Crow;
Crow()
{
}
@ -39,18 +40,18 @@ namespace flask
return router_.new_rule_tagged<Tag>(std::move(rule));
}
Flask& port(std::uint16_t port)
self_t& port(std::uint16_t port)
{
port_ = port;
return *this;
}
Flask& multithreaded()
self_t& multithreaded()
{
return concurrency(std::thread::hardware_concurrency());
}
Flask& concurrency(std::uint16_t concurrency)
self_t& concurrency(std::uint16_t concurrency)
{
if (concurrency < 1)
concurrency = 1;
@ -66,7 +67,7 @@ namespace flask
void run()
{
validate();
Server<Flask> server(this, port_, concurrency_);
Server<self_t> server(this, port_, concurrency_);
server.run();
}
void debug_print()

View File

@ -4,7 +4,7 @@
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/filesystem.hpp>
namespace flask
namespace crow
{
// code from http://stackoverflow.com/questions/2838524/use-boost-date-time-to-parse-and-create-http-dates
class DateTime

View File

@ -1,56 +1,56 @@
#include "flask.h"
#include "crow.h"
#include "json.h"
#include <sstream>
int main()
{
flask::Flask app;
crow::Crow app;
FLASK_ROUTE(app, "/")
CROW_ROUTE(app, "/")
.name("hello")
([]{
return "Hello World!";
});
FLASK_ROUTE(app, "/about")
CROW_ROUTE(app, "/about")
([](){
return "About Flask example.";
return "About Crow example.";
});
// simple json response
FLASK_ROUTE(app, "/json")
CROW_ROUTE(app, "/json")
([]{
flask::json::wvalue x;
crow::json::wvalue x;
x["message"] = "Hello, World!";
return x;
});
FLASK_ROUTE(app,"/hello/<int>")
CROW_ROUTE(app,"/hello/<int>")
([](int count){
if (count > 100)
return flask::response(400);
return crow::response(400);
std::ostringstream os;
os << count << " bottles of beer!";
return flask::response(os.str());
return crow::response(os.str());
});
// Compile error with message "Handler type is mismatched with URL paramters"
//FLASK_ROUTE(app,"/another/<int>")
//CROW_ROUTE(app,"/another/<int>")
//([](int a, int b){
//return flask::response(500);
//return crow::response(500);
//});
// more json example
FLASK_ROUTE(app, "/add_json")
([](const flask::request& req){
auto x = flask::json::load(req.body);
CROW_ROUTE(app, "/add_json")
([](const crow::request& req){
auto x = crow::json::load(req.body);
if (!x)
return flask::response(400);
return crow::response(400);
int sum = x["a"].i()+x["b"].i();
std::ostringstream os;
os << sum;
return flask::response{os.str()};
return crow::response{os.str()};
});
app.port(18080)

View File

@ -11,7 +11,7 @@
#include "http_response.h"
#include "datetime.h"
namespace flask
namespace crow
{
using namespace boost;
using tcp = asio::ip::tcp;
@ -68,7 +68,7 @@ namespace flask
res = handler_->handle(req);
#ifdef FLASK_ENABLE_LOGGING
#ifdef CROW_ENABLE_LOGGING
std::cerr << "HTTP/" << parser_.http_major << "." << parser_.http_minor << ' ';
std::cerr << method_name(req.method);
std::cerr << " " << res.code << std::endl;

View File

@ -2,7 +2,7 @@
#include "common.h"
namespace flask
namespace crow
{
struct request
{

View File

@ -3,7 +3,7 @@
#include <unordered_map>
#include "json.h"
namespace flask
namespace crow
{
struct response
{

View File

@ -8,7 +8,7 @@
// TEST
#include <iostream>
namespace flask
namespace crow
{
using namespace boost;
using tcp = asio::ip::tcp;

76
json.h
View File

@ -1,6 +1,6 @@
#pragma once
//#define FLASKPP_JSON_NO_ERROR_CHECK
//#define CROW_JSON_NO_ERROR_CHECK
#include <string>
#include <unordered_map>
@ -12,20 +12,20 @@
#include <boost/operators.hpp>
#ifdef __GNUG__
#define flask_json_likely(x) __builtin_expect(x, 1)
#define flask_json_unlikely(x) __builtin_expect(x, 0)
#define crow_json_likely(x) __builtin_expect(x, 1)
#define crow_json_unlikely(x) __builtin_expect(x, 0)
#else
#ifdef __clang__
#define flask_json_likely(x) __builtin_expect(x, 1)
#define flask_json_unlikely(x) __builtin_expect(x, 0)
#define crow_json_likely(x) __builtin_expect(x, 1)
#define crow_json_unlikely(x) __builtin_expect(x, 0)
#else
#define flask_json_likely(x) x
#define flask_json_unlikely(x) x
#define crow_json_likely(x) x
#define crow_json_unlikely(x) x
#endif
#endif
namespace flask
namespace crow
{
namespace json
{
@ -135,7 +135,7 @@ namespace flask
length_ = length;
owned_ = 1;
}
friend rvalue flask::json::load(const char* data, size_t size);
friend rvalue crow::json::load(const char* data, size_t size);
};
bool operator < (const r_string& l, const r_string& r)
@ -240,7 +240,7 @@ namespace flask
type t() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (option_ & error_bit)
{
throw std::runtime_error("invalid json object");
@ -251,7 +251,7 @@ namespace flask
int64_t i() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Number)
throw std::runtime_error("value is not number");
#endif
@ -260,7 +260,7 @@ namespace flask
double d() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Number)
throw std::runtime_error("value is not number");
#endif
@ -269,7 +269,7 @@ namespace flask
detail::r_string s() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::String)
throw std::runtime_error("value is not string");
#endif
@ -309,7 +309,7 @@ namespace flask
rvalue* begin() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Object && t() != type::List)
throw std::runtime_error("value is not a container");
#endif
@ -317,7 +317,7 @@ namespace flask
}
rvalue* end() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Object && t() != type::List)
throw std::runtime_error("value is not a container");
#endif
@ -331,7 +331,7 @@ namespace flask
size_t size() const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Object && t() != type::List)
throw std::runtime_error("value is not a container");
#endif
@ -340,7 +340,7 @@ namespace flask
const rvalue& operator[](int index) const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::List)
throw std::runtime_error("value is not a list");
if (index >= (int)lsize_ || index < 0)
@ -351,7 +351,7 @@ namespace flask
const rvalue& operator[](size_t index) const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::List)
throw std::runtime_error("value is not a list");
if (index >= lsize_)
@ -367,7 +367,7 @@ namespace flask
const rvalue& operator[](const std::string& str) const
{
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Object)
throw std::runtime_error("value is not an object");
#endif
@ -394,7 +394,7 @@ namespace flask
auto it = lower_bound(begin(), end(), str, Pred());
if (it != end() && it->key_ == str)
return *it;
#ifndef FLASKPP_JSON_NO_ERROR_CHECK
#ifndef CROW_JSON_NO_ERROR_CHECK
throw std::runtime_error("cannot find key");
#else
static rvalue nullValue;
@ -563,7 +563,7 @@ namespace flask
bool consume(char c)
{
if (flask_json_unlikely(*data != c))
if (crow_json_unlikely(*data != c))
return false;
data++;
return true;
@ -576,13 +576,13 @@ namespace flask
rvalue decode_string()
{
if (flask_json_unlikely(!consume('"')))
if (crow_json_unlikely(!consume('"')))
return {};
const char* start = data;
uint8_t has_escaping = 0;
while(1)
{
if (flask_json_likely(*data != '"' && *data != '\\' && *data != '\0'))
if (crow_json_likely(*data != '"' && *data != '\\' && *data != '\0'))
{
data ++;
}
@ -625,13 +625,13 @@ namespace flask
rvalue decode_list()
{
rvalue ret(type::List);
if (flask_json_unlikely(!consume('[')))
if (crow_json_unlikely(!consume('[')))
{
ret.set_error();
return ret;
}
ws_skip();
if (flask_json_unlikely(*data == ']'))
if (crow_json_unlikely(*data == ']'))
{
data++;
return ret;
@ -640,7 +640,7 @@ namespace flask
while(1)
{
auto v = decode_value();
if (flask_json_unlikely(!v))
if (crow_json_unlikely(!v))
{
ret.set_error();
break;
@ -652,7 +652,7 @@ namespace flask
data++;
break;
}
if (flask_json_unlikely(!consume(',')))
if (crow_json_unlikely(!consume(',')))
{
ret.set_error();
break;
@ -677,7 +677,7 @@ namespace flask
DigitsAfterE,
Invalid,
} state{Minus};
while(flask_json_likely(state != Invalid))
while(crow_json_likely(state != Invalid))
{
switch(*data)
{
@ -766,7 +766,7 @@ namespace flask
return {};*/
break;
default:
if (flask_json_likely(state == NumberParsingState::ZeroFirst ||
if (crow_json_likely(state == NumberParsingState::ZeroFirst ||
state == NumberParsingState::Digits ||
state == NumberParsingState::DigitsAfterPoints ||
state == NumberParsingState::DigitsAfterE))
@ -837,7 +837,7 @@ namespace flask
rvalue decode_object()
{
rvalue ret(type::Object);
if (flask_json_unlikely(!consume('{')))
if (crow_json_unlikely(!consume('{')))
{
ret.set_error();
return ret;
@ -845,7 +845,7 @@ namespace flask
ws_skip();
if (flask_json_unlikely(*data == '}'))
if (crow_json_unlikely(*data == '}'))
{
data++;
return ret;
@ -854,14 +854,14 @@ namespace flask
while(1)
{
auto t = decode_string();
if (flask_json_unlikely(!t))
if (crow_json_unlikely(!t))
{
ret.set_error();
break;
}
ws_skip();
if (flask_json_unlikely(!consume(':')))
if (crow_json_unlikely(!consume(':')))
{
ret.set_error();
break;
@ -872,7 +872,7 @@ namespace flask
ws_skip();
auto v = decode_value();
if (flask_json_unlikely(!v))
if (crow_json_unlikely(!v))
{
ret.set_error();
break;
@ -881,12 +881,12 @@ namespace flask
v.key_ = std::move(key);
ret.emplace_back(std::move(v));
if (flask_json_unlikely(*data == '}'))
if (crow_json_unlikely(*data == '}'))
{
data++;
break;
}
if (flask_json_unlikely(!consume(',')))
if (crow_json_unlikely(!consume(',')))
{
ret.set_error();
break;
@ -1225,5 +1225,5 @@ namespace flask
}
}
#undef flask_json_likely
#undef flask_json_unlikely
#undef crow_json_likely
#undef crow_json_unlikely

View File

@ -6,7 +6,7 @@
#include "http_request.h"
namespace flask
namespace crow
{
template <typename Handler>
struct HTTPParser : public http_parser

View File

@ -12,36 +12,20 @@
#include "http_request.h"
#include "utility.h"
//TEST
#include <iostream>
namespace flask
namespace crow
{
class BaseRule
{
public:
BaseRule(std::string rule) noexcept
: rule_(std::move(rule))
{
}
virtual ~BaseRule()
{
}
BaseRule& name(std::string name) noexcept
{
name_ = std::move(name);
return *this;
}
virtual void validate() = 0;
virtual response handle(const request&, const routing_params&) = 0;
protected:
std::string rule_;
std::string name_;
friend class Router;
};
@ -122,24 +106,37 @@ namespace flask
cparams.req,
cparams.params.template get<typename Args1::type>(Args1::pos)...
);
#ifdef FLASK_ENABLE_LOGGING
#ifdef CROW_ENABLE_LOGGING
std::cerr << "ERROR cannot find handler" << std::endl;
#endif
return response(500);
}
};
public:
using self_t = TaggedRule<Args...>;
TaggedRule(std::string rule)
: BaseRule(std::move(rule))
: rule_(std::move(rule))
{
}
TaggedRule<Args...>& name(std::string name) noexcept
self_t& name(std::string name) noexcept
{
name_ = std::move(name);
return *this;
}
self_t& methods(HTTPMethod method)
{
methods_ = 1<<(int)method;
}
template <typename ... MethodArgs>
self_t& methods(HTTPMethod method, MethodArgs ... args_method)
{
methods(args_method...);
methods_ |= 1<<(int)method;
}
void validate()
{
if (!handler_ && !handler_with_req_)
@ -153,11 +150,11 @@ namespace flask
operator()(Func&& f)
{
static_assert(black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
black_magic::CallHelper<Func, black_magic::S<flask::request, Args...>>::value
black_magic::CallHelper<Func, black_magic::S<crow::request, Args...>>::value
,
"Handler type is mismatched with URL paramters");
static_assert(!std::is_same<void, decltype(f(std::declval<Args>()...))>::value,
"Handler function cannot have void return type; valid return types: string, int, flask::resposne, flask::json::wvalue");
"Handler function cannot have void return type; valid return types: string, int, crow::resposne, crow::json::wvalue");
handler_ = [f = std::move(f)](Args ... args){
return response(f(args...));
@ -170,13 +167,13 @@ namespace flask
operator()(Func&& f)
{
static_assert(black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
black_magic::CallHelper<Func, black_magic::S<flask::request, Args...>>::value
black_magic::CallHelper<Func, black_magic::S<crow::request, Args...>>::value
,
"Handler type is mismatched with URL paramters");
static_assert(!std::is_same<void, decltype(f(std::declval<flask::request>(), std::declval<Args>()...))>::value,
"Handler function cannot have void return type; valid return types: string, int, flask::resposne, flask::json::wvalue");
static_assert(!std::is_same<void, decltype(f(std::declval<crow::request>(), std::declval<Args>()...))>::value,
"Handler function cannot have void return type; valid return types: string, int, crow::resposne, crow::json::wvalue");
handler_with_req_ = [f = std::move(f)](const flask::request& request, Args ... args){
handler_with_req_ = [f = std::move(f)](const crow::request& request, Args ... args){
return response(f(request, args...));
};
handler_ = nullptr;
@ -191,7 +188,6 @@ namespace flask
response handle(const request& req, const routing_params& params)
{
//return handler_();
return
call<
call_params<
@ -206,12 +202,15 @@ namespace flask
decltype(handler_with_req_)>
{handler_, handler_with_req_, params, req}
);
//return response(500);
}
private:
std::function<response(Args...)> handler_;
std::function<response(flask::request, Args...)> handler_with_req_;
std::function<response(crow::request, Args...)> handler_with_req_;
std::string rule_;
std::string name_;
uint32_t methods_{1<<(int)HTTPMethod::GET};
template <typename T, int Pos>
struct call_pair
@ -585,7 +584,7 @@ public:
if (rule_index >= rules_.size())
throw std::runtime_error("Trie internal structure corrupted!");
#ifdef FLASK_ENABLE_LOGGING
#ifdef CROW_ENABLE_LOGGING
std::cerr << req.url << ' ' << rules_[rule_index]->rule_ << std::endl;
#endif
return rules_[rule_index]->handle(req, found.second);

View File

@ -1,12 +1,12 @@
//#define FLASK_ENABLE_LOGGING
//#define CROW_ENABLE_LOGGING
#include <iostream>
#include <vector>
#include "routing.h"
#include "utility.h"
#include "flask.h"
#include "crow.h"
#include "json.h"
using namespace std;
using namespace flask;
using namespace crow;
struct Test { Test(); virtual void test() = 0; };
vector<Test*> tests;
@ -76,7 +76,7 @@ TEST(Rule)
ASSERT_EQUAL(1, x);
// registering handler with request argument
r([&x](const flask::request&){x = 2;return "";});
r([&x](const crow::request&){x = 2;return "";});
r.validate();
@ -108,32 +108,32 @@ TEST(ParameterTagging)
TEST(RoutingTest)
{
Flask app;
Crow app;
int A{};
uint32_t B{};
double C{};
string D{};
string E{};
FLASK_ROUTE(app, "/0/<uint>")
CROW_ROUTE(app, "/0/<uint>")
([&](uint32_t b){
B = b;
return "OK";
});
FLASK_ROUTE(app, "/1/<int>/<uint>")
CROW_ROUTE(app, "/1/<int>/<uint>")
([&](int a, uint32_t b){
A = a; B = b;
return "OK";
});
FLASK_ROUTE(app, "/4/<int>/<uint>/<double>/<string>")
CROW_ROUTE(app, "/4/<int>/<uint>/<double>/<string>")
([&](int a, uint32_t b, double c, string d){
A = a; B = b; C = c; D = d;
return "OK";
});
FLASK_ROUTE(app, "/5/<int>/<uint>/<double>/<string>/<path>")
CROW_ROUTE(app, "/5/<int>/<uint>/<double>/<string>/<path>")
([&](int a, uint32_t b, double c, string d, string e){
A = a; B = b; C = c; D = d; E = e;
return "OK";
@ -221,9 +221,9 @@ TEST(simple_response_routing_params)
TEST(server_handling_error_request)
{
static char buf[2048];
Flask app;
FLASK_ROUTE(app, "/")([]{return "A";});
Server<Flask> server(&app, 45451);
Crow app;
CROW_ROUTE(app, "/")([]{return "A";});
Server<Crow> server(&app, 45451);
auto _ = async(launch::async, [&]{server.run();});
std::string sendmsg = "POX";
asio::io_service is;
@ -250,12 +250,12 @@ TEST(server_handling_error_request)
TEST(multi_server)
{
static char buf[2048];
Flask app1, app2;
FLASK_ROUTE(app1, "/")([]{return "A";});
FLASK_ROUTE(app2, "/")([]{return "B";});
Crow app1, app2;
CROW_ROUTE(app1, "/")([]{return "A";});
CROW_ROUTE(app2, "/")([]{return "B";});
Server<Flask> server1(&app1, 45451);
Server<Flask> server2(&app2, 45452);
Server<Crow> server1(&app1, 45451);
Server<Crow> server2(&app2, 45452);
auto _ = async(launch::async, [&]{server1.run();});
auto _2 = async(launch::async, [&]{server2.run();});

View File

@ -3,7 +3,7 @@
#include <stdint.h>
#include <stdexcept>
namespace flask
namespace crow
{
namespace black_magic
{