Skip to content

Commit

Permalink
Merge branch 'master' into v1.1
Browse files Browse the repository at this point in the history
* master:
  fix: call after_handlers for legitimate requests without body part
  Handle _CROW_ILL or _CROW_ICD being NOTFOUND
  small explanations in the example on using CORS middleware in Crow v1.0
  Use const std::string& as argument to route() (#684)
  fix: minimize the precision loss when dumping double to string (#712)
  package format changed to zip, version set to >1.1.0 (first release)
  Fix #754 (#755)
  • Loading branch information
gittiver committed Feb 21, 2024
2 parents 05f7f33 + 5ecd04a commit ae87100
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 40 deletions.
21 changes: 17 additions & 4 deletions cmake/CrowConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ check_required_components("@PROJECT_NAME@")
get_target_property(_CROW_ILL Crow::Crow INTERFACE_LINK_LIBRARIES)
get_target_property(_CROW_ICD Crow::Crow INTERFACE_COMPILE_DEFINITIONS)

if(_CROW_ILL STREQUAL "_CROW_ILL-NOTFOUND")
set(_CROW_ILL "")
endif()
if(_CROW_ICD STREQUAL "_CROW_ICD-NOTFOUND")
set(_CROW_ICD "")
endif()

list(REMOVE_ITEM _CROW_ILL "ZLIB::ZLIB" "OpenSSL::SSL")
list(REMOVE_ITEM _CROW_ICD "CROW_ENABLE_SSL" "CROW_ENABLE_COMPRESSION")

Expand All @@ -41,7 +48,13 @@ if("ssl" IN_LIST CROW_FEATURES)
list(APPEND _CROW_ICD "CROW_ENABLE_SSL")
endif()

set_target_properties(Crow::Crow PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "${_CROW_ICD}"
INTERFACE_LINK_LIBRARIES "${_CROW_ILL}"
)
if( NOT (_CROW_ICD STREQUAL "" ) )
set_target_properties(Crow::Crow PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "${_CROW_ICD}"
)
endif()
if( NOT (_CROW_ILL STREQUAL "" ) )
set_target_properties(Crow::Crow PROPERTIES
INTERFACE_LINK_LIBRARIES "${_CROW_ILL}"
)
endif()
8 changes: 8 additions & 0 deletions examples/middlewares/example_cors.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
#include "crow.h"
#include "crow/middlewares/cors.h"

// Warning!
// If you want to use CORS with OPTIONS cache on browser requests,
// be sure to specify each headers you use, please do not use "*"
// else otherwise the browser will ignore you
// Example:
// .headers("Origin", "Content-Type", "Accept", *Your-Headers*)
// .max_age(5);

int main()
{
// Enable CORS
Expand Down
20 changes: 10 additions & 10 deletions include/crow/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,25 @@ namespace crow
}

/// Create a dynamic route using a rule (**Use CROW_ROUTE instead**)
DynamicRule& route_dynamic(std::string&& rule)
DynamicRule& route_dynamic(const std::string& rule)
{
return router_.new_rule_dynamic(std::move(rule));
return router_.new_rule_dynamic(rule);
}

///Create a route using a rule (**Use CROW_ROUTE instead**)
/// Create a route using a rule (**Use CROW_ROUTE instead**)
template<uint64_t Tag>
#ifdef CROW_GCC83_WORKAROUND
auto& route(std::string&& rule)
auto& route(const std::string& rule)
#else
auto route(std::string&& rule)
auto route(const std::string& rule)
#endif
#if defined CROW_CAN_USE_CPP17 && !defined CROW_GCC83_WORKAROUND
-> typename std::invoke_result<decltype(&Router::new_rule_tagged<Tag>), Router, std::string&&>::type
-> typename std::invoke_result<decltype(&Router::new_rule_tagged<Tag>), Router, const std::string&>::type
#elif !defined CROW_GCC83_WORKAROUND
-> typename std::result_of<decltype (&Router::new_rule_tagged<Tag>)(Router, std::string&&)>::type
-> typename std::result_of<decltype (&Router::new_rule_tagged<Tag>)(Router, const std::string&)>::type
#endif
{
return router_.new_rule_tagged<Tag>(std::move(rule));
return router_.new_rule_tagged<Tag>(rule);
}

/// Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
Expand Down Expand Up @@ -187,7 +187,7 @@ namespace crow
bindaddr_ = bindaddr;
return *this;
}

/// Get the address that Crow will handle requests on
std::string bindaddr()
{
Expand All @@ -208,7 +208,7 @@ namespace crow
concurrency_ = concurrency;
return *this;
}

/// Get the number of threads that server is using
std::uint16_t concurrency()
{
Expand Down
1 change: 1 addition & 0 deletions include/crow/http_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ namespace crow
if (!routing_handle_result_->rule_index)
{
parser_.done();
need_to_call_after_handlers_ = true;
complete_request();
}
}
Expand Down
2 changes: 2 additions & 0 deletions include/crow/http_response.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ namespace crow
if (complete_request_handler_)
{
complete_request_handler_();
manual_length_header = false;
skip_body = false;
}
}
}
Expand Down
49 changes: 38 additions & 11 deletions include/crow/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#include <cmath>
#include <cfloat>

#include "crow/utility.h"
#include "crow/settings.h"
Expand Down Expand Up @@ -105,7 +106,8 @@ namespace crow
Signed_integer,
Unsigned_integer,
Floating_point,
Null
Null,
Double_precision_floating_point
};

class rvalue;
Expand Down Expand Up @@ -781,6 +783,7 @@ namespace crow
switch (r.nt())
{
case num_type::Floating_point: os << r.d(); break;
case num_type::Double_precision_floating_point: os << r.d(); break;
case num_type::Signed_integer: os << r.i(); break;
case num_type::Unsigned_integer: os << r.u(); break;
case num_type::Null: throw std::runtime_error("Number with num_type Null");
Expand Down Expand Up @@ -1318,7 +1321,9 @@ namespace crow
ui(value) {}
constexpr number(std::int64_t value) noexcept:
si(value) {}
constexpr number(double value) noexcept:
explicit constexpr number(double value) noexcept:
d(value) {}
explicit constexpr number(float value) noexcept:
d(value) {}
} num; ///< Value if type is a number.
std::string s; ///< Value if type is a string.
Expand Down Expand Up @@ -1357,7 +1362,7 @@ namespace crow
wvalue(float value):
returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
wvalue(double value):
returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
returnable("application/json"), t_(type::Number), nt(num_type::Double_precision_floating_point), num(static_cast<double>(value)) {}

wvalue(char const* value):
returnable("application/json"), t_(type::String), s(value) {}
Expand Down Expand Up @@ -1408,7 +1413,7 @@ namespace crow
return;
case type::Number:
nt = r.nt();
if (nt == num_type::Floating_point)
if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
num.d = r.d();
else if (nt == num_type::Signed_integer)
num.si = r.i();
Expand Down Expand Up @@ -1444,7 +1449,7 @@ namespace crow
return;
case type::Number:
nt = r.nt;
if (nt == num_type::Floating_point)
if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
num.d = r.num.d;
else if (nt == num_type::Signed_integer)
num.si = r.num.si;
Expand Down Expand Up @@ -1514,7 +1519,7 @@ namespace crow
return *this;
}

wvalue& operator=(double value)
wvalue& operator=(float value)
{
reset();
t_ = type::Number;
Expand All @@ -1523,6 +1528,15 @@ namespace crow
return *this;
}

wvalue& operator=(double value)
{
reset();
t_ = type::Number;
num.d = value;
nt = num_type::Double_precision_floating_point;
return *this;
}

wvalue& operator=(unsigned short value)
{
reset();
Expand Down Expand Up @@ -1835,7 +1849,7 @@ namespace crow
case type::True: out += "true"; break;
case type::Number:
{
if (v.nt == num_type::Floating_point)
if (v.nt == num_type::Floating_point || v.nt == num_type::Double_precision_floating_point)
{
if (isnan(v.num.d) || isinf(v.num.d))
{
Expand All @@ -1850,11 +1864,22 @@ namespace crow
zero
} f_state;
char outbuf[128];
if (v.nt == num_type::Double_precision_floating_point)
{
#ifdef _MSC_VER
sprintf_s(outbuf, sizeof(outbuf), "%f", v.num.d);
sprintf_s(outbuf, sizeof(outbuf), "%.*g", DECIMAL_DIG, v.num.d);
#else
snprintf(outbuf, sizeof(outbuf), "%f", v.num.d);
snprintf(outbuf, sizeof(outbuf), "%.*g", DECIMAL_DIG, v.num.d);
#endif
}
else
{
#ifdef _MSC_VER
sprintf_s(outbuf, sizeof(outbuf), "%f", v.num.d);
#else
snprintf(outbuf, sizeof(outbuf), "%f", v.num.d);
#endif
}
char *p = &outbuf[0], *o = nullptr; // o is the position of the first trailing 0
f_state = start;
while (*p != '\0')
Expand Down Expand Up @@ -1968,14 +1993,16 @@ namespace crow
{
int64_t get(int64_t fallback)
{
if (ref.t() != type::Number || ref.nt == num_type::Floating_point)
if (ref.t() != type::Number || ref.nt == num_type::Floating_point ||
ref.nt == num_type::Double_precision_floating_point)
return fallback;
return ref.num.si;
}

double get(double fallback)
{
if (ref.t() != type::Number || ref.nt != num_type::Floating_point)
if (ref.t() != type::Number || ref.nt != num_type::Floating_point ||
ref.nt == num_type::Double_precision_floating_point)
return fallback;
return ref.num.d;
}
Expand Down
2 changes: 1 addition & 1 deletion include/crow/middlewares/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ namespace crow
{
case type::Number:
{
if (rv.nt() == num_type::Floating_point)
if (rv.nt() == num_type::Floating_point || rv.nt() == num_type::Double_precision_floating_point)
return multi_value{rv.d()};
else if (rv.nt() == num_type::Unsigned_integer)
return multi_value{int64_t(rv.u())};
Expand Down
14 changes: 6 additions & 8 deletions include/crow/routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -1154,25 +1154,23 @@ namespace crow
return static_dir_;
}

DynamicRule& new_rule_dynamic(std::string&& rule)
DynamicRule& new_rule_dynamic(const std::string& rule)
{
std::string new_rule = std::move(rule);
new_rule = '/' + prefix_ + new_rule;
auto ruleObject = new DynamicRule(new_rule);
std::string new_rule = '/' + prefix_ + rule;
auto ruleObject = new DynamicRule(std::move(new_rule));
ruleObject->custom_templates_base = templates_dir_;
all_rules_.emplace_back(ruleObject);

return *ruleObject;
}

template<uint64_t N>
typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(std::string&& rule)
typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(const std::string& rule)
{
std::string new_rule = std::move(rule);
new_rule = '/' + prefix_ + new_rule;
std::string new_rule = '/' + prefix_ + rule;
using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;

auto ruleObject = new RuleT(new_rule);
auto ruleObject = new RuleT(std::move(new_rule));
ruleObject->custom_templates_base = templates_dir_;
all_rules_.emplace_back(ruleObject);

Expand Down
28 changes: 22 additions & 6 deletions tests/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,11 +1038,13 @@ TEST_CASE("json::wvalue::wvalue(float)")

TEST_CASE("json::wvalue::wvalue(double)")
{
double d = 4.2;
double d = 0.036303908355795146;
json::wvalue value = d;

CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "4.2");
auto dumped_value = value.dump();
CROW_LOG_DEBUG << dumped_value;
CHECK(std::abs(utility::lexical_cast<double>(dumped_value) - d) < numeric_limits<double>::epsilon());
} // json::wvalue::wvalue(double)

TEST_CASE("json::wvalue::wvalue(char const*)")
Expand Down Expand Up @@ -1867,15 +1869,29 @@ TEST_CASE("middleware_cors")
return "-";
});

auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(45451).run_async();
const auto port = 33333;
auto _ = app.bindaddr(LOCALHOST_ADDRESS).port(port).run_async();

app.wait_for_server_start();
asio::io_service is;

{
asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(
asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
asio::ip::address::from_string(LOCALHOST_ADDRESS), port));

c.send(asio::buffer("OPTIONS / HTTP/1.1\r\n\r\n"));

c.receive(asio::buffer(buf, 2048));
c.close();

CHECK(std::string(buf).find("Access-Control-Allow-Origin: *") != std::string::npos);
}

{
asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(
asio::ip::address::from_string(LOCALHOST_ADDRESS), port));

c.send(asio::buffer("GET /\r\n\r\n"));

Expand All @@ -1888,7 +1904,7 @@ TEST_CASE("middleware_cors")
{
asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(
asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
asio::ip::address::from_string(LOCALHOST_ADDRESS), port));

c.send(asio::buffer("GET /origin\r\n\r\n"));

Expand All @@ -1901,7 +1917,7 @@ TEST_CASE("middleware_cors")
{
asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(
asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
asio::ip::address::from_string(LOCALHOST_ADDRESS), port));

c.send(asio::buffer("GET /nocors/path\r\n\r\n"));

Expand Down

0 comments on commit ae87100

Please sign in to comment.