您的位置:首页 > 汽车 > 时评 > 揭阳网站制作软件_建站之星7大核心价值_网址最全的浏览器_百度竞价代运营外包

揭阳网站制作软件_建站之星7大核心价值_网址最全的浏览器_百度竞价代运营外包

2024/12/28 4:34:09 来源:https://blog.csdn.net/2201_75584283/article/details/143271681  浏览:    关键词:揭阳网站制作软件_建站之星7大核心价值_网址最全的浏览器_百度竞价代运营外包
揭阳网站制作软件_建站之星7大核心价值_网址最全的浏览器_百度竞价代运营外包

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】【Linux网络编程】

目录

1、状态码 

1.1、 HttpServer类(404)

1.1.1、基本结构

1.1.2、构造函数

1.1.3、HandlerHttpRequest()

1.1.4、login.html

1.1.5、404.html

1.2、重定向状态码

1.2.1、测试重定向

2、查看HTTP方法

3、增加表单

3.1、POST方法

3.2、GET方法

3.3、GET vs POST

4、增加服务函数

4.1、HttpServer类

4.2、InsertService()

4.3、IsServiceExists()

4.4、HandlerHttpRequest()

4.4、ServerMain.cc


1、状态码 

最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

状态码含义应用样例
100Continue上传大文件时, 服务器告诉客户端可以继续上传
200OK访问网站首页, 服务器返回网页内容
201Created发布新文章, 服务器返回文章创建成功的信息
204No Content删除文章后, 服务器返回“无内容”表示操作成功
301Moved
Permanently

网站换域名后, 自动跳转到新域名; 搜索引擎更新网站链接时使用

302Found 或 See
Other
用户登录成功后, 重定向到用户首页
304Not Modified浏览器缓存机制, 对未修改的资源返回304 状态码
400Bad Request填写表单时, 格式不正确导致提交失败
401Unauthorized访问需要登录的页面时, 未登录或认证失败
403Forbidden尝试访问你没有权限查看的页面
404Not Found访问不存在的网页链接
500Internal Server
Error
服务器崩溃或数据库错误导致页面无法加载
502Bad Gateway使用代理服务器时, 代理服务器无法从上游服务器获取有效响应
503Service
Unavailable
服务器维护或过载, 暂时无法处理请求

HTTP 的状态码还有对应的描述信息,我们此处也可以使用哈希表存储状态码与描述信息映射关系! 

1.1、 HttpServer类(404)

HttpServer类 增加一个状态码转描述信息的哈希表,并在构造函数插入对象的映射关系内容!

1.1.1、基本结构

HttpServer类 增加一个状态码转描述信息的哈希表成员变量!

class HttpServer
{
private:std::unordered_map<std::string, std::string> _mine_type; // 类型对应表std::unordered_map<int, std::string> _code_to_desc; // 状态转描述表
};

1.1.2、构造函数

构造函数插入对象的映射关系内容!

HttpServer()
{_mine_type.insert(std::make_pair(".html", "text/html"));_mine_type.insert(std::make_pair(".jpg", "image/jpg"));_mine_type.insert(std::make_pair(".png", "image/png"));_mine_type.insert(std::make_pair(".default", "text/html"));_code_to_desc.insert(std::make_pair(100,"Continue"));_code_to_desc.insert(std::make_pair(200,"OK"));_code_to_desc.insert(std::make_pair(201,"Created"));_code_to_desc.insert(std::make_pair(404,"Not Found"));
}

1.1.3、HandlerHttpRequest()

const static std::string html_404 = "404.html";std::string HandlerHttpRequest(std::string &reqstr)
{std::cout << "---------------------------------------------" << std::endl;std::cout << reqstr;std::cout << "---------------------------------------------" << std::endl;HttpRequest req;         // 构建请求对象req.Deserialize(reqstr); // 反序列化字符串// 最基础的上层处理HttpResponse resp;std::string content = GetFileContent(req.Path());if (content.empty()){content = GetFileContent("wwwroot/404.html"); // 在默认错误文件获取内容// resp.AddCode(404, "Not Found");resp.AddCode(404, _code_to_desc[404]); // 内容为空添加404状态码resp.AddHeader("Content-Length", std::to_string(content.size()));resp.AddHeader("Content-Type", _mine_type["./html"]); // 类型默认为./htmlresp.AddBodyText(content);}else{// resp.AddCode(200, "OK");resp.AddCode(200, _code_to_desc[200]);resp.AddHeader("Content-Length", std::to_string(content.size()));resp.AddHeader("Content-Type", _mine_type[req.Suffix()]);resp.AddBodyText(content);}return resp.Serialize();
}

AddCode()

void AddCode(int code, const std::string &desc)
{_status_code = code;_desc = desc;
}

1.1.4、login.html

login.html 文件增加一个测试404页面的链接!

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>登录页面</title>
</head>
<body><h1>登录页面</h1><a href="/content.html">进入内容页面</a><br><a href="/a/b/c.html">测试404</a>
</body>
</html>

1.1.5、404.html

404.html 为404页面内容!

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>(404) The page you were looking for doesn't exist.</title><link rel="stylesheet" type="text/css" href="//cloud.typography.com/746852/739588/css/fonts.css" /><style type="text/css">html,body {margin: 0;padding: 0;height: 100%;}body {font-family: "Whitney SSm A", "Whitney SSm B", "Helvetica Neue", Helvetica, Arial, Sans-Serif;background-color: #2D72D9;color: #fff;-moz-font-smoothing: antialiased;-webkit-font-smoothing: antialiased;}.error-container {text-align: center;height: 100%;}@media (max-width: 480px) {.error-container {position: relative;top: 50%;height: initial;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);}}.error-container h1 {margin: 0;font-size: 130px;font-weight: 300;}@media (min-width: 480px) {.error-container h1 {position: relative;top: 50%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);}}@media (min-width: 768px) {.error-container h1 {font-size: 220px;}}.return {color: rgba(255, 255, 255, 0.6);font-weight: 400;letter-spacing: -0.04em;margin: 0;}@media (min-width: 480px) {.return {position: absolute;width: 100%;bottom: 30px;}}.return a {padding-bottom: 1px;color: #fff;text-decoration: none;border-bottom: 1px solid rgba(255, 255, 255, 0.6);-webkit-transition: border-color 0.1s ease-in;transition: border-color 0.1s ease-in;}.return a:hover {border-bottom-color: #fff;}</style>
</head><body><div class="error-container"><h1>404</h1><p class="return">Take me back to <a href="/">designernews.co</a></p>
</div></body>
</html>

1.2、重定向状态码

以下是仅包含重定向相关状态码的表格:

状态码含义是否为临时重定向应用样例
301Moved
Permanently
否(永久重定向)网站换域名后, 自动跳转到新域名;搜索引擎更新网站
链接时使用
302Found 或 See
Other
是(临时重定向)用户登录成功后,重定向到用户首页
307Temporary
Redirect
是(临时重定向)临时重定向资源到新的位置(较少使用)
308Permanent
Redirect
否(永久重定向)永久重定向资源到新的位置(较少使用)

关于重定向的验证,以 301 为代表
HTTP 状态码 301(永久重定向)和 302(临时重定向)都依赖 Location 选项。以下是关于两者依赖 Location 选项的详细说明:
HTTP 状态码 301(永久重定向):

  • 当服务器返回 HTTP 301 状态码时,表示请求的资源已经被永久移动到新的位置
  • 在这种情况下,服务器会在响应中添加一个 Location 头部,用于指定资源的新位置。这个 Location 头部包含了新的 URL 地址,浏览器会自动重定向到该地址。
  • 例如,在 HTTP 响应中,可能会看到类似于以下的头部信息:
HTTP/1.1 301 Moved Permanently\r\n
Location: https://www.new-url.com\r\n

HTTP 状态码 302(临时重定向):

  • 当服务器返回 HTTP 302 状态码时,表示请求的资源临时被移动到新的位置
  • 同样地,服务器也会在响应中添加一个 Location 头部来指定资源的新位置。浏览器会暂时使用新的 URL 进行后续的请求,但不会缓存这个重定向。
  • 例如,在 HTTP 响应中,可能会看到类似于以下的头部信息:
HTTP/1.1 302 Found\r\n
Location: https://www.new-url.com\r\n

总结:无论是 HTTP 301 还是 HTTP 302 重定向,都需要依赖 Location 选项来指定资源的新位置。这个 Location 选项是一个标准的 HTTP 响应头部,用于告诉浏览器应该将请求重定向到哪个新的 URL 地址

1.2.1、测试重定向

在登录页面增加测试重定向的代码!

login.html 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>登录页面</title>
</head>
<body><h1>登录页面</h1><a href="/content.html">进入内容页面</a><br><a href="/a/b/c.html">测试404</a><br><a href="/redir">测试重定向</a><br></body>
</html>

优化:当我们点击测试重定向的时候,直接进入https://www.qq.com! 

构造函数需要插入状态码与状态描述

HttpServer()
{_mine_type.insert(std::make_pair(".html", "text/html"));_mine_type.insert(std::make_pair(".jpg", "image/jpg"));_mine_type.insert(std::make_pair(".png", "image/png"));_mine_type.insert(std::make_pair(".default", "text/html"));_code_to_desc.insert(std::make_pair(100, "Continue"));_code_to_desc.insert(std::make_pair(200, "OK"));_code_to_desc.insert(std::make_pair(201, "Created"));_code_to_desc.insert(std::make_pair(301, "Moved Permanently"));_code_to_desc.insert(std::make_pair(302, "Found"));_code_to_desc.insert(std::make_pair(404, "Not Found"));
}

HandlerHttpRequest()

std::string HandlerHttpRequest(std::string &reqstr)
{HttpRequest req; // 构建请求对象HttpResponse resp;req.Deserialize(reqstr); // 反序列化字符串if (req.Path() == "wwwroot/redir"){// 重定向处理std::string redir_path = "https://www.qq.com"; // 以什么协议去访问resp.AddCode(302, _code_to_desc[302]);resp.AddHeader("Location", redir_path);}else{// 处理静态资源std::string content = GetFileContent(req.Path());if (content.empty()){content = GetFileContent("wwwroot/404.html"); // 在默认错误文件获取内容resp.AddCode(404, _code_to_desc[404]); // 内容为空添加404状态码resp.AddHeader("Content-Length", std::to_string(content.size()));resp.AddHeader("Content-Type", _mine_type["./html"]); // 类型默认为./htmlresp.AddBodyText(content);}else{// resp.AddCode(200, "OK");resp.AddCode(200, _code_to_desc[200]);resp.AddHeader("Content-Length", std::to_string(content.size()));resp.AddHeader("Content-Type", _mine_type[req.Suffix()]);resp.AddBodyText(content);}}return resp.Serialize();
}

2、查看HTTP方法

 在Request类增加获取方法的成员函数即可!

std::string Method()
{LOG(DEBUG, "Client request method is %s\n", _method.c_str());return _method;
}

调用方法:

req.Method();

 

注意:此处可以使用Postman软件! 

3、增加表单

在登录页面我们可以增加表单

3.1、POST方法

POST方法增加表单,参数内容是存放在正文(参数以问号分割),因此我们需要继续解析请求行!

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>登录页面</title>
</head><body><h1>登录页面</h1><a href="/content.html">进入内容页面</a><br><a href="/a/b/c.html">测试404</a><br><a href="/redir">测试重定向</a><br><div><form action="/login" method="post">用户名: <input type="text" name="username" value="."><br>密码: <input type="password" name="userpasswd" value=""><br><input type="submit" value="提交"></form></div></body></html>

解析请求行

const static std::string arg_sep = "?";// 解析请求行
void ParseReqLine()
{std::stringstream ss(_req_line); // 以空格为分隔符 cin >>// /a/b/c.html or /login?user=xxx&passwd=1234 /registerss >> _method >> _url >> _version; // 以空格为分隔符依次将请求行的内容赋值给成员变量// 以GET方式请求资源,则将参数内容存放到正文if (strcasecmp(_method.c_str(), "GET") == 0){auto pos = _url.find(arg_sep);if (pos != std::string::npos){_body_text = _url.substr(pos + arg_sep.size());_url.resize(pos); // url 只取参数前的内容}}_path += _url;// 只有web根目录返回index.htmlif (_path[_path.size() - 1] == '/'){_path += homepage;}// wwwroot/index.html// wwwroot/image/1.pngauto pos = _path.rfind(suffixsep);if (pos != std::string::npos){_suffix = _path.substr(pos);}else{_suffix = ".default";}
}

3.2、GET方法

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>登录页面</title>
</head><body><h1>登录页面</h1><a href="/content.html">进入内容页面</a><br><a href="/a/b/c.html">测试404</a><br><a href="/redir">测试重定向</a><br><div><form action="/login" method="get">用户名: <input type="text" name="username" value="."><br>密码: <input type="password" name="userpasswd" value=""><br><input type="submit" value="提交"></form></div></body></html>

3.3、GET vs POST

1、GET一般用来获取静态资源,也可以通过url向服务器传递参数

2、POST 可以通过http request的正文来进行参数传递

3、url 传递参数,参数的体量一定不大,正文可以很大

4、POST方法比GET方法传参更加私密,但是都不安全!对http的参数进行加密 -> https协议!

4、增加服务函数

前面获取的都是静态资源,我们也可以通过函数获取其他资源,此处就用到回调函数!

4.1、HttpServer类

要执行回调函数,需要在HttpServer类增加一个服务列表,用于存储需要执行的服务,在HandlerHttpRequest()函数中处理服务,此处只测试一个服务!

// 回调函数声明
using func_t = std::function<HttpResponse(HttpRequest&)>;class HttpServer
{
private:std::unordered_map<std::string, std::string> _mine_type; // 类型对应表std::unordered_map<int, std::string> _code_to_desc;      // 状态转描述表std::unordered_map<std::string, func_t> _service_list;   // 服务列表
};

4.2、InsertService()

InsertService() 函数插入需要执行的方法!

void InsertService(const std::string &servicename, func_t f)
{std::string s = prefixpath + servicename;_service_list[s] = f;
}

4.3、IsServiceExists()

IsServiceExists() 判断服务列表中是否存在服务,存在才需要处理!

bool IsServiceExists(const std::string servicename)
{auto iter = _service_list.find(servicename);if(iter == _service_list.end()) return false;else return true;
}

4.4、HandlerHttpRequest()

HandlerHttpRequest()函数处理请求,讨论三种情况,重定向情况,调用服务情况以及处理静态资源情况

std::string HandlerHttpRequest(std::string &reqstr)
{std::cout << "---------------------------------------------" << std::endl;std::cout << reqstr;std::cout << "---------------------------------------------" << std::endl;HttpRequest req; // 构建请求对象HttpResponse resp;req.Deserialize(reqstr); // 反序列化字符串if (req.Path() == "wwwroot/redir"){// 重定向处理std::string redir_path = "https://www.qq.com"; // 以什么协议去访问resp.AddCode(302, _code_to_desc[302]);resp.AddHeader("Location", redir_path);}// 最后服务新增,有参数需要请求服务else if(!req.GetRequestBody().empty()){if(IsServiceExists(req.Path())){resp = _service_list[req.Path()](req);}}else{// 处理静态资源std::string content = GetFileContent(req.Path());if (content.empty()){content = GetFileContent("wwwroot/404.html"); // 在默认错误文件获取内容// resp.AddCode(404, "Not Found");resp.AddCode(404, _code_to_desc[404]); // 内容为空添加404状态码resp.AddHeader("Content-Length", std::to_string(content.size()));resp.AddHeader("Content-Type", _mine_type["./html"]); // 类型默认为./htmlresp.AddBodyText(content);}else{// resp.AddCode(200, "OK");resp.AddCode(200, _code_to_desc[200]);resp.AddHeader("Content-Length", std::to_string(content.size()));resp.AddHeader("Content-Type", _mine_type[req.Suffix()]);resp.AddBodyText(content);}}return resp.Serialize();
}

4.4、ServerMain.cc

ServerMain.cc文件实现服务端主函数!

#include "TcpServer.hpp" // 会话层
#include "Http.hpp"HttpResponse Login(HttpRequest &req)
{HttpResponse resp;std::cout << "外部已经拿到了参数了: " << std::endl;req.GetRequestBody();std::cout << "####################" << std::endl;resp.AddCode(200,"OK");resp.AddBodyText("<html><h1>result done</h1></html>");// username=hahahahah&userpasswd=123456// 1.pipe// 2.dup2// 3.fork()// 4.exec* -> Python,PHP,Java!业务处理return resp;
}
// ./httpserver 8888
int main(int argc, char *argv[])
{if (argc != 2){std::cerr << "Usage: " << argv[0] << "local-port" << std::endl;exit(0);}uint16_t port = std::stoi(argv[1]);HttpServer hserver;hserver.InsertService("/login",Login);// hserver.InsertService("/register",Register);// hserver.InsertService("/Search",Search);std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(std::bind(&HttpServer::HandlerHttpRequest, &hserver, std::placeholders::_1),port);tsvr->Loop();return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com