C++实战——Http业务逻辑

文章代码来源:高并发Web服务器

简单介绍

书接上文,这里是http处理业务请求的具体逻辑内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
bool HttpConn::process() {
//初始化
request_.Init();
//没有数据可读直接返回false
if(readBuff_.ReadableBytes() <= 0) {
return false;
}
else if(request_.parse(readBuff_)) //请求解析成功后 初始化相应
{
LOG_DEBUG("%s", request_.path().c_str());
response_.Init(srcDir, request_.path(), request_.IsKeepAlive(), 200);
} else {
//400代表解析不成功
response_.Init(srcDir, request_.path(), false, 400);
}
//创造相应
response_.MakeResponse(writeBuff_);
/* 响应头 */
iov_[0].iov_base = const_cast<char*>(writeBuff_.Peek());
iov_[0].iov_len = writeBuff_.ReadableBytes();
iovCnt_ = 1;

/* 文件 */
if(response_.FileLen() > 0 && response_.File()) {
iov_[1].iov_base = response_.File();
iov_[1].iov_len = response_.FileLen();
iovCnt_ = 2;
}
LOG_DEBUG("filesize:%d, %d to %d", response_.FileLen() , iovCnt_, ToWriteBytes());
return true;
}

解析http请求的逻辑

下面简单分析,对http请求的解析的逻辑。

1677937698830

从http的请求报文的格式可看出,可以分为三个部分,请求首行请求头部请求数据 也叫请求体(body),http解析也以此划分阶段。当解析数据还有剩余,会依据当前状态解析相应的部分。如:ParseRequestLine_()ParseHeader_()ParseBody_.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
bool HttpRequest::parse(Buffer& buff) {
const char CRLF[] = "\r\n";
if(buff.ReadableBytes() <= 0) {
return false;
}
//还有数据且状态不为解析完毕则不会跳出循环
while(buff.ReadableBytes() && state_ != FINISH) {
const char* lineEnd = search(buff.Peek(), buff.BeginWriteConst(), CRLF, CRLF + 2);
std::string line(buff.Peek(), lineEnd);
switch(state_)
{
case REQUEST_LINE:
if(!ParseRequestLine_(line)) {
return false;
}
ParsePath_();
break;
case HEADERS:
ParseHeader_(line);
if(buff.ReadableBytes() <= 2) {
state_ = FINISH;
}
break;
case BODY:
ParseBody_(line);
break;
default:
break;
}
if(lineEnd == buff.BeginWrite()) { break; }
buff.RetrieveUntil(lineEnd + 2);
}
LOG_DEBUG("[%s], [%s], [%s]", method_.c_str(), path_.c_str(), version_.c_str());
return true;
}

创建响应的逻辑

同样,当请求的资源存在,可以响应时,也依次此创建响应。

1677939294522

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void HttpResponse::MakeResponse(Buffer& buff) {
/* 判断请求的资源文件 */
if(stat((srcDir_ + path_).data(), &mmFileStat_) < 0 || S_ISDIR(mmFileStat_.st_mode)) {
code_ = 404; //访问的是目录不是具体资源???
}
else if(!(mmFileStat_.st_mode & S_IROTH)) {
code_ = 403; //权限不够
}
else if(code_ == -1) {
code_ = 200; //
}
ErrorHtml_(); //提醒错误的网页
AddStateLine_(buff); //创建响应首行
AddHeader_(buff); //创建响应头部
AddContent_(buff); //创建内容
}