qicosmos / cinatra Goto Github PK
View Code? Open in Web Editor NEWmodern c++(c++20), cross-platform, header-only, easy to use http framework
License: MIT License
modern c++(c++20), cross-platform, header-only, easy to use http framework
License: MIT License
目前静态文件的判断有点粗暴, 每次请求进来判断内容中有'.'的就认为是静态文件
这种设计不太好
建议参考其他WEB框架如django 设置一个static文件目录 和目录的路由 通过路由去执行静态文件处理
之所以会发现这个问题,是我在对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;
`
错误日志
错误(活动) E0266 "byte" 不明确 Common c:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um\ObjIdl.h 10774
错误 C2872 “byte”: 不明确的符号 Common c:\program files (x86)\windows kits\10\include\10.0.16299.0\um\objidl.h 15127
https://github.com/qicosmos/cinatra/blob/master/utils.hpp#L224
编译完成开启后任何没有访问请求,top查看显示cpu始终占有6%左右,运行环境ubuntu16.04 CPU:8核 i7-6700 内存:8G
有没有类似于django在html中的{% for %}或{% if %}方法,在html中根据服务器端传过来的参数进行循环或判断的方法?
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]
以上就是我上传文件时候的总结,一定要多看文档,多看文档,多看文档!!!
intellij idea如何创建c/c++ project,有什么plugin吗?高手指教下
在上传小文件时会偶尔翻车,加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>;
(我看到已经写了注释??)
cinatra/include/cinatra/multipart_reader.hpp
Lines 97 to 98 in ba17d4a
或者设计一个垃圾回收,触发multipart_reader::cbHeadersEnd()
时,把之前的buffer再收掉。
还有一个想法 buffer改用类似链表结构,把已经submit的string_view直接砍掉,会不会造成内存很零散?。。。
另外还有一个enhancement
在class upload_file里面,打开文件失败了请给个提示。。
针对这几行举例,依然是两个post碎片,CR没有随着第一次feed(buffer1)到来,而在下一次feed(buffer2)时才送来。但是string_view引用的buffer1已经没了。
cinatra/include/cinatra/multipart_parser.hpp
Lines 148 to 161 in ba17d4a
第一次送来的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
解决方案?
同上吧,我觉得存下来比较好,我们没办法保证数据包在哪里断掉。。
在multipart_reader.hpp中
self->currentHeaderName
和 self->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"}
我在学习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类的模板类型好像就固定死了,没有必要了。这样写是否有所不妥?
谢谢。
在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
server 最好能传入 io_context 的引用,方便和其他基于 asio 的库集成共用一个 io_context.
cinatra/include/cinatra/request.hpp
Lines 731 to 734 in e461b52
I saw a lot of reference on the pointer request.buf_.data()
in source code.
But you also use vector.resize()
here, that may cause memory reallocation.
( ̄▽ ̄")
编译命令如下: 生成编译文件成功,但编译时出错, 出错信息如下(粘贴部分内容,主要是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_);
^~~~~
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?
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
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
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.
你好,我正在使用你们的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地址没必要让用户传递,建议在头文件里面取消这俩参数
#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;
}
日至相关的其实都可以不要,但有了这个就导致与几乎所有的日志库冲突了
绑定其他IP地址没有问题,经过排查发现是端口被其他程序占用了,但是库中不给出明确提示,这可能不算是个Bug,但是期望给出明确的错误起因。
from中传递一个长字换串使用get_query_value接受不到
现在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 没有去解析非文件的部分。
麻烦大佬帮忙看看
我们项目中用 cinatra 对接 微信登录需要 https client
请问 cinatra 支持吗
存在问题:
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标识,使得服务端存储了所有链接后,能准确识别某个链接(逻辑代码需要识别指定链接)
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="text"" class="validate">
cinatra
gcc 是不是 要求 GCC8+
clang+llvm 是不是要求 llvm7+
Apple LLVM version 9.1.0 (clang-902.0.39.2) 对应的应该是 llvm6版本
linux安装的gcc7.3
都编译不通过
跨域问题有什么解决思路吗?
能否新增一个功能,指定对一个接口进行限速,或者指定对一个session进行限速,或者对所有请求设定io最大传输速度?
目前服务器的run是写死的,建议再加上run_once、run_for与run_until,使得服务器线程能手工控制,从而使其安全退出服务。
connection.hpp 116行有一句 static_assert(size != 0 || size != 2); 显然无论size为何值都会返回true。导致断言失效。
谢谢。
你好,我正在使用你们的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可以借鉴,谢谢
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?
CMake中
install(TARGETS cinatra DESTINATION include)
这里是不是应该把头文件安装过去,而不是可执行文件.
在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则服务器正常运行且图片正常显示。
你好,我在使用这个库的时候出现了一个奇怪的问题,我猜测应该是由于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 {};
}
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;
由此以下代码无法运行
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_的相应键值就无效了。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.