增加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

View File

@@ -34,12 +34,64 @@
#define HTTP_INTERCEPTOR_PRINT 0
// http lua 引擎
//#define HTTP_LUA_ENGINE 0
namespace ylib
{
namespace network
{
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>
@@ -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,7 +31,10 @@ namespace ylib
std::map<std::string, std::string>* headers();
bool redirect(const std::string& filepath, bool MovedPermanently = false);
bool forward(const std::string& filepath);
public:
void response_done(){m_response = true;}
bool is_response_done(){return m_response;}
public:
ylib::json sjson;
private:
bool filecache(const uint64& last_modify_time);

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);