GithubHelp home page GithubHelp logo

qicosmos / cinatra Goto Github PK

View Code? Open in Web Editor NEW
1.8K 1.8K 370.0 10.98 MB

modern c++(c++20), cross-platform, header-only, easy to use http framework

License: MIT License

CMake 0.17% C++ 98.80% HTML 0.05% CSS 0.01% JavaScript 0.04% Dockerfile 0.01% Assembly 0.92%

cinatra's People

Contributors

afengsoft avatar asanchez-amadeus avatar bbbgan avatar employeeno427 avatar firechickrsx avatar flushhip avatar helintongh avatar hungmingwu avatar jacyking avatar kidsunbo avatar lizhichaounicorn avatar polina4096 avatar poor-circle avatar ptbxzrt avatar qicosmos avatar qinrhx avatar quronox avatar sandyhsia avatar sulingzhi97 avatar tearshark avatar tianyime avatar uniqss avatar utigox avatar uurun avatar vrqq avatar wofeicaoge avatar xiesiping avatar xmh0511 avatar zhengjian526 avatar zhenhua-li 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  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

cinatra's Issues

关于websocket自动掉线的疑问

websocket将会话连接指针存放于外部,然后客户端不发任何信息,服务器每秒都会向客户端主动推送消息,代码如下:

req.on (cinatra::ws_open, [] (cinatra::request& req) {
    LOG_INFO ("websocket start");
    std::lock_guard lg (g_conn_mutex);
    s_conn = req.get_conn ();
});
req.on (cinatra::ws_message, [] (cinatra::request& req) {
    auto part_data = req.get_part_data ();
    ////echo
    //std::string str = std::string (part_data.data (), part_data.length ());
    //req.get_conn ()->send_ws_string (std::move (str));
    //std::cout << part_data.data () << std::endl;
});
req.on (cinatra::ws_close, [] (cinatra::request& req) {
    LOG_INFO ("websocket close");
    std::lock_guard lg (g_conn_mutex);
    s_conn = nullptr;
});
req.on (cinatra::ws_error, [] (cinatra::request& req) {
    LOG_INFO ("websocket error");
});

然后外部线程每秒通过s_conn给客户端推数据

std::lock_guard lg (g_conn_mutex);
try {
    if (s_conn && s_conn->socket ().is_open ()) {
        s_conn->send_ws_binary (std::move (_data));
        return;
    }
} catch (...) {
    // 这个位置稳定复现异常捕获
}
s_conn = nullptr;

客户端为HTML5,每分钟服务器稳定被catch,异常截图为:
image
这种情况是否需要我这边再做什么处理呢?

在html中调用$(document).ready崩溃

在html中调用$(document).ready,服务器直接崩溃。
网页body部分为:

<div class="parallax-container">
    <div class="parallax"><img src="www/images/parallax1.jpg"></div>
  </div>
  <div class="section white">
    <div class="row container">
      <h2 class="header">Parallax</h2>
      <p class="grey-text text-darken-3 lighten-3">视差</p>
    </div>
  </div>
  <div class="parallax-container">
    <div class="parallax"><img src="www/images/parallax2.jpg"></div>
  </div>

<script>
$(document).ready(function(){
      $('.parallax').parallax();
    });
  </script>

服务器代码为:

#include "cinatra.hpp"
using namespace cinatra;

int main() {
	int max_thread_num = std::thread::hardware_concurrency();
	http_server server(max_thread_num);
	server.listen("0.0.0.0", "8080");
	server.set_http_handler<GET, POST>("/", [](request& req, response& res) {
		res.render_view(./www/index.html)
	});

	server.run();
	return 0;
}

html调用了Materialize框架,在访问http://0.0.0.0:8080/时,服务器直接退出。通过验证,不使用其余任何框架,直接调用$(document).ready或者onload,服务器都会直接崩溃退出,删除js则服务器正常运行且图片正常显示。

http_router::map_invokers_键值类型为std::string_view

由此以下代码无法运行
void foo(cinatra::http_server *server) {
std::string url("/1");
server->set_http_handler<GET, POST>(std::string_view(url.c_str()), [](request &req, response &res) {
res.set_status_and_content(status_type::ok, "ok");
});
}
在函数传值过程中形参一直为std::string_view,url销毁后map_invokers_的相应键值就无效了。

https_client

我们项目中用 cinatra 对接 微信登录需要 https client
请问 cinatra 支持吗

当req.get_query_value(0)在不同的cpp文件中使用时,memento::pathinfo_mem.size() 出现为空的情况

你好,我在使用这个库的时候出现了一个奇怪的问题,我猜测应该是由于C++17 的 inline 变量引起的。
当我仅在main中使用http-server时 一切正常。例如这样:

http_server server(std::thread::hardware_concurrency());	
server.set_http_handler<GET, POST>("/pathinfo/*", [](request& req, response& res) {
		auto s = req.get_query_value(0);
		res.render_string(std::string(s.data(), s.length()));
	});
bool r = server.listen("0.0.0.0", "8090");
server.run();

但是,当我在实现另一个cpp文件中的某个类函数时,如果我调用了req.get_query_value(0),那么主函数中的get_query_value就会出现问题,比如这样:

void HttpServer::BindHttpHandle()
{
	Server.set_http_handler<GET>("/Charts/*", [](request& Req, response& Res)
	{
		auto File=Req.get_query_value(0);
	}, enable_cache{ bEnableCache });
}

经过我的调试发现一个非常有趣的问题,在我调试进入get_query_value()后,VS中能看到memento::pathinfo_mem 变量的数量,但是for循环却始终进不去。当我尝试用cout输出它的长度或者使用临时变量转存的时候,发现它的长度为0,且临时变量中也不存在数据。但是当我实现上方函数(BindHttpHandle)的时候,一切正常。(上方函数(BindHttpHandle)仅做了实现,并未调用)。
我新增调试代码后的函数如下:

std::string_view get_query_value(size_t n) {
			auto url = get_url();
			size_t tail = (url.back() == '/') ? 1 : 0;

			auto pathinfo_mem_size = memento::pathinfo_mem.size();
			auto temp_pathinfo_mem = memento::pathinfo_mem;

			for (auto item : memento::pathinfo_mem) {
				if (url.find(item) != std::string_view::npos) {
					if (item.length() == url.length())
						return {};

					auto str = url.substr(item.length(), url.length() - item.length() - tail);
					auto params = split(str, "/");
					if (n >= params.size())
						return {};
					if(code_utils::is_url_encode(params[n]))
					{
                        auto map_url = url.length()>1 && url.back()=='/' ? url.substr(0,url.length()-1):url;
                        std::string map_key = std::string(map_url.data(),map_url.size())+ std::to_string(n);

						auto ret = utf8_character_pathinfo_params_.emplace(map_key, code_utils::get_string_by_urldecode(params[n]));
						return std::string_view(ret.first->second.data(), ret.first->second.size());
					}
					return params[n];
				}
			}

			return {};
		}

调试时,VS变量窗口如下:
image

我编译的时候遇到了下面的问题,使用第一个测试用例

g++ -std=c++17 -o test test.cpp
/tmp/ccZkW8KL.o: In function boost::asio::detail::posix_event::posix_event()': test.cpp:(.text._ZN5boost4asio6detail11posix_eventC2Ev[_ZN5boost4asio6detail11posix_eventC5Ev]+0x3e): undefined reference to pthread_condattr_setclock'
/tmp/ccZkW8KL.o: In function boost::asio::detail::posix_thread::~posix_thread()': test.cpp:(.text._ZN5boost4asio6detail12posix_threadD2Ev[_ZN5boost4asio6detail12posix_threadD5Ev]+0x26): undefined reference to pthread_detach'
/tmp/ccZkW8KL.o: In function boost::asio::detail::posix_thread::join()': test.cpp:(.text._ZN5boost4asio6detail12posix_thread4joinEv[_ZN5boost4asio6detail12posix_thread4joinEv]+0x2b): undefined reference to pthread_join'
/tmp/ccZkW8KL.o: In function boost::asio::detail::posix_thread::start_thread(boost::asio::detail::posix_thread::func_base*)': test.cpp:(.text._ZN5boost4asio6detail12posix_thread12start_threadEPNS2_9func_baseE[_ZN5boost4asio6detail12posix_thread12start_threadEPNS2_9func_baseE]+0x29): undefined reference to pthread_create'
/tmp/ccZkW8KL.o: In function std::experimental::filesystem::v1::exists(std::experimental::filesystem::v1::path const&)': test.cpp:(.text._ZNSt12experimental10filesystem2v16existsERKNS1_4pathE[_ZNSt12experimental10filesystem2v16existsERKNS1_4pathE]+0x14): undefined reference to std::experimental::filesystem::v1::status(std::experimental::filesystem::v1::path const&)'
/tmp/ccZkW8KL.o: In function uuids::uuid_system_generator::operator()()': test.cpp:(.text._ZN5uuids21uuid_system_generatorclEv[_ZN5uuids21uuid_system_generatorclEv]+0x15): undefined reference to uuid_generate'
/tmp/ccZkW8KL.o: In function std::experimental::filesystem::v1::path::path<char*, std::experimental::filesystem::v1::path>(char* const&)': test.cpp:(.text._ZNSt12experimental10filesystem2v14pathC2IPcS2_EERKT_[_ZNSt12experimental10filesystem2v14pathC5IPcS2_EERKT_]+0x6a): undefined reference to std::experimental::filesystem::v1::path::_M_split_cmpts()'
/tmp/ccZkW8KL.o: In function cinatra::http_server_<cinatra::io_service_pool>::run()': test.cpp:(.text._ZN7cinatra12http_server_INS_15io_service_poolEE3runEv[_ZN7cinatra12http_server_INS_15io_service_poolEE3runEv]+0x88): undefined reference to std::experimental::filesystem::v1::create_directory(std::experimental::filesystem::v1::path const&)'
/tmp/ccZkW8KL.o: In function std::thread::thread<cinatra::io_service_pool::run()::{lambda(std::shared_ptr<boost::asio::io_context>)#1}, std::shared_ptr<boost::asio::io_context>&>(cinatra::io_service_pool::run()::{lambda(std::shared_ptr<boost::asio::io_context>)#1}&&, std::shared_ptr<boost::asio::io_context>&)': test.cpp:(.text._ZNSt6threadC2IZN7cinatra15io_service_pool3runEvEUlSt10shared_ptrIN5boost4asio10io_contextEEE_JRS7_EEEOT_DpOT0_[_ZNSt6threadC5IZN7cinatra15io_service_pool3runEvEUlSt10shared_ptrIN5boost4asio10io_contextEEE_JRS7_EEEOT_DpOT0_]+0x25): undefined reference to pthread_create'
/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a(thread44.o): In function std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)())': (.text._ZNSt6thread15_M_start_threadESt10unique_ptrINS_6_StateESt14default_deleteIS1_EEPFvvE+0x11): undefined reference to pthread_create'
/opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/libstdc++_nonshared.a(thread44.o): In function std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void (*)())': (.text._ZNSt6thread15_M_start_threadESt10shared_ptrINS_10_Impl_baseEEPFvvE+0x5f): undefined reference to pthread_create'
collect2: error: ld returned 1 exit status
You have new mail in /var/spool/mail/root
[root@ip-10-12-33-201 cinatra-0.07]# g++ version
g++: error: version: No such file or directory
g++: fatal error: no input files
compilation terminated.
[root@ip-10-12-33-201 cinatra-0.07]# g++-- version
bash: g++--: command not found
[root@ip-10-12-33-201 cinatra-0.07]# g++ --version
g++ (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

connection.hpp 116行有一处BUG

connection.hpp 116行有一句 static_assert(size != 0 || size != 2); 显然无论size为何值都会返回true。导致断言失效。
谢谢。

python request 上传文件踩坑之一

with open(img_path, "rb") as file:
    img = file.read()

# 1.上传文件  multipart/form-data 格式一定要使用 encode_multipart_formdata 编码
#  2. encode_multipart_formdata 编码时候一定带上文件类型。
encode_data = encode_multipart_formdata({"file":("test1.png",
                                                 open("../data/img/test1.png", "rb").read(), "image/png")})
headers = {"Content-Type": encode_data[1]}
print(encode_data[1])
req_url = "http://10.19.177.213:8081/ocr"
res = requests.post(req_url, headers=headers, data=encode_data[0]

以上就是我上传文件时候的总结,一定要多看文档,多看文档,多看文档!!!

[Suggestion] We should add scripts to build thirdparty library.

  1. It's necessary for users to build this project with only one command, like sh build.sh or cmake or others.

We should make the building-processes more simple.
So, could we add a script named build.sh and clone the thirdparty library with it.

This is the best way for a such mature project, right?

  1. Btw, I think our structure of this repo is a bit disorganized, why we don't organize our repo like the following:

    |---thirdparty
    |---src
    |---www
    |---docs
    |---etc

[BugReport] Memory Leak on request.hpp

在request.hpp的第87行,queries_ = parse_query(raw_url_.substr(pos+1, url_len_-pos-1));在substr时候产生了新的string,而parse_query函数传入值为string_view。在执行完这个函数后,所产生的substr失效,导致一系列string_view失效。
改成queries_ = parse_query(std::string_view{raw_url_}.substr(pos+1, url_len_-pos-1));即可!
( 要pull request吗<( ̄︶ ̄)/ )

另外建议编译时可加参数-fsanitize=address 调AddressSanitizer

cinatra下载文件崩溃

TIM图片20191106151345

TIM截图20191106151438

#pragma comment (linker, "/subsystem:console")
#define _CRT_SECURE_NO_WARNINGS
#define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#include "cinatra.hpp"


#include <iostream>
#include <string>
#include <string_view>
#include <thread>
#include <chrono>

int main () {
    try {
        cinatra::http_server _server (1);
        _server.listen ("0.0.0.0", "8181");
        _server.set_http_handler<cinatra::GET> ("/", [] (cinatra::request& req, cinatra::response& res) {
            std::cout << "http request: /" << std::endl;
            res.set_status_and_content (cinatra::status_type::ok, "hello world");
            std::cout << "    response: hello world" << std::endl;
        });
        std::thread ([] () {
            std::this_thread::sleep_for (std::chrono::seconds (1));
            auto _client = cinatra::client_factory::instance ().new_client ("127.0.0.1", "8181");
            _client->on_length ([] (size_t _length) {
                std::cout << "download file: on_length: " << _length << std::endl;
            });
            _client->on_data ([] (std::string_view _data) {
                std::cout << "download file: on_data: length-" << (int) _data.size () << std::endl;
            });
            _client->download_file ("down.tmp", "/", [] (boost::system::error_code ec) {
                std::cout << "download file: on_complete: " << (!ec ? "true - " : "false - ") << (ec ? ec.message () : "") << std::endl;
            });
            std::this_thread::sleep_for (std::chrono::seconds (5));
        }).detach ();
        _server.run ();
    } catch (std::exception &e) {
        std::cout << "catch error: " << e.what () << std::endl;
    } catch (...) {
        std::cout << "catch error" << std::endl;
    }
    std::getchar ();
    return 0;
}

代码编译错误

image

变量名写错了,变量后缀没有_,但你用的时候却带上_了

[BugReport] Memory Leak on multipart_reader::currentHeaders

在上传小文件时会偶尔翻车,加AddressSanitizer提示function multipart_reader::cbHeaderEnd()函数内heap-use-after-free on address。

如图所示,将HTTP POST请求拆成2部分送达feed()函数
图链接
备用地址:draw.io

  • 我们称第一个request fragment送来的地址是bufferA
    第一次把bufferA送入multipart_parser::feed()后,状态机调用multipart_reader::cbHeaderEnd()函数,将两个string_view存入multipart_headers::currentHeaders中,结束后currentHeaders.size()==1

  • 第二个request fragment随之到来,存于bufferB
    依旧是feed()调用cbHeaderEnd(),
    此时bufferA已经释放,导致上述两个multipart_headers::currentHeaders中的string_view悬空
    程序再次调用multipart_reader::cbHeaderEnd()时,multimap试图读取原有string_views内容时读到了已经被释放的地址,在此处crash。

如果幸运的话,分片不会把某一组header隔开,就不会触发bug。但也可以构造一个超级长的header,然后强行分片送抵服务器,就一定会触发。

解决方案?
想到把using multipart_headers = std::multimap<std::string_view, std::string_view>;
改成using multipart_headers = std::multimap<std::string, std::string>;
(我看到已经写了注释??)

//self->currentHeaders.emplace(std::string{ self->currentHeaderName.data(), self->currentHeaderName.length() },
// std::string{ self->currentHeaderValue.data(), self->currentHeaderValue.length() });

或者设计一个垃圾回收,触发multipart_reader::cbHeadersEnd()时,把之前的buffer再收掉。

还有一个想法 buffer改用类似链表结构,把已经submit的string_view直接砍掉,会不会造成内存很零散?。。。

另外还有一个enhancement
在class upload_file里面,打开文件失败了请给个提示。。

第二组bug: feed()状态机不能处理多次送达的buffer

针对这几行举例,依然是两个post碎片,CR没有随着第一次feed(buffer1)到来,而在下一次feed(buffer2)时才送来。但是string_view引用的buffer1已经没了。

case HEADER_VALUE_START:
if (c == SPACE) {
break;
}
headerValueMark = i;
state = HEADER_VALUE;
case HEADER_VALUE:
if (c == CR) {
dataCallback(onHeaderValue, headerValueMark, buffer, i, len, true, true);
callback(onHeaderEnd);
state = HEADER_VALUE_ALMOST_DONE;
}
break;

第一次送来的buffer:

-----------------------------4833311154639
Content-Disposition: form-data; name="file"; filename="20190628001428.png" (结尾没有\r)

第二次feed送来的buffer:

\r
Content-Type: image/png\r

PNG<binary data......binary data......>
-----------------------------4833311154639--

错误依旧为 heap-use-after-free in cinatra::multipart_reader::cbHeaderEnd

解决方案?
同上吧,我觉得存下来比较好,我们没办法保证数据包在哪里断掉。。

第三组bug:当feed()分片到达时,可能会打断正在解析的header内容

在multipart_reader.hpp中
self->currentHeaderNameself->currentHeaderValue 两个变量,第二次到达的会覆盖前一次到达的值。

同样我觉得用string比较好操作,直接连接起来。。或者就滚动buffer,改下状态机不做multipart_parser.hpp#L192-L194

这个bug的确定理由:

Breakpoint at multipart_reader.hpp:90
(gdb) p self->currentHeaderValue
	form-data; name=\"file\"; filename=\"2019

Breakpoint at multipart_reader.hpp:90
(gdb) p self->currentHeaderValue
	"0628001428.png\""

Breakpoint at connection.hpp:562
(gdb) p headers
	std::multimap with 2 elements = {["Content-Disposition"] = "1428.png\"", ["Content-Type"] = "image/png"}

connection.hpp中 tcp_socket& socket()方法修改建议

我在学习cinatra的代码。
template class connection 类是一个模板类。其中成员变量socket_为从模板传入的socket_type类型。 然而其中的tcp_socket& socket() {return socket_;} 方法却返回tcp_socket类型。 其中tcp_socket类型是在request.hpp中定义的 using tcp_socket = boost::asio::ip::tcp::socket;
这样connection类的模板类型好像就固定死了,没有必要了。这样写是否有所不妥?
谢谢。

建议去掉LOG_INFO

日至相关的其实都可以不要,但有了这个就导致与几乎所有的日志库冲突了

url中带有中文的问题

你好,我正在使用你们的cinatra开发一个大文件上次下载C++服务器,因为我们自己的业务,url中会出现中文的情况,我尝试了下,好像不能实现,不知道是不支持还是我代码的问题。
代码如下
server.set_http_handler<GET, POST>("/中文测试", [](request& req, response& res) {
res.render_string("中文测试");
});

返回错误:the url is not right
请问是否支持url带有中文的

关于项目的一些建议

1、首先这个项目所用到的编译器和库都比较新,能否加入类似gcc的./contrib/download_prerequisites,一键升级、安装所需版本的编译器及第三方库到编译项目所需的版本
2、是否考虑加入static_assets,将某个路径下所有请求定位到某个文件夹,比如请求css、js这类
3、建议将http response改为基于流,直接使用res << "hello world"的方式写入返回的内容
4、服务类构造函数的那个最大并发量参数及监听时设置ip地址没必要让用户传递,建议在头文件里面取消这俩参数

gcc 7.3 mingw 64(64位), windows 10 boost 1.67, 能生成编译文件,但编译时出错!

编译命令如下: 生成编译文件成功,但编译时出错, 出错信息如下(粘贴部分内容,主要是thread, mutex报错。):

F:\temp\cinatra-master>cmake . -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS=" -m64 -Id:\mingw64\x86_64-w64-mingw32\include -Id:\mingw64\lib\gcc\x86_64-w64-mingw32\7.3.0\include\c++ -Ld:\mingw64\lib\gcc\x86_64-w64-mingw32\7.3.0 -std=c++17 -lstd++ -lpthread " -DENABLE_SSL=ON -DENALBE_GZIP=ON -DCMAKE_BUILD_TYPE=Release -DBOOST_INCLUDEDIR="e:\workspace_git\boost64_1_67\include" -G "MinGW Makefiles"
-- Boost version: 1.67.0
-- Found the following Boost libraries:
-- system
-- Configuring done
-- Generating done
-- Build files have been written to: F:/temp/cinatra-master

F:\temp\cinatra-master>mingw32-make -f Makefile cinatra
[ 50%] Building CXX object CMakeFiles/cinatra.dir/main.cpp.obj
In file included from F:\temp\cinatra-master\http_server.hpp:14:0,
from F:\temp\cinatra-master\main.cpp:2:
F:\temp\cinatra-master\io_service_pool.hpp: In member function 'void cinatra::io_service_pool::run()':
F:\temp\cinatra-master\io_service_pool.hpp:26:37: error: 'thread' is not a member of 'std'
std::vector<std::shared_ptrstd::thread > threads;
^~~~~~
F:\temp\cinatra-master\io_service_pool.hpp:26:37: note: suggested alternative: 'tera'
std::vector<std::shared_ptrstd::thread > threads;
^~~~~~
tera
F:\temp\cinatra-master\io_service_pool.hpp:26:43: error: template argument 1 is invalid
std::vector<std::shared_ptrstd::thread > threads;
^
F:\temp\cinatra-master\io_service_pool.hpp:26:45: error: template argument 1 is invalid
std::vector<std::shared_ptrstd::thread > threads;
^
F:\temp\cinatra-master\io_service_pool.hpp:26:45: error: template argument 2 is invalid
F:\temp\cinatra-master\io_service_pool.hpp:28:13: error: request for member 'emplace_back' in 'threads', which is of non-class type 'int'
threads.emplace_back(std::make_sharedstd::thread(
^~~~~~~~~~~~
F:\temp\cinatra-master\io_service_pool.hpp:28:48: error: 'thread' is not a member of 'std'
threads.emplace_back(std::make_sharedstd::thread(
^~~~~~
F:\temp\cinatra-master\io_service_pool.hpp:28:48: note: suggested alternative: 'tera'
threads.emplace_back(std::make_sharedstd::thread(
^~~~~~
tera
F:\temp\cinatra-master\io_service_pool.hpp:31:24: error: no matching function for call to 'make_shared< >(cinatra::io_service_pool::run()::<lambda(cinatra::io_service_pool::io_service_ptr)>, gnu_cxx::alloc_traits<std::allocator<std::shared_ptrboost::asio::io_context > >::value_type&)'
}, io_services
[i]));
^
In file included from D:/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/memory:81:0,
from E:/workspace_git/boost64_1_67/include/boost/asio/associated_allocator.hpp:19,
from E:/workspace_git/boost64_1_67/include/boost/asio.hpp:20,
from F:\temp\cinatra-master\use_asio.hpp:23,
from F:\temp\cinatra-master\http_server.hpp:2,
from F:\temp\cinatra-master\main.cpp:2:
D:/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h:703:5: note: candidate: template<class Tp, class ... Args> std::shared_ptr<Tp> std::make_shared(Args&& ...)
make_shared(Args&&... args)
^~~~~~~~~~~
D:/mingw64/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/bits/shared_ptr.h:703:5: note: template argument deduction/substitution failed:
In file included from F:\temp\cinatra-master\http_server.hpp:14:0,
from F:\temp\cinatra-master\main.cpp:2:
F:\temp\cinatra-master\io_service_pool.hpp:31:24: error: template argument 1 is invalid
}, io_services
[i]));
^
F:\temp\cinatra-master\io_service_pool.hpp:34:40: error: request for member 'size' in 'threads', which is of non-class type 'int'
for (std::size_t i = 0; i < threads.size(); ++i)
^~~~
F:\temp\cinatra-master\io_service_pool.hpp:35:14: error: invalid types 'int[std::size_t {aka long long unsigned int}]' for array subscript
threads[i]->join();
^
In file included from F:\temp\cinatra-master\request.hpp:12:0,
from F:\temp\cinatra-master\connection.hpp:7,
from F:\temp\cinatra-master\http_server.hpp:15,
from F:\temp\cinatra-master\main.cpp:2:
F:\temp\cinatra-master\session.hpp: At global scope:
F:\temp\cinatra-master\session.hpp:107:8: error: 'mutex' in namespace 'std' does not name a type
std::mutex mtx
;
^~~~~
F:\temp\cinatra-master\session.hpp: In member function 'void cinatra::session::set_data(const string&, std::any)':
F:\temp\cinatra-master\session.hpp:38:26: error: 'mutex' is not a member of 'std'
std::unique_lockstd::mutex lock(mtx
);
^~~~~
F:\temp\cinatra-master\session.hpp:38:26: note: suggested alternative: 'quoted'
std::unique_lockstd::mutex lock(mtx
);
^~~~~
quoted
F:\temp\cinatra-master\session.hpp:38:31: error: template argument 1 is invalid
std::unique_lockstd::mutex lock(mtx
);
^
F:\temp\cinatra-master\session.hpp:38:38: error: 'mtx
' was not declared in this scope
std::unique_lockstd::mutex lock(mtx
);
^~~~
F:\temp\cinatra-master\session.hpp: In member function 'T cinatra::session::get_data(const string&)':
F:\temp\cinatra-master\session.hpp:45:26: error: 'mutex' is not a member of 'std'
std::unique_lockstd::mutex lock(mtx
);
^~~~~
F:\temp\cinatra-master\session.hpp:45:26: note: suggested alternative: 'quoted'
std::unique_lockstd::mutex lock(mtx
);
^~~~~
quoted
F:\temp\cinatra-master\session.hpp:45:31: error: template argument 1 is invalid
std::unique_lockstd::mutex lock(mtx
);
^
F:\temp\cinatra-master\session.hpp:45:38: error: 'mtx_' was not declared in this scope
std::unique_lockstd::mutex lock(mtx_);
^~~~
F:\temp\cinatra-master\session.hpp: In member function 'bool cinatra::session::has(const string&)':
F:\temp\cinatra-master\session.hpp:55:26: error: 'mutex' is not a member of 'std'
std::unique_lockstd::mutex lock(mtx_);
^~~~~
F:\temp\cinatra-master\session.hpp:55:26: note: suggested alternative: 'quoted'
std::unique_lockstd::mutex lock(mtx_);
^~~~~
quoted
F:\temp\cinatra-master\session.hpp:55:31: error: template argument 1 is invalid
std::unique_lockstd::mutex lock(mtx_);
^
F:\temp\cinatra-master\session.hpp:55:38: error: 'mtx_' was not declared in this scope
std::unique_lockstd::mutex lock(mtx_);
^~~~
F:\temp\cinatra-master\session.hpp: In member function 'void cinatra::session::set_max_age(time_t)':
F:\temp\cinatra-master\session.hpp:66:26: error: 'mutex' is not a member of 'std'
std::unique_lockstd::mutex lock(mtx_);
^~~~~

url中正则表达式的匹配

你好,我正在使用你们的cinatra做个大文件上传下载的C++服务器,根据我们的业务使用,现在遇到一个问题,我们的url类似这样的http://127.0.0.1:8080\upload\video\XXXX\20190906,upload后面的字符串我们是作为存储路径,每次都会变化,我使用你们的库,尝试使用正则表达式进行path的通配,发现无法正常通配,正则表达式应该是正确的。
server.set_http_handler("/upload/[^\s]*", [](request& req, response& res) {
if (req.get_content_type() == content_type::multipart)
{
auto& files = req.get_upload_files();
for (auto& file : files) {
std::cout << file.get_file_path() << " " << file.get_file_size() << std::endl;
}
res.render_string("multipart finished");
}
else
{
res.render_string(" not multipart data");
}
});

我使用的另外一个第三方库是可以的,想要咨询下,是否支持path的正则表达式通配,如果支持,是有demo可以借鉴,谢谢

关于限速

能否新增一个功能,指定对一个接口进行限速,或者指定对一个session进行限速,或者对所有请求设定io最大传输速度?

Check for cache

Hi,

Newbie question. I'm trying to understand the code in http_server.hpp and I'm having a hard time understanding line 172:

bool b = true;
((b&&(b = need_cache(std::forward<AP>(ap))), false),...);

Could you please explain why there's a false? Eclipse tells me there's a syntax error, by the way.

Thanks in advance,
Allister

cpu占用过高

编译完成开启后任何没有访问请求,top查看显示cpu始终占有6%左右,运行环境ubuntu16.04 CPU:8核 i7-6700 内存:8G

头文件中定义全局函数导致重定义错误

  1. utils.hpp line:471 get_cookies_map()
  2. utils.hpp line:254 from_urldecode()
  3. uuid.h line:775 to_string()
  4. uuid.h line:782 to_wstring()
    以上都被定义为全局函数。

之所以会发现这个问题,是我在对cinatra进行封装时发现的。
pass以上问题之后,我又发现session_manager的成员变量也会出现重定义错误。
这里我可以通过注释掉成员变量的定义,取而代之在cpp文件中定义来解决。
但不知道有没有更好的办法(我反正是没想出来 = =

`
session_manager{
......
private:
static std::map<std::string, std::shared_ptr> map_;
static std::mutex mtx_;
static int max_age_;
};
std::map<std::string, std::shared_ptr> session_manager::map_;
std::mutex session_manager::mtx_;
int session_manager::max_age_ = 10 * 60;

`

API 上的一个小建议

server 最好能传入 io_context 的引用,方便和其他基于 asio 的库集成共用一个 io_context.

【增强】OPTIONS返回格式默认指定

TIM图片20191030093455
OPTIONS请求默认应该返回支持的请求类型,比如支持GET、POST和PUT,应该返回:
GET,POST,PUT
返回方式类似POST,但不同之处为这个请求不会执行任何用户逻辑,所以应该在框架里面封装支持

[Question] Plan to enable CI

I think we should enable CI to help us check some code style, unit tests, etc.
This is very useful tool for us when others request a PR or push some commits.

How do you guys think of this?

cinatra对编译器的要求

cinatra
gcc 是不是 要求 GCC8+
clang+llvm 是不是要求 llvm7+

Apple LLVM version 9.1.0 (clang-902.0.39.2) 对应的应该是 llvm6版本
linux安装的gcc7.3
都编译不通过

[websocket]问题整理

存在问题:
1、疑似因客户端某种原因导致客户端连续调用error和close持续调用,以下是记录的日志
20200217.log
2、send_ws_binary函数需传递std::string可能在vc的sso优化时候拷贝一份,疑似存在性能问题
3、当客户端网页直接关闭后,存在start回调与close回调对不上的情况。此处网页关闭十几分钟后依旧没有调用close关闭ws链接

[20200218_160946_519] websocket start
[20200218_160952_840] websocket start
[20200218_160953_892] websocket start
[20200218_161006_397] websocket close
[20200218_161006_398] websocket error
[20200218_161006_401] websocket close
[20200218_161006_402] websocket error
[20200218_161006_957] websocket error
(此处关闭网页十几分钟了,没有调用最后的close)

建议优化:
1、有时候会遇到ws链接close后再次error
2、cinatra::connection类增加uuid标识,使得服务端存储了所有链接后,能准确识别某个链接(逻辑代码需要识别指定链接)

关于静态文件的建议

目前静态文件的判断有点粗暴, 每次请求进来判断内容中有'.'的就认为是静态文件
这种设计不太好

  1. 限制了URL设计 非静态文件访问URL内容不能带'.'
  2. cinatra有可能只用来做api server 每次都判断是否静态文件 带来性能开销

建议参考其他WEB框架如django 设置一个static文件目录 和目录的路由 通过路由去执行静态文件处理

安全退出http服务

目前服务器的run是写死的,建议再加上run_once、run_for与run_until,使得服务器线程能手工控制,从而使其安全退出服务。

multipart上传文件

现在cinatra上传文件,会自动往目录写文件。我把upload_file.hpp修改成:保存文件在buf_中首地址和长度。
这样修改后,用postman自测没有问题。如果通过中转发过来的话,buf_会resize,造成文件损坏。
然后我又将buf_的初始化长度修改为256,在接受完http header后,会一次性扩展buf_的size到content-lenght。这样解决了文件首地址异常现象。
但是现在又出现一个问题,multipart上传时,form-data中如果是 (key=condition value=xxxxx)(key=file value=file.txt)这样一个顺序上传,得到正确结果。如果是(key=file value=file.txt)(key=condition value=xxxxx)上传,则不能解析key=condition的值,但是文件存取正常。看了一下代码,好像是multipart_parser_.on_part_data 没有去解析非文件的部分。
麻烦大佬帮忙看看

res.set_attr 空字符串错误

JavaScript:

<form action="/submit" method="POST">
					<div class="input-field col s6">
						<input id="value1" name="value1" value=${value1} type="text" class="validate">
        			    <label for="value1">value1</label>
					</div>
</form> 

c++:

res.set_attr("value1","");

界面value显示错误:显示结果:

<input id="camera_number" name="camera_number" value="type=&quot;text&quot;" class="validate">

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.