WHAT - 不同 HTTP Methods 使用场景、使用方法和可能遇到的问题

前言

HTTP Methods: Request methods define the type of action you are requesting to be performed.

  1. GET - Requests retrieve resource information
  2. POST - The server creates a new entry in a database
  3. PUT - Updates an existing resource
  4. PATCH - Very similar to PUT but makes a partial update on a resource
  5. DELETE - Deletes resource or related component
  6. HEAD - Retrieve response headers identical to those of a GET request, but without the response body.
  7. CONNECT - Establishes a tunnel to the server identified by the target resource
  8. OPTIONS - Describe the communication options for the target resource
  9. TRACE - Performs a message loop-back test along the path to the target resource
  10. <custom> - Some APIs use custom request methods such as LIST. Type in your custom methods.

基本介绍

MDN - HTTP Request Methods

HTTP 方法是用于指示请求的类型的动作的标准化方式。以下是常见的 HTTP 方法:

  1. GET: 从服务器检索资源。通常用于获取数据。
  2. POST: 向服务器发送数据以创建资源。常用于提交表单或上传文件。
  3. PUT: 向服务器发送数据以更新资源。通常用于更新现有资源的全部内容。
  4. PATCH: 向服务器发送部分数据以更新资源。通常用于部分更新资源。
  5. DELETE: 从服务器删除资源。
  6. HEAD: 检索资源的头部信息,类似于 GET 请求,但不返回资源的主体部分。
  7. OPTIONS: 返回服务器支持的所有 HTTP 方法。
  8. CONNECT: 建立一个到目标资源的隧道。主要用于代理服务器。
  9. TRACE: 执行一个消息环回测试,沿着路径到目标资源的请求的路由。

示例代码

这里是一个简单的使用 fetch 函数执行几种常见 HTTP 方法(get、post、put、patch、delete)的示例代码:

async function httpRequest(method: string, url: string, data?: any) {
  const options: RequestInit = {
    method: method,
    headers: {
      'Content-Type': 'application/json'
    },
    body: data ? JSON.stringify(data) : undefined
  };

  try {
    const response = await fetch(url, options);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const result = await response.json();
    return result;
  } catch (error) {
    console.error('Error:', error);
  }
}

// 示例用法
const apiUrl = 'https://jsonplaceholder.typicode.com/posts';

// GET 请求
httpRequest('GET', apiUrl).then(data => console.log(data));

// POST 请求
httpRequest('POST', apiUrl, { title: 'foo', body: 'bar', userId: 1 })
  .then(data => console.log(data));

// PUT 请求
httpRequest('PUT', `${apiUrl}/1`, { id: 1, title: 'foo', body: 'bar', userId: 1 })
  .then(data => console.log(data));

// PATCH 请求
httpRequest('PATCH', `${apiUrl}/1`, { title: 'foo' })
  .then(data => console.log(data));

// DELETE 请求
httpRequest('DELETE', `${apiUrl}/1`)
  .then(data => console.log(data));

说明

  1. httpRequest: 一个通用的 HTTP 请求函数,接受 HTTP 方法、URL 和可选的数据。
  2. RequestInit: 用于配置 fetch 请求的选项,包括方法、头部和主体。
  3. fetch: 执行 HTTP 请求的 JavaScript API。

这个示例演示了如何使用 fetch 函数执行各种 HTTP 方法的请求。你可以根据需要调整 urldata 参数以匹配你的具体 API。

具体介绍

前置知识:幂等和非幂等

幂等性(Idempotency)是计算机科学中的一个重要概念,用于描述操作的可重复性和稳定性。在 HTTP 请求中,幂等性表示多次执行相同的请求应当产生相同的结果。

幂等操作

定义: 幂等操作是指无论操作执行多少次,产生的效果都相同。

HTTP 方法的幂等性:

  • GET: 幂等。多次执行 GET 请求会返回相同的资源数据,不会改变服务器状态。
  • PUT: 幂等。多次执行 PUT 请求将资源替换为相同内容,因此效果相同。
  • DELETE: 幂等。多次执行 DELETE 请求会删除资源,且删除不存在的资源不会再有变化。
  • HEAD: 幂等。多次执行 HEAD 请求会返回相同的头部信息,不会改变服务器状态。
  • OPTIONS: 幂等。多次执行 OPTIONS 请求会返回相同的支持方法列表,不会改变服务器状态。
  • TRACE: 幂等。多次执行 TRACE 请求会返回相同的路径信息,不会改变服务器状态。

非幂等操作

定义: 非幂等操作是指操作执行多次会产生不同的效果。

HTTP 方法的非幂等性:

  • POST: 非幂等。多次执行 POST 请求会创建多个资源,产生不同的结果。
  • PATCH: 通常非幂等。多次执行 PATCH 请求可能会导致资源的部分更新,产生不同的结果。尽管有时可以设计成幂等,但一般认为是非幂等的。

幂等性和非幂等性的应用场景

幂等性应用场景:

  • 数据读取: 使用 GET 方法读取数据,无论请求多少次,数据不会改变。
  • 资源替换: 使用 PUT 方法完全替换资源,多次请求结果相同。
  • 资源删除: 使用 DELETE 方法删除资源,多次请求结果一致。

非幂等性应用场景:

  • 数据创建: 使用 POST 方法创建新资源,每次请求都会产生新的资源。
  • 部分更新: 使用 PATCH 方法更新资源的部分内容,每次请求可能产生不同的结果。

总结

理解幂等性和非幂等性对于设计和实现可靠的 HTTP API 非常重要。幂等操作可以提高系统的稳定性和可预测性,而非幂等操作适合用于创建或部分更新资源。在实际开发中,选择合适的 HTTP 方法来满足业务需求,同时考虑幂等性,确保系统的健壮性和一致性。

1. GET

使用场景:

  • 用于从服务器获取资源数据,如网页、图片、JSON 数据等。
  • 适合只读取数据而不改变服务器状态的请求。

使用方法:

fetch('https://example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));

可能遇到的问题:

  • 缓存问题:浏览器可能缓存 GET 请求的响应,导致获取的不是最新数据。可以通过设置请求头或在 URL 中添加时间戳来避免。
  • URL 长度限制:有些浏览器对 URL 长度有限制,GET 请求参数太多时可能会出问题。

2. POST

使用场景:

  • 用于向服务器发送数据以创建新资源,例如提交表单、上传文件等。
  • 适合需要将数据发送到服务器进行处理的请求。

使用方法:

fetch('https://example.com/api', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'John', age: 30 })
})
  .then(response => response.json())
  .then(data => console.log(data));

可能遇到的问题:

  • 重复提交:用户可能会多次点击提交按钮,导致重复提交。可以通过禁用按钮或其他方式避免。
  • CSRF 攻击:需要防范跨站请求伪造攻击,通常通过使用 CSRF 令牌来防御。

3. PUT

使用场景:

  • 用于更新服务器上的现有资源的全部内容。
  • 适合需要完全替换资源的请求。

使用方法:

fetch('https://example.com/api/resource/1', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ id: 1, name: 'John', age: 31 })
})
  .then(response => response.json())
  .then(data => console.log(data));

可能遇到的问题:

  • 幂等性:PUT 请求应当是幂等的,多次执行相同的 PUT 请求应当产生相同的结果。
  • 数据完整性:需要确保发送的数据是完整的,因为 PUT 是替换整个资源。

4. PATCH

使用场景:

  • 用于更新服务器上的资源的部分内容。
  • 适合需要部分更新资源的请求。

使用方法:

fetch('https://example.com/api/resource/1', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ age: 31 })
})
  .then(response => response.json())
  .then(data => console.log(data));

可能遇到的问题:

  • 部分更新:确保只发送需要更新的字段,避免影响其他字段。
  • 幂等性:虽然 PATCH 可以是非幂等的,但尽量使其幂等,即多次相同的 PATCH 请求应当产生相同的结果。

延伸

要确保 PATCH 请求是幂等的,可以采取以下几种策略:

1. 确保操作是幂等的

在服务器端处理 PATCH 请求时,确保每次相同的请求对资源产生相同的修改效果。这通常涉及在更新资源时使用幂等的方法。

示例: 更新用户的某个属性

// PATCH 请求体
{
  "age": 31
}

服务器接收到这个请求时,只更新 age 属性,不改变其他属性。

2. 使用版本控制或条件更新

通过检查资源的版本或条件来确保更新操作的幂等性。例如,可以使用乐观锁定或 If-Match 头来进行条件更新。

示例:

PATCH /resource/1 HTTP/1.1
Host: example.com
Content-Type: application/json
If-Match: "abc123"

{
  "age": 31
}

服务器只有在资源的版本匹配 If-Match 头中提供的版本时才会进行更新,这样可以确保幂等性。

3. 全量更新部分属性

尽量在 PATCH 请求中提供所有需要更新的字段,即使某些字段的值没有变化。这确保了每次请求都是对特定字段的完整更新,而不是依赖于资源的当前状态。

示例:

// PATCH 请求体
{
  "name": "John",
  "age": 31,
  "email": "john@example.com"
}

4. 使用特定操作指令

在 PATCH 请求体中明确指定操作类型,如 replaceaddremove 等。这些操作可以使用 JSON Patch 格式来表示。

JSON Patch 示例:

[
  { "op": "replace", "path": "/age", "value": 31 }
]

服务器根据操作指令执行相应的更新,从而确保幂等性。

5. 幂等标识符

使用幂等标识符来确保每个请求只被处理一次。客户端生成一个唯一的幂等标识符,并在请求中发送给服务器。服务器在处理请求时检查这个标识符,确保每个标识符只处理一次。

示例:

PATCH /resource/1 HTTP/1.1
Host: example.com
Content-Type: application/json
Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000

{
  "age": 31
}

示例代码

以下是一个简单的 Node.js 服务器示例,展示如何实现幂等的 PATCH 请求:

const express = require('express');
const app = express();
app.use(express.json());

let resource = { id: 1, name: 'John', age: 30, email: 'john@example.com' };
let processedRequests = {};

app.patch('/resource/:id', (req, res) => {
  const idempotencyKey = req.headers['idempotency-key'];

  if (idempotencyKey && processedRequests[idempotencyKey]) {
    return res.status(200).send(processedRequests[idempotencyKey]);
  }

  const update = req.body;

  // Update resource in an idempotent way
  if (update.name !== undefined) resource.name = update.name;
  if (update.age !== undefined) resource.age = update.age;
  if (update.email !== undefined) resource.email = update.email;

  const response = { message: 'Resource updated', resource };

  if (idempotencyKey) {
    processedRequests[idempotencyKey] = response;
  }

  res.status(200).send(response);
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

总结

确保 PATCH 请求幂等性的方法包括:

  1. 确保操作是幂等的:每次相同的请求应产生相同的结果。
  2. 使用版本控制或条件更新:如 If-Match 头。
  3. 全量更新部分属性:确保所有需要更新的字段都包含在请求中。
  4. 使用特定操作指令:如 JSON Patch 格式。
  5. 使用幂等标识符:确保每个请求只处理一次。

通过这些方法,可以确保 PATCH 请求的幂等性,从而提高系统的可靠性和一致性。

5. DELETE

使用场景:

  • 用于从服务器删除资源。
  • 适合需要删除资源的请求。

使用方法:

fetch('https://example.com/api/resource/1', {
  method: 'DELETE'
})
  .then(response => {
    if (response.ok) {
      console.log('Resource deleted');
    }
  });

可能遇到的问题:

  • 幂等性:DELETE 请求应当是幂等的,多次执行相同的 DELETE 请求应当产生相同的结果。
  • 资源不存在:需要处理删除不存在的资源的情况,通常返回 404 状态码。

6. HEAD

使用场景:

  • 用于检索资源的元数据,而不获取资源的主体部分。
  • 适合需要检查资源是否存在或获取资源的头部信息(如大小、类型)的请求。

使用方法:

fetch('https://example.com/data', {
  method: 'HEAD'
})
  .then(response => {
    if (response.ok) {
      console.log('Resource exists');
    }
  });

可能遇到的问题:

  • 信息有限:HEAD 请求只返回头部信息,不返回实际数据主体,需根据返回的头部信息判断资源状态。

7. OPTIONS

使用场景:

  • 用于查询服务器支持的请求方法。
  • 适合在跨域请求前检查服务器是否允许特定方法的请求。

使用方法:

fetch('https://example.com/api', {
  method: 'OPTIONS'
})
  .then(response => {
    if (response.ok) {
      console.log('Options:', response.headers.get('Allow'));
    }
  });

可能遇到的问题:

8. CONNECT

使用场景:

  • 用于建立到目标资源的隧道,主要用于代理服务器。
  • 适合在需要通过代理进行安全连接(如 HTTPS)的请求。

使用方法:
CONNECT 方法通常由浏览器或其他客户端自动处理,用户不直接使用。

可能遇到的问题:

  • 代理配置:确保代理服务器正确配置,以支持 CONNECT 方法。

9. TRACE

使用场景:

  • 用于执行消息环回测试,诊断路径问题。
  • 适合在开发和调试时检查请求的路径和中间代理的修改。

使用方法:
TRACE 方法通常由开发工具或诊断工具使用,用户不直接使用。

可能遇到的问题:

  • 安全问题:TRACE 方法可能被滥用进行跨站脚本攻击(XSS),许多服务器默认禁用 TRACE 方法。

总结

每个 HTTP 方法都有其特定的使用场景和可能遇到的问题。根据需求选择合适的方法,并注意相应的安全性和幂等性,确保请求的正确性和可靠性。

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值