第二章 HTTP请求方法、状态码详解与缓存机制解析

1. 请求方法(GET、POST、PUT、DELETE等)及其应用场景

本质上只有get和post请求,其他都是post请求

1.1 GET

  • 定义:GET是HTTP中最常用的方法,用于从服务器获取资源。
  • 特点
    • 请求参数通常放在URL的查询字符串中,即?key1=value1&key2=value2格式。
    • GET请求可被浏览器缓存,并且会被保存在浏览历史记录中。(不理解没关系,后面会单独说)
    • 2m的数据限制。
    • 不应有副作用,也就是说,它不应该改变服务器上的资源状态。
  • 应用场景
    • 获取静态页面内容。
    • 查询数据库以获取列表信息或详情信息。

1.2 POST

  • 定义:POST方法用于向指定资源提交数据,请求被包含在请求体中,可能引起服务器端资源的创建、更新或操作。
  • 特点
    • 数据不会显示在URL中,而是通过请求体传输,可以携带大量数据。
    • 可能会有副作用,比如新增用户信息、发表评论等操作。
    • 非幂等性:多次执行相同的POST请求可能会有不同的结果,例如每次提交都会创建一个新的资源实例。
  • 应用场景
    • 提交表单数据。
    • 创建新的资源,如添加一篇文章、上传文件等。

POST请求的请求体(Body)是用来承载客户端要发送给服务器的数据部分,根据不同的应用场景和内容类型(Content-Type),请求体的内容格式会有所不同。对于上传文件的情况,通常采用multipart/form-dataapplication/x-www-form-urlencodedapplication/json

multipart/form-data
这是最常见的文件上传方式,尤其在HTML表单中通过元素选择文件时,默认使用此Content-Type。请求体被划分为多个部分(parts),每个部分包含一个或多个字段及其对应的值,文件字段则包含了文件内容本身。每个部分都有自己的Header描述信息,例如:

--boundary_string
Content-Disposition: form-data; name="field1"

value1
--boundary_string
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

... file contents here ...
--boundary_string--

在这个例子中,“boundary_string”是一个由服务器指定或者浏览器自动生成的分隔符,用于区分各个部分。文件字段通过Content-Disposition头部中的filename属性来标识上传文件的名字,并且其内容紧跟在头部后面。

application/x-www-form-urlencoded
尽管这种Content-Type也能上传少量数据,但不适合大文件或二进制文件的上传,因为这种方式下所有的键值对都会被编码为一串连续的字符序列,例如:

field1=value1&file=encoded_file_contents

对于文件内容,通常是不现实的将其编码成URL安全的形式并作为请求体的一部分。

在实际编程过程中,比如使用Python的requests库、JavaScript的Fetch API或XMLHttpRequest等工具,都需要正确设置Content-Type,并将文件内容以适当的方式添加到请求体中。例如,在requests库中,可以这样上传文件:

import requests

url = 'https://example.com/upload'
files = {'file': ('example.txt', open('path_to_your_file.txt', 'rb'))}
response = requests.post(url, files=files)

这里open('path_to_your_file.txt', 'rb')用来打开文件并以二进制读取模式准备上传,requests库会自动处理请求头和请求体的格式化工作。
在使用multipart/form-data格式上传文件时,除了基本的文件内容传输外,还可以携带其他非文件字段数据。例如,在一个表单中可能同时包含文本输入框和其他控件的数据,整个POST请求体将会包括这些额外信息:

--boundary_string
Content-Disposition: form-data; name="title"

File Title
--boundary_string
Content-Disposition: form-data; name="description"

A brief description of the file
--boundary_string
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

... file contents here ...
--boundary_string--

这里的“File Title”和“A brief description of the file”是与文件一同提交的额外字段数据。

在服务器端处理POST请求时,需要能够解析这种多部分格式的请求体来提取出各个字段的值以及文件内容。大多数现代Web框架(如Django、Express.js等)都提供了内置或第三方中间件来方便地处理multipart/form-data类型的文件上传。

另外,对于大文件的上传,还需要考虑以下几点:

  • 分块上传:为了支持大文件上传并提高稳定性,可以采用分块上传的方式,将文件分成多个小块分别发送,最后在服务器端合并。
  • 限制大小:服务器通常会设置最大允许上传文件的大小限制,以防止资源耗尽或其他安全风险。
  • 进度监控:在前端实现文件上传时,可以通过监听事件来实时显示上传进度,提升用户体验。

总之,POST请求体用于文件上传是一个相对复杂的过程,涉及到了HTTP协议、浏览器行为、服务器端编程等多个环节的协同工作。

1.3 PUT

  • 定义:PUT方法用于替换目标资源的所有当前表示。如果资源不存在,则服务器通常会创建该资源。与POST相比,PUT更强调幂等性,即多次执行同样的PUT操作,服务器端状态应该保持一致。
  • 特点
    • 客户端需提供完整的资源实体,服务器根据请求URI进行更新或创建。
    • 操作具有幂等性,多次执行同样的PUT请求应该产生相同的效果(除非资源本身发生了变化)。
  • 应用场景
    • 更新已存在的资源属性,例如修改用户个人资料。
    • 对于RESTful API设计,全量更新资源时使用。

1.4 DELETE

  • 定义:DELETE方法请求服务器删除指定的资源。
  • 特点
    • 删除操作无响应主体,仅通过HTTP响应头部和状态码告知结果。
    • 也具有幂等性,多次发出相同的DELETE请求都会删除同一个资源。
  • 应用场景
    • 删除某个特定资源,例如删除一个文章、账户或者订单。

1.5 其他方法

除了上述四种常见方法外,还有HEAD、OPTIONS、PATCH等:

  • HEAD类似于GET,但只返回响应头而不返回实体主体,常用来检查资源是否存在或获取资源的元信息。
  • OPTIONS允许客户端查看服务器支持哪些HTTP方法,用于服务发现或跨域预检。
  • PATCH用于对资源进行部分更新,仅提交需要更改的内容而不是整个资源。

2. 状态码含义及常见状态码分析

常见状态码:
  • 200 OK:请求成功,服务器已成功处理请求并返回资源。
  • 301 Moved Permanently:永久重定向,请求的资源已被分配了新的URL。
  • 302 Found:临时重定向,请求的资源临时位于其他URL下。
  • 400 Bad Request:客户端请求语法错误,服务器无法理解。
  • 401 Unauthorized:请求未经授权,需要提供认证信息(如API Key、Token等)。
  • 403 Forbidden:服务器理解请求,但拒绝提供服务,通常因为权限问题。
  • 404 Not Found:请求的资源在服务器上未找到。
  • 500 Internal Server Error:服务器遇到了意外情况,无法完成请求。
  • 503 Service Unavailable:服务器暂时无法处理请求,可能由于过载或维护。

3. 请求头与响应头关键字段解析

3.1 常见请求头:

  • User-Agent:标识客户端应用程序的信息,如浏览器类型、版本等。
  • Authorization:用于验证用户的凭证,例如Bearer Token或Basic Auth凭据。
  • Content-Type:指示请求主体的数据格式,如application/jsonmultipart/form-data等。
  • Accept:告诉服务器客户端接受哪些媒体类型作为响应。
  • Cookie:客户端发送到服务器的cookies信息,用于保持会话状态。

3.2 常见响应头:

  • Content-Type:同请求头,指示响应主体的数据格式。
  • Content-Length:响应主体内容的长度(字节数)。
  • Location:用于重定向的URL,在3xx状态码出现时使用。
  • Set-Cookie:服务器发给客户端的cookie信息,用于设置新会话或更新现有会话。
  • Cache-Control:控制缓存策略,如最大Age、是否允许缓存等。

4. HTTP缓存机制介绍

HTTP协议支持多种缓存机制来提高性能和减少网络带宽消耗,主要通过以下几种头部字段实现:

  • Expires:规定缓存过期时间,到了这个时间点后,缓存不再有效。

  • Cache-Control:更详细的缓存控制指令集,包括max-age、no-cache、public、private等。

    • max-age:设置缓存的最大生存时间(秒数)。
    • no-cache:要求验证缓存的有效性,即使有缓存也要与服务器确认。
    • public:指示响应可以被任何中间缓存存储。
    • private:指示响应只能被单个用户浏览器缓存,不能被共享缓存(如CDN)存储。
  • Last-Modified / If-Modified-Since:基于时间戳判断资源是否发生过改动。

  • ETag / If-None-Match:基于资源实体标签判断资源是否发生过变动。

HTTP缓存机制是Web性能优化中非常重要的一环,它允许浏览器、代理服务器以及其他中间件存储HTTP响应的副本,并在后续请求时使用这些副本来避免不必要的网络延迟。以下是一些核心的HTTP缓存机制以及相关的代码示例:

4.1. Expires

  • Expires头字段是一个绝对时间戳,表示缓存何时应该失效。
HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: max-age=3600
Expires: Wed, 01 Jan 2025 00:00:00 GMT

在上述响应头中,Cache-Control: max-age=3600 表示资源在接下来的一个小时内有效;而 Expires 设置了一个未来的时间点,过了这个时间点后,浏览器认为缓存过期。

4.2. Cache-Control

  • Cache-Control 是一个更强大的缓存控制策略,它可以设置多种指令如:max-age(相对有效期)、no-cache(需要验证缓存的有效性)、public(可以被任何缓存存储)和 private(只能被单个用户浏览器缓存)等。
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=300, public

4.3. Last-Modified / If-Modified-Since

  • 服务器通过 Last-Modified 头部提供资源最后修改的时间戳,客户端在下一次请求时带上 If-Modified-Since 头部,询问服务器资源是否自上次访问以来有变化。
// 首次请求响应:
HTTP/1.1 200 OK
Last-Modified: Sat, 23 Oct 2021 08:23:45 GMT

// 客户端再次请求时:
GET /resource HTTP/1.1
If-Modified-Since: Sat, 23 Oct 2021 08:23:45 GMT

如果资源未改变,服务器会返回304 Not Modified状态码,并且没有响应体,客户端则从缓存中获取内容。

4.4. ETag / If-None-Match

  • ETag(实体标签)是服务器为每个资源生成的一个唯一标识符,用来判断资源是否有变动。与 Last-Modified 类似,客户端会在下次请求时携带 If-None-Match 头部。
// 首次请求响应:
HTTP/1.1 200 OK
ETag: "ae3f7e9a"

// 客户端再次请求时:
GET /resource HTTP/1.1
If-None-Match: "ae3f7e9a"

如果ETag匹配,服务器同样会返回304状态码。

在实际编程中,开发者通常不需要直接编写处理这些头部信息的代码,因为现代Web框架或库(如Express.js、axios等)已经内置了对HTTP缓存机制的支持。不过,开发者可以根据业务需求配置响应头,以实现定制化的缓存策略。例如,在Node.js的Express框架中:

const express = require('express');
const app = express();

app.get('/resource', (req, res) => {
  // 假设这里的getResource函数从数据库获取数据
  const resource = getResource();
  
  // 设置缓存策略
  res.setHeader('Cache-Control', 'public, max-age=3600');
  res.setHeader('ETag', generateETag(resource)); // 假设有generateETag函数用于生成ETag
  
  res.json(resource);
});

5. HTTPS加密传输原理

HTTPS(Hypertext Transfer Protocol Secure)是在HTTP协议的基础上加入了SSL/TLS协议,为数据传输提供了安全保证。

  • 握手过程:客户端与服务器首先进行TLS握手阶段,协商加密算法、交换证书等,建立安全连接。
  • 证书验证:服务器向客户端发送其数字证书,客户端验证证书合法性,确保与正确的服务器通信。
  • 密钥交换:双方利用非对称加密算法(如RSA)生成会话密钥,用于后续的数据加密。
  • 加密传输:实际数据传输阶段,所有通信内容都采用协商好的会话密钥进行对称加密,确保数据在传输过程中不被窃取或篡改。

通过HTTPS,客户端和服务器之间建立起了一条安全通道,既保证了数据的机密性,又确保了数据的完整性,同时还能够防止中间人攻击。

你可能感兴趣的:(http,缓存,网络协议)