1 Star 1 Fork 0

guanzhanyi/webServer

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
httpData.cpp 13.60 KB
一键复制 编辑 原始数据 按行查看 历史
guanzhanyi 提交于 2021-05-11 13:17 . 成功运行
/*
用于解析HTTP请求报文
*/
#include <sys/epoll.h>
#include <unistd.h>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <sstream>
#include "tcp_connection.h"
#include "eventloop.h"
#include "timer.h"
#include "httpData.h"
#include "log.h"
char favicon[555] = {
'\x89', 'P', 'N', 'G', '\xD', '\xA', '\x1A', '\xA', '\x0',
'\x0', '\x0', '\xD', 'I', 'H', 'D', 'R', '\x0', '\x0',
'\x0', '\x10', '\x0', '\x0', '\x0', '\x10', '\x8', '\x6', '\x0',
'\x0', '\x0', '\x1F', '\xF3', '\xFF', 'a', '\x0', '\x0', '\x0',
'\x19', 't', 'E', 'X', 't', 'S', 'o', 'f', 't',
'w', 'a', 'r', 'e', '\x0', 'A', 'd', 'o', 'b',
'e', '\x20', 'I', 'm', 'a', 'g', 'e', 'R', 'e',
'a', 'd', 'y', 'q', '\xC9', 'e', '\x3C', '\x0', '\x0',
'\x1', '\xCD', 'I', 'D', 'A', 'T', 'x', '\xDA', '\x94',
'\x93', '9', 'H', '\x3', 'A', '\x14', '\x86', '\xFF', '\x5D',
'b', '\xA7', '\x4', 'R', '\xC4', 'm', '\x22', '\x1E', '\xA0',
'F', '\x24', '\x8', '\x16', '\x16', 'v', '\xA', '6', '\xBA',
'J', '\x9A', '\x80', '\x8', 'A', '\xB4', 'q', '\x85', 'X',
'\x89', 'G', '\xB0', 'I', '\xA9', 'Q', '\x24', '\xCD', '\xA6',
'\x8', '\xA4', 'H', 'c', '\x91', 'B', '\xB', '\xAF', 'V',
'\xC1', 'F', '\xB4', '\x15', '\xCF', '\x22', 'X', '\x98', '\xB',
'T', 'H', '\x8A', 'd', '\x93', '\x8D', '\xFB', 'F', 'g',
'\xC9', '\x1A', '\x14', '\x7D', '\xF0', 'f', 'v', 'f', '\xDF',
'\x7C', '\xEF', '\xE7', 'g', 'F', '\xA8', '\xD5', 'j', 'H',
'\x24', '\x12', '\x2A', '\x0', '\x5', '\xBF', 'G', '\xD4', '\xEF',
'\xF7', '\x2F', '6', '\xEC', '\x12', '\x20', '\x1E', '\x8F', '\xD7',
'\xAA', '\xD5', '\xEA', '\xAF', 'I', '5', 'F', '\xAA', 'T',
'\x5F', '\x9F', '\x22', 'A', '\x2A', '\x95', '\xA', '\x83', '\xE5',
'r', '9', 'd', '\xB3', 'Y', '\x96', '\x99', 'L', '\x6',
'\xE9', 't', '\x9A', '\x25', '\x85', '\x2C', '\xCB', 'T', '\xA7',
'\xC4', 'b', '1', '\xB5', '\x5E', '\x0', '\x3', 'h', '\x9A',
'\xC6', '\x16', '\x82', '\x20', 'X', 'R', '\x14', 'E', '6',
'S', '\x94', '\xCB', 'e', 'x', '\xBD', '\x5E', '\xAA', 'U',
'T', '\x23', 'L', '\xC0', '\xE0', '\xE2', '\xC1', '\x8F', '\x0',
'\x9E', '\xBC', '\x9', 'A', '\x7C', '\x3E', '\x1F', '\x83', 'D',
'\x22', '\x11', '\xD5', 'T', '\x40', '\x3F', '8', '\x80', 'w',
'\xE5', '3', '\x7', '\xB8', '\x5C', '\x2E', 'H', '\x92', '\x4',
'\x87', '\xC3', '\x81', '\x40', '\x20', '\x40', 'g', '\x98', '\xE9',
'6', '\x1A', '\xA6', 'g', '\x15', '\x4', '\xE3', '\xD7', '\xC8',
'\xBD', '\x15', '\xE1', 'i', '\xB7', 'C', '\xAB', '\xEA', 'x',
'\x2F', 'j', 'X', '\x92', '\xBB', '\x18', '\x20', '\x9F', '\xCF',
'3', '\xC3', '\xB8', '\xE9', 'N', '\xA7', '\xD3', 'l', 'J',
'\x0', 'i', '6', '\x7C', '\x8E', '\xE1', '\xFE', 'V', '\x84',
'\xE7', '\x3C', '\x9F', 'r', '\x2B', '\x3A', 'B', '\x7B', '7',
'f', 'w', '\xAE', '\x8E', '\xE', '\xF3', '\xBD', 'R', '\xA9',
'd', '\x2', 'B', '\xAF', '\x85', '2', 'f', 'F', '\xBA',
'\xC', '\xD9', '\x9F', '\x1D', '\x9A', 'l', '\x22', '\xE6', '\xC7',
'\x3A', '\x2C', '\x80', '\xEF', '\xC1', '\x15', '\x90', '\x7', '\x93',
'\xA2', '\x28', '\xA0', 'S', 'j', '\xB1', '\xB8', '\xDF', '\x29',
'5', 'C', '\xE', '\x3F', 'X', '\xFC', '\x98', '\xDA', 'y',
'j', 'P', '\x40', '\x0', '\x87', '\xAE', '\x1B', '\x17', 'B',
'\xB4', '\x3A', '\x3F', '\xBE', 'y', '\xC7', '\xA', '\x26', '\xB6',
'\xEE', '\xD9', '\x9A', '\x60', '\x14', '\x93', '\xDB', '\x8F', '\xD',
'\xA', '\x2E', '\xE9', '\x23', '\x95', '\x29', 'X', '\x0', '\x27',
'\xEB', 'n', 'V', 'p', '\xBC', '\xD6', '\xCB', '\xD6', 'G',
'\xAB', '\x3D', 'l', '\x7D', '\xB8', '\xD2', '\xDD', '\xA0', '\x60',
'\x83', '\xBA', '\xEF', '\x5F', '\xA4', '\xEA', '\xCC', '\x2', 'N',
'\xAE', '\x5E', 'p', '\x1A', '\xEC', '\xB3', '\x40', '9', '\xAC',
'\xFE', '\xF2', '\x91', '\x89', 'g', '\x91', '\x85', '\x21', '\xA8',
'\x87', '\xB7', 'X', '\x7E', '\x7E', '\x85', '\xBB', '\xCD', 'N',
'N', 'b', 't', '\x40', '\xFA', '\x93', '\x89', '\xEC', '\x1E',
'\xEC', '\x86', '\x2', 'H', '\x26', '\x93', '\xD0', 'u', '\x1D',
'\x7F', '\x9', '2', '\x95', '\xBF', '\x1F', '\xDB', '\xD7', 'c',
'\x8A', '\x1A', '\xF7', '\x5C', '\xC1', '\xFF', '\x22', 'J', '\xC3',
'\x87', '\x0', '\x3', '\x0', 'K', '\xBB', '\xF8', '\xD6', '\x2A',
'v', '\x98', 'I', '\x0', '\x0', '\x0', '\x0', 'I', 'E',
'N', 'D', '\xAE', 'B', '\x60', '\x82',
};
HttpData::HttpData(EventLoop* p, int fd,std::string path):
m_tcp_server(new TcpConnection(p,fd)),
m_method(GET),
m_httpversion(HTTP_11),
m_path(path),
m_readpos(0),
m_state(STATE_PARSE_URI),
m_hState(H_START),
m_keepalive(false)
{
m_tcp_server->setCall(std::bind(&HttpData::process,this));
m_tcp_server->setSeperate(std::bind(&HttpData::seperateTimer,this));
}
EventLoop* HttpData::getLoop()
{
return m_tcp_server->getLoop();
}
void HttpData::handleClose()
{
m_tcp_server->handleClose();
}
void HttpData::newEvent()
{
m_tcp_server->set_event(EPOLLIN|EPOLLET|EPOLLONESHOT);
//m_tcp_server->set_event(EPOLLIN|EPOLLET);
m_tcp_server->register_event();
}
shared_ptr<Channel> HttpData::getChannel()
{
return m_tcp_server->getChannel();
}
void HttpData::seperateTimer() {
if (m_timer.lock()) {
shared_ptr<TimerNode> my_timer(m_timer.lock());
my_timer->clearReq();
m_timer.reset();
}
}
void HttpData::reset()
{
m_filename.clear();
m_path.clear();
m_readpos = 0;
m_state = STATE_PARSE_URI;
m_hState = H_START;
m_headers.clear();
m_keepalive = false;
//this->seperateTimer();
}
URIState HttpData::parse_URI()
{
string& str = m_tcp_server->getInbuffer();
// '\r\n' status line
size_t pos = str.find('\r',m_readpos);
if(pos == string::npos)
{
return PARSE_URI_ERROR;
}
string request_line = str.substr(0,pos);//complete request line
if(str.size() > pos+1)
str = str.substr(pos+1);
else
str.clear();
int posget = request_line.find("GET");
int pospost = request_line.find("POST");
int poshead = request_line.find("HEAD");
if(posget >= 0){ //get method
pos = posget;
m_method = GET;
}else if(pospost >= 0 ){
pos = pospost;
m_method = POST;
}else if(poshead >= 0){
pos = poshead;
m_method = HEAD;
}else{
return PARSE_URI_ERROR;
}
pos = request_line.find("/",pos);//get uri
if(pos == string::npos){
m_filename = "index.html";
m_httpversion = HTTP_11;
return PARSE_URI_ERROR;
}else{
size_t _pos = request_line.find(' ',pos);
if(_pos == string::npos){
return PARSE_URI_ERROR;
}else{
if(pos+1 == _pos){
m_filename = "index.html";
}else{
m_filename = request_line.substr(pos+1,_pos-pos-1);
size_t args = m_filename.find('?');
if(args != string::npos){
m_filename = m_filename.substr(0,args);
}
}
}
pos = _pos;
}
pos = request_line.find('/',pos);// get http version
if(pos == string::npos){
return PARSE_URI_ERROR;
}else{
if(request_line.size()-pos < 4){
return PARSE_URI_ERROR;
}else{
string tmp = request_line.substr(pos+1,3);
if(tmp == "1.0")
m_httpversion = HTTP_10;
else if(tmp == "1.1")
m_httpversion = HTTP_11;
else
return PARSE_URI_ERROR;
}
}
return PARSE_URI_SUCCESS;
}
HeaderState HttpData::parse_Headers()
{
string& str = m_tcp_server->getInbuffer();
int keys = -1, keye = -1, vals = -1, vale = -1;
int nowpos_ = 0;
bool notfinsh = true;
size_t i = 0;
for(;i < str.size() && notfinsh; ++i)
{
switch(m_hState)
{
case H_START:{
if(str[i] == '\n' || str[i] == '\r') break;
m_hState = H_KEY;
keys = i;
nowpos_ = i;
break;
}
case H_KEY:{
if(str[i] == ':'){
keye = i;
if(keye <= keys) return PARSE_HEADER_ERROR;
m_hState = H_COLON;
}else if(str[i] == '\n' || str[i] == '\r'){
return PARSE_HEADER_ERROR;
}
break;
}
case H_COLON:{
if (str[i] == ' ') {
m_hState = H_SPACES_AFTER_COLON;
} else
return PARSE_HEADER_ERROR;
break;
}
case H_SPACES_AFTER_COLON: {
m_hState = H_VALUE;
vals = i;
break;
}
case H_VALUE:{
if(str[i] == '\r'){
m_hState = H_CR;
vale = i;
if(vale <= vals) return PARSE_HEADER_ERROR;
}else if(i - vals > 255){
return PARSE_HEADER_ERROR;
}
break;
}
case H_CR:{
if(str[i] == '\n'){
m_hState = H_LF;
string key(str.begin()+keys,str.begin()+keye);
string value(str.begin()+vals,str.begin()+vale);
m_headers[key] = value;
nowpos_ = i;
}else{
return PARSE_HEADER_ERROR;
}
break;
}
case H_LF:{
if(str[i] == '\r'){
m_hState = H_END_CR;
}else{
keys = i;
m_hState = H_KEY;
}
break;
}
case H_END_CR:{
if(str[i] == '\n'){
m_hState = H_END_LF;
}else{
return PARSE_HEADER_ERROR;
}
break;
}
case H_END_LF:{
notfinsh = false;
nowpos_ = i;
break;
}
}//end switch
}//end for
if(m_hState == H_END_LF){
str = str.substr(i);
return PARSE_HEADER_SUCCESS;
}
str = str.substr(nowpos_);
return PARSE_HEADER_AGAIN;
}
AnalysisState HttpData::analysisRequest()
{
record()<<m_filename<<" "<<m_method<<endl;
//string body_buff;
string header;
stringstream buff;
if(m_method == POST){}
else if(m_method == GET || m_method == HEAD)
{
record()<<m_path+"/"+m_filename;
std::ifstream inf(m_path+"/"+m_filename,ios::in|ios::binary);
if(!inf.is_open()){
record()<<"file not exits";
buff<<"file not exit";
string header("HTTP/1.1 404 Not Found\r\n");
header += "Connection: Close\r\n";
header += "Content-Length: " + to_string(buff.str().size()) + "\r\n";
header += "\r\n";
}
else{
char ch;
while(buff&&inf.get(ch)){
buff.put(ch);
}
header+="HTTP/1.1 200 OK\r\n";
//header += "Content-Type: text/html\r\n";
header += "Connection: Close\r\n";
header += "Content-Length: " + to_string(buff.str().size()) + "\r\n";
header += "\r\n";
}
}
record()<<header;
//record()<<body_buff;
m_tcp_server->setOutbuffer(header+buff.str());
return ANALYSIS_SUCCESS;
}
int HttpData::process()
{
if(m_state == STATE_PARSE_URI)
{
URIState flag = parse_URI();
if(flag == PARSE_URI_AGAIN)
return -1;
else if(flag == PARSE_URI_ERROR){
record() <<"process uri error..." ;
m_tcp_server->clearAndError();
return -2;
}else{
m_state = STATE_PARSE_HEADERS;
}
}
if(m_state == STATE_PARSE_HEADERS)
{
HeaderState flag = parse_Headers();
if(flag == PARSE_HEADER_AGAIN){
return -1;
}else if(flag == PARSE_HEADER_ERROR){
record()<<"process header error..." ;
m_tcp_server->clearAndError();
return -2;
}
if(m_method == POST){
m_state = STATE_RECV_BODY;
}else{
m_state = STATE_ANALYSIS;
}
}
string& buf = m_tcp_server->getInbuffer();
if(m_state == STATE_RECV_BODY){
int content_length = -1;
if (m_headers.find("Content-length") != m_headers.end()) {
content_length = stoi(m_headers["Content-length"]);
} else {
record()<< "(m_state == STATE_RECV_BODY)";
m_tcp_server->clearAndError();
return -2;
}
if (static_cast<int>(buf.size()) < content_length) return -2;
m_state = STATE_ANALYSIS;
}
if (m_state == STATE_ANALYSIS) {
AnalysisState flag = analysisRequest();
if (flag == ANALYSIS_SUCCESS) {
m_state = STATE_FINISH;
reset();
return 0;
} else {
record()<< "m_state == STATE_ANALYSIS";
m_tcp_server->clearAndError();
return -2;
}
}
return -2;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/guanzhanyi/web-server.git
git@gitee.com:guanzhanyi/web-server.git
guanzhanyi
web-server
webServer
master

搜索帮助