当前位置: 首页 > news >正文

Sylar服务器框架——Http模块

1、http.h

  • 定义了HttpMethod和HttpStatus
/* Request Methods */
#define HTTP_METHOD_MAP(XX)         \XX(0,  DELETE,      DELETE)       \XX(1,  GET,         GET)          \XX(2,  HEAD,        HEAD)         \XX(3,  POST,        POST)         \XX(4,  PUT,         PUT)          \
.../* Status Codes */
#define HTTP_STATUS_MAP(XX)                                                 \XX(100, CONTINUE,                        Continue)                        \XX(101, SWITCHING_PROTOCOLS,             Switching Protocols)             \XX(102, PROCESSING,                      Processing)                      \XX(200, OK,                              OK)                              \XX(201, CREATED,                         Created)                         \XX(202, ACCEPTED,                        Accepted)                        \XX(203, NON_AUTHORITATIVE_INFORMATION,   Non-Authoritative Information)   \
...
/*** @brief HTTP方法枚举*/
enum class HttpMethod {
#define XX(num, name, string) name = num,HTTP_METHOD_MAP(XX)
#undef XXINVALID_METHOD
};/*** @brief HTTP状态枚举*/
enum class HttpStatus {
#define XX(code, name, desc) name = code,HTTP_STATUS_MAP(XX)
#undef XX
};
  • HttpRequest和HttpResponse
    Http请求和响应的格式可以参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Messages
    HttpRequest和HttpResponse其实可以看成是容器,将请求消息和响应消息那一坨字符串,拆解开放在里面,这样就可以让机器去按照这些信息去做操作。
    对于HTTP请求,需要关注HTTP方法,请求路径和参数,HTTP版本,HTTP头部的key-value结构,Cookies,以及HTTP Body内容。
    对于HTTP响应,需要关注HTTP版本,响应状态码,响应字符串,响应头部的key-value结构,以及响应的Body内容。
    2、http_parser.h
    这个模块的作用就是将输入的字节流信息解析到HttpRequest和HttpResponse结构体中。这里是基于https://github.com/nodejs/http-parser实现的,采用了有限状态机算法,效率非常快。
  • HttpRequestParser
    当解析完相关项时就会执行相应的回调,将数据放到指定位置
void on_request_method(void *data, const char *at, size_t length) {HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);HttpMethod m = CharsToHttpMethod(at);if(m == HttpMethod::INVALID_METHOD) {SYLAR_LOG_WARN(g_logger) << "invalid http request method: "<< std::string(at, length);parser->setError(1000);return;}parser->getData()->setMethod(m);
}void on_request_uri(void *data, const char *at, size_t length) {
}void on_request_fragment(void *data, const char *at, size_t length) {//SYLAR_LOG_INFO(g_logger) << "on_request_fragment:" << std::string(at, length);HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);parser->getData()->setFragment(std::string(at, length));
}void on_request_path(void *data, const char *at, size_t length) {HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);parser->getData()->setPath(std::string(at, length));
}void on_request_query(void *data, const char *at, size_t length) {HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);parser->getData()->setQuery(std::string(at, length));
}void on_request_version(void *data, const char *at, size_t length) {HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);uint8_t v = 0;if(strncmp(at, "HTTP/1.1", length) == 0) {v = 0x11;} else if(strncmp(at, "HTTP/1.0", length) == 0) {v = 0x10;} else {SYLAR_LOG_WARN(g_logger) << "invalid http request version: "<< std::string(at, length);parser->setError(1001);return;}parser->getData()->setVersion(v);
}void on_request_header_done(void *data, const char *at, size_t length) {//HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);
}void on_request_http_field(void *data, const char *field, size_t flen,const char *value, size_t vlen) {HttpRequestParser* parser = static_cast<HttpRequestParser*>(data);if(flen == 0) {SYLAR_LOG_WARN(g_logger) << "invalid http request field length == 0";//parser->setError(1002);return;}parser->getData()->setHeader(std::string(field, flen),std::string(value, vlen));
}
  • HttpResponseParser
void on_response_reason(void *data, const char *at, size_t length) {HttpResponseParser* parser = static_cast<HttpResponseParser*>(data);parser->getData()->setReason(std::string(at, length));
}void on_response_status(void *data, const char *at, size_t length) {HttpResponseParser* parser = static_cast<HttpResponseParser*>(data);HttpStatus status = (HttpStatus)(atoi(at));parser->getData()->setStatus(status);
}void on_response_chunk(void *data, const char *at, size_t length) {
}void on_response_version(void *data, const char *at, size_t length) {HttpResponseParser* parser = static_cast<HttpResponseParser*>(data);uint8_t v = 0;if(strncmp(at, "HTTP/1.1", length) == 0) {v = 0x11;} else if(strncmp(at, "HTTP/1.0", length) == 0) {v = 0x10;} else {SYLAR_LOG_WARN(g_logger) << "invalid http response version: "<< std::string(at, length);parser->setError(1001);return;}parser->getData()->setVersion(v);
}void on_response_header_done(void *data, const char *at, size_t length) {
}void on_response_last_chunk(void *data, const char *at, size_t length) {
}void on_response_http_field(void *data, const char *field, size_t flen,const char *value, size_t vlen) {HttpResponseParser* parser = static_cast<HttpResponseParser*>(data);if(flen == 0) {SYLAR_LOG_WARN(g_logger) << "invalid http response field length == 0";//parser->setError(1002);return;}parser->getData()->setHeader(std::string(field, flen),std::string(value, vlen));
}

3、http_session.h

  • 继承自SocketStream,实现了在套接字流上读取HTTP请求与发送HTTP响应的功能,在读取HTTP请求时需要借助HTTP解析器,以便于将套接字流上的内容解析成HTTP请求。 从每个请求的通信套接字读到请求数据,利用parser将流数据转换成自己定义的结构体由该模块完成。解析完后,会由servlet执行相关操作,把信息封装在HttpResponse,由该模块通过通信套接字传给客户端。
    4、servlet.h
  • 提供HTTP请求路径到处理类的映射,用于规范化的HTTP消息处理流程。HTTP Servlet包括两部分,第一部分是Servlet对象,每个Servlet对象表示一种处理HTTP消息的方法,第二部分是ServletDispatch,它包含一个请求路径到Servlet对象的映射,用于指定一个请求路径该用哪个Servlet来处理。
    /*** @brief 处理请求* @param[in] request HTTP请求* @param[in] response HTTP响应* @param[in] session HTTP连接* @return 是否处理成功*/virtual int32_t handle(sylar::http::HttpRequest::ptr request, sylar::http::HttpResponse::ptr response, sylar::http::HttpSession::ptr session) = 0;

5、http_server.h

  • 继承自TcpServer,重载handleClient方法,将accept后得到的客户端套接字封装成HttpSession结构,以便于接收和发送HTTP消息。
void HttpServer::handleClient(Socket::ptr client) {SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client;HttpSession::ptr session(new HttpSession(client));do {auto req = session->recvRequest();if(!req) {SYLAR_LOG_DEBUG(g_logger) << "recv http request fail, errno="<< errno << " errstr=" << strerror(errno)<< " cliet:" << *client << " keep_alive=" << m_isKeepalive;break;}HttpResponse::ptr rsp(new HttpResponse(req->getVersion(),req->isClose() || !m_isKeepalive));rsp->setHeader("Server", getName());m_dispatch->handle(req, rsp, session);session->sendResponse(rsp);if(!m_isKeepalive || req->isClose()) {break;}} while(true);session->close();
}

6、http_connection

  • 用于发起GET/POST等请求并获取响应,支持设置超时,keep-alive,支持连接池。HTTP服务端的业务模型是接收请求→ 发送响应,而HTTP客户端的业务模型是发送请求→ 接收响应。
  • 关于连接池,是指提前预备好一系列已接建立连接的socket,这样,在发起请求时,可以直接从中选择一个进行通信,而不用重复创建套接字→ 发起connect→ 发起请求 的流程。
  • 连接池与发起请求时的keep-alive参数有关,如果使用连接池来发起GET/POST请求,在未设置keep-alive时,连接池并没有什么卵用。
http://www.lryc.cn/news/390921.html

相关文章:

  • 7km远距离WiFi实时图传模块,无人机海上无线传输方案,飞睿智能WiFi MESH自组网技术
  • 2024年上半年网络工程师下午真题及答案解析
  • Jmeter下载、安装及配置
  • 掌握高效实用的VS调试技巧
  • 实验2 字符及字符串输入输出与分支程序设计实验
  • docker容器间网络仿真工具-pumba
  • A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用
  • vue2 + element三级菜单实现模板
  • vue H5页面video 视频流自动播放, 解决ios不能自动播放问题
  • 自闭症儿童:探索症状背后的多彩内心世界
  • 在Centos7上安装PostgreSQL16的详细步骤
  • MySQL 图形化界面
  • 【人工智能】GPT-5的即将到来:从高中生进化到,,,博士生?
  • 【收录率高丨投稿范围广 | 往届均已EI检索】第四届光学与通信技术国际学术会议(ICOCT 2024,8月9-11)
  • 小阿轩yx-LVS负载均衡群集
  • CPP知识点记录总结
  • Spring源码(一) 如何阅读 Spring 源码
  • 【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84
  • CTF常用sql注入(一)联合注入和宽字节
  • 薄冰英语语法学习--冠词1
  • 基于Java中的SSM框架实现野生动物公益保护系统项目【项目源码+论文说明】计算机毕业设计
  • c->c++(二):class
  • 11 UDP的可靠传输协议QUIC
  • 14-20 Vision Transformer用AI的画笔描绘新世界
  • LVS FILTER UNUSED OPTION
  • Python后端面试题
  • docker打包 arm32v7/debian 问题总结
  • 【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(二十)
  • Vuetify3:监听当前手机还是电脑
  • Zabbix 配置钉钉告警