增加websocket支持

This commit is contained in:
Dev User
2026-08-04 20:06:33 +08:00
parent 0ffb86d5a0
commit c7a9e1c457
13 changed files with 517 additions and 59 deletions

200
.gitignore vendored
View File

@@ -1,3 +1,203 @@
/.vs
/3rdparty/HP-Socket
/out
build/cmake_install.cmake
build/CMakeCache.txt
build/install_manifest.txt
build/Makefile
build/3rdparty/sqlite3/cmake_install.cmake
build/3rdparty/sqlite3/Makefile
build/3rdparty/sqlite3/CMakeFiles/CMakeDirectoryInformation.cmake
build/3rdparty/sqlite3/CMakeFiles/progress.marks
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/build.make
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/cmake_clean_target.cmake
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/cmake_clean.cmake
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/compiler_depend.internal
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/compiler_depend.make
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/compiler_depend.ts
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/depend.make
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/DependInfo.cmake
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/flags.make
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/link.txt
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/progress.make
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/shell.c.o
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/shell.c.o.d
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.o
build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.o.d
build/CMakeFiles/cmake.check_cache
build/CMakeFiles/CMakeDirectoryInformation.cmake
build/CMakeFiles/CMakeOutput.log
build/CMakeFiles/Makefile.cmake
build/CMakeFiles/Makefile2
build/CMakeFiles/progress.marks
build/CMakeFiles/TargetDirectories.txt
build/CMakeFiles/3.22.1/CMakeCCompiler.cmake
build/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake
build/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_C.bin
build/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin
build/CMakeFiles/3.22.1/CMakeSystem.cmake
build/CMakeFiles/3.22.1/CompilerIdC/a.out
build/CMakeFiles/3.22.1/CompilerIdC/CMakeCCompilerId.c
build/CMakeFiles/3.22.1/CompilerIdCXX/a.out
build/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp
build/lib/libsqlite3_d.a
build/lib/libylib_d.a
build/src/cmake_install.cmake
build/src/Makefile
build/src/CMakeFiles/CMakeDirectoryInformation.cmake
build/src/CMakeFiles/progress.marks
build/src/CMakeFiles/ylib.dir/build.make
build/src/CMakeFiles/ylib.dir/cmake_clean_target.cmake
build/src/CMakeFiles/ylib.dir/cmake_clean.cmake
build/src/CMakeFiles/ylib.dir/compiler_depend.internal
build/src/CMakeFiles/ylib.dir/compiler_depend.make
build/src/CMakeFiles/ylib.dir/compiler_depend.ts
build/src/CMakeFiles/ylib.dir/depend.make
build/src/CMakeFiles/ylib.dir/DependInfo.cmake
build/src/CMakeFiles/ylib.dir/flags.make
build/src/CMakeFiles/ylib.dir/link.txt
build/src/CMakeFiles/ylib.dir/progress.make
build/src/CMakeFiles/ylib.dir/base/buffer.cpp.o
build/src/CMakeFiles/ylib.dir/base/buffer.cpp.o.d
build/src/CMakeFiles/ylib.dir/base/conversion.cpp.o
build/src/CMakeFiles/ylib.dir/base/conversion.cpp.o.d
build/src/CMakeFiles/ylib.dir/base/environment.cpp.o
build/src/CMakeFiles/ylib.dir/base/environment.cpp.o.d
build/src/CMakeFiles/ylib.dir/base/error.cpp.o
build/src/CMakeFiles/ylib.dir/base/error.cpp.o.d
build/src/CMakeFiles/ylib.dir/base/exception.cpp.o
build/src/CMakeFiles/ylib.dir/base/exception.cpp.o.d
build/src/CMakeFiles/ylib.dir/base/log4.cpp.o
build/src/CMakeFiles/ylib.dir/base/log4.cpp.o.d
build/src/CMakeFiles/ylib.dir/db/mssql.cpp.o
build/src/CMakeFiles/ylib.dir/db/mssql.cpp.o.d
build/src/CMakeFiles/ylib.dir/db/mysql.cpp.o
build/src/CMakeFiles/ylib.dir/db/mysql.cpp.o.d
build/src/CMakeFiles/ylib.dir/db/sqler.cpp.o
build/src/CMakeFiles/ylib.dir/db/sqler.cpp.o.d
build/src/CMakeFiles/ylib.dir/db/sqlite.cpp.o
build/src/CMakeFiles/ylib.dir/db/sqlite.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/ftp_client.cpp.o
build/src/CMakeFiles/ylib.dir/net/ftp_client.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_agent.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_agent.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_cache.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_cache.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_cdn.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_cdn.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_center.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_center.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_client_cache.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_client_cache.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_client_plus.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_client_plus.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_controller.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_controller.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_cookie.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_cookie.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_header.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_header.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_host.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_host.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_interceptor.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_interceptor.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_interface.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_interface.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_reqpack.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_reqpack.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_request.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_request.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_response.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_response.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_router.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_router.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_server_lst.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_server_lst.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_server.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_server.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_session.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_session.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_ssl.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_ssl.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_subscribe.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_subscribe.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_website.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_website.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/http_wsserver.cpp.o
build/src/CMakeFiles/ylib.dir/net/http_wsserver.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/make_form.cpp.o
build/src/CMakeFiles/ylib.dir/net/make_form.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_agent_lst.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_agent_lst.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_agent.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_agent.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_client_lst.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_client_lst.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_client.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_client.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_forward.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_forward.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_server_lst.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_server_lst.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp_server.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp_server.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/tcp2tcp.cpp.o
build/src/CMakeFiles/ylib.dir/net/tcp2tcp.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/ttu_client.cpp.o
build/src/CMakeFiles/ylib.dir/net/ttu_client.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/udp_node_lst.cpp.o
build/src/CMakeFiles/ylib.dir/net/udp_node_lst.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/udp_node.cpp.o
build/src/CMakeFiles/ylib.dir/net/udp_node.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/util.cpp.o
build/src/CMakeFiles/ylib.dir/net/util.cpp.o.d
build/src/CMakeFiles/ylib.dir/net/utt_server.cpp.o
build/src/CMakeFiles/ylib.dir/net/utt_server.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/cache.cpp.o
build/src/CMakeFiles/ylib.dir/util/cache.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/codec_des3.cpp.o
build/src/CMakeFiles/ylib.dir/util/codec_des3.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/codec.cpp.o
build/src/CMakeFiles/ylib.dir/util/codec.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/coroution.cpp.o
build/src/CMakeFiles/ylib.dir/util/coroution.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/debug.cpp.o
build/src/CMakeFiles/ylib.dir/util/debug.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/desktop.cpp.o
build/src/CMakeFiles/ylib.dir/util/desktop.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/file.cpp.o
build/src/CMakeFiles/ylib.dir/util/file.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/img.cpp.o
build/src/CMakeFiles/ylib.dir/util/img.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/ini.cpp.o
build/src/CMakeFiles/ylib.dir/util/ini.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/json.cpp.o
build/src/CMakeFiles/ylib.dir/util/json.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/localstorage.cpp.o
build/src/CMakeFiles/ylib.dir/util/localstorage.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/md5.cpp.o
build/src/CMakeFiles/ylib.dir/util/md5.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/mem.cpp.o
build/src/CMakeFiles/ylib.dir/util/mem.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/package.cpp.o
build/src/CMakeFiles/ylib.dir/util/package.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/print.cpp.o
build/src/CMakeFiles/ylib.dir/util/print.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/process.cpp.o
build/src/CMakeFiles/ylib.dir/util/process.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/sharedmem.cpp.o
build/src/CMakeFiles/ylib.dir/util/sharedmem.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/sqlite3.cpp.o
build/src/CMakeFiles/ylib.dir/util/sqlite3.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/strutils.cpp.o
build/src/CMakeFiles/ylib.dir/util/strutils.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/system.cpp.o
build/src/CMakeFiles/ylib.dir/util/system.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/thread.cpp.o
build/src/CMakeFiles/ylib.dir/util/thread.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/time.cpp.o
build/src/CMakeFiles/ylib.dir/util/time.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/timeout.cpp.o
build/src/CMakeFiles/ylib.dir/util/timeout.cpp.o.d
build/src/CMakeFiles/ylib.dir/util/window.cpp.o
build/src/CMakeFiles/ylib.dir/util/window.cpp.o.d

View File

@@ -34,6 +34,10 @@
#define HTTP_INTERCEPTOR_PRINT 0
// http lua 引擎
//#define HTTP_LUA_ENGINE 0
namespace ylib
{
namespace network
@@ -41,6 +45,54 @@ namespace ylib
namespace http
{
/// <summary>
/// 消息类型
/// </summary>
/// <returns></returns>
enum message_type {
// 普通
HTTP_SERVER_MESSAGE_TYPE_NORMAL = 0,
// WebSocket
HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET = 1,
};
enum ws_type {
// 升级
HTTP_SERVER_WEBSOCKET_TYPE_UPGRADE = 0,
// 消息头
HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_HEADER = 1,
// 消息包
HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_BODY = 2,
// 关闭
HTTP_SERVER_WEBSOCKET_TYPE_CLOSE = 3,
};
struct websocket_message {
struct ws_header {
// 是否结束帧
bool _final = false;
// 帧操作码
// 0x0 连续帧
// 0x1 文本帧
// 0x2 二进制帧
// 0x3-7 为非控制帧保留
// 0x8 连接关闭
// 0x9 ping
// 0xA pong
// 0xB-F 为控制帧保留
int opcode = 0x00;
// 是否使用掩码
uchar mask[4] = {0};
// 长度
uint64 length = 0;
};
ws_type type;
ws_header header;
std::string sec_websocket_key;
std::string filepath;
uint64 connid = 0;
};
/// <summary>
/// 服务端缓存
/// </summary>
struct server_cache_config {
@@ -187,6 +239,8 @@ namespace ylib
std::map<std::string, ssl_config> cert;
// 最大上传大小限制
uint64 max_upload_size = 0;
// 支持WebSocket
bool websocket_enable = false;
};
class agent;
@@ -221,6 +275,12 @@ namespace ylib
std::string host;
// 缓存路径
ylib::file_io cache_file;
// WS自定义数据
std::string ws_filepath;
// 是WS
bool is_ws = false;
// WS消息
websocket_message ws_msg;
};
// 代理
struct proxy
@@ -270,6 +330,9 @@ namespace ylib
size_t offset = 0;
size_t length = 0;
};
}
}

View File

@@ -31,7 +31,9 @@ namespace ylib
/// <param name="connid"></param>
/// <param name="server"></param>
/// <param name="website"></param>
reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server,network::http::website* website);
/// <param name="msg_type"></param>
/// <param name="ws_msg"></param>
reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server,network::http::website* website, network::http::message_type msg_type, std::shared_ptr<network::http::websocket_message> ws_msg = nullptr);
~reqpack();
/// <summary>
/// 请求对象
@@ -78,11 +80,30 @@ namespace ylib
/// </summary>
/// <returns></returns>
ylib::json& extra() { return m_extra; }
/// <summary>
/// 消息类型
/// </summary>
/// <returns></returns>
network::http::message_type msg_type() { return m_msg_type; }
/// <summary>
/// WebSocket消息
/// </summary>
/// <returns></returns>
const std::shared_ptr<network::http::websocket_message>& ws_msg() { return m_ws_msg; }
/// <summary>
/// 设置为关闭连接包
/// </summary>
void set_close() { m_is_close = true; }
bool is_close() { return m_is_close; }
private:
// 请求
std::shared_ptr<network::http::request> m_request;
// 回复
std::shared_ptr<network::http::response> m_response;
// WebSocket消息
std::shared_ptr<network::http::websocket_message> m_ws_msg;
// httpserver
network::http::server* m_server = nullptr;
// 请求地址
@@ -97,6 +118,11 @@ namespace ylib
uint64 m_connid = 0;
// 附加数据
ylib::json m_extra;
// 消息类型
network::http::message_type m_msg_type = HTTP_SERVER_MESSAGE_TYPE_NORMAL;
// 是否为关闭连接包
bool m_is_close = false;
};
}
}

View File

@@ -84,7 +84,6 @@ namespace ylib
/// </summary>
/// <returns></returns>
ylib::buffer& body();
private:
// reqpack

View File

@@ -20,6 +20,9 @@ namespace ylib
public:
response(network::http::reqpack* reqpack);
~response();
bool send_header(ushort stateNum, const std::string& stateDesc = "OK");
/// <summary>发送 WebSocket 帧。opcode 默认 0x1 文本0x2二进制 0x8关闭 0xA pong</summary>
bool send_ws(const char* buf, size_t buf_len, int opcode = 0x1);
bool send(const char* buf, size_t buf_len, ushort stateNum = 200, const std::string& stateDesc = "OK");
bool send(const ylib::buffer& value, ushort stateNum = 200, const std::string& stateDesc = "OK");
bool send(const std::string& value, ushort stateNum = 200, const std::string& stateDesc = "OK");
@@ -28,6 +31,9 @@ namespace ylib
std::map<std::string, std::string>* headers();
bool redirect(const std::string& filepath, bool MovedPermanently = false);
bool forward(const std::string& filepath);
void response_done(){m_response = true;}
bool is_response_done(){return m_response;}
public:
ylib::json sjson;
private:

View File

@@ -64,11 +64,16 @@ namespace ylib
* param
* callback 触发回调
******************************************************************/
void other(std::function<void(network::http::request*, network::http::response*)> callback);
void other(std::function<void(network::http::request*, network::http::response*,network::http::websocket_message*)> callback);
/******************************************************************
* function数据接收后回调
******************************************************************/
void on_recved(std::function<void(const ylib::buffer& begin, ylib::buffer* end)> callback);
/******************************************************************
* function关闭回调
******************************************************************/
void on_close(std::function<void(uint64 connid,network::http::websocket_message* ws_msg)> callback);
/******************************************************************
* function数据发送前回调
* desc不支持大文件断点传输方式
@@ -90,6 +95,8 @@ namespace ylib
private:
// 添加任务
void push(reqpack* rp);
// 添加连接断开任务
void push_close(uint64 connid,std::shared_ptr<network::http::websocket_message> ws_msg);
// 是否为代理任务
bool is_proxy(reqpack* rp);
// 是否为CDN服务
@@ -102,11 +109,13 @@ namespace ylib
// 线程池
IHPThreadPool* m_threadpool;
// [回调] 未订阅请求
std::function<void(network::http::request*, network::http::response*)> m_callback_other;
std::function<void(network::http::request*, network::http::response*,network::http::websocket_message*)> m_callback_other;
// [回调] 接收后
std::function<void(const ylib::buffer& begin, ylib::buffer* end)> m_callback_recved;
// [回调] 发送前
std::function<void(const ylib::buffer& begin, ylib::buffer* end)> m_callback_sendbefore;
// [回调] 关闭
std::function<void(uint64 connid,network::http::websocket_message* ws_msg)> m_callback_close;
// 拦截器
std::unique_ptr<network::http::interceptor> m_interceptor;
// 订阅器

View File

@@ -44,6 +44,8 @@ namespace ylib
EnHandleResult OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen);
EnHandleResult OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
EnHandleResult OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID);
private:
bool _MessageComplete(IHttpServer* pSender,CONNID dwConnID,message_type msg_type,std::shared_ptr<websocket_message> ws_msg = nullptr);
private:
// HPSERVER 指针
network::http::server* m_server;

View File

@@ -19,8 +19,8 @@ namespace ylib
std::regex regex;
std::string pattern;
std::string extra;
std::function<void(network::http::request* request, network::http::response* response, const std::string& pattern, const std::string& extra)> callback;
std::function<void(network::http::request* request, network::http::response* response)> callback2;
std::function<void(network::http::request* request, network::http::response* response,network::http::websocket_message* ws_msg, const std::string& pattern, const std::string& extra)> callback;
std::function<void(network::http::request* request, network::http::response* response,network::http::websocket_message* ws_msg)> callback2;
};
/******************************************************
* class订阅器
@@ -30,7 +30,7 @@ namespace ylib
public:
subscribe();
~subscribe();
bool add(const std::string& pattern,const std::string& extra,std::function<void(network::http::request* request, network::http::response* response, const std::string& pattern, const std::string& extra)> callback);
bool add(const std::string& pattern,const std::string& extra,std::function<void(network::http::request* request, network::http::response* response,network::http::websocket_message* ws_msg, const std::string& pattern, const std::string& extra)> callback);
bool remove(const std::string& pattern);
bool exist(const std::string& pattern);
bool trigger(const std::string& url, network::http::reqpack* rp);

View File

@@ -23,19 +23,23 @@ If you have any questions, please contact us: 1585346868@qq.com Or visit our web
#include "net/http_response.h"
#include "util/time.h"
#define HPSERVER
ylib::network::http::reqpack::reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server, network::http::website* website)
ylib::network::http::reqpack::reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server, network::http::website* website, network::http::message_type msg_type, std::shared_ptr<network::http::websocket_message> ws_msg)
:m_url(url)
,m_host(host)
,m_data(data)
,m_connid(connid)
,m_server(server)
,m_msg_type(msg_type)
,m_ws_msg(ws_msg)
{
this->website(website);
if(m_msg_type == network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET){
m_filepath = url;
}else{
m_filepath = strutils::F(((IHttpServer*)m_server->hpserver())->GetUrlField((CONNID)m_connid, HUF_PATH));
}
// 防止访问上级目录
m_filepath = strutils::remove(m_filepath, "..");
}
ylib::network::http::reqpack::~reqpack()
{
@@ -59,4 +63,5 @@ const std::shared_ptr<network::http::response>& network::http::reqpack::response
}
return m_response;
}
#endif

View File

@@ -58,6 +58,14 @@ ylib::network::http::response::~response()
send((std::string)"The server does not return any data to the browser", 500, "Internal Server Error");
}
}
bool ylib::network::http::response::send_ws(const char* buf, size_t buf_len, int opcode)
{
// 异步入队后 GetWSMessageState 可能已失效,由调用方指定 opcode
// 必须标记已响应,否则析构会再发 HTTP 500把 WebSocket 连接打断
m_response = true;
return (bool)HPSERVER->SendWSMessage((CONNID)m_reqpack->connid(), TRUE, 0, (BYTE)opcode, (const BYTE*)buf, (int)buf_len);
}
bool ylib::network::http::response::send(const char* buf, size_t buf_len, ushort stateNum, const std::string& stateDesc)
{
@@ -85,6 +93,7 @@ bool ylib::network::http::response::send(const char* buf, size_t buf_len, ushort
m_response = true;
//合成THeader
//Content-Type
if(view.length() > 0)
{
HEADER_SET("Content-Type", "text/html");
HEADER_SET("Content-Length", std::to_string((uint64)view.length()));
@@ -113,13 +122,22 @@ bool ylib::network::http::response::send(const char* buf, size_t buf_len, ushort
idx++;
}
this->m_reqpack->server()->qps()->response(view.length());
bool result = (bool)HPSERVER->SendResponse((CONNID)m_reqpack->connid(), stateNum, stateDesc.c_str(), headers, (int32)m_headers.size(), (const BYTE*)view.data(),(int)view.length());
bool result = false;
if(view.length() > 0){
result = (bool)HPSERVER->SendResponse((CONNID)m_reqpack->connid(), stateNum, stateDesc.c_str(), headers, (int32)m_headers.size(), (const BYTE*)view.data(),(int)view.length());
}else{
result = (bool)HPSERVER->SendResponse((CONNID)m_reqpack->connid(), stateNum, stateDesc.c_str(), headers, (int32)m_headers.size());
}
delete[] headers;
return result;
}
}
bool ylib::network::http::response::send_header(ushort stateNum, const std::string& stateDesc)
{
return send(NULL, 0, stateNum, stateDesc);
}
bool ylib::network::http::response::send(const ylib::buffer& value, ushort stateNum, const std::string& stateDesc)
{
return send(value.data(), value.length(), stateNum, stateDesc);
@@ -378,7 +396,7 @@ bool ylib::network::http::response::forward(const std::string& filepath)
if(m_response == true)
return false;
m_response = true;
network::http::reqpack* reqpack = new network::http::reqpack(filepath,m_reqpack->host(),m_reqpack->body(),m_reqpack->connid(), m_reqpack->server(), m_reqpack->website());
network::http::reqpack* reqpack = new network::http::reqpack(filepath,m_reqpack->host(),m_reqpack->body(),m_reqpack->connid(), m_reqpack->server(), m_reqpack->website(), m_reqpack->msg_type(), m_reqpack->ws_msg());
reqpack->extra() = m_reqpack->extra();
m_reqpack->website()->router()->push(reqpack);

View File

@@ -97,10 +97,14 @@ network::http::subscribe* ylib::network::http::router::subscribe()
m_subscribe->center(center());
return m_subscribe.get();
}
void network::http::router::other(std::function<void(network::http::request*,network::http::response*)> callback)
void network::http::router::other(std::function<void(network::http::request*,network::http::response*,network::http::websocket_message*)> callback)
{
this->m_callback_other = callback;
}
void ylib::network::http::router::on_close(std::function<void(uint64 connid,network::http::websocket_message* ws_msg)> callback)
{
m_callback_close = callback;
}
void ylib::network::http::router::on_recved(std::function<void(const ylib::buffer &begin, ylib::buffer* end)> callback)
{
m_callback_recved = callback;
@@ -119,7 +123,12 @@ VOID __HP_CALL TaskProc_function(PVOID pvArg)
}
void ylib::network::http::router::__thread_callback(reqpack* rp)
{
if(rp->is_close()){
if(m_callback_close != nullptr){
m_callback_close((uint64)rp->connid(), rp->ws_msg().get());
}
return;
}
/*======== ======CDN服务==============*/
if (is_cdn(rp))
return;
@@ -150,7 +159,7 @@ void ylib::network::http::router::__thread_callback(reqpack* rp)
// 其它
if (m_callback_other != nullptr)
m_callback_other(rp->request().get(), rp->response().get());
m_callback_other(rp->request().get(), rp->response().get(), rp->ws_msg().get());
}
catch (const std::exception& e)
{
@@ -165,7 +174,14 @@ void ylib::network::http::router::push(reqpack *rp)
{
m_handle_queue.push(rp);
}
void ylib::network::http::router::push_close(uint64 connid,std::shared_ptr<network::http::websocket_message> ws_msg)
{
// url/host 必须是合法 string传 0/nullptr 会按 const char* 构造 std::string 直接 logic_error
std::string url = (ws_msg != nullptr) ? ws_msg->filepath : std::string();
reqpack* rp = new reqpack(url, std::string(), ylib::buffer(), connid, nullptr, nullptr, network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET, ws_msg);
rp->set_close();
m_handle_queue.push(rp);
}
bool ylib::network::http::router::is_cdn(reqpack* rp)
{

View File

@@ -31,8 +31,6 @@ If you have any questions, please contact us: 1585346868@qq.com Or visit our web
#include "net/util.h"
#include "net/http_cache.h"
#include "util/codec.h"
#define BARE_HP 0
ylib::network::http::http_server_lst::http_server_lst(server* server)
{
@@ -51,9 +49,7 @@ EnHandleResult ylib::network::http::http_server_lst::OnPrepareListen(ITcpServer*
EnHandleResult ylib::network::http::http_server_lst::OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
{
//std::cout << "[OnAccept] HttpServerConnect:" << pSender->GetConnectionCount() << std::endl;
#if BARE_HP == 0
pSender->SetConnectionExtra(dwConnID, (PVOID)new temp_recv);
#endif
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnAccept ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
@@ -116,7 +112,6 @@ EnHandleResult ylib::network::http::http_server_lst::OnClose(ITcpServer* pSender
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnClose ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
@@ -129,11 +124,26 @@ EnHandleResult ylib::network::http::http_server_lst::OnClose(ITcpServer* pSender
m_server->agent()->disconnect(tr->agent_ssl,tr->agent_connid);
}
#endif
if(tr->is_ws){
auto website = m_server->center()->website(tr->host);
if (website != nullptr)
{
std::shared_ptr<network::http::websocket_message> ws_msg = std::make_shared<network::http::websocket_message>();
ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_CLOSE;
ws_msg->filepath = tr->ws_filepath;
website->router()->push_close((uint64)dwConnID,ws_msg);
}
}
delete tr;
}
}
#endif
return HR_OK;
}
@@ -142,7 +152,7 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageBegin(IHttpServ
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnMessageBegin ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
@@ -151,7 +161,7 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageBegin(IHttpServ
((temp_recv*)extra)->data.clear();
}
}
#endif
return HPR_OK;
}
@@ -161,16 +171,15 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnRequestLine(IHttpServe
// ylib::log->info("OnRequestLine ("+nstring::from((uint64)dwConnID)+")","http_server");
//#endif
#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
if (extra != 0)
{
((temp_recv*)extra)->url = lpszUrl;
((temp_recv*)extra)->ws_filepath = std::string(lpszUrl);
}
}
#endif
return HPR_OK;
}
@@ -188,7 +197,6 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnHeader(IHttpServer* pS
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnHeader ("+std::to_string((uint64)dwConnID)+")"+lpszName+":"+lpszValue,"http_server");
#endif
#if BARE_HP == 0
if(strcmp(lpszName,"Host") == 0){
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
@@ -200,7 +208,6 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnHeader(IHttpServer* pS
}
}
#endif
return HPR_OK;
}
@@ -232,6 +239,53 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnUpgrade(IHttpServer* p
ylib::log->info("OnUpgrade ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
if (m_server->center()->config().websocket_enable)
{
if (enUpgradeType == HUT_WEB_SOCKET)
{
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
if (extra != 0)
{
((temp_recv*)extra)->is_ws = true;
}
}
LPCSTR lpszValue = nullptr;
if (pSender->GetHeader(dwConnID,"Sec-WebSocket-Key", &lpszValue) == false)
return HPR_ERROR;
// std::string value = std::string(lpszValue)+ "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
// std::string accept_value = codec::base64::en(codec::sha1(value));
// THeader headers[3];
// headers[0].name = "Connection";
// headers[0].value = "Upgrade";
// headers[1].name = "Upgrade";
// headers[1].value = "WebSocket";
// headers[2].name = "Sec-WebSocket-Accept";
// headers[2].value = accept_value.c_str();
// pSender->SendResponse(dwConnID, 101, "Switching Protocols", headers,3);
std::shared_ptr<network::http::websocket_message> ws_msg = std::make_shared<network::http::websocket_message>();
ws_msg->sec_websocket_key = std::string(lpszValue);
ws_msg->connid = (uint64)dwConnID;
ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_UPGRADE;
if (_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET,ws_msg))
return HPR_OK;
return HPR_ERROR;
}
else
return HPR_ERROR;
}
return HPR_OK;
}
@@ -241,7 +295,6 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnBody(IHttpServer* pSen
ylib::log->info("OnBody ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
@@ -257,19 +310,10 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnBody(IHttpServer* pSen
}
}
}
#endif
return HPR_OK;
}
EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
bool ylib::network::http::http_server_lst::_MessageComplete(IHttpServer* pSender,CONNID dwConnID,network::http::message_type msg_type,std::shared_ptr<network::http::websocket_message> ws_msg)
{
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnMessageComplete ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
#if BARE_HP == 1
pSender->SendResponse(dwConnID, 200, "OK", nullptr, 0, (const BYTE*)"ONLY_HP_OK", 3);
return HPR_OK;
#endif
network::http::reqpack* rp = nullptr;
temp_recv* tr = nullptr;
{
@@ -280,10 +324,10 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpS
if (extra != 0)
tr = (temp_recv*)extra;
else
return HPR_OK;
return true;
}
else
return HPR_OK;
return true;
}
// QPS记录
@@ -294,10 +338,16 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpS
{
pSender->SendResponse(dwConnID, 404, "Not Found", nullptr, 0, (const BYTE*)"No fount site", 12);
delete rp;
return HPR_OK;
return false;
}
// 创建请求包
rp = new network::http::reqpack(tr->url, tr->host, tr->data, (uint64)dwConnID, m_server, website);
std::string url;
if(msg_type == network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET){
url = tr->ws_filepath;
}else{
url = tr->url;
}
rp = new network::http::reqpack(url, tr->host, tr->data, (uint64)dwConnID, m_server, website, msg_type, ws_msg);
// 开始前处理请求包
{
@@ -311,12 +361,18 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpS
}
}
// 追加置路由
website->router()->push(rp);
return true;
}
EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
{
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnMessageComplete ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
if (_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_NORMAL,nullptr))
return HPR_OK;
return HPR_ERROR;
}
EnHttpParseResult ylib::network::http::http_server_lst::OnParseError(IHttpServer* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
@@ -339,16 +395,74 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnParseError(IHttpServer
EnHandleResult ylib::network::http::http_server_lst::OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
{
if(iReserved != 0)
return HR_ERROR; // 服务器不支持扩展
std::shared_ptr<network::http::websocket_message> ws_msg = std::make_shared<network::http::websocket_message>();
ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_HEADER;
ws_msg->connid = (uint64)dwConnID;
ws_msg->header._final = bFinal;
ws_msg->header.opcode = iOperationCode;
ws_msg->header.mask[0] = lpszMask[0];
ws_msg->header.mask[1] = lpszMask[1];
ws_msg->header.mask[2] = lpszMask[2];
ws_msg->header.mask[3] = lpszMask[3];
ws_msg->header.length = ullBodyLen;
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
if (extra != 0)
{
((temp_recv*)extra)->data.clear();
((temp_recv*)extra)->ws_msg = *ws_msg.get();
}
}
if (_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET,ws_msg))
return HR_OK;
return HR_ERROR;
}
EnHandleResult ylib::network::http::http_server_lst::OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
if (extra != 0)
{
((temp_recv*)extra)->data.append((char*)pData, iLength);
}
}
return HR_OK;
}
EnHandleResult ylib::network::http::http_server_lst::OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID)
{
std::shared_ptr<network::http::websocket_message> ws_msg = std::make_shared<network::http::websocket_message>();
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
if (extra != 0)
{
// 先带上 HEADER 缓存的 opcode 等信息;不要在这里 clear data
// 否则 _MessageComplete 拷贝到 reqpack 的 body 会是空的
*ws_msg.get() = ((temp_recv*)extra)->ws_msg;
}
}
ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_BODY;
ws_msg->connid = (uint64)dwConnID;
if(_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET,ws_msg))
{
return HR_OK;
}
return HR_ERROR;
}
#endif

View File

@@ -30,7 +30,7 @@ network::http::subscribe::~subscribe()
{
clear();
}
bool network::http::subscribe::add(const std::string& pattern, const std::string& extra, std::function<void(network::http::request* request, network::http::response* response, const std::string& pattern,const std::string& extra)> callback)
bool network::http::subscribe::add(const std::string& pattern, const std::string& extra, std::function<void(network::http::request* request, network::http::response* response,network::http::websocket_message* ws_msg, const std::string& pattern,const std::string& extra)> callback)
{
std::unique_lock<std::shared_mutex> lock(m_rw_mutex);
// 判断是否存在
@@ -81,7 +81,7 @@ bool network::http::subscribe::trigger(const std::string& url, network::http::re
for (size_t i = 0; i < m_list.size(); i++)
{
if (std::regex_match(url.c_str(), m_list[i].regex)) {
m_list[i].callback(rp->request().get(), rp->response().get(), m_list[i].pattern, m_list[i].extra);
m_list[i].callback(rp->request().get(), rp->response().get(), rp->ws_msg().get(), m_list[i].pattern, m_list[i].extra);
return true;
}
}