Giter Site home page Giter Site logo

crowcpp / crow Goto Github PK

View Code? Open in Web Editor NEW
2.8K 49.0 306.0 47.52 MB

A Fast and Easy to use microframework for the web.

Home Page: https://crowcpp.org

License: Other

CMake 1.03% Python 0.53% C 0.05% C++ 97.55% Shell 0.83%
crow cpp webserver framework header-only http websocket http-server

crow's Introduction

A Fast and Easy to use microframework for the web.

Build Status Coverage Status Documentation Gitter Open Collective

Description

Crow is a C++ framework for creating HTTP or Websocket web services. It uses routing similar to Python's Flask which makes it easy to use. It is also extremely fast, beating multiple existing C++ frameworks as well as non-C++ frameworks.

Features

  • Easy Routing (similar to Flask).
  • Type-safe handlers.
  • Blazingly fast (see this benchmark and this benchmark).
  • Built in JSON support.
  • Mustache based templating library (crow::mustache).
  • Header only library (single header file available).
  • Middleware support for extensions.
  • HTTP/1.1 and Websocket support.
  • Multi-part request and response support.
  • Uses modern C++ (11/14)

Still in development

Documentation

Available here.

Warning

If you are using Crow v0.3, then you have to put #define CROW_MAIN at the top of one and only one source file.

Examples

Hello World

#include "crow.h"

int main()
{
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")([](){
        return "Hello world";
    });

    app.port(18080).multithreaded().run();
}

JSON Response

CROW_ROUTE(app, "/json")
([]{
    crow::json::wvalue x({{"message", "Hello, World!"}});
    x["message2"] = "Hello, World.. Again!";
    return x;
});

Arguments

CROW_ROUTE(app,"/hello/<int>")
([](int count){
    if (count > 100)
        return crow::response(400);
    std::ostringstream os;
    os << count << " bottles of beer!";
    return crow::response(os.str());
});

Handler arguments type check at compile time

// Compile error with message "Handler type is mismatched with URL parameters"
CROW_ROUTE(app,"/another/<int>")
([](int a, int b){
    return crow::response(500);
});

Handling JSON Requests

CROW_ROUTE(app, "/add_json")
.methods("POST"_method)
([](const crow::request& req){
    auto x = crow::json::load(req.body);
    if (!x)
        return crow::response(crow::status::BAD_REQUEST); // same as crow::response(400)
    int sum = x["a"].i()+x["b"].i();
    std::ostringstream os;
    os << sum;
    return crow::response{os.str()};
});

More examples can be found here.

Setting Up / Building

Available here.

Disclaimer

CrowCpp/Crow is a project based on ipkn/crow. Neither CrowCpp, it's members, or this project have been associated with, or endorsed or supported by ipkn (Jaeseung Ha) in any way. We do use ipkn/crow's source code under the BSD-3 clause license and sometimes refer to the public comments available on the github repository. But we do not in any way claim to be associated with or in contact with ipkn (Jaeseung Ha) regarding CrowCpp or CrowCpp/Crow

Attributions

Crow has incorporated the following libraries into its source.

http-parser (used for converting http strings to crow::request objects)

https://github.com/nodejs/http-parser

http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
Igor Sysoev.

Additional changes are licensed under the same terms as NGINX and
copyright Joyent, Inc. and other Node contributors. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE. 

---------------------------------------------------------------------------


qs_parse (used for reading query string parameters)

https://github.com/bartgrantham/qs_parse

Copyright (c) 2010 Bart Grantham
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

---------------------------------------------------------------------------


TinySHA1 (used during the websocket handshake, not for security)

https://github.com/mohaps/TinySHA1

TinySHA1 - a header only implementation of the SHA1 algorithm. Based on the
implementation in boost::uuid::details

Copyright (c) 2012-22 SAURAV MOHAPATRA [email protected]
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright 
notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

---------------------------------------------------------------------------


Catch2 (used only in unit tests, not part of the actual framework)

https://github.com/catchorg/Catch2

Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

crow's People

Contributors

acron0 avatar alibitek avatar ayaankhan98 avatar belugum avatar danielskeenan avatar deuscanon avatar dranikpg avatar erikaldsund avatar gittiver avatar hg333 avatar ipkn avatar iuliean avatar luca-schlecker avatar michaelsb avatar mkokryashkin avatar mrozigor avatar navidcity avatar neumannt avatar nx10 avatar okaestne avatar pierobot avatar rasie1 avatar robertgodfrey avatar ryanrussell avatar sfinktah avatar stefanopetrilli avatar the-edev avatar tibbel avatar vhuynh25 avatar whoshuu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

crow's Issues

Streaming response

ipkn#169, ipkn#46, ipkn#37, ipkn#8

Seems to be the logical continuation of static file serving, because as far as I understand, the connection times out regardless of what's going on, so a large static file is extremely likely not to be sent fully.

Enabling SSL leaves http code without any actual use

To put it simply, if you want Crow to run SSL (I mean OpenSSL, which includes TLS), you have to enable it using the flag CROW_ENABLE_SSL, which means that a program can either be compiled as SSL or not. Yet when compiling for SSL, Crow retains almost all the non SSL functionality (I'm saying almost because i'm not 100% sure it retains all the classes and methods). All these classes go unused since now all the routes are defined for HTTPS rather than HTTP. This creates 2 main consequences:

  1. Crow can still use HTTP when compiled for SSL
  2. Crow does not use HTTP

This is a problem primarily because a large portion of the code is just going unused. Either all non SSL classes should be removed if SSL is enabled, or Crow should automatically redirect HTTP requests to HTTPS.

Thinking about this, it might be possible to have a non SSL crow app only to redirect to the SSL version, although testing is needed to confirm or deny this.

server-sent events

I'm using crow for a lightweight webservices server and I have to implement a CZML one, which requires event-stream.
Is it already supported in any way?

Defining CROW_STATIC_ENDPOINT breaks compilation

Defining CROW_STATIC_ENDPOINT as described in https://crowcpp.org/guides/static/ and here https://github.com/CrowCpp/crow/blob/4e801d085ae1f1ab72d1ee080796b2241f01cd0b/examples/example_static_file.cpp#L2 leads to compilation error in the following minimal example:

// disabling this define fixes the error
#define CROW_STATIC_ENDPOINT "static_"

#include "crow_all.h"

int main() {
    crow::SimpleApp app;
    app.port(8080).run();
    return 0;
}

The error looks like:

[ 33%] Building CXX object CMakeFiles/bin.dir/main.cc.o
In file included from /home/user/dev/test/2021-02-09 crow race condition test/main.cc:4:
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h: In instantiation of ‘typename std::enable_if<(((! crow::black_magic::CallHelper<Func, crow::black_magic::S<Args ...> >::value) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::request, Args ...> >::value)) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::response&, Args ...> >::value)), void>::type crow::TaggedRule<Args>::operator()(Func&&) [with Func = crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>; Args = {}; typename std::enable_if<(((! crow::black_magic::CallHelper<Func, crow::black_magic::S<Args ...> >::value) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::request, Args ...> >::value)) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::response&, Args ...> >::value)), void>::type = void]’:
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:10846:13:   required from ‘void crow::Crow<Middlewares>::run() [with Middlewares = {}]’
/home/user/dev/test/2021-02-09 crow race condition test/main.cc:8:22:   required from here
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8792:94: error: static assertion failed: Handler type is mismatched with URL parameters
 8791 |             static_assert(black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
      |                                                                                   ~~~~~~~~    
 8792 |                 black_magic::CallHelper<Func, black_magic::S<crow::request, Args...>>::value ||
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
 8793 |                 black_magic::CallHelper<Func, black_magic::S<crow::request, crow::response&, Args...>>::value
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8796:56: error: no match for call to ‘(crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>) (crow::request, crow::response&)’
 8796 |             static_assert(std::is_same<void, decltype(f(std::declval<crow::request>(), std::declval<crow::response&>(), std::declval<Args>()...))>::value,
      |                                                       ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8796:56: note: candidate: ‘void (*)(const crow::request&, crow::response&, std::string)’ {aka ‘void (*)(const crow::request&, crow::response&, std::__cxx11::basic_string<char>)’} (conversion)
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8796:56: note:   candidate expects 4 arguments, 3 provided
In file included from /home/user/dev/test/2021-02-09 crow race condition test/main.cc:4:
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:10846:14: note: candidate: ‘crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>’
10846 |             ([](const crow::request&, crow::response& res, std::string file_path_partial)
      |              ^
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:10846:14: note:   candidate expects 3 arguments, 2 provided
In file included from /home/user/dev/test/2021-02-09 crow race condition test/main.cc:4:
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8799:26: error: no match for ‘operator=’ (operand types are ‘std::function<void(const crow::request&, crow::response&)>’ and ‘std::remove_reference<crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>&>::type’ {aka ‘crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>’})
 8799 |                 handler_ = std::move(f);
      |                 ~~~~~~~~~^~~~~~~~~~~~~~
In file included from /usr/include/c++/10.2.0/functional:59,
                 from /usr/include/boost/system/detail/error_category.hpp:17,
                 from /usr/include/boost/system/detail/error_code.hpp:13,
                 from /usr/include/boost/system/error_code.hpp:13,
                 from /usr/include/boost/asio/detail/throw_error.hpp:19,
                 from /usr/include/boost/asio/detail/impl/posix_event.ipp:23,
                 from /usr/include/boost/asio/detail/posix_event.hpp:172,
                 from /usr/include/boost/asio/detail/event.hpp:25,
                 from /usr/include/boost/asio/execution/blocking_adaptation.hpp:19,
                 from /usr/include/boost/asio/execution.hpp:22,
                 from /usr/include/boost/asio/system_executor.hpp:20,
                 from /usr/include/boost/asio/associated_executor.hpp:22,
                 from /usr/include/boost/asio.hpp:21,
                 from /home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:2894,
                 from /home/user/dev/test/2021-02-09 crow race condition test/main.cc:4:
/usr/include/c++/10.2.0/bits/std_function.h:396:7: note: candidate: ‘std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {const crow::request&, crow::response&}]’
  396 |       operator=(const function& __x)
      |       ^~~~~~~~
/usr/include/c++/10.2.0/bits/std_function.h:396:33: note:   no known conversion for argument 1 from ‘std::remove_reference<crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>&>::type’ {aka ‘crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>’} to ‘const std::function<void(const crow::request&, crow::response&)>&’
  396 |       operator=(const function& __x)
      |                 ~~~~~~~~~~~~~~~~^~~
/usr/include/c++/10.2.0/bits/std_function.h:414:7: note: candidate: ‘std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::function<_Res(_ArgTypes ...)>&&) [with _Res = void; _ArgTypes = {const crow::request&, crow::response&}]’
  414 |       operator=(function&& __x) noexcept
      |       ^~~~~~~~
/usr/include/c++/10.2.0/bits/std_function.h:414:28: note:   no known conversion for argument 1 from ‘std::remove_reference<crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>&>::type’ {aka ‘crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>’} to ‘std::function<void(const crow::request&, crow::response&)>&&’
  414 |       operator=(function&& __x) noexcept
      |                 ~~~~~~~~~~~^~~
/usr/include/c++/10.2.0/bits/std_function.h:428:7: note: candidate: ‘std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::nullptr_t) [with _Res = void; _ArgTypes = {const crow::request&, crow::response&}; std::nullptr_t = std::nullptr_t]’
  428 |       operator=(nullptr_t) noexcept
      |       ^~~~~~~~
/usr/include/c++/10.2.0/bits/std_function.h:428:17: note:   no known conversion for argument 1 from ‘std::remove_reference<crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>&>::type’ {aka ‘crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>’} to ‘std::nullptr_t’
  428 |       operator=(nullptr_t) noexcept
      |                 ^~~~~~~~~
/usr/include/c++/10.2.0/bits/std_function.h:457:2: note: candidate: ‘template<class _Functor> std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<typename std::decay<_Functor>::type>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = _Functor; _Res = void; _ArgTypes = {const crow::request&, crow::response&}]’
  457 |  operator=(_Functor&& __f)
      |  ^~~~~~~~
/usr/include/c++/10.2.0/bits/std_function.h:457:2: note:   template argument deduction/substitution failed:
/usr/include/c++/10.2.0/bits/std_function.h: In substitution of ‘template<class _Res, class ... _ArgTypes> template<class _Cond, class _Tp> using _Requires = typename std::enable_if<_Cond::value, _Tp>::type [with _Cond = std::function<void(const crow::request&, crow::response&)>::_Callable<crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>, std::__invoke_result<crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>&, const crow::request&, crow::response&> >; _Tp = std::function<void(const crow::request&, crow::response&)>&; _Res = void; _ArgTypes = {const crow::request&, crow::response&}]’:
/usr/include/c++/10.2.0/bits/std_function.h:457:2:   required by substitution of ‘template<class _Functor> std::function<void(const crow::request&, crow::response&)>::_Requires<std::function<void(const crow::request&, crow::response&)>::_Callable<typename std::decay<_Tp>::type, std::__invoke_result<typename std::decay<_Tp>::type&, const crow::request&, crow::response&> >, std::function<void(const crow::request&, crow::response&)>&> std::function<void(const crow::request&, crow::response&)>::operator=<_Functor>(_Functor&&) [with _Functor = crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>]’
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8799:26:   required from ‘typename std::enable_if<(((! crow::black_magic::CallHelper<Func, crow::black_magic::S<Args ...> >::value) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::request, Args ...> >::value)) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::response&, Args ...> >::value)), void>::type crow::TaggedRule<Args>::operator()(Func&&) [with Func = crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>; Args = {}; typename std::enable_if<(((! crow::black_magic::CallHelper<Func, crow::black_magic::S<Args ...> >::value) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::request, Args ...> >::value)) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::response&, Args ...> >::value)), void>::type = void]’
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:10846:13:   required from ‘void crow::Crow<Middlewares>::run() [with Middlewares = {}]’
/home/user/dev/test/2021-02-09 crow race condition test/main.cc:8:22:   required from here
/usr/include/c++/10.2.0/bits/std_function.h:319:8: error: no type named ‘type’ in ‘struct std::enable_if<false, std::function<void(const crow::request&, crow::response&)>&>’
  319 |  using _Requires = typename enable_if<_Cond::value, _Tp>::type;
      |        ^~~~~~~~~
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h: In instantiation of ‘typename std::enable_if<(((! crow::black_magic::CallHelper<Func, crow::black_magic::S<Args ...> >::value) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::request, Args ...> >::value)) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::response&, Args ...> >::value)), void>::type crow::TaggedRule<Args>::operator()(Func&&) [with Func = crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>; Args = {}; typename std::enable_if<(((! crow::black_magic::CallHelper<Func, crow::black_magic::S<Args ...> >::value) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::request, Args ...> >::value)) && (! crow::black_magic::CallHelper<Func, crow::black_magic::S<crow::response&, Args ...> >::value)), void>::type = void]’:
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:10846:13:   required from ‘void crow::Crow<Middlewares>::run() [with Middlewares = {}]’
/home/user/dev/test/2021-02-09 crow race condition test/main.cc:8:22:   required from here
/usr/include/c++/10.2.0/bits/std_function.h:466:2: note: candidate: ‘template<class _Functor> std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::reference_wrapper<_Functor>) [with _Functor = _Functor; _Res = void; _ArgTypes = {const crow::request&, crow::response&}]’
  466 |  operator=(reference_wrapper<_Functor> __f) noexcept
      |  ^~~~~~~~
/usr/include/c++/10.2.0/bits/std_function.h:466:2: note:   template argument deduction/substitution failed:
In file included from /home/user/dev/test/2021-02-09 crow race condition test/main.cc:4:
/home/user/dev/test/2021-02-09 crow race condition test/crow_all.h:8799:26: note:   ‘crow::Crow<Middlewares>::run<{}>::<lambda(const crow::request&, crow::response&, std::string)>’ is not derived from ‘std::reference_wrapper<_Tp>’
 8799 |                 handler_ = std::move(f);
      |                 ~~~~~~~~~^~~~~~~~~~~~~~
make[3]: *** [CMakeFiles/bin.dir/build.make:82: CMakeFiles/bin.dir/main.cc.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:123: CMakeFiles/bin.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:103: CMakeFiles/run.dir/rule] Error 2
make: *** [Makefile:137: run] Error 2

The compiler call looks like:

/usr/bin/c++ -DBOOST_ALL_NO_LIB -DBOOST_SYSTEM_DYN_LINK  -pthread -o CMakeFiles/bin.dir/main.cc.o -c "/<path>/main.cc"

I'm using commit 4e801d0 and gcc 10.2.0 on Arch.

`HEAD` and `OPTIONS` methods handling

  • HEAD should return the same response as GET, just without the body.
  • OPTIONS should return an Allow header with the allowed methods, separated by , .

Websites with images are (sometimes) broken on localhost

Introduction

Im building a website based on crow that features HTML pages that include linked images.
Here is a "minimum breaking example": https://github.com/rittelle/test-crow-race-condition

Expected behavior

http://localhost:8080 should show a very simple webpage with an image.

Actual behavior

Sometimes some XML code appears instead of the webpage. A look at the requests in the developer tools reveals that crow seems to sometimes respond with the content of static/image.svg instead of the intended content of / from main.cc. This is not happening every time (but most of the time for me, which is quite annoying), so it's maybe something like a race condition between the routes when both are requested?

The error also does not occur, when:

  • the page is refreshed with CTRL-F5 instead of F5
    • maybe Firefox makes requests in parallel, when the page is in its cache and CTRL-F5 prevents that?
  • the html page also resides in the static folder
    • testable using the link on the main page
    • maybe it's a race condition between the static/ routes in general and the other routes?
  • accessing the site from another computer (in the same network)

Test setup

  • using crow_all.h from 4e801d0
  • gcc 10.2.0, Firefox 85.0.1 on Arch

Final note

I didn't try other browser / OSes, yet. I may find the time to further investigate in the next days, but I don't know the codebase; any pointers would be appreciated ;) .

Allow extensible returning in handlers

we have JSON mode, basically sets the content-type header to application/json, just make the same thing for multipart, instead of converting to string and returning that, something like:

    CROW_ROUTE(app,"/multipart")
    ([](const crow::request& req){
        crow::multipart::message msg(req);
        return msg;
    });

Redirection is quite bare

Redirection is done through res.redirect("URL"), only problem with that is that it requires an absolute URL, meaning the code has to contain the whole http://domain.xyz/ which is an inconvenience.

However just having routes instead of full URLs isn't as simple as it may seem, requiring the request's URL in order to create the new URL, the problem with that is that it can't be part of the response code, since the response doesn't get any request reference.

In short, 2 solutions seem feasible:

  1. Have a local redirect method with a request argument.
  2. have the redirect function(s) be separate from the response code, maybe as part of the router code or the app code.

Related to ipkn#346

Possible to provide prebuilt "crow_all.h" file.

As a Visual Studio user it seems to be beyond me to be able to build the "crow_all.h" file myself.

Is there any chance someone could provide this file here, as they used to do on the previous version of the project? It would be a huge help to those of us less competent.

If that's not feasible, then perhaps you could provide an simple example of how the "merge_all.py" script should be used, because right now it makes no sense to me.

Many thanks for all your efforts.

Compile issues using crow_all.h in Visual Studio 2019.

I'm unable to compile Crow in Visual Studio 2019 using the combined crow_all.h file in an otherwise empty project with just the very simply Crow example.

Using the "Release v0.2" version of crow_all.h I get 31 compile errors. Using a version compile from the latest commit I get three errors as follows:

------ Build started: Project: \ConsoleApplication7, Configuration: Release x64 ------
ConsoleApplication7.cpp
Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:
- add -D_WIN32_WINNT=0x0601 to the compiler command line; or
- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.
Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).
\ConsoleApplication7\crow_all.h(1089,37): warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(1338,1): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(1351,1): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(1366,1): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(2777,39): warning C4267: 'argument': conversion from 'size_t' to 'uint32_t', possible loss of data
\ConsoleApplication7\crow_all.h(3043,1): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3291,1): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3310,1): warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3312,1): warning C4267: 'argument': conversion from 'size_t' to '_Ty', possible loss of data
        with
        [
            _Ty=int
        ]
\ConsoleApplication7\crow_all.h(3408,1): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3536,1): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3545,1): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3604,1): warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(3691,1): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(6240,42): warning C4244: '=': conversion from '__int64' to 'uint16_t', possible loss of data
\ConsoleApplication7\crow_all.h(6247,42): warning C4244: '=': conversion from '__int64' to 'uint16_t', possible loss of data
\ConsoleApplication7\crow_all.h(6254,42): warning C4244: '=': conversion from '__int64' to 'uint16_t', possible loss of data
\ConsoleApplication7\crow_all.h(6263,46): warning C4244: '=': conversion from '__int64' to 'uint16_t', possible loss of data
\ConsoleApplication7\crow_all.h(6356,31): warning C4244: '=': conversion from '__int64' to 'uint16_t', possible loss of data
\ConsoleApplication7\crow_all.h(6496,1): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(7937,1): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
\ConsoleApplication7\crow_all.h(8703,108): warning C4244: 'argument': conversion from '__int64' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8721,109): warning C4244: 'argument': conversion from '__int64' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8739,111): warning C4244: 'argument': conversion from '__int64' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8758,1): warning C4267: 'argument': conversion from 'size_t' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8771,1): warning C4267: 'argument': conversion from 'size_t' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8784,1): warning C4267: 'argument': conversion from 'size_t' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8826,1): warning C4267: '+=': conversion from 'size_t' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8908,1): warning C4267: 'return': conversion from 'size_t' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(8954,1): warning C4267: 'argument': conversion from 'size_t' to 'unsigned int', possible loss of data
\ConsoleApplication7\crow_all.h(10513,19): error C2039: 'set_static_file_info': is not a member of 'crow::response'
\ConsoleApplication7\crow_all.h(7638): message : see declaration of 'crow::response'
\ConsoleApplication7\crow_all.h(10508): message : while compiling class template member function 'void crow::Crow<>::run(void)'
\ConsoleApplication7\\ConsoleApplication7.cpp(19): message : see reference to function template instantiation 'void crow::Crow<>::run(void)' being compiled
\ConsoleApplication7\\ConsoleApplication7.cpp(13): message : see reference to class template instantiation 'crow::Crow<>' being compiled
\ConsoleApplication7\crow_all.h(10508,1): error C2039: '__this': is not a member of 'crow::response'
\ConsoleApplication7\crow_all.h(7638): message : see declaration of 'crow::response'
Done building project "\ConsoleApplication7.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Thank you again for your work.

compilation error for BOOST version == 1.64

Compiler complaints the following which does not happened in BOOST version == 1.74 and it does not happened in ipkn/crow master branch.

/home/workspace/http_server_c/crow/include/crow/http_response.h:188:106: note:   no known conversion for argument 1 from ‘boost::system::error_code’ to ‘std::error_code’
In file included from /home/workspace/http_server_c/crow/include/crow/http_response.h:7:0,
                 from /home/workspace/http_server_c/crow/include/crow/routing.h:12,
                 from /home/workspace/http_server_c/crow/include/crow/app.h:16,
                 from /home/workspace/http_server_c/crow/include/crow.h:3,
                 from examples/helloworld.cpp:1:
/home/workspace/http_server_c/crow/include/crow/json.h: In function ‘void crow::json::escape(const string&, std::__cxx11::string&)’:
/home/workspace/http_server_c/crow/include/crow/json.h:50:31: warning: comparison is always true due to limited range of data type [-Wtype-limits]
                         if (0 <= c && c < 0x20)
                               ^
In file included from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/write.hpp:618:0,
                 from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/buffered_write_stream.hpp:29,
                 from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/buffered_stream.hpp:22,
                 from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio.hpp:38,
                 from /home/workspace/http_server_c/crow/include/crow/http_request.h:3,
                 from /home/workspace/http_server_c/crow/include/crow/http_response.h:8,
                 from /home/workspace/http_server_c/crow/include/crow/routing.h:12,
                 from /home/workspace/http_server_c/crow/include/crow/app.h:16,
                 from /home/workspace/http_server_c/crow/include/crow.h:3,
                 from examples/helloworld.cpp:1:
/home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/impl/write.hpp: In instantiation of ‘std::size_t boost::asio::write(SyncWriteStream&, const ConstBufferSequence&, CompletionCondition, boost::system::error_code&) [with SyncWriteStream = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; ConstBufferSequence = std::vector<boost::asio::const_buffer>; CompletionCondition = crow::response::do_write_sendfile(Adaptor) [with Adaptor = crow::SocketAdaptor*]::<lambda(std::error_code, std::size_t)>; std::size_t = unsigned int]’:
/home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/impl/write.hpp:80:40:   required from ‘std::size_t boost::asio::write(SyncWriteStream&, const ConstBufferSequence&, CompletionCondition) [with SyncWriteStream = boost::asio::basic_stream_socket<boost::asio::ip::tcp>; ConstBufferSequence = std::vector<boost::asio::const_buffer>; CompletionCondition = crow::response::do_write_sendfile(Adaptor) [with Adaptor = crow::SocketAdaptor*]::<lambda(std::error_code, std::size_t)>; std::size_t = unsigned int]’
/home/workspace/http_server_c/crow/include/crow/http_response.h:188:39:   required from ‘void crow::response::do_write_sendfile(Adaptor) [with Adaptor = crow::SocketAdaptor*]’
/home/workspace/http_server_c/crow/include/crow/http_connection.h:471:13:   required from ‘void crow::Connection<Adaptor, Handler, Middlewares>::do_write_static() [with Adaptor = crow::SocketAdaptor; Handler = crow::Crow<>; Middlewares = {}]’
/home/workspace/http_server_c/crow/include/crow/http_connection.h:358:32:   required from ‘void crow::Connection<Adaptor, Handler, Middlewares>::complete_request() [with Adaptor = crow::SocketAdaptor; Handler = crow::Crow<>; Middlewares = {}]’
/home/workspace/http_server_c/crow/include/crow/http_connection.h:322:61:   required from ‘crow::Connection<Adaptor, Handler, Middlewares>::handle()::<lambda()> [with Adaptor = crow::SocketAdaptor; Handler = crow::Crow<>; Middlewares = {}]’
/home/workspace/http_server_c/crow/include/crow/http_connection.h:322:54:   [ skipping 13 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/home/workspace/http_server_c/crow/include/crow/http_server.h:197:25:   required from ‘crow::Server<Handler, Adaptor, Middlewares>::do_accept()::<lambda(boost::system::error_code)> [with Handler = crow::Crow<>; Adaptor = crow::SocketAdaptor; Middlewares = {}]’
/home/workspace/http_server_c/crow/include/crow/http_server.h:193:28:   required from ‘struct crow::Server<Handler, Adaptor, Middlewares>::do_accept() [with Handler = crow::Crow<>; Adaptor = crow::SocketAdaptor; Middlewares = {}]::<lambda(class boost::system::error_code)>’
/home/workspace/http_server_c/crow/include/crow/http_server.h:192:13:   required from ‘void crow::Server<Handler, Adaptor, Middlewares>::do_accept() [with Handler = crow::Crow<>; Adaptor = crow::SocketAdaptor; Middlewares = {}]’
/home/workspace/http_server_c/crow/include/crow/http_server.h:160:22:   required from ‘void crow::Server<Handler, Adaptor, Middlewares>::run() [with Handler = crow::Crow<>; Adaptor = crow::SocketAdaptor; Middlewares = {}]’
/home/workspace/http_server_c/crow/include/crow/app.h:123:17:   required from ‘void crow::Crow<Middlewares>::run() [with Middlewares = {}]’
examples/helloworld.cpp:12:25:   required from here
/home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/impl/write.hpp:46:29: error: no match for call to ‘(crow::response::do_write_sendfile(Adaptor) [with Adaptor = crow::SocketAdaptor*]::<lambda(std::error_code, std::size_t)>) (boost::system::error_code&, std::size_t&)’
         completion_condition(ec, total_transferred)));
                             ^
In file included from /home/workspace/http_server_c/crow/include/crow/routing.h:12:0,
                 from /home/workspace/http_server_c/crow/include/crow/app.h:16,
                 from /home/workspace/http_server_c/crow/include/crow.h:3,
                 from examples/helloworld.cpp:1:
/home/workspace/http_server_c/crow/include/crow/http_response.h:188:106: note: candidate: crow::response::do_write_sendfile(Adaptor)::<lambda(std::error_code, std::size_t)> [with Adaptor = crow::SocketAdaptor*; std::size_t = unsigned int]
                     boost::asio::write(adaptor->socket(), buffers, [this](std::error_code ec, std::size_t)
                                                                                                          ^
/home/workspace/http_server_c/crow/include/crow/http_response.h:188:106: note:   no known conversion for argument 1 from ‘boost::system::error_code’ to ‘std::error_code’
In file included from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/write.hpp:618:0,
                 from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/buffered_write_stream.hpp:29,
                 from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/buffered_stream.hpp:22,
                 from /home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio.hpp:38,
                 from /home/workspace/http_server_c/crow/include/crow/http_request.h:3,
                 from /home/workspace/http_server_c/crow/include/crow/http_response.h:8,
                 from /home/workspace/http_server_c/crow/include/crow/routing.h:12,
                 from /home/workspace/http_server_c/crow/include/crow/app.h:16,
                 from /home/workspace/http_server_c/crow/include/crow.h:3,
                 from examples/helloworld.cpp:1:
/home/local/libs/armnn-devenv/boost_armhf_install/include/boost/asio/impl/write.hpp:53:31: error: no match for call to ‘(crow::response::do_write_sendfile(Adaptor) [with Adaptor = crow::SocketAdaptor*]::<lambda(std::error_code, std::size_t)>) (boost::system::error_code&, std::size_t&)’
           completion_condition(ec, total_transferred)));
                               ^
In file included from /home/workspace/http_server_c/crow/include/crow/routing.h:12:0,
                 from /home/workspace/http_server_c/crow/include/crow/app.h:16,
                 from /home/workspace/http_server_c/crow/include/crow.h:3,
                 from examples/helloworld.cpp:1:
/home/workspace/http_server_c/crow/include/crow/http_response.h:188:106: note: candidate: crow::response::do_write_sendfile(Adaptor)::<lambda(std::error_code, std::size_t)> [with Adaptor = crow::SocketAdaptor*; std::size_t = unsigned int]
                     boost::asio::write(adaptor->socket(), buffers, [this](std::error_code ec, std::size_t)
                                                                                                          ^
/home/workspace/http_server_c/crow/include/crow/http_response.h:188:106: note:   no known conversion for argument 1 from ‘boost::system::error_code’ to ‘std::error_code’
Makefile:52: recipe for target 'helloworld' failed

Separate middleware.h from the main project

middleware.h only contains a cookie handling middleware, while it's important to handle cookies, the middleware isn't being used by any core part, neither is it necessary to run a basic server.

I suggest separating the cookie parser and more middlewares into a separate repository. or at least a name change.

@mrozigor what do you think?

Zlib HTTP compression

ipkn#144

Should support compression and decompression for http requests.

This could be needed before HTTP/2 could be implemented.

SSL refreshes

ipkn#319, ipkn#269

I've run into this problem myself (while testing SSL file transfer), although it doesn't happen all the time, and seems to happen randomly for me.

ipkn#347 is a possible fix
Edit: While i do believe the PR above is useful, it does not fix the SSL refresh issue, more research needed.

example HTTP hello_world program takes 192K

I just compiled the example HTTP hello_world program with clang-10.0.0-4ubuntu1 and lld-10.0.0:

clang++ -std=c++17 -Oz -Wall -flto -fno-asynchronous-unwind-tables -fno-unwind-tables -fmerge-all-constants
              -I /path/to/crow/ -fvisibility=hidden
              -s -Wl,-icf=all,--gc-sections,--as-needed -flto -Wl,--plugin-opt=O3 -fuse-ld=lld
              -lpthread -lboost_system

and the executable I get is 192K:

192K    hello.out

The size of executable is much larger than I expected.
As a comparison, libnghttp2 which fully supports HTTP/2.0 is much smaller:

160K    /usr/lib/x86_64-linux-gnu/libnghttp2.so.14.19.0

To find out what is taking so much size, I used bloaty to analyze the makeup of this program:

   FILE SIZE        VM SIZE                       
--------------  --------------                    
 52.8%  99.9Ki  53.0%  99.8Ki    .text            
 14.4%  27.3Ki  14.5%  27.3Ki    .rodata          
 12.0%  22.7Ki  12.0%  22.7Ki    .eh_frame        
  3.9%  7.47Ki   3.9%  7.41Ki    .dynstr          
  3.7%  6.95Ki   3.7%  6.89Ki    .gcc_except_table
  2.9%  5.45Ki   2.9%  5.39Ki    .dynsym          
  2.5%  4.73Ki   2.5%  4.66Ki    .rela.plt        
  1.8%  3.47Ki   1.8%  3.41Ki    .eh_frame_hdr    
  1.7%  3.19Ki   1.7%  3.12Ki    .plt             
  0.9%  1.70Ki   0.8%  1.58Ki    .got.plt         
  0.8%  1.52Ki   0.2%     320    [15 Others]      
  0.0%       0   0.7%  1.30Ki    .bss             
  0.4%     819   0.0%       0    [Unmapped]       
  0.0%       0   0.4%     784    .bss.rel.ro      
  0.4%     759   0.4%     759    [LOAD #2 [R]]    
  0.4%     680   0.3%     616    .data            
  0.3%     616   0.3%     552    .rela.dyn        
  0.3%     544   0.2%     480    .gnu.version_r   
  0.3%     524   0.2%     460    .gnu.version     
  0.3%     512   0.2%     448    .dynamic         
  0.2%     476   0.2%     412    .gnu.hash        
100.0%   189Ki 100.0%   188Ki    TOTAL            

and found that there is 99.9KB of assembly for the hello_world program which is suprisingly large, given that crow is header-only library that only supports HTTP/1.0, clang should be able to produce much smaller code.

Perhaps crow overuse virtual function and should consider use CRTP, a template techique, to replace these virtual base classes and the size of executable will be much smaller and the performance also will be better.

The .eh_frame also takes 22.7KB which makes me want to disable exception all together to make the executable smaller, but crow clearly hasn't support -fno-exceptions yet.

Test infinite hanging

Some tests require app.stop(); to be run after the REQUIRE() (or ASSERT_XYZ with the old system).

It seems that the old system allowed the rest of the code to be run if an assertion fails, allowing app.stop(); to run, ending the test. This doesn't seem to be the case with Catch, which causes the test to basically run in an infinite loop if a test that requires app.stop(); fails.

Example program crashes

#include "crow_all.hpp"

int main() {
  crow::SimpleApp app;

  CROW_ROUTE(app, "/")([](){
      return "Hello world";
      });

  app.port(18080).multithreaded().run();
}

This crashes in the app.port-line with an error in the depths of boost

template<class E> BOOST_NORETURN void throw_exception( E const & e )
{
    throw_exception_assert_compatibility( e );
    throw wrapexcept<E>( e );
}

Call stack and the exception:
image

I am using boost 1.75, windows 10 and clang ( llvm11 ).

Tests

  • websocket.h is seemingly not being tested at all, should probably be addressed
  • mustache.h is quite low, not sure why, should probably be investigated.. mustachetest is not generating gcov files
  • Also I think there's no testing for SSL

Close WebSocket connections on exit

from ipkn/crow#377

The problem with some of the comments there though is that they use line numbers in crow_all.h which means that the smallest change in any header file puts that number way off. Best to use method names or namespaces.

Example build issue

I was trying to build the websocket example in using G++ and the build seems to be failing and am not sure exactly what the problem is - I'm new to the language and terrible at debugging so trying to provide as much information as possible for potential bug (or more likely an issue on my environment).

OS - CentOS7 (RH)
gcc/g++ version 8.3.1.20190223
I'm not sure what version of boost I am using but pulled from github just the other day when building
I have Codeblocks to link with -lpthread and -lboost_system on build and also tried to add a search directory as /usr/local/include (just incase there was some link to this directory)

Line 10580 - Internal compiler error: in write_expression, at cp/mangle.c:3050

Codeblocks seems to pull open crow_all.h and points me to the following method:

//Create a route using a rule (**USE CROW_ROUTE instead**)
template <uint64_t Tag>
auto route(std::string&& rule)
-> typename std::result_of<decltype(&Router::new_rule_tagged<Tag>)(Router, std::string&&)>::type
{
return router_.new_rule_tagged<Tag>(std::move(rule));
}

Let me know i you have any questions I have missed or suggestions

Route specific middleware

This is me daydreaming but it would be nice if middlewares could be defined per route as well as per server. Those defined per server will run on every request as usual, but the ones defined per route will run only on that request (I'm mainly talking about before_handle and after_handle)

static_file_info and _WIN32

Hi,

I met a problem while compiling on Windows:

on http_response.h the static_file_info is only defined if !defined(_WIN32)

http_connection.h uses it without _WIN32 checking

also app.h calls set_static_file info if CROW_DISABLE_STATIC_DIR is not defined

It was not immediately obvious to me, why the static_file_info part is disabled on _WIN32 compile.
The code compiles with Microsoft Visual studio, thus the easiest way to avoid the problem was to remove the condition in http_response.h I should understand it first though...

Eero

Extra Documentation

So the API reference is coming along nicely (about as nice as trying to type what I learned in the past 20 minutes in a coherent readable manner).

But I don't believe this is it, sure it is helpful if someone wants to go to the next level in using crow (or even editing it). But there should be something for people who are just starting out with Crow or C++ even (me 2 months ago).

Currently we have examples to fulfill this role. But I get the feeling They're not enough. Things like setting up the environment, connecting to a proxy, compiling with SSL, creating middlewares, even creating crow_all.h are not in these examples, and frankly the examples themselves aren't documented, they don't mention any quirks or tricks that might come up, nor do they explain why things are the way they are.

To be frank, currently our documentation mirrors that of ASIO, which holy crap do I hate going through.

So the solution in my opinion is having the API reference (doxygen stuff) be only 1 part of a much larger documentation effort, @ipkn was trying to accomplish this via the wiki. This could be done the same way or through increasing the size of the github.io to add tutorials, introductions, and explanations (they all probably mean the same thing I'm just overexpressing).

We can later move this out of github.io into our own website, I mean.. we have a logo, the only thing left is everything else.

I believe this is an important step to take for crow to go from "just another C++ project" to something actually viable in a production environment, and I would like it if we could do this either before or around v0.3 (I know the line between0.3 and 1.0 is getting more and more blurry).

HTTP/2 support

in response to ipkn/crow#47, ipkn/crow#219, ipkn/crow#292.

I'm not sure how to go about this, a good place to start implementing would be the comments of the issues themselves, and maybe we could also take a look at this to further understand how to implement the standard fully.

Run Travis CI

We have .travis.yml, we just might need to change things like the compiler or notification channel, and we'll be able to run unit tests again.

#7 probably depends on this.

Documentation

in response to ipkn/crow#45, ipkn/crow#180, ipkn/crow#288.

We could either use the wiki and just explain things or set something like doxygen up.

either way some explanation as to how every part works and some form of API reference is needed.

Randomly failing tests

The test for streaming response bodies randomly fails because the client fails to receive the first 1-5 bytes, which causes all subsequent comparisons to fail as well, a potential fix was to check the length, but this fix only checks if the last x bytes are missing.

Versioned Documentation

Basically have a folder for every crow version + a latest folder, update only the latest folder, then a release rename latest to version name.

return crow::json::wvalue doesn't work for non "json object" types.

in the handler lambda, if you do return value_item withvalue_time being a list crow::json::wvalue object, you get nothing, it only works if you do return crow::response(value_item).

This is also true for all other non object types.

This is the code I used

CROW_ROUTE(app, "/json/thing")
([](){
        crow::json::wvalue value_item;
        std::vector<int> value_list;
        value_list.emplace_back(5);
        value_list.emplace_back(2);
        value_list.emplace_back(3);
        value_list.emplace_back(4);
        value_item = value_list;
        return value_item;
});

Documentation regarding templates directory

https://crowcpp.org/guides/templating/ states:

The HTML page (including the mustache tags). It is usually loaded into crow::mustache::template_t. It needs to be placed in templates directory (relative to where the crow executable is).

This seems to be incorrect on version 0.2 at least, where it seems that the templates/ folder needs to be in the current working directory.
So it should state:

The HTML page (including the mustache tags). It is usually loaded into crow::mustache::template_t. It needs to be placed in the templates directory which should be in the current working directory of the crow executable.

Missing template files get silently ignored (even on the debug log level), too. This should not be the case...

handler return automatically sets content-type

discussion in ipkn#250

Currently Crow only supports this with its own JSON data type, no xml, no anything.

one potential solution would be to create a response constructor argument that specifies the content type (as opposed to just headers), this can be done by using an extention (e.g. xml) and then using mime_types.h to get the proper content-type header.

Blueprint support

Some way of combining similar requests or modulating the application, with their own prefixes, and maybe even middlewares.

Based on Flask's blueprints

Connect Crow to Apache and Nginx using custom modules

Currently Crow uses the http and websocket proxy modules in Apache and Nginx to allow them to handle connections rather than crow itself. This can be slow and a potentially better approach would be to instead have a module translate the HTTP requests to Crow format and responses to something Apache and Nginx can send.

Update http_parser

Crow currently uses version 2.3.0, latest version is 2.9.4, might be best to upgrade since a skim of the changelog shows memory leak plugs.

static directory support

Have the /static directory be fully accessible to clients, this is similar to how Flask handles static files.

This can be done either by having a /static/<path> rule be always present (possible with an option to disable it). or with middleware that checks for any requests that start with /static and just does a set_static_file_info to whatever the request url is.

ipkn#386 is somewhat related.

Crow does not accept 0 MASK bit in websockets

Crow does not check the mask bit, instead it applies the mask regardless (since the mask is always 0 if the mask bit is not set), but this would still involve memory allocation, asio reading, and a loop containing XOR and MOD operations.

a better implementation would be to check the mask bit and ignore any operation if the bit isn't set.

How can framework users write tests?

I'm sorry if this has already been addressed, but I'm wondering about writing a basic unit test.

For example, the type of test you might write for Flask, and simulating a client request:

def test_empty_db(client):
    """Start with a blank database."""

    rv = client.get('/')
    assert b'No entries here so far' in rv.data

I thought I might find something here, but I haven't. Can anyone point me in the right direction?

Feature request: Add fastCGI support please

Most people building websites nowadays use nginx or appache to reverse proxy the real dynamic content server instead of directly expose the underlying server directly as

  • nobody would expose their underlying server directly to outside world, as they would like find CVE in their underlying server or their server would be under attack by hackers.
    The http/https code in nginx and appache are much more battle tested and has less bug.
  • people who really needs to use C++ to write their dynamic content server would probably also use distributed computing and fastCGI is a more efficient protocol to use than http or https
  • performance of https in nginx and appache is probably much better than crow
  • developers are familiar with nginx and appache and know how to tune them. Some might even has special patch applied to them for their own use case
  • Separating https server and content server enables them to run at different privileges:
    The https server could run as root while the content server can run as a normal user.
    Any bug in content server won't cause privilege escalation or crash in https server and the user won't feel the crash of content server as the server can be restarted in background without the https connection being closed.

There are broader audience who needs fastCGI in their content server.

While nginx and appache can also proxy http, it is slower than fastCGI as

  • http is a text based protocol while fastCGI is a binary one
  • fastCGI support multiplexing while http does not
  • fastCGI support unix socket for proxying local server while http does not

and nobody in their right mind would proxy their underlying content server over https as it is too heavy weight.
The right solution here is fastCGI. It is designed for this kind of application, so the experience programming with fastCGI is probably better than http.

Thus I think crow should have fastCGI support as it is extremely important.

I found archive of the specification of fastCGI here and it also has a reference implementation of fastCGI library fcgi2.

There are also kcgi and fastcgipp that are C and C++ server that supports fastCGI.

potentially useful PRs

the following PRs could be useful.

they should probably be cloned, tested (thoroughly, we don't need another sendifle), cleaned up, and merged.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.