188080501 / jqhttpserver Goto Github PK
View Code? Open in Web Editor NEW基于Qt开发的轻量级HTTP/HTTPS服务器
License: MIT License
基于Qt开发的轻量级HTTP/HTTPS服务器
License: MIT License
你好,你这个轻量级http服务器很不错。不够头疼的是5.12以后,在回调中调用数据库一直失败,请问有什么好的方法在收到http请求时调用数据库吗
你好我使用 您的库 请求 http 有时会发现 就算外网 不可请求到 也是一直阻塞直到超时 才返回 是否可以 立即返回
如题,因为对于部分网页应用而言,Content-Type的类型是必须的。(如模块化加载JavaScript和图片显示)
这也可以简化对于小型HTTP服务获取文件类型的判断
我目前更改了一下replyBytes的接口,如下:
static QString replyBytesFormat(
"HTTP/1.1 %1 OK\r\n"
"Content-Type: %2\r\n"
"Content-Length: %3\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Access-Control-Allow-Headers: Content-Type,X-Requested-With\r\n"
"\r\n"
);
void JQHttpServer::Session::replyBytes(const QByteArray &bytes, const int &httpStatusCode,const QString mime)
{
JQHTTPSERVER_SESSION_REPLY_PROTECTION( "replyBytes" )
if ( QThread::currentThread() != this->thread( ))
{
replyHttpCode_ = httpStatusCode;
QMetaObject::invokeMethod(this, "replyBytes", Qt::QueuedConnection, Q_ARG(QByteArray, bytes), Q_ARG(int, httpStatusCode), Q_ARG(QString, mime));
return;
}
JQHTTPSERVER_SESSION_REPLY_PROTECTION2( "replyBytes" )
auto buffer = new QBuffer;
buffer->setData( bytes );
if ( !buffer->open( QIODevice::ReadWrite ) )
{
qDebug() << "JQHttpServer::Session::replyBytes: open buffer error";
delete buffer;
this->deleteLater();
return;
}
ioDeviceForReply_.reset( buffer );
ioDeviceForReply_->seek( 0 );
replyBodySize_ = buffer->buffer().size();
const auto &&data = replyBytesFormat.arg(
QString::number( httpStatusCode ),
mime,
QString::number( replyBodySize_ )
).toUtf8();
waitWrittenByteCount_ = data.size() + buffer->buffer().size();
ioDevice_->write(data);
}
这样在返回HTTP回复的时候就可以设置Content-Type了
你好,我在win10和ubuntu 16.04下进行性能测试(Qt5.7),发现单次请求、响应时间延迟非常大,每个请求20ms左右。
测试方法为:在同一台电脑上先启动HttpServerDemo,然后运行HttpClientDemo,在client端发起5000次请求(单线程,即在main线程内),方法同benchMarkFor5000,并计算时间。测试过程中,两个进程的cpu利用率以及系统cpu利用率都很低。
折算下来,空跑QPS才50,请问这可能是什么原因导致性能上不去?
When i run this JQHttpServer using my valid ssl certification with digicert cert, Got error from third party enggine : "SSL routines:tls_process_server_certificate:certificate verify failed". And also got error message from the application : "JQHttpServer::Session::inspectionBuffer: error3: HEAD". Could you help me to solve this problem?
Thank you.
我发现在 AbstractManage::newSession 中,使用了 QMutex 对 availableSessions_ 进行了保护,但是这种保护是否必要?
我没有在.pro文件里发现相关配置
Hello!Thank you for sharing your code firstly!
I want to use your server to test my client,however it was failed when I compiled your code.The error info is as follows.Could you help me to fix this problem?Thank you again.
/home/xue/JQHttpServer/JQHttpServer/library/JQLibrary/src/JQNet.cpp:281: error: conversion from 'const QByteArray' to 'QIODevice*' is ambiguous
auto reply = manage_.sendCustomRequest( request, "PATCH", appendData );
/home/xue/JQHttpServer/JQHttpServer/library/JQLibrary/src/JQNet.cpp:315: error: conversion from 'const QByteArray' to 'QIODevice*' is ambiguous
auto reply = manage_.sendCustomRequest( request, "PATCH", appendData );
您好,还是原来那个问题,我在linux(Ubuntu18.04)qt(5.14.1)下也测试过。使用lambda函数,好像只能在mian函数内,客户端请求才能收到,一但在不在,客户端请求接收不到,返回false。还请帮忙看看
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowTitle("HttpServer");
w.show();
#if 1
JQHttpServer::TcpServerManage tcpServerManage(10); // 设置最大处理线程数,默认2个
tcpServerManage.setHttpAcceptedCallback(
[]( const QPointer< JQHttpServer::Session > &session )
{
// 回调发生在新的线程内,不是主线程,请注意线程安全
// 若阻塞了此回调,那么新的连接将不会得到处理(默认情况下有2个线程可以阻塞2次,第3个连接将不会被处理)
qDebug() << "请求来源IP: "+session->requestSourceIp(); //请求来源IP
qDebug() << "url:"+session->requestUrl(); //url 后面参数
qDebug() << "请求方式: "+session->requestMethod(); //POST GET
qDebug() << "postdata: "+session->requestBody();
QByteArray postdata = session->requestBody();
QString ssize = QString::number(postdata.size(),10);
qDebug() << "postdata.size: "+ssize;
session->replyText( QString( "url:%1\nbody:%2" ).arg( session->requestUrl(), QString( session->requestBody() ) ) );
// 注1:因为一个session对应一个单一的HTTP请求,所以session只能reply一次
// 注2:在reply后,session的生命周期不可控,所以reply后不要再调用session的接口了
} );
qDebug() << "listen:" << tcpServerManage.listen( QHostAddress("192.168.124.128"), 9091);
qDebug() << ("Http服务已启动");
#endif
return a.exec();`
eventLoop 没有办法退出。
如果调用readyToClose tcpServer_.data 就会被delete两次。
请教一下,用这个server,如何解析提交的文件和键值混和表单数据,主要不知道如何解析出请求头的文件名称
When starting the application "HttpsServerDemo", i got this error:
qt.network.ssl: QSslSocket: cannot resolve TLSv1_1_client_method
qt.network.ssl: QSslSocket: cannot resolve TLSv1_2_client_method
qt.network.ssl: QSslSocket: cannot resolve TLSv1_1_server_method
qt.network.ssl: QSslSocket: cannot resolve TLSv1_2_server_method
qt.network.ssl: QSslSocket: cannot resolve SSL_select_next_proto
qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
qt.network.ssl: QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
qt.network.ssl: QSslSocket: cannot resolve SSL_set_alpn_protos
qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_alpn_select_cb
qt.network.ssl: QSslSocket: cannot resolve SSL_get0_alpn_selected
sslCertificate: QSslCertificate("1", "ae:01:71:c8:21:fc:00:c2", "eKXBjkCzjZbWnEvw5NXsWw==", ("Internet Widgits Pty Ltd"), ("Internet Widgits Pty Ltd"), QMap(), QDateTime(2017-04-09 07:07:27.000 UTC Qt::TimeSpec(UTC)), QDateTime(2027-04-07 07:07:27.000 UTC Qt::TimeSpec(UTC)))
sslKey: QSslKey(PrivateKey, RSA, 2048)
caCertificates: ()
listen: true
And when i send packet data to the server, the server got error like this:
qt.network.ssl: QSslSocket: cannot call unresolved function TLSv1_2_server_method
qt.network.ssl: QSslSocket: cannot call unresolved function TLSv1_2_server_method
could you help me, why this happens ?
包含头文件,然后客户端使用示例代码:
const auto &&reply = JQNet::HTTP::post( "http://127.0.0.1:23412/TestUrl", "AppendData" );
进行120ms/次请求,则出现内存不断增长的问题,请问这个问题有什么好的解决方案吗?
服务端正常,客户端出现内存泄露?期待你的交流,我的QQ4589968
在使用EventSouce时,希望能不关闭连接,但调用replyXXX函数后,总是会关闭连接。需要怎样修改呢?
用浏览器访问一次,服务器显示处理了两次
第一次为正常请求
Body ""
Header QMap(("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8")("Accept-Encoding", "gzip, deflate")("Accept-Language", "zh-CN,en-US;q=0.8")("Cache-Control", "max-age=0")("Connection", "keep-alive")("Host", "191.167.2.36:23412")("Upgrade-Insecure-Requests", "1")("User-Agent", "Mozilla/5.0 (Linux; Android 7.1.1; 1801-A01 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/59.0.3071.82 Mobile Safari/537.36")("X-Requested-With", "org.qtproject.example.minibrowser"))
Method "GET"
UrlPath ""
Url "/"
UrlQuery QMap()
UrlPathSplitToList ()
第二次为/favicon 请求打印出来如下
Body ""
Header QMap(("Accept", "image/webp,image/apng,image/,/*;q=0.8")("Accept-Encoding", "gzip, deflate")("Accept-Language", "zh-CN,en-US;q=0.8")("Connection", "keep-alive")("Host", "191.167.2.36:23412")("Referer", "http://191.167.2.36:23412/")("User-Agent", "Mozilla/5.0 (Linux; Android 7.1.1; 1801-A01 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/59.0.3071.82 Mobile Safari/537.36")("X-Requested-With", "org.qtproject.example.minibrowser"))
Method "GET"
UrlPath "/favicon.ico"
Url "/favicon.ico"
UrlQuery QMap()
UrlPathSplitToList ("favicon.ico")
不知道为什么会有两次
经测试HttpServerCallback中超过30秒左右没返回,调用方就提示Connection Closed Gracefully.
然后Qt这边就提示JQHttpServer::Session::replyText: current session this is null
library/JQLibrary/src/JQHttpServer.cpp: In member function ‘bool JQHttpServer::AbstractManage::startServerThread()’:
library/JQLibrary/src/JQHttpServer.cpp:804:7: error: no matching function for call to ‘run(QThreadPool*, JQHttpServer::AbstractManage::startServerThread()::<lambda()>)’
} );
^
In file included from /usr/include/qt5/QtConcurrent/QtConcurrent:14:0,
from library/JQLibrary/src/JQHttpServer.cpp:34:
/usr/include/qt5/QtConcurrent/qtconcurrentrun.h:70:12: note: candidate: template QFuture QtConcurrent::run(T (*)())
QFuture run(T (functionPointer)())
^~~
/usr/include/qt5/QtConcurrent/qtconcurrentrun.h:70:12: note: template argument deduction/substitution failed:
library/JQLibrary/src/JQHttpServer.cpp:804:7: note: mismatched types ‘T()’ and ‘QThreadPool’
} );
^
In file included from /usr/include/qt5/QtConcurrent/QtConcurrent:14:0,
from library/JQLibrary/src/JQHttpServer.cpp:34:
/usr/include/qt5/QtConcurrent/qtconcurrentrun.h:75:12: note: candidate: template<class T, class Param1, class Arg1> QFuture QtConcurrent::run(T ()(Param1), const Arg1&)
QFuture run(T (*functionPointer)(Param1), const Arg1 &arg1)
^~~
你好,感谢上一次的回复建议。
这里请教一个问题:就是如何在session中返回一个自定义错误?
代码:
static JQHttpServer::TcpServerManage httpServer( maxThreads ); // 设置最大处理线程数,默认2个
httpServer.setHttpAcceptedCallback( std::bind(onHttpAccepted, std::placeholders::_1 ) );
设置了onHttpAccepted 回调函数,同时在Session 中增加了一个自定义错误代码 internalErrorCode_,
通过如下代码暴露出来:
int JQHttpServer::Session::internalErrorCode() const
{
// JQHTTPSERVER_SESSION_PROTECTION( "internalErrorCode", 0 )
return internalErrorCode_;
}
在session的 replyImage中修改internalErrorCode_,该值在回调函数中不能获得(修改没起作用),是不是哪里有问题 ?
尝试修改:
int JQHttpServer::Session::replyHttpCode() const
中的 replyHttpCode返回,也没有效果,不知是哪里问题?请教!
在次感谢!
请问C++服务端这边如何支持跨域
请问为什么linux下将patch函数注释掉了?
如何替代同样功能?
在Qt5.15.0(Ubuntu20.04自编译)环境下,发现使用JQNet.cpp会提示
‘void QNetworkReply::error(QNetworkReply::NetworkError)’ is deprecated: Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead
看起来是有一些API变更了呢
附带错误提示全文:
../H2server/library/JQLibrary/src/JQNet.cpp: In member function ‘void JQNet::HTTP::handle(QNetworkReply*, const int&, const std::function<void(const QList<QPair<QByteArray, QByteArray> >&, const QByteArray&)>&, const std::function<void(const QList<QPair<QByteArray, QByteArray> >&, const QNetworkReply::NetworkError&, const QByteArray&)>&, const std::function<void()>&)’:
../H2server/library/JQLibrary/src/JQNet.cpp:682:124: warning: ‘void QNetworkReply::error(QNetworkReply::NetworkError)’ is deprecated: Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead [-Wdeprecated-declarations]
682 | QObject::connect( reply, static_cast< void( QNetworkReply::* )( QNetworkReply::NetworkError ) >( &QNetworkReply::error ), [ reply, timer, onError, isCalled ](const QNetworkReply::NetworkError &code)
| ^
In file included from /opt/qt5.15.0/include/QtNetwork/QNetworkReply:1,
from ../H2server/library/JQLibrary/include/JQNet.h:31,
from ../H2server/library/JQLibrary/src/JQNet.cpp:18:
/opt/qt5.15.0/include/QtNetwork/qnetworkreply.h:161:10: note: declared here
161 | void error(QNetworkReply::NetworkError);
| ^~~~~
../H2server/library/JQLibrary/src/JQNet.cpp:682:124: warning: ‘void QNetworkReply::error(QNetworkReply::NetworkError)’ is deprecated: Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead [-Wdeprecated-declarations]
682 | QObject::connect( reply, static_cast< void( QNetworkReply::* )( QNetworkReply::NetworkError ) >( &QNetworkReply::error ), [ reply, timer, onError, isCalled ](const QNetworkReply::NetworkError &code)
| ^
In file included from /opt/qt5.15.0/include/QtNetwork/QNetworkReply:1,
from ../H2server/library/JQLibrary/include/JQNet.h:31,
from ../H2server/library/JQLibrary/src/JQNet.cpp:18:
/opt/qt5.15.0/include/QtNetwork/qnetworkreply.h:161:10: note: declared here
161 | void error(QNetworkReply::NetworkError);
| ^~~~~
您好,我想请问一下,我要实现服务端能主动下发,也就是长连接,我测试每次请求都会有新的连接过来,这时候我保留套接字,然后重新new一个session 来应答,这样是否可行?
put post都可以“const QByteArray &body”,但是get不行,请教大神帮忙解答下。要怎么实现body
我在使用 jmeter 多线程测试多个接口时,发现如果都勾选了 keep-alive,每个线程第一个请求之后的请求都会失败。
我看到 JQHttpServer::Session 里有个 30秒 的计时器,推测这个库应该有支持 Http/1.1 的长连接功能。
检查了下代码,发现是由于在 JQHttpServer::Session::onBytesWritten 函数里,大约第826行,调用了 socket_->disconnectFromHost() 关掉了该连接,导致后续请求都不会被接收。
建议 session 增加一个 reset 函数,在一个请求结束后(比如 第826行 的 回复完成后),将 session 的解析参数重置为默认值,以继续解析后续请求。
Could you help me, how to add custom header when running this POST script :
JQNet::HTTP::post( "https://127.0.0.1:24684/TestUrl", "AppendData" );
Thank you for your concern.
你好!
如果我想发送的信息是变量,应该怎么做呢?
是不是不支持?没法请求成功. 能支持下吗
在CPU负载较高,或回调执行时间较长下,程序可能崩溃。
看了下代码,回调是在另一个线程下运行,当调用session->reply时,session,iodeviece_都有可能随时被删除(如超时);
另外,如果客户端提前超时,关闭连接,那么服务端对accept的TcpSocket未做处理,这种场景下程序运行行为如何,是否导致ioDevice_指向已销毁的socket资源。
请问一下这个是设置问题么?
您好,我测试server的回调函数,只能放在mian函数中,否则就无法收不到请求
https服务在sslServerManage->listen启动成功后如何可以关闭服务?看Demo中好像只有启动没有关闭的代码,请赐教谢谢
Hi 188080501
我用JQHttp 发布地图瓦片数据,使用稳定。希望增加一个针对地图数据特点的 replyTmsImage,对地图数据进行预读与缓存,提高地图数据的相应速度。TMS格式的地图瓦片数据访问有一定的规律,简单说就是将当前访问的图片文件的前后图片预读,或者使用进行缓存,缓存数量可以通过参数设定。谢谢!
请问Service模块的作用是什么?
你好, 我用了它进行服务器开发, 需要加入websocket向客户端广播消息. 有一些思路吗?
比如浏览器访问:http://localhost:23412/index
服务器收到index后我想返回一个本地已经写好的html页面,以下是demo中的例子:
session->replyText( QString( "url:%1\nbody:%2" ).arg( session->requestUrl(), QString( session->requestBody() ) ) );
session->replyRedirects( QUrl( "http://www.baidu.com" ) );
session->replyJsonObject( { { { "message", "ok测试部" } } } );
session->replyJsonArray( { "a", "b", "c" } );
session->replyFile( "/Users/jason/Desktop/Test1.Test2" );
session->replyImage( QImage( "/Users/jason/Desktop/Test.png" ) );
session->replyBytes(QByteArray(4,'\x24'));
看到请解释下,非常感谢
我测试过程中发现服务端不能设置编码集,客户端发中文json过去后乱码,请问下有没有解决方法。
现在使用静态路由要自行实现 sessionAccepted 函数,颇为不便,建议增加专用的静态路由功能
在 readme 中提及了并发数的问题。
推荐使用Linux系统或者Unix系统,因为在5.7后,Qt更换了Unix相关系统的底层模型,从select更换为了poll,这样子网络库的并发就脱离了1024个的限制。
看起来应该可以应用方向是小型,实用上。
这里我想探讨一下是否可以有 QML 的接口。或者说 QML 的接口该如何设计呢?
我有一个需求是服务器同时返回一段文本和一张图片。
我尝试过的方法:
1、在setHttpAcceptedCallback回调中同时调用
{
session->replyText(...)
session->replyImage(...)
}
这样会出现 服务器程序停止运行
2、我用session->replyFile 函数返回一个html 文件
(代码格式是故意少写了<,不然该页面不能显示)
html>
body >
img src ="http://www.baidu.com/img/bd_logo1.png" />
img src ="http://192.168.31.101:23412/bb.png"/>
/body>
/html>
第一张百度图片显示正常。
第二张图片是我服务器上的图片,不能正常显示。
请问是否我图片路径有问题,通过html方法如何访问我的服务器图片
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.