Ai
1 Star 0 Fork 0

Aurora/Linux

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
HttpProtocol.hpp 7.97 KB
一键复制 编辑 原始数据 按行查看 历史
Aurora 提交于 2025-07-12 00:38 +08:00 . http version4
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <unordered_map>
#include "Common.hpp"
#include "Log.hpp"
const std::string Sep = "\r\n";
const std::string LineSep = " ";
const std::string HeaderLineSep = ": ";
const std::string BlankLine = Sep;
const std::string defaulthomepage = "wwwroot";
const std::string http_version = "HTTP/1.0";
const std::string page404 = "wwwroot/404.html";
const std::string firstpage = "index.html";
using namespace LogModule;
// B/S模式 S客户端就是浏览器
class HttpRequest
{
public:
HttpRequest() {}
~HttpRequest() {}
// GET / HTTP/1.1
// Host: 112.126.76.148:8080
// Connection: keep-alive
// Cache-Control: max-age=0
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
// Accept-Encoding: gzip, deflate
// Accept-Language: zh-CN,zh;q=0.9
bool ParseHeaderkv()
{
std::string key, value;
for (auto &header : _req_header)
{
// Connection: keep-alive
if (SplitString(header, HeaderLineSep, &key, &value))
{
_headerkv.insert(std::make_pair(key, value));
}
}
return true;
}
bool ParseHeader(std::string &request_str)
{
std::string line;
while (true)
{
bool r = ParseOneLine(request_str, &line, Sep);
if (r && !line.empty())
{
_req_header.push_back(line);
}
else if (r && line.empty())
{
_blank_line = Sep;
break;
}
else
{
return false;
}
}
ParseHeaderkv();
return true;
}
void Deserialize(std::string &request_str)
{
if (ParseOneLine(request_str, &_req_line, Sep))
{
// 提取请求行中的详细字段
ParseReqLine(_req_line, LineSep);
ParseHeader(request_str);
_body = request_str;
}
}
std::string GetContent()
{
std::string content;
std::ifstream in(_uri, std::ios::binary);
if (!in.is_open())
return std::string();
in.seekg(0, in.end);
int filesize = in.tellg();
in.seekg(0, in.beg);
content.resize(filesize);
in.read((char *)content.c_str(), filesize);
in.close();
return content;
// 暂时做法
// std::string content;
// std::ifstream in(_uri);
// if(!in.is_open()) return std::string();
// std::string line;
// while(std::getline(in,line))
// {
// content += line;
// }
// in.close();
// return content;
}
void Print()
{
std::cout << "_method: " << _method << std::endl;
std::cout << "_uri: " << _uri << std::endl;
std::cout << "_version: " << _version << std::endl;
// for(auto &line : _req_header)
// {
// std::cout << line << "\n" << std::endl;
// }
for (auto &kv : _headerkv)
{
std::cout << kv.first << "#" << kv.second << std::endl;
}
std::cout << "_blank_line: " << _blank_line << std::endl;
std::cout << "_body: " << _body << std::endl;
}
std::string Uri()
{
return _uri;
}
void SetUri(const std::string newuri)
{
_uri = newuri;
}
std::string Suffix()
{
auto pos = _uri.rfind(".");
if (pos == std::string::npos)
return std::string(".html");
else
return _uri.substr(pos);
}
private:
void ParseReqLine(std::string &_req_line, const std::string sep)
{
(void)sep;
std::stringstream ss(_req_line);
ss >> _method >> _uri >> _version;
_uri = defaulthomepage + _uri;
}
private:
std::string _req_line;
std::vector<std::string> _req_header;
std::string _blank_line;
std::string _body;
// 在反序列化的过程中,细化我们解析出来的字段
std::string _method;
std::string _uri; // 用户想要这个
std::string _version;
std::unordered_map<std::string, std::string> _headerkv;
};
class HttpResponse
{
public:
HttpResponse() : _version(http_version), _blank_line(Sep)
{
}
~HttpResponse()
{
}
void Build(HttpRequest &req)
{
// #define TestRedir 1
// #ifdef TestRedir
// std::string uri = req.Uri(); // wwwroot/ wwwroot/a/b/
// if (uri.back() == '/')
// {
// _status_code = 301;
// _status_desc = Code2Desc(_status_code); // 和状态码是强相关的
// // SetHeader("Location","https://www.qq.com/");
// SetHeader("Location", "http://112.126.76.148:8080/register.html");
// for (auto &header : _header_kv)
// {
// _resp_header.push_back(header.first + HeaderLineSep + header.second);
// }
// LOG(LogLevel::DEBUG) << ".........客户端在请求: " << req.Uri();
// return;
// }
// #else
std::string uri = req.Uri(); // wwwroot/ wwwroot/a/b/
if (uri.back() == '/')
{
uri += firstpage; // wwwroot/index.html
req.SetUri(uri);
}
LOG(LogLevel::DEBUG) << "......客户端在请求: " << req.Uri();
req.Print();
LOG(LogLevel::DEBUG) << "......................";
_content = req.GetContent();
if (_content.empty())
{
// 用户请求的资源并不存在
_status_code = 404;
req.SetUri(page404);
_content = req.GetContent();
}
else
{
_status_code = 200;
}
_status_desc = Code2Desc(_status_code); // 和状态码是强相关的
if (!_content.empty())
{
SetHeader("Content-Length", std::to_string(_content.size()));
}
// LOG(LogLevel::DEBUG) << "客户端在请求: " << req.Uri();
std::string mini_type = Suffix2Desc(req.Suffix());
SetHeader("Content-Type", mini_type);
for (auto &header : _header_kv)
{
_resp_header.push_back(header.first + HeaderLineSep + header.second);
}
// #endif
}
void Seserialize(std::string *resp_str)
{
_resp_line = _version + LineSep + std::to_string(_status_code) + LineSep + _status_desc + Sep;
_body = _content;
// 序列化
*resp_str = _resp_line;
for (auto &line : _resp_header)
{
*resp_str += (line + Sep);
}
*resp_str += _blank_line;
*resp_str += _body;
}
void SetHeader(const std::string &k, const std::string &v)
{
_header_kv[k] = v;
}
private:
std::string Code2Desc(int code)
{
switch (code)
{
case 200:
return "OK";
case 404:
return "Not Found";
case 301:
return "Moved Permanently";
case 302:
return "Found";
default:
return std::string();
}
}
std::string Suffix2Desc(const std::string &suffix)
{
if (suffix == ".html")
return "text/html";
else if (suffix == ".jpg")
return "application/x-jpg";
else
return "text/html";
}
private:
// 必备的要素
std::string _version;
int _status_code;
std::string _status_desc;
std::string _content;
std::unordered_map<std::string, std::string> _header_kv;
// 最终要这四部分,,构建应答
std::string _resp_line;
std::vector<std::string> _resp_header;
std::string _blank_line;
std::string _body;
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/Axurea/linux.git
git@gitee.com:Axurea/linux.git
Axurea
linux
Linux
master

搜索帮助