目录HTTP 协议认识 URLurlencode 和 urldecodeHTTP 协议请求与响应格式HTTP 请求编写 HTTP 请求的代码 - 验证 http 请求HTTP 的方法HTTP 常见方法1. GET 方法重点2. POST 方法重点3. PUT 方法不常用4. HEAD 方法5. DELETE 方法不常用6. OPTIONS 方法HTTP 的状态码表格一常见 HTTP 状态码100503表格二重定向相关状态码301、302、307、308HTTP 常见 Header关于 connection 报头HTTP 常见 Header最简单的 HTTP 服务器HTTP 历史及版本核心技术与时代背景HTTP/0.9HTTP/1.0HTTP/1.1HTTP/2.0HTTP/3.0HTTP 协议虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现 成的, 又非常好用的应用层协议, 供我们直接参考使用.HTTP(超文本传输协议)就是其 中之一。在互联网世界中HTTPHyperText Transfer Protocol超文本传输协议是一个至 关重要的协议。它定义了客户端如浏览器与服务器之间如何通信以交换或传输 超文本如 HTML 文档。HTTP 协议是客户端与服务器之间通信的基础。客户端通过 HTTP 协议向服务器发送 请求服务器收到请求后处理并返回响应。HTTP 协议是一个无连接、无状态的协 议即每次请求都需要建立新的连接且服务器不会保存客户端的状态信息。认识 URL平时我们俗称的 网址 其实就是说的 URLurlencode 和 urldecode像 / ? : 等这样的字符, 已经被 url 当做特殊意义理解了. 因此这些字符不能随意出现. 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.转义的规则如下:将需要转码的字符转为 16 进制然后从右到左取 4 位(不足 4 位直接处理)每 2 位 做一位前面加上%编码成%XY 格式例如 被转义成了 %2Burldecode 就是 urlencode 的逆过程UrlEncode编码/UrlDecode解码 - 站长工具HTTP 协议请求与响应格式HTTP 请求• 首行: [方法] [url] [版本]•Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\r\n 分隔; 遇到空行表示 Header 部分结束• Body: 空行后面的内容都是 Body. Body 允许为空字符串. 如果 Body 存在, 则在Header 中会有一个 Content-Length 属性来标识 Body 的长度;编写 HTTP 请求的代码 - 验证 http 请求需要现场基于历史代码先架构处一个基本的 HTTP 服务器然后用浏览器进行验 证HTTP 响应• 首行: [版本号] [状态码] [状态码解释]• Header:请求的属性, 冒号分割的键值对;每组属性之间使用\r\n 分隔;遇到空行表示 Header 部分结束• Body: 空行后面的内容都是 Body. Body 允许为空字符串. 如果 Body 存在, 则在 Header 中会有一个 Content-Length 属性来标识 Body 的长度; 如果服务器返回了一 个 html 页面, 那么 html 页面内容就是在 body 中.基本的应答格式HTTP 的方法方法说明支持的HTTP协议版本GET获取资源1.0、1.1POST传输实体主体1.0、1.1PUT传输文件1.0、1.1HEAD获得报文首部1.0、1.1DELETE删除文件1.0、1.1OPTIONS询问支持的方法1.1TRACE追踪路径1.1CONNECT要求用隧道协议连接代理1.1LINK建立和资源之间的联系1.0UNLINE断开连接关系1.0最常用的就是 GET 方法和 POST 方法.HTTP 常见方法1. GET 方法重点用途用于请求 URL 指定的资源。示例GET /index.html HTTP/1.1特性指定资源经服务器端解析后返回响应内容。form 表单https://www.runoob.com/html/html-forms.html//要通过历史写的 http 服务器验证 GET 方法,这里需要了解一下 FORM 表单的 //问题 //这里就要引入 web 根目录文件读取的基本操作了 #include fstream #include string #include vector std::string GetFileContentHelper(const std::string path) { std::ifstream in(path, std::ios::binary); if (!in.is_open()) return ; in.seekg(0, std::ios::end); size_t filesize in.tellg(); in.seekg(0, std::ios::beg); std::string content; content.resize(filesize); // 正确写法使用 content[0] 或 content.data() (C17) in.read(content[0], filesize); in.close(); return content; }2. POST 方法重点用途用于传输实体的主体通常用于提交表单数据。示例POST /submit.cgi HTTP/1.1特性可以发送大量的数据给服务器并且数据包含在请求体中。form 表单https://www.runoob.com/html/html-forms.html要通过历史写的 http 服务器验证 POST 方法,这里需要了解一下 FORM 表单 的问题3. PUT 方法不常用用途用于传输文件将请求报文主体中的文件保存到请求 URL 指定的位置。示例PUT /example.html HTTP/1.1特性不太常用但在某些情况下如 RESTful API 中用于更新资源。4. HEAD 方法用途与 GET 方法类似但不返回报文主体部分仅返回响应头。示例HEAD /index.html HTTP/1.1特性用于确认 URL 的有效性及资源更新的日期时间等// curl -i 显示 $ curl -i www.baidu.com HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: private, no-cache, no-store, proxy-revalidate, notransform Connection: keep-alive Content-Length: 2381 Content-Type: text/html Date: Sun, 16 Jun 2024 08:38:04 GMT Etag: 588604dc-94d Last-Modified: Mon, 23 Jan 2017 13:27:56 GMT Pragma: no-cache Server: bfe/1.0.8.18 Set-Cookie: BDORZ27315; max-age86400; domain.baidu.com; path/ !DOCTYPE html ... // 使用 head 方法只会返回响应头 $ curl --head www.baidu.com HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: private, no-cache, no-store, proxy-revalidate, notransform Connection: keep-alive Content-Length: 277 Content-Type: text/html Date: Sun, 16 Jun 2024 08:43:38 GMT Etag: 575e1f71-115 Last-Modified: Mon, 13 Jun 2016 02:50:25 GMT Pragma: no-cache Server: bfe/1.0.8.185. DELETE 方法不常用用途用于删除文件是 PUT 的相反方法。示例DELETE /example.html HTTP/1.1特性按请求 URL 删除指定的资源。6. OPTIONS 方法用途用于查询针对请求 URL 指定的资源支持的方法。示例OPTIONS * HTTP/1.1特性返回允许的方法如 GET、POST不支持的效果// 搭建一个 nginx 用来测试 // sudo apt install nginx // sudo nginx -- 开启 // ps ajx | grep nginx -- 查看 // sudo nginx -s stop -- 停止服务 $ sudo nginx -s stop $ ps ajx | grep nginx 2944845 2945390 2945389 2944845 pts/1 2945389 S 1002 0:00 grep --colorauto nginx $ sudo nginx $ ps axj | grep nginx 1 2945393 2945393 2945393 ? -1 Ss 0 0:00 nginx: master process nginx 2945393 2945394 2945393 2945393 ? -1 S 33 0:00 nginx: worker process 2945393 2945395 2945393 2945393 ? -1 S 33 0:00 nginx: worker process 2944845 2945397 2945396 2944845 pts/1 2945396 S 1002 0:00 grep --colorauto nginx // -X(大 x) 指明方法 $ curl -X OPTIONS -i http://127.0.0.1/ HTTP/1.1 405 Not Allowed Server: nginx/1.18.0 (Ubuntu) Date: Sun, 16 Jun 2024 08:48:22 GMT Content-Type: text/html Content-Length: 166 Connection: keep-alive html headtitle405 Not Allowed/title/head body centerh1405 Not Allowed/h1/center hrcenternginx/1.18.0 (Ubuntu)/center /body /html支持的效果HTTP/1.1 200 OK Allow: GET, HEAD, POST, OPTIONS Content-Type: text/plain Content-Length: 0 Server: nginx/1.18.0 (Ubuntu) Date: Sun, 16 Jun 2024 09:04:44 GMT Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization // 注意这里没有响应体因为 Content-Length 为 0HTTP 的状态码类别原因短语说明1XXInformational信息性状态码接收的请求正在处理2XXSuccess成功状态码请求正常处理完毕3XXRedirection重定向状态码需要进行附加操作以完成请求4XXClient Error客户端错误状态码服务器无法处理请求5XXServer Error服务器错误状态码服务器处理请求出错最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定 向), 504(Bad Gateway)表格一常见 HTTP 状态码100503状态码含义应用样例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服务器维护或过载暂时无法处理请求表格二重定向相关状态码301、302、307、308状态码含义是否为临时重定向应用样例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\nHTTP 状态码 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 地址HTTP 常见 Header• Content-Type: 数据类型(text/html 等)。告诉客户端浏览器、App 等响应体或请求体的数据格式如text/html、application/json、image/png、application/x-www-form-urlencoded等。• Content-Length: 表示 body 部分的字节长度注意不是字符长度。• Host: 客户端告知服务器请求的资源在哪台主机域名的哪个端口上HTTP/1.1 强制要求携带Host头否则服务器返回 400。用途一台服务器IP上托管多个域名虚拟主机例如www.a.com和www.b.com部署在同一台服务器上服务器通过Host决定访问哪个网站。格式Host: host:port端口默认 80http或 443https时可省略。高频考点“为什么 HTTP/1.1 要求必须有Host头”虚拟主机技术“反向代理Nginx如何利用Host进行转发”也常与“HTTP 1.0 vs 1.1 的区别”一起考。• User-Agent: 声明用户的操作系统、浏览器名称/版本、渲染引擎等信息。• referer: 表示当前页面是从哪个 URL 跳转过来的即来源页面。“防盗链是如何实现的”基于Referer判断“Referer可能被篡改吗”可以客户端可随意修改所以不用于严谨的身份验证。“什么是空 Referer 场景”直接输入地址、书签访问、HTTPS 跳转到 HTTP 时一般不发。• Location: 配合 3xx 状态码301/302/307/308使用告诉客户端新的资源地址301 永久重定向后续请求应直接访问新地址浏览器会缓存重定向。302 临时重定向每次仍先请求原地址。响应头示例Location: https://www.new-site.com/page在登录后跳转、URL 规范化如强制 HTTPS中很常见。“301 和 302 的区别对 SEO 有什么影响”301 权重转移302 不转移“重定向过程中请求方法会变化吗”301/302 典型会将 POST 转成 GET但 307/308 会保持原方法。也常结合状态码考察。• Cookie: 在客户端存储少量信息通常 4KB用于维持会话session、用户追踪、个性化设置等服务器通过Set-Cookie响应头设置 Cookie客户端后续请求自动携带Cookie头回传。Cookie 属性Domain、Path、Expires/Max-Age、Secure仅 HTTPS、HttpOnly禁止 JS 访问防 XSS、SameSite防 CSRF。会话 Cookie不设置过期时间在浏览器关闭后失效持久 Cookie 保存在磁盘中。安全风险XSS 可读取非 HttpOnly 的 CookieCSRF 可冒用已认证用户的 Cookie。面试极高频率“Cookie、Session、Token 的区别”“如何保证 Cookie 安全”HttpOnly、Secure、SameSite“Cookie 的跨域问题”默认同站可通过 Domain 设置二级域名共享但无法跨完全不同的域名。“Set-Cookie与Cookie头的关系”关于 connection 报头HTTP 中的 Connection 字段是 HTTP 报文头的一部分它主要用于控制和管理客户 端与服务器之间的连接状态核心作用• 管理持久连接Connection 字段还用于管理持久连接也称为长连接。持久 连接允许客户端和服务器在请求/响应完成后不立即关闭 TCP 连接以便在同一个连接 上发送多个请求和接收多个响应。持久连接长连接• HTTP/1.1在 HTTP/1.1 协议中默认使用持久连接。当客户端和服务器都不明 确指定关闭连接时连接将保持打开状态以便后续的请求和响应可以复用同一个连 接。• HTTP/1.0在 HTTP/1.0 协议中默认连接是非持久的。如果希望在 HTTP/1.0 上实现持久连接需要在请求头中显式设置 Connection: keep-alive。语法格式• Connection: keep-alive表示希望保持连接以复用 TCP 连接。• Connection: close表示请求/响应完成后应该关闭 TCP 连接。下面附上一张关于 HTTP 常见 header 的表格HTTP 常见 Header字段名含义样例Accept客户端可接受的响应内容类型Accept: text/html, application/xhtmlxml, application/xml; q0.9, image/webp, */*; q0.8Accept-Encoding客户端支持的数据压缩格式Accept-Encoding: gzip, deflate, brAccept-Language客户端可接受的语言类型Accept-Language: zh-CN, zh; q0.9, en; q0.8Host请求的主机名和端口号Host: www.example.com:8080User-Agent客户端的软件环境信息操作系统、浏览器等User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ... Chrome/91.0Cookie客户端发送给服务器的 HTTP Cookie 信息Cookie: session_idabcdefg12345; user_id123Referer请求的来源 URL当前页面从哪个 URL 跳转而来Referer: http://www.example.com/previous_page.htmlContent-Type实体主体的媒体类型Content-Type: application/x-www-form-urlencoded表单提交或application/jsonJSON 数据Content-Length实体主体的字节大小Content-Length: 150Authorization认证信息如用户名和密码常用于 Basic 认证Authorization: Basic QWxhZGRpbjpvcGVuIENlc2FtZQBase64 编码后的用户名:密码Cache-Control缓存控制指令请求和响应均可使用请求时Cache-Control: no-cache或max-age3600响应时Cache-Control: public, max-age3600Connection请求完成后是否关闭连接Connection: keep-alive或Connection: closeDate请求或响应的日期和时间GMT 格式Date: Wed, 21 Oct 2023 07:28:00 GMTLocation重定向的目标 URL通常与 3xx 状态码配合Location: http://www.example.com/new_location.html配合 302Server服务器软件信息Server: Apache/2.4.41 (Unix)Last-Modified资源的最后修改时间用于缓存对比Last-Modified: Wed, 21 Oct 2023 07:20:00 GMTETag资源的唯一标识符用于强缓存验证ETag: 3f80f-1b6-5f4e2512a4100Expires响应过期的日期和时间HTTP/1.0 缓存机制Expires: Wed, 21 Oct 2023 08:28:00 GMT最简单的 HTTP 服务器实现一个最简单的 HTTP 服务器, 只在网页上输出 hello world; 只要我们按照 HTTP 协议的要求构造数据, 就很容易能做到#include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include stdio.h #include string.h #include stdlib.h void Usage() { printf(usage: ./server [ip] [port]\n); } int main(int argc, char* argv[]) { if (argc ! 3) { Usage(); return 1; } int fd socket(AF_INET, SOCK_STREAM, 0); if (fd 0) { perror(socket); return 1; } struct sockaddr_in addr; addr.sin_family AF_INET; addr.sin_addr.s_addr inet_addr(argv[1]); addr.sin_port htons(atoi(argv[2])); int ret bind(fd, (struct sockaddr*)addr, sizeof(addr)); if (ret 0) { perror(bind); return 1; } ret listen(fd, 10); if (ret 0) { perror(listen); return 1; } for (;;) { struct sockaddr_in client_addr; socklen_t len; int client_fd accept(fd, (struct sockaddr*)client_addr, len); if (client_fd 0) { perror(accept); continue; } char input_buf[1024 * 10] {0}; // 用一个足够大的缓冲区直接把数据读完。 ssize_t read_size read(client_fd, input_buf, sizeof(input_buf) - 1); if (read_size 0) { return 1; } printf([Request] %s, input_buf); char buf[1024] {0}; const char* hello h1hello world/h1; sprintf(buf, HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s, strlen(hello), hello); write(client_fd, buf, strlen(buf)); } return 0; }编译, 启动服务. 在浏览器中输入 http://[ip]:[port], 就能看到显示的结果 Hello World此处我们使用 9090 端口号启动了 HTTP 服务器. 虽然 HTTP 服务器一般使用 80 端 口, 但这只是一个通用的习惯. 并不是说 HTTP 服务器就不能使用其他的端口号. 使用 chrome 测试我们的服务器时, 可以看到服务器打出的请求中还有一个 GET /favicon.ico HTTP/1.1 这样的请求. 同学们自行查找资料, 去理解 favicon.ico 的作用.实验 把返回的状态码改成 404, 403, 504 等, 看浏览器上分别会出现什么样的效果.HTTP 历史及版本核心技术与时代背景HTTPHypertext Transfer Protocol超文本传输协议作为互联网中浏览器和服务 器间通信的基石经历了从简单到复杂、从单一到多样的发展过程。以下将按照时间 顺序介绍 HTTP 的主要版本、核心技术及其对应的时代背景。HTTP/0.9• 仅支持 GET 请求方法。• 仅支持纯文本传输主要是 HTML 格式。• 无请求和响应头信息。时代背景• 1991 年HTTP/0.9 版本作为 HTTP 协议的最初版本用于传输基本的超文本 HTML 内容。• 当时的互联网还处于起步阶段网页内容相对简单主要以文本为主。HTTP/1.0• 引入 POST 和 HEAD 请求方法。• 请求和响应头信息支持多种数据格式MIME。• 支持缓存cache。• 状态码status code、多字符集支持等。时代背景• 1996 年随着互联网的快速发展网页内容逐渐丰富HTTP/1.0 版本应运而 生。• 为了满足日益增长的网络应用需求HTTP/1.0 增加了更多的功能和灵活性。• 然而HTTP/1.0 的工作方式是每次 TCP 连接只能发送一个请求性能上存在一定局限HTTP/1.1• 引入持久连接persistent connection支持管道化pipelining。• 允许在单个 TCP 连接上进行多个请求和响应提高了性能。• 引入分块传输编码chunked transfer encoding。• 支持 Host 头允许在一个 IP 地址上部署多个 Web 站点。时代背景• 1999 年随着网页加载的外部资源越来越多HTTP/1.0 的性能问题愈发突出。• HTTP/1.1 通过引入持久连接和管道化等技术有效提高了数据传输效率。• 同时互联网应用开始呈现出多元化、复杂化的趋势HTTP/1.1 的出现满足了 这些需求。HTTP/2.0• 多路复用multiplexing一个 TCP 连接允许多个 HTTP 请求。• 二进制帧格式binary framing优化数据传输。• 头部压缩header compression减少传输开销。• 服务器推送server push提前发送资源到客户端。时代背景• 2015 年随着移动互联网的兴起和云计算技术的发展网络应用对性能的要求越 来越高。• HTTP/2.0 通过多路复用、二进制帧格式等技术显著提高了数据传输效率和网 络性能。• 同时HTTP/2.0 还支持加密传输HTTPS提高了数据传输的安全性。HTTP/3.0• 使用 QUIC 协议替代 TCP 协议基于 UDP 构建的多路复用传输协议。• 减少了 TCP 三次握手及 TLS 握手时间提高了连接建立速度• 解决了 TCP 中的线头阻塞问题提高了数据传输效率。时代背景• 2022 年随着 5G、物联网等技术的快速发展网络应用对实时性、可靠性的要 求越来越高。• HTTP/3.0 通过使用 QUIC 协议提高了连接建立速度和数据传输效率满足了这 些需求。• 同时HTTP/3.0 还支持加密传输HTTPS保证了数据传输的安全性
五、应用层协议HTTP
目录HTTP 协议认识 URLurlencode 和 urldecodeHTTP 协议请求与响应格式HTTP 请求编写 HTTP 请求的代码 - 验证 http 请求HTTP 的方法HTTP 常见方法1. GET 方法重点2. POST 方法重点3. PUT 方法不常用4. HEAD 方法5. DELETE 方法不常用6. OPTIONS 方法HTTP 的状态码表格一常见 HTTP 状态码100503表格二重定向相关状态码301、302、307、308HTTP 常见 Header关于 connection 报头HTTP 常见 Header最简单的 HTTP 服务器HTTP 历史及版本核心技术与时代背景HTTP/0.9HTTP/1.0HTTP/1.1HTTP/2.0HTTP/3.0HTTP 协议虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现 成的, 又非常好用的应用层协议, 供我们直接参考使用.HTTP(超文本传输协议)就是其 中之一。在互联网世界中HTTPHyperText Transfer Protocol超文本传输协议是一个至 关重要的协议。它定义了客户端如浏览器与服务器之间如何通信以交换或传输 超文本如 HTML 文档。HTTP 协议是客户端与服务器之间通信的基础。客户端通过 HTTP 协议向服务器发送 请求服务器收到请求后处理并返回响应。HTTP 协议是一个无连接、无状态的协 议即每次请求都需要建立新的连接且服务器不会保存客户端的状态信息。认识 URL平时我们俗称的 网址 其实就是说的 URLurlencode 和 urldecode像 / ? : 等这样的字符, 已经被 url 当做特殊意义理解了. 因此这些字符不能随意出现. 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.转义的规则如下:将需要转码的字符转为 16 进制然后从右到左取 4 位(不足 4 位直接处理)每 2 位 做一位前面加上%编码成%XY 格式例如 被转义成了 %2Burldecode 就是 urlencode 的逆过程UrlEncode编码/UrlDecode解码 - 站长工具HTTP 协议请求与响应格式HTTP 请求• 首行: [方法] [url] [版本]•Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\r\n 分隔; 遇到空行表示 Header 部分结束• Body: 空行后面的内容都是 Body. Body 允许为空字符串. 如果 Body 存在, 则在Header 中会有一个 Content-Length 属性来标识 Body 的长度;编写 HTTP 请求的代码 - 验证 http 请求需要现场基于历史代码先架构处一个基本的 HTTP 服务器然后用浏览器进行验 证HTTP 响应• 首行: [版本号] [状态码] [状态码解释]• Header:请求的属性, 冒号分割的键值对;每组属性之间使用\r\n 分隔;遇到空行表示 Header 部分结束• Body: 空行后面的内容都是 Body. Body 允许为空字符串. 如果 Body 存在, 则在 Header 中会有一个 Content-Length 属性来标识 Body 的长度; 如果服务器返回了一 个 html 页面, 那么 html 页面内容就是在 body 中.基本的应答格式HTTP 的方法方法说明支持的HTTP协议版本GET获取资源1.0、1.1POST传输实体主体1.0、1.1PUT传输文件1.0、1.1HEAD获得报文首部1.0、1.1DELETE删除文件1.0、1.1OPTIONS询问支持的方法1.1TRACE追踪路径1.1CONNECT要求用隧道协议连接代理1.1LINK建立和资源之间的联系1.0UNLINE断开连接关系1.0最常用的就是 GET 方法和 POST 方法.HTTP 常见方法1. GET 方法重点用途用于请求 URL 指定的资源。示例GET /index.html HTTP/1.1特性指定资源经服务器端解析后返回响应内容。form 表单https://www.runoob.com/html/html-forms.html//要通过历史写的 http 服务器验证 GET 方法,这里需要了解一下 FORM 表单的 //问题 //这里就要引入 web 根目录文件读取的基本操作了 #include fstream #include string #include vector std::string GetFileContentHelper(const std::string path) { std::ifstream in(path, std::ios::binary); if (!in.is_open()) return ; in.seekg(0, std::ios::end); size_t filesize in.tellg(); in.seekg(0, std::ios::beg); std::string content; content.resize(filesize); // 正确写法使用 content[0] 或 content.data() (C17) in.read(content[0], filesize); in.close(); return content; }2. POST 方法重点用途用于传输实体的主体通常用于提交表单数据。示例POST /submit.cgi HTTP/1.1特性可以发送大量的数据给服务器并且数据包含在请求体中。form 表单https://www.runoob.com/html/html-forms.html要通过历史写的 http 服务器验证 POST 方法,这里需要了解一下 FORM 表单 的问题3. PUT 方法不常用用途用于传输文件将请求报文主体中的文件保存到请求 URL 指定的位置。示例PUT /example.html HTTP/1.1特性不太常用但在某些情况下如 RESTful API 中用于更新资源。4. HEAD 方法用途与 GET 方法类似但不返回报文主体部分仅返回响应头。示例HEAD /index.html HTTP/1.1特性用于确认 URL 的有效性及资源更新的日期时间等// curl -i 显示 $ curl -i www.baidu.com HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: private, no-cache, no-store, proxy-revalidate, notransform Connection: keep-alive Content-Length: 2381 Content-Type: text/html Date: Sun, 16 Jun 2024 08:38:04 GMT Etag: 588604dc-94d Last-Modified: Mon, 23 Jan 2017 13:27:56 GMT Pragma: no-cache Server: bfe/1.0.8.18 Set-Cookie: BDORZ27315; max-age86400; domain.baidu.com; path/ !DOCTYPE html ... // 使用 head 方法只会返回响应头 $ curl --head www.baidu.com HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: private, no-cache, no-store, proxy-revalidate, notransform Connection: keep-alive Content-Length: 277 Content-Type: text/html Date: Sun, 16 Jun 2024 08:43:38 GMT Etag: 575e1f71-115 Last-Modified: Mon, 13 Jun 2016 02:50:25 GMT Pragma: no-cache Server: bfe/1.0.8.185. DELETE 方法不常用用途用于删除文件是 PUT 的相反方法。示例DELETE /example.html HTTP/1.1特性按请求 URL 删除指定的资源。6. OPTIONS 方法用途用于查询针对请求 URL 指定的资源支持的方法。示例OPTIONS * HTTP/1.1特性返回允许的方法如 GET、POST不支持的效果// 搭建一个 nginx 用来测试 // sudo apt install nginx // sudo nginx -- 开启 // ps ajx | grep nginx -- 查看 // sudo nginx -s stop -- 停止服务 $ sudo nginx -s stop $ ps ajx | grep nginx 2944845 2945390 2945389 2944845 pts/1 2945389 S 1002 0:00 grep --colorauto nginx $ sudo nginx $ ps axj | grep nginx 1 2945393 2945393 2945393 ? -1 Ss 0 0:00 nginx: master process nginx 2945393 2945394 2945393 2945393 ? -1 S 33 0:00 nginx: worker process 2945393 2945395 2945393 2945393 ? -1 S 33 0:00 nginx: worker process 2944845 2945397 2945396 2944845 pts/1 2945396 S 1002 0:00 grep --colorauto nginx // -X(大 x) 指明方法 $ curl -X OPTIONS -i http://127.0.0.1/ HTTP/1.1 405 Not Allowed Server: nginx/1.18.0 (Ubuntu) Date: Sun, 16 Jun 2024 08:48:22 GMT Content-Type: text/html Content-Length: 166 Connection: keep-alive html headtitle405 Not Allowed/title/head body centerh1405 Not Allowed/h1/center hrcenternginx/1.18.0 (Ubuntu)/center /body /html支持的效果HTTP/1.1 200 OK Allow: GET, HEAD, POST, OPTIONS Content-Type: text/plain Content-Length: 0 Server: nginx/1.18.0 (Ubuntu) Date: Sun, 16 Jun 2024 09:04:44 GMT Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization // 注意这里没有响应体因为 Content-Length 为 0HTTP 的状态码类别原因短语说明1XXInformational信息性状态码接收的请求正在处理2XXSuccess成功状态码请求正常处理完毕3XXRedirection重定向状态码需要进行附加操作以完成请求4XXClient Error客户端错误状态码服务器无法处理请求5XXServer Error服务器错误状态码服务器处理请求出错最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定 向), 504(Bad Gateway)表格一常见 HTTP 状态码100503状态码含义应用样例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服务器维护或过载暂时无法处理请求表格二重定向相关状态码301、302、307、308状态码含义是否为临时重定向应用样例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\nHTTP 状态码 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 地址HTTP 常见 Header• Content-Type: 数据类型(text/html 等)。告诉客户端浏览器、App 等响应体或请求体的数据格式如text/html、application/json、image/png、application/x-www-form-urlencoded等。• Content-Length: 表示 body 部分的字节长度注意不是字符长度。• Host: 客户端告知服务器请求的资源在哪台主机域名的哪个端口上HTTP/1.1 强制要求携带Host头否则服务器返回 400。用途一台服务器IP上托管多个域名虚拟主机例如www.a.com和www.b.com部署在同一台服务器上服务器通过Host决定访问哪个网站。格式Host: host:port端口默认 80http或 443https时可省略。高频考点“为什么 HTTP/1.1 要求必须有Host头”虚拟主机技术“反向代理Nginx如何利用Host进行转发”也常与“HTTP 1.0 vs 1.1 的区别”一起考。• User-Agent: 声明用户的操作系统、浏览器名称/版本、渲染引擎等信息。• referer: 表示当前页面是从哪个 URL 跳转过来的即来源页面。“防盗链是如何实现的”基于Referer判断“Referer可能被篡改吗”可以客户端可随意修改所以不用于严谨的身份验证。“什么是空 Referer 场景”直接输入地址、书签访问、HTTPS 跳转到 HTTP 时一般不发。• Location: 配合 3xx 状态码301/302/307/308使用告诉客户端新的资源地址301 永久重定向后续请求应直接访问新地址浏览器会缓存重定向。302 临时重定向每次仍先请求原地址。响应头示例Location: https://www.new-site.com/page在登录后跳转、URL 规范化如强制 HTTPS中很常见。“301 和 302 的区别对 SEO 有什么影响”301 权重转移302 不转移“重定向过程中请求方法会变化吗”301/302 典型会将 POST 转成 GET但 307/308 会保持原方法。也常结合状态码考察。• Cookie: 在客户端存储少量信息通常 4KB用于维持会话session、用户追踪、个性化设置等服务器通过Set-Cookie响应头设置 Cookie客户端后续请求自动携带Cookie头回传。Cookie 属性Domain、Path、Expires/Max-Age、Secure仅 HTTPS、HttpOnly禁止 JS 访问防 XSS、SameSite防 CSRF。会话 Cookie不设置过期时间在浏览器关闭后失效持久 Cookie 保存在磁盘中。安全风险XSS 可读取非 HttpOnly 的 CookieCSRF 可冒用已认证用户的 Cookie。面试极高频率“Cookie、Session、Token 的区别”“如何保证 Cookie 安全”HttpOnly、Secure、SameSite“Cookie 的跨域问题”默认同站可通过 Domain 设置二级域名共享但无法跨完全不同的域名。“Set-Cookie与Cookie头的关系”关于 connection 报头HTTP 中的 Connection 字段是 HTTP 报文头的一部分它主要用于控制和管理客户 端与服务器之间的连接状态核心作用• 管理持久连接Connection 字段还用于管理持久连接也称为长连接。持久 连接允许客户端和服务器在请求/响应完成后不立即关闭 TCP 连接以便在同一个连接 上发送多个请求和接收多个响应。持久连接长连接• HTTP/1.1在 HTTP/1.1 协议中默认使用持久连接。当客户端和服务器都不明 确指定关闭连接时连接将保持打开状态以便后续的请求和响应可以复用同一个连 接。• HTTP/1.0在 HTTP/1.0 协议中默认连接是非持久的。如果希望在 HTTP/1.0 上实现持久连接需要在请求头中显式设置 Connection: keep-alive。语法格式• Connection: keep-alive表示希望保持连接以复用 TCP 连接。• Connection: close表示请求/响应完成后应该关闭 TCP 连接。下面附上一张关于 HTTP 常见 header 的表格HTTP 常见 Header字段名含义样例Accept客户端可接受的响应内容类型Accept: text/html, application/xhtmlxml, application/xml; q0.9, image/webp, */*; q0.8Accept-Encoding客户端支持的数据压缩格式Accept-Encoding: gzip, deflate, brAccept-Language客户端可接受的语言类型Accept-Language: zh-CN, zh; q0.9, en; q0.8Host请求的主机名和端口号Host: www.example.com:8080User-Agent客户端的软件环境信息操作系统、浏览器等User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ... Chrome/91.0Cookie客户端发送给服务器的 HTTP Cookie 信息Cookie: session_idabcdefg12345; user_id123Referer请求的来源 URL当前页面从哪个 URL 跳转而来Referer: http://www.example.com/previous_page.htmlContent-Type实体主体的媒体类型Content-Type: application/x-www-form-urlencoded表单提交或application/jsonJSON 数据Content-Length实体主体的字节大小Content-Length: 150Authorization认证信息如用户名和密码常用于 Basic 认证Authorization: Basic QWxhZGRpbjpvcGVuIENlc2FtZQBase64 编码后的用户名:密码Cache-Control缓存控制指令请求和响应均可使用请求时Cache-Control: no-cache或max-age3600响应时Cache-Control: public, max-age3600Connection请求完成后是否关闭连接Connection: keep-alive或Connection: closeDate请求或响应的日期和时间GMT 格式Date: Wed, 21 Oct 2023 07:28:00 GMTLocation重定向的目标 URL通常与 3xx 状态码配合Location: http://www.example.com/new_location.html配合 302Server服务器软件信息Server: Apache/2.4.41 (Unix)Last-Modified资源的最后修改时间用于缓存对比Last-Modified: Wed, 21 Oct 2023 07:20:00 GMTETag资源的唯一标识符用于强缓存验证ETag: 3f80f-1b6-5f4e2512a4100Expires响应过期的日期和时间HTTP/1.0 缓存机制Expires: Wed, 21 Oct 2023 08:28:00 GMT最简单的 HTTP 服务器实现一个最简单的 HTTP 服务器, 只在网页上输出 hello world; 只要我们按照 HTTP 协议的要求构造数据, 就很容易能做到#include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include stdio.h #include string.h #include stdlib.h void Usage() { printf(usage: ./server [ip] [port]\n); } int main(int argc, char* argv[]) { if (argc ! 3) { Usage(); return 1; } int fd socket(AF_INET, SOCK_STREAM, 0); if (fd 0) { perror(socket); return 1; } struct sockaddr_in addr; addr.sin_family AF_INET; addr.sin_addr.s_addr inet_addr(argv[1]); addr.sin_port htons(atoi(argv[2])); int ret bind(fd, (struct sockaddr*)addr, sizeof(addr)); if (ret 0) { perror(bind); return 1; } ret listen(fd, 10); if (ret 0) { perror(listen); return 1; } for (;;) { struct sockaddr_in client_addr; socklen_t len; int client_fd accept(fd, (struct sockaddr*)client_addr, len); if (client_fd 0) { perror(accept); continue; } char input_buf[1024 * 10] {0}; // 用一个足够大的缓冲区直接把数据读完。 ssize_t read_size read(client_fd, input_buf, sizeof(input_buf) - 1); if (read_size 0) { return 1; } printf([Request] %s, input_buf); char buf[1024] {0}; const char* hello h1hello world/h1; sprintf(buf, HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s, strlen(hello), hello); write(client_fd, buf, strlen(buf)); } return 0; }编译, 启动服务. 在浏览器中输入 http://[ip]:[port], 就能看到显示的结果 Hello World此处我们使用 9090 端口号启动了 HTTP 服务器. 虽然 HTTP 服务器一般使用 80 端 口, 但这只是一个通用的习惯. 并不是说 HTTP 服务器就不能使用其他的端口号. 使用 chrome 测试我们的服务器时, 可以看到服务器打出的请求中还有一个 GET /favicon.ico HTTP/1.1 这样的请求. 同学们自行查找资料, 去理解 favicon.ico 的作用.实验 把返回的状态码改成 404, 403, 504 等, 看浏览器上分别会出现什么样的效果.HTTP 历史及版本核心技术与时代背景HTTPHypertext Transfer Protocol超文本传输协议作为互联网中浏览器和服务 器间通信的基石经历了从简单到复杂、从单一到多样的发展过程。以下将按照时间 顺序介绍 HTTP 的主要版本、核心技术及其对应的时代背景。HTTP/0.9• 仅支持 GET 请求方法。• 仅支持纯文本传输主要是 HTML 格式。• 无请求和响应头信息。时代背景• 1991 年HTTP/0.9 版本作为 HTTP 协议的最初版本用于传输基本的超文本 HTML 内容。• 当时的互联网还处于起步阶段网页内容相对简单主要以文本为主。HTTP/1.0• 引入 POST 和 HEAD 请求方法。• 请求和响应头信息支持多种数据格式MIME。• 支持缓存cache。• 状态码status code、多字符集支持等。时代背景• 1996 年随着互联网的快速发展网页内容逐渐丰富HTTP/1.0 版本应运而 生。• 为了满足日益增长的网络应用需求HTTP/1.0 增加了更多的功能和灵活性。• 然而HTTP/1.0 的工作方式是每次 TCP 连接只能发送一个请求性能上存在一定局限HTTP/1.1• 引入持久连接persistent connection支持管道化pipelining。• 允许在单个 TCP 连接上进行多个请求和响应提高了性能。• 引入分块传输编码chunked transfer encoding。• 支持 Host 头允许在一个 IP 地址上部署多个 Web 站点。时代背景• 1999 年随着网页加载的外部资源越来越多HTTP/1.0 的性能问题愈发突出。• HTTP/1.1 通过引入持久连接和管道化等技术有效提高了数据传输效率。• 同时互联网应用开始呈现出多元化、复杂化的趋势HTTP/1.1 的出现满足了 这些需求。HTTP/2.0• 多路复用multiplexing一个 TCP 连接允许多个 HTTP 请求。• 二进制帧格式binary framing优化数据传输。• 头部压缩header compression减少传输开销。• 服务器推送server push提前发送资源到客户端。时代背景• 2015 年随着移动互联网的兴起和云计算技术的发展网络应用对性能的要求越 来越高。• HTTP/2.0 通过多路复用、二进制帧格式等技术显著提高了数据传输效率和网 络性能。• 同时HTTP/2.0 还支持加密传输HTTPS提高了数据传输的安全性。HTTP/3.0• 使用 QUIC 协议替代 TCP 协议基于 UDP 构建的多路复用传输协议。• 减少了 TCP 三次握手及 TLS 握手时间提高了连接建立速度• 解决了 TCP 中的线头阻塞问题提高了数据传输效率。时代背景• 2022 年随着 5G、物联网等技术的快速发展网络应用对实时性、可靠性的要 求越来越高。• HTTP/3.0 通过使用 QUIC 协议提高了连接建立速度和数据传输效率满足了这 些需求。• 同时HTTP/3.0 还支持加密传输HTTPS保证了数据传输的安全性