目录
[一、HTTP 常见方法概述](#一、HTTP 常见方法概述)
[二、GET 方法和 POST 方法深入剖析](#二、GET 方法和 POST 方法深入剖析)
[GET 方法](#GET 方法)
[POST 方法](#POST 方法)
[三、Postman 演示 GET 和 POST 的区别](#三、Postman 演示 GET 和 POST 的区别)
[2、GET 方法演示](#2、GET 方法演示)
[3、POST 方法演示](#3、POST 方法演示)
[四、TCP 套接字演示 GET 和 POST 的区别](#四、TCP 套接字演示 GET 和 POST 的区别)
[1、GET 方法提交](#1、GET 方法提交)
[HTML 表单设置 和 服务端的更改](#HTML 表单设置 和 服务端的更改)
[2、POST 方法提交](#2、POST 方法提交)
[1、GET 方法(重点)](#1、GET 方法(重点))
[2、POST 方法(重点)](#2、POST 方法(重点))
[3、PUT 方法(不常用)](#3、PUT 方法(不常用))
[4、HEAD 方法](#4、HEAD 方法)
[5、DELETE 方法(不常用)](#5、DELETE 方法(不常用))
[6、OPTIONS 方法](#6、OPTIONS 方法)
[7、其他 HTTP 方法](#7、其他 HTTP 方法)
[TRACE 方法](#TRACE 方法)
[CONNECT 方法](#CONNECT 方法)
[PATCH 方法](#PATCH 方法)
一、HTTP 常见方法概述

HTTP(Hypertext Transfer Protocol,超文本传输协议)定义了一组请求方法,用于指示对服务器上资源执行的操作类型。这些方法为客户端与服务器之间的交互提供了标准化的方式。
| 方法 | 说明 | 支持的 HTTP 协议版本 |
|---|---|---|
| GET | 用于从服务器获取指定资源的信息。它是一种幂等操作,即多次执行相同请求不会对服务器上的资源产生额外影响。 | 1.0、1.1 |
| POST | 主要用于向服务器提交数据,通常用于创建新资源或触发服务器上的某些处理逻辑。POST 请求不是幂等的,多次执行可能会创建多个相同或不同的资源。 | 1.0、1.1 |
| PUT | 用于将实体主体(数据)传输到服务器上的指定位置,以替换该位置现有的资源。如果资源不存在,则创建新资源。PUT 请求是幂等的。 | 1.0、1.1 |
| HEAD | 与 GET 方法类似,但只返回响应报文的首部,而不返回实际资源内容。常用于检查资源是否存在、获取资源的元信息等。 | 1.0、1.1 |
| DELETE | 用于请求服务器删除指定位置的资源。DELETE 请求是幂等的。 | 1.0、1.1 |
| OPTIONS | 用于询问服务器支持哪些 HTTP 方法,以及服务器对特定资源的支持选项。常用于跨域请求前的预检请求。 | 1.1 |
| TRACE | 用于沿着请求 - 响应链追踪请求的路径,主要用于测试和诊断目的。不过,由于存在安全风险(如 XST 攻击),现在很少使用。 | 1.1 |
| CONNECT | 要求服务器使用隧道协议(如 SSL/TLS)连接代理,通常用于建立 HTTPS 连接时的隧道。 | 1.1 |
| LINK | 用于建立当前资源与另一个资源之间的联系,定义资源之间的关系。不过,该方法在实际应用中较少使用。 | 1.0 |
| UNLINK | 用于断开当前资源与另一个资源之间的连接关系。同样,在实际应用中较少使用。 | 1.0 |
在实际应用中,最常用的 HTTP 方法是 GET 方法和 POST 方法,下面将重点对这两种方法进行详细讲解。
二、GET 方法和 POST 方法深入剖析
1、基本用途
-
GET 方法:一般用于从服务器获取某种资源信息。例如,在浏览器中输入一个网址,浏览器就会使用 GET 方法向服务器请求该网址对应的网页内容。
-
POST 方法:一般用于将数据上传给服务器。比如,在登录表单中填写用户名和密码并提交,就是使用 POST 方法将用户输入的数据发送给服务器进行验证。
虽然通常按照上述方式使用,但实际开发中也有特殊情况。例如,百度搜索在提交搜索关键词时,实际使用的是 GET 方法。这是因为搜索操作主要是获取与关键词相关的搜索结果,符合 GET 方法获取资源的本质,而且 GET 方法便于用户分享包含特定关键词的搜索链接。
2、传参方式
GET 方法
-
通过 URL 传参。
-
参数会附加在 URL 后面,以
?开头,多个参数之间用&连接。 -
例如:
https://www.example.com/search?keyword=apple&page=1,其中keyword=apple和page=1就是通过 URL 传递的参数。
POST 方法
-
通过请求正文传参。
-
参数包含在 HTTP 请求的正文部分,不会显示在 URL 中。
-
例如,在登录表单提交时,用户名和密码等数据会被封装在请求正文中发送给服务器。
3、参数容量与私密性
参数容量
-
由于 URL 的长度是有限制的(不同浏览器和服务器对 URL 长度的限制有所不同,但通常不会太长),所以 GET 方法通过 URL 传参能携带的数据量相对较少。
-
而 POST 方法通过正文传参,理论上可以携带更多的数据,不受 URL 长度的限制。
私密性
-
POST 方法传参更加私密。
-
因为 POST 方法不会将参数回显到 URL 当中,所以其他人不容易通过查看 URL 来获取传递的参数。
-
然而,不能因此就认为 POST 方法比 GET 方法更安全。
-
实际上,GET 方法和 POST 方法在传输数据时默认都是明文传送,都存在安全风险。要确保数据传输的安全性,只能通过加密技术(如 HTTPS 协议,它使用 SSL/TLS 协议对数据进行加密传输)来完成。
三、Postman 演示 GET 和 POST 的区别
Postman 是一款常用的 API 开发和测试工具,下面通过 Postman 来演示 GET 和 POST 方法在传参方面的区别。
1、Postman平台介绍
Postman 是一个用于API开发和测试的协作平台,主要功能包括:
-
API请求构建与发送:支持HTTP/HTTPS请求(GET、POST等),可自定义请求头、参数、Body等。
-
自动化测试:支持编写测试脚本验证响应结果。
-
团队协作:可共享API集合、环境变量等。
-
文档生成:自动根据请求生成API文档。
-
Mock服务器:模拟API响应进行前端开发。
2、GET 方法演示
参数设置
当使用 GET 方法访问服务器时,应该在 URL 中进行传参。在 Postman 中,可以在 "Params" 选项卡下进行参数设置。设置参数时,可以看到对应的 URL 会随之变化,参数会自动附加到 URL 后面。
例如,设置参数 a=1&b=2,URL 会变成类似 https://yourserver.com/api?a=1&b=2 的形式。

服务器接收情况
此时在服务器收到的 HTTP 请求中,可以在请求行中的 URL 里看到我们刚才在 Postman 中设置的参数。这表明 GET 方法确实是通过 URL 来传递参数的。

3、POST 方法演示
参数设置
如果使用 POST 方法,则应该通过请求正文进行传参。在 Postman 中,可以在 "Body" 选项卡下进行参数设置。可以选择 "raw" 方式传参,"raw" 表示原始传参,即输入的参数是什么样,实际传递的参数就是什么样。
例如,可以输入 JSON 格式的数据 {"name": "John", "age": 25} 作为参数。

服务器接收情况
此时服务器收到的 HTTP 请求的请求正文就不再是空字符串,而是我们通过正文传递的参数。同时,由于响应正文不为空字符串,响应报头当中会出现 "Content - Length" 属性,该属性表示响应正文的长度。如下:

四、TCP 套接字演示 GET 和 POST 的区别
为了更直观地演示 GET 方法和 POST 方法传参的区别,我们可以通过编写简单的 HTML 表单和服务器端代码,利用 TCP 套接字来实现浏览器提交参数的功能。
1、GET 方法提交
HTML 表单设置 和 服务端的更改
在 index.html 文件中加入两个表单,用于用户输入用户名和密码,并新增一个提交按钮。表单中可以通过修改 method 属性来指定参数提交的方法(GET 或 POST),还有一个 action 属性,表示想把这个表单提交给服务器上的哪个资源(通常是一个服务器端处理程序的文件路径)。示例代码如下:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTTP Server Test</title>
</head>
<body>
<h1>Hello HTTP Server</h1>
<h2>GET 表单提交测试</h2>
<form method="GET" action="/">
User name:<br>
<input type="text" name="username" placeholder="Enter username">
<br><br>
User password:<br>
<input type="password" name="psw" placeholder="Enter password">
<br><br>
<input type="submit" value="Submit">
</form>
<hr>
<h3>调试信息:</h3>
<p>提交表单后,查看服务器控制台输出的请求信息</p>
<p>提交后URL会变成: http://your-ip:8080/?username=xxx&psw=yyy</p>
<script>
// 显示当前URL
document.write('<p>当前URL: ' + window.location.href + '</p>');
document.write('<p>表单提交后,请注意查看服务器控制台的输出</p>');
</script>
</body>
</html>
method="GET":指定表单提交方式
-
GET:数据通过URL参数传递(
?name=value&...) -
POST:数据通过请求体传递(更安全,适合敏感信息)
action="/":指定表单提交的目标URL
-
/:提交到当前服务器的根路径 -
如果为空
"",则提交到当前页面
同时更新一下服务端的代码,如下:
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
// 创建套接字
int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock < 0) {
cerr << "socket error!" << endl;
return 1;
}
// 绑定
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(8080);
local.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
cerr << "bind error!" << endl;
return 2;
}
// 监听
if (listen(listen_sock, 5) < 0) {
cerr << "listen error!" << endl;
return 3;
}
cout << "Server started on port 8080..." << endl;
// 启动服务器
for (;;) {
struct sockaddr_in peer;
memset(&peer, 0, sizeof(peer));
socklen_t len = sizeof(peer);
int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
if (sock < 0) {
cerr << "accept error!" << endl;
continue;
}
// 输出客户端信息
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &peer.sin_addr, client_ip, sizeof(client_ip));
cout << "Connection from: " << client_ip << ":" << ntohs(peer.sin_port) << endl;
if (fork() == 0) { // 子进程
close(listen_sock);
// 读取HTTP请求
char buffer[4096] = {0};
int bytes_received = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
cout << "--------------------------http request begin--------------------------" << endl;
cout << buffer;
cout << "---------------------------http request end---------------------------" << endl;
// 解析请求方法
string request(buffer);
size_t method_end = request.find(' ');
string method = request.substr(0, method_end);
// 解析请求路径
size_t path_start = method_end + 1;
size_t path_end = request.find(' ', path_start);
string path = request.substr(path_start, path_end - path_start);
cout << "Method: " << method << endl;
cout << "Path: " << path << endl;
// 如果是根路径或表单提交路径,返回HTML
if (path == "/" || path.find('/') == 0) {
// 读取HTML文件
ifstream in("index.html", ios::binary); // 以二进制模式打开
if (in.is_open()) {
in.seekg(0, ios::end);
int file_size = in.tellg();
in.seekg(0, ios::beg);
char* file_content = new char[file_size + 1];
in.read(file_content, file_size);
file_content[file_size] = '\0';
in.close();
// 构建HTTP响应(正确的HTTP格式)
string response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n"; // 添加字符集
response += "Content-Length: " + to_string(file_size) + "\r\n";
response += "Connection: close\r\n";
response += "\r\n"; // 空行,分隔头部和正文
response += string(file_content, file_size);
send(sock, response.c_str(), response.size(), 0);
delete[] file_content;
} else {
// 404 Not Found
string response = "HTTP/1.1 404 Not Found\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n";
response += "\r\n";
response += "<html><body><h1>404 Not Found</h1></body></html>";
send(sock, response.c_str(), response.size(), 0);
}
}
}
close(sock);
exit(0);
}
close(sock);
waitpid(-1, nullptr, WNOHANG); // 非阻塞等待子进程
}
close(listen_sock);
return 0;
}
此时我们跑起来服务端,然后在浏览器上请求访问服务端:


浏览器访问与参数提交
-
当用浏览器访问服务器时,会显示上述两个表单。
-
如果选择使用 GET 方法提交参数,填充完用户名和密码并点击提交按钮后,用户名和密码会自动同步到 URL 当中。
-
例如,URL 可能变成
https://yourserver.com/submit?username=John&password=123456。 -
同时,在服务器端可以通过解析 URL 来获取刚才在浏览器提交的参数。


2、POST 方法提交
同上,为了方便测试,我们修改一下相关的代码:
index.html
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTTP Server Test</title>
</head>
<body>
<h1>Hello HTTP Server</h1>
<h2>POST 表单提交测试</h2>
<form method="POST" action="/">
User name:<br>
<input type="text" name="username" placeholder="Enter username">
<br><br>
User password:<br>
<input type="password" name="psw" placeholder="Enter password">
<br><br>
<input type="submit" value="Submit">
</form>
<hr>
<h3>调试信息:</h3>
<p>提交表单后,查看服务器控制台输出的请求信息和POST数据</p>
<p>注意:POST提交后URL不会变化,数据在请求体中</p>
<script>
// 显示当前URL
document.write('<p>当前URL: ' + window.location.href + '</p>');
document.write('<p>使用POST方法提交,数据不会显示在URL中</p>');
</script>
</body>
</html>
server.cpp
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sstream>
#include <vector>
using namespace std;
// 解析POST数据
string parsePostData(const string& request) {
size_t header_end = request.find("\r\n\r\n");
if (header_end == string::npos) {
return "";
}
string body = request.substr(header_end + 4);
// 查找Content-Length
size_t content_length_pos = request.find("Content-Length: ");
if (content_length_pos == string::npos) {
return "";
}
size_t content_length_end = request.find("\r\n", content_length_pos);
string content_length_str = request.substr(content_length_pos + 16,
content_length_end - content_length_pos - 16);
int content_length = stoi(content_length_str);
// 确保我们有完整的body
if (body.length() < (size_t)content_length) {
return "";
}
body = body.substr(0, content_length);
return body;
}
// 解析查询字符串(用于GET和POST的body)
void parseQueryString(const string& query, vector<pair<string, string>>& params) {
size_t start = 0;
while (start < query.length()) {
size_t end = query.find('&', start);
if (end == string::npos) {
end = query.length();
}
string param = query.substr(start, end - start);
size_t equal_pos = param.find('=');
if (equal_pos != string::npos) {
string key = param.substr(0, equal_pos);
string value = param.substr(equal_pos + 1);
params.push_back(make_pair(key, value));
}
start = end + 1;
}
}
int main()
{
// 创建套接字
int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock < 0) {
cerr << "socket error!" << endl;
return 1;
}
// 设置SO_REUSEADDR选项,避免"Address already in use"错误
int opt = 1;
if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
cerr << "setsockopt error!" << endl;
return 1;
}
// 绑定
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(8080);
local.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
cerr << "bind error!" << endl;
return 2;
}
// 监听
if (listen(listen_sock, 5) < 0) {
cerr << "listen error!" << endl;
return 3;
}
cout << "Server started on port 8080..." << endl;
cout << "Visit http://localhost:8080 in your browser" << endl;
// 启动服务器
for (;;) {
struct sockaddr_in peer;
memset(&peer, 0, sizeof(peer));
socklen_t len = sizeof(peer);
int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
if (sock < 0) {
cerr << "accept error!" << endl;
continue;
}
// 输出客户端信息
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &peer.sin_addr, client_ip, sizeof(client_ip));
cout << "\nConnection from: " << client_ip << ":" << ntohs(peer.sin_port) << endl;
if (fork() == 0) { // 子进程
close(listen_sock);
// 读取HTTP请求
char buffer[8192] = {0}; // 增加缓冲区大小以容纳POST数据
int bytes_received = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
cout << "--------------------------http request begin--------------------------" << endl;
cout << buffer;
cout << "---------------------------http request end---------------------------" << endl;
// 解析请求方法
string request(buffer);
size_t method_end = request.find(' ');
string method = request.substr(0, method_end);
// 解析请求路径
size_t path_start = method_end + 1;
size_t path_end = request.find(' ', path_start);
string path = request.substr(path_start, path_end - path_start);
cout << "Method: " << method << endl;
cout << "Path: " << path << endl;
// 解析POST数据
if (method == "POST") {
string postData = parsePostData(request);
if (!postData.empty()) {
cout << "POST Data: " << postData << endl;
// 解析POST参数
vector<pair<string, string>> params;
parseQueryString(postData, params);
cout << "Parsed POST parameters:" << endl;
for (const auto& param : params) {
cout << " " << param.first << " = " << param.second << endl;
}
}
}
// 解析GET参数
else if (method == "GET") {
size_t query_start = path.find('?');
if (query_start != string::npos) {
string query = path.substr(query_start + 1);
path = path.substr(0, query_start);
cout << "GET Query: " << query << endl;
// 解析GET参数
vector<pair<string, string>> params;
parseQueryString(query, params);
cout << "Parsed GET parameters:" << endl;
for (const auto& param : params) {
cout << " " << param.first << " = " << param.second << endl;
}
}
}
// 如果是根路径,返回HTML
if (path == "/" || path == "/index.html") {
// 读取HTML文件
ifstream in("index.html", ios::binary);
if (in.is_open()) {
in.seekg(0, ios::end);
int file_size = in.tellg();
in.seekg(0, ios::beg);
char* file_content = new char[file_size + 1];
in.read(file_content, file_size);
file_content[file_size] = '\0';
in.close();
// 构建HTTP响应
string response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n";
response += "Content-Length: " + to_string(file_size) + "\r\n";
response += "Connection: close\r\n";
response += "\r\n";
response += string(file_content, file_size);
send(sock, response.c_str(), response.size(), 0);
delete[] file_content;
} else {
// 404 Not Found
string response = "HTTP/1.1 404 Not Found\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n";
response += "Content-Length: 48\r\n";
response += "\r\n";
response += "<html><body><h1>404 Not Found</h1></body></html>";
send(sock, response.c_str(), response.size(), 0);
}
} else {
// 404 Not Found
string response = "HTTP/1.1 404 Not Found\r\n";
response += "Content-Type: text/html; charset=UTF-8\r\n";
response += "Content-Length: 48\r\n";
response += "\r\n";
response += "<html><body><h1>404 Not Found</h1></body></html>";
send(sock, response.c_str(), response.size(), 0);
}
}
close(sock);
exit(0);
}
close(sock);
waitpid(-1, nullptr, WNOHANG); // 非阻塞等待子进程
}
close(listen_sock);
return 0;
}
此时浏览器刚开始请求到服务器,如下:

可以看到,如果使用提交表单的方法为 POST 方法,填充完用户名和密码并点击提交按钮后,对应提交的参数不会在 URL 当中体现出来,而是会通过请求正文将这两个参数传递给服务器。服务器端需要通过读取请求正文来获取用户提交的数据。如下:


3、注意事项
数据敏感性
-
当我们使用 GET 方法时,提交的参数会回显到 URL 当中,因此 GET 方法一般用于处理数据不敏感的情况。
-
如果你要传递的数据比较私密(如密码、银行卡号等),一定要使用 POST 方法。
-
不过,再次强调,POST 方法并非更安全,只是相对更私密,因为 GET 和 POST 方法传参时都是明文传送,要实现真正的安全传输,必须使用加密技术。
通过以上对 HTTP 方法的详细讲解以及 Postman 和 TCP 套接字的演示,相信你对 HTTP 方法,尤其是 GET 和 POST 方法有了更深入的理解。在实际开发中,应根据具体需求合理选择合适的 HTTP 方法,以确保数据传输的正确性和安全性。
五、HTTP常见方法
HTTP (Hypertext Transfer Protocol) 定义了多种请求方法,用于指示要对给定资源执行的操作。
1、GET 方法(重点)
用途:用于请求 URL 指定的资源,是最常用的 HTTP 方法之一。
示例:
cpp
GET /index.html HTTP/1.1
Host: www.example.com
特性:
-
请求指定的资源,服务器返回解析后的响应内容
-
参数通常附加在 URL 后(如
?key1=value1&key2=value2) -
有长度限制(受 URL 最大长度限制)
-
可被缓存、保留在历史记录中
-
幂等的(多次相同请求应产生相同效果)
表单验证 :在 HTML 表单(HTML 表单 | 菜鸟教程)中,当 method="get" 时,表单数据会附加在 URL 上发送:
html
<form action="/submit" method="get">
<input type="text" name="username">
<input type="submit" value="Submit">
</form>

服务器端处理示例(C++):
cpp
std::string GetFileContentHelper(const std::string &path) {
// 简单的二进制文件读取代码
std::ifstream in(path, std::ios::binary);
if (!in.is_open()) return "";
in.seekg(0, in.end);
int filesize = in.tellg();
in.seekg(0, in.beg);
std::string content;
content.resize(filesize);
in.read((char *)content.c_str(), filesize);
in.close();
return content;
}
2、POST 方法(重点)
用途:用于传输实体的主体,通常用于提交表单数据或上传文件。
示例:
cpp
POST /submit.cgi HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
username=john&age=30
特性:
-
数据包含在请求体中
-
没有长度限制
-
不会被缓存
-
不会保留在历史记录中
-
不幂等(多次提交可能产生副作用)
表单验证 :当 method="post" 时,表单数据在请求体中发送:
html
<form action="/submit" method="post">
<input type="text" name="username">
<input type="submit" value="Submit">
</form>
3、PUT 方法(不常用)
用途:用于传输文件,将请求报文主体中的文件保存到请求 URL 指定的位置。
示例:
cpp
PUT /example.html HTTP/1.1
Host: www.example.com
Content-Type: text/html
Content-Length: 1256
<html>...</html>
特性:
-
用于创建或替换目标资源
-
客户端需要指定资源的完整表示
-
在 RESTful API 中常用于更新资源
-
幂等的(多次相同请求效果相同)
4、HEAD 方法
用途:与 GET 方法类似,但不返回报文主体部分,仅返回响应头。
示例:
cpp
HEAD /index.html HTTP/1.1
Host: www.example.com
特性:
-
用于获取资源的元信息而不传输实际内容
-
常用于:
-
检查资源是否存在
-
检查资源是否被修改(结合 Last-Modified 或 ETag)
-
检查服务器性能
-
curl 示例:
bash
# 完整请求(显示响应头和体)
curl -i www.baidu.com

bash
# 仅显示响应头
curl --head www.baidu.com

5、DELETE 方法(不常用)
用途:用于删除文件,是 PUT 的相反方法。
示例:
cpp
DELETE /example.html HTTP/1.1
Host: www.example.com
特性:
-
请求服务器删除指定的资源
-
在 RESTful API 中用于删除资源
-
幂等的(多次删除已不存在的资源不应报错)
6、OPTIONS 方法
用途:用于查询针对请求 URL 指定的资源支持的方法。
示例:
cpp
OPTIONS * HTTP/1.1
Host: www.example.com
特性:
-
返回服务器支持的 HTTP 方法
-
常用于 CORS (跨域资源共享) 预检请求
-
可用于检查服务器功能而不实际访问资源
服务器响应示例:
cpp
HTTP/1.1 200 OK
Allow: GET, HEAD, POST, OPTIONS
Content-Type: text/plain
Content-Length: 0
不支持 OPTIONS 的服务器响应:
cpp
HTTP/1.1 405 Not Allowed
Content-Type: text/html
Content-Length: 166
<html>
<head><title>405 Not Allowed</title></head>
<body>
<center><h1>405 Not Allowed</h1></center>
</body>
</html>
7、其他 HTTP 方法
TRACE 方法
- 用途:回显服务器收到的请求,主要用于诊断。
CONNECT 方法
- 用途:用于代理服务器,建立隧道连接(如 HTTPS)。
PATCH 方法
- 用途:用于对资源进行部分修改(RESTful API 中常用)。
8、方法特性总结
| 方法 | 幂等 | 安全 | 缓存 | 请求体 | 典型用途 |
|---|---|---|---|---|---|
| GET | 是 | 是 | 是 | 否 | 获取资源 |
| HEAD | 是 | 是 | 是 | 否 | 获取元信息 |
| POST | 否 | 否 | 可 | 是 | 提交数据 |
| PUT | 是 | 否 | 否 | 是 | 替换资源 |
| DELETE | 是 | 否 | 否 | 可 | 删除资源 |
| OPTIONS | 是 | 是 | 否 | 可 | 获取支持的方法 |
| PATCH | 否 | 否 | 可 | 是 | 部分更新资源 |
说明:
-
幂等:多次相同请求应产生相同效果
-
安全:不会修改服务器资源状态
-
缓存:响应是否可被缓存
9、实际应用建议
-
GET vs POST:
-
使用 GET 获取数据(参数在 URL 中可见)
-
使用 POST 提交数据(参数在请求体中)
-
-
RESTful API 设计:
-
GET /users - 获取用户列表
-
POST /users - 创建新用户
-
GET /users/1 - 获取特定用户
-
PUT /users/1 - 更新特定用户
-
DELETE /users/1 - 删除特定用户
-
-
安全考虑:
-
不要使用 GET 传输敏感信息(参数可见于 URL 和历史记录)
-
使用 HTTPS 保护所有方法的数据传输
-
-
性能优化:
-
使用 HEAD 先检查资源是否存在再决定是否下载
-
使用 OPTIONS 预先检查服务器支持的方法
-
理解这些 HTTP 方法及其特性对于开发健壮的 Web 应用程序和 API 至关重要。