HttpServer模块概述
封装HttpSession
接收请求报文,发送响应报文,该类继承自SocketStream
。
封装Servlet
,虚拟接口,当Server
命中某个uri
时,执行对应的Servlet
。
封装HttpServer
服务器,继承自TcpServer
。
HttpSession详解
class HttpSession
HttpSession(构造函数)
HttpSession::HttpSession(Socket::ptr sock, bool owern)
:SocketStream(sock, owern) {
}
recvRequest(接收请求报文)
HttpRequest::ptr HttpSession::recvRequest() {
// 创建HttpRequestParser
HttpRequestParser::ptr parser(new HttpRequestParser);
// 获取缓冲区大小
uint64_t buff_size = HttpRequestParser::GetHttpRequestBufferSize();
// 交给智能指针托管
std::shared_ptr<char> buffer(
new char[buff_size], [](char* ptr) {
delete[] ptr;
});
char* data = buffer.get();
int offset = 0;
do {
// 在offset后面接着读数据
int len = read(data + offset, buff_size - offset);
if (len <= 0) {
close();
return nullptr;
}
// 当前已经读取的数据长度
len += offset;
// 解析缓冲区data中的数据
// execute会将data向前移动nparse个字节,nparse为已经成功解析的字节数
size_t nparse = parser->execute(data, len);
if (parser->hasError()) {
close();
return nullptr;
}
// 此时data还剩下已经读到的数据 - 解析过的数据
offset = len - nparse;
// 缓冲区满了还没解析完
if (offset == (int)buff_size) {
close();
return nullptr;
}
// 解析结束
if (parser->isFinished()) {
break;
}
} while (true);
// 获得body的长度
int64_t length = parser->getContentLength();
if (length > 0) {
std::string body;
body.resize(length);
int len = 0;
// 如果body长度比缓冲区剩余的还大,将缓冲区全部加进来
if (length >= offset) {
mempcpy(&body[0], data, offset);
len = offset;
} else {
// 否则将取length
memcpy(&body[0], data, length);
len = length;
}
length -= offset;
// 缓冲区里的数据也不够,继续读取直到满足length
if (length > 0) {
if (readFixSize(&body[len], length) <= 0) {
close();
return nullptr;
}
}
// 设置body
parser->getData()->setBody(body);
}
//返回解析完的HttpRequest
return parser->getData();
}
sendResponse(发送响应报文)
int HttpSession::sendResponse(HttpResponse::ptr rsp) {
std::stringstream ss;
ss << *rsp;
std::string data = ss.str();
return writeFixSize(data.c_str(), data.size());
}
Servlet详解
class Servlet
抽象类,基类,提供一个纯虚函数。当访问到该servlet
时,执行handle
方法
virtual int32_t handle(sylar::http::HttpRequest::ptr request
, sylar::http::HttpResponse::ptr response
, sylar::http::HttpSession::ptr session) = 0;
mumber(成员变量)
// servlet名字
std::string m_name;
Servlet(构造函数)
Servlet(const std::string& name)
:m_name(name) {
}
class FunctionServlet
mumber(成员变量)
typedef std::function<int32_t(sylar::http::HttpRequest::ptr request
, sylar::http::HttpResponse::ptr response
, sylar::http::HttpSession::ptr session)> callback;
// 执行函数
callback m_cb;
FunctionServlet(构造函数)
FunctionServlet::FunctionServlet(callback cb)
:Servlet("FunctionServlet")
,m_cb(cb) {
}
handle(执行函数)
int32_t FunctionServlet::handle(sylar::http::HttpRequest::ptr request
, sylar::http::HttpResponse::ptr response
, sylar::http::HttpSession::ptr session) {
return m_cb(request, response, session);
}
class ServletDispatch
Servlet
管理类
mumber(成员变量)
// 读写锁
RWMutexType m_mutex;
// uri(/sylar/xxx) -> servlet 精准匹配
std::unordered_map<std::string, Servlet::ptr> m_datas;
// uri(/sylar/*) -> servlet 模糊匹配
std::vector<std::pair<std::string, Servlet::ptr> > m_globs;
// 默认servlet返回404 Not found,所有路径无匹配使用
Servlet::ptr m_default;
ServletDispatch(构造函数)
ServletDispatch::ServletDispatch()
:Servlet("ServletDispatch") {
m_default.reset(new NotFoundServlet("sylar/1.0"));
}
handle(执行函数)
int32_t ServletDispatch::handle(sylar::http::HttpRequest::ptr request
, sylar::http::HttpResponse::ptr response
, sylar::http::HttpSession::ptr session) {
auto slt = getMatchedServlet(request->getPath());
if (slt) {
slt->handle(request, response, session);
}
return 0;
}
addServlet(添加精准Servlet,智能指针)
void ServletDispatch::addServlet(const std::string& uri, Servlet::ptr slt) {
RWMutexType::WriteLock lock(m_mutex);
m_datas[uri] = slt;
}
addServlet(添加精准Servlet,回调函数)
void ServletDispatch::addServlet(const std::string& uri, FunctionServlet::callback cb) {
RWMutexType::WriteLock lock(m_mutex);
m_datas[uri].reset(new FunctionServlet(cb));
}
addGlobServlet(添加模糊Servlet,智能指针)
void ServletDispatch::addGlobServlet(const std::string& uri, Servlet::ptr slt) {
RWMutexType::WriteLock lock(m_mutex);
// 将原先的删除
for (auto it = m_globs.begin();
it != m_globs.end(); ++it) {
if (it->first == uri) {
m_globs.erase(it);
break;
}
}
m_globs.push_back(std::make_pair(uri, slt));
}
addServlet(添加模糊Servlet,回调函数)
void ServletDispatch::addGlobServlet(const std::string& uri, FunctionServlet::callback cb) {
return addGlobServlet(uri, FunctionServlet::ptr(new FunctionServlet(cb)));
}
delServlet(删除精准Servlet)
void ServletDispatch::delServlet(const std::string& uri) {
RWMutexType::WriteLock lock(m_mutex);
m_datas.erase(uri);
}
delGlobServlet(删除模糊Servlet)
void ServletDispatch::delGlobServlet(const std::string& uri) {
RWMutexType::WriteLock lock(m_mutex);
for (auto it = m_globs.begin();
it != m_globs.end(); ++it) {
if (it->first == uri) {
m_globs.erase(it);
break;
}
}
}
getServlet(返回精准Servlet)
Servlet::ptr ServletDispatch::getServlet(const std::string& uri) {
RWMutexType::ReadLock lock(m_mutex);
auto it = m_datas.find(uri);
return it == m_datas.end() ? nullptr : it->second;
}
getGlobServlet(返回模糊Servlet)
Servlet::ptr ServletDispatch::getGlobServlet(const std::string& uri) {
RWMutexType::ReadLock lock(m_mutex);
for (auto it = m_globs.begin();
it != m_globs.end(); ++it) {
if (it->first == uri) {
return it->second;
}
}
return nullptr;
}
getMatchedServlet(匹配Servlet)
Servlet::ptr ServletDispatch::getMatchedServlet(const std::string& uri) {
RWMutexType::ReadLock lock(m_mutex);
// 先找精准的Servlet
auto mit = m_datas.find(uri);
if (mit != m_datas.end()) {
return mit->second;
}
// 再找模糊的Servlet
for (auto it = m_globs.begin();
it != m_globs.end(); ++it) {
// 模糊匹配Servlet
if (!fnmatch(it->first.c_str(), uri.c_str(), 0)) {
return it->second;
}
}
// 都没有返回404
return m_default;
}
class NotFoundServlet
默认返回404
mumber(成员变量)
// 服务器版本名称
std::string m_name;
// body
std::string m_content;
NotFoundServlet(构造函数)
NotFoundServlet::NotFoundServlet(const std::string& name)
:Servlet("NotFoundServlet")
,m_name(name) {
m_content = "<html><head><title>404 Not Found"
"</title></head><body><center><h1>404 Not Found</h1></center>"
"<hr><center>" + name + "</center></body></html>";
}
handle(执行函数)
int32_t NotFoundServlet::handle(sylar::http::HttpRequest::ptr request
, sylar::http::HttpResponse::ptr response
, sylar::http::HttpSession::ptr session) {
response->setStatue(sylar::http::HttpStatus::NOT_FOUND);
response->setHeader("Server", "sylar/1.0.0");
response->setHeader("Content-Type", "text/html");
response->setBody(m_content);
return 0;
}
HttpServer详解
class HttpServer
mumber(成员变量)
// 是否长连接
bool m_isKeepalive;
// servlet
ServletDispatch::ptr m_dispatch;
HttpServer(构造函数)
HttpServer::HttpServer(bool keepalive
, sylar::IOManager* worker
, sylar::IOManager* accept_worker)
:TcpServer(worker, accept_worker)
,m_isKeepalive(keepalive) {
m_dispatch.reset(new ServletDispatch);
}
setName(设置服务器名称)
void HttpServer::setName(const std::string& v) {
TcpServer::setName(v);
// 设置默认servlet名称
m_dispatch->setDefault(std::make_shared<NotFoundServlet>(v));
}
handleClient(与客户端通信)
void HttpServer::handleClient(Socket::ptr client) {
sylar::http::HttpSession::ptr session(new HttpSession(client));
do {
// 接收请求报文
auto req = session->recvRequest();
if (!req) {
SYLAR_LOG_WARN(g_logger) << "recv http request fail, errno = "
<< errno << " errstr = " << strerror(errno)
<< " cliet: " << *client;
break;
}
// 创建响应报文
HttpResponse::ptr rsp(new HttpResponse(req->getVersion()
, req->isClosed() || !m_isKeepalive));
// 设置Server名Head
rsp->setHeader("Server", getName());
// 执行操作
m_dispatch->handle(req, rsp, session);
// 发送响应报文
session->sendResponse(rsp);
// 若不支持长连接,关闭
if (!m_isKeepalive || req->isClosed()) {
break;
}
} while (true);
// 关闭socket
session->close();
}