编程 HTTP QUERY方法深度剖析:为什么GET和POST之间的鸿沟终于被填平了

2026-07-24 11:44:45 +0800 CST views 6

HTTP QUERY方法深度剖析:为什么GET和POST之间的鸿沟终于被填平了

2026年6月,IETF正式发布了RFC 10008,为HTTP协议引入了一个全新的请求方法——QUERY。这不是一个小改动,而是自HTTP/1.1标准化以来最重要的方法扩展之一。本文从工程师视角,深度拆解QUERY方法的诞生背景、核心语义、工程实现,以及它将如何重塑API设计。

一、为什么我们需要QUERY?GET与POST之间的那道鸿沟

1.1 GET的困境:URL长度限制与复杂查询

在RESTful API的世界里,GET方法是获取资源的首选。它的语义清晰——安全(不会修改服务器状态)和幂等(多次请求结果相同)。HTTP规范将GET定义为只读操作,浏览器和缓存中间件可以放心地重试、预取和缓存GET请求。

但GET有一个根本性的限制:查询参数必须编码在URL中

这在大多数场景下没有问题——几十个字节的过滤条件、几个分页参数,URL完全装得下。但当查询变得复杂时,问题就来了:

复杂搜索场景:想象一个企业级搜索API,用户需要按20多个字段进行组合过滤,包括嵌套的日期范围、多值标签、地理围栏坐标数组……把这些全部塞进URL查询字符串,要么超出浏览器和服务器的URL长度限制(RFC 7231建议不超过8000字节),要么让URL变得不可读、不可维护。

GraphQL式查询:当你需要向服务端传递一个结构化的查询描述(比如过滤表达式、排序规则、字段选择集)时,URL根本不是合适的载体。你可以把JSON序列化成URL编码的字符串塞进去,但这既不优雅也容易出错。

敏感数据的两难:查询参数在URL中,意味着它们会出现在浏览器历史记录、服务器日志、CDN缓存key、Referer头、代理日志……任何一个环节都可能泄露敏感信息。PUT/POST/PATCH的请求体不会出现在这些地方,但它们不是幂等的

1.2 POST的妥协:非幂等性的代价

面对复杂查询的现实需求,大多数开发者选择妥协——用POST代替GET,把查询参数放到请求体中。这在工程实践中非常普遍,甚至成为了一种"Post-Get"反模式:

POST /api/search HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "filters": {
    "status": ["active", "pending"],
    "created_after": "2026-01-01",
    "tags": ["vip", "priority"],
    "geo": {
      "lat": 39.9042,
      "lng": 116.4074,
      "radius_km": 50
    }
  },
  "pagination": {"page": 1, "size": 20},
  "sort": [{"field": "created_at", "order": "desc"}]
}

这样做能工作,但代价是什么?

语义混乱:POST本意是"向指定资源提交数据,可能修改服务器状态"。用它来查询只读数据,语义上驴唇不对马嘴。任何看到这个请求的开发者或运维人员,第一反应都是"这个请求在修改什么?"

幂等性丧失:POST不是幂等的。相同的POST请求在不同时间点发送,可能因为服务器状态变化而产生不同结果。这意味着:中间件不能安全地重试POST请求(网络超时重试可能导致数据被重复提交),缓存层无法判断POST是否可缓存,负载均衡器的某些优化策略也受限。

缓存不兼容:HTTP缓存机制(ETag、Last-Modified、条件请求)都是为GET设计的。POST请求的响应默认不会被任何HTTP缓存层缓存,即使查询本身是完全只读的。

1.3 填补鸿沟:QUERY方法的诞生

正是GET和POST之间的这道语义鸿沟,催生了QUERY方法。2026年6月,IETF正式发布了RFC 10008,为HTTP引入了一个全新方法:

QUERY方法:一种安全的(safe)、幂等的(idempotent)HTTP方法,允许携带请求体,用于执行只读查询。

这句话的每一个词都是精心设计的:

  • 安全:不会修改服务器状态,与GET一样可以放心让中间件处理
  • 幂等:多次相同请求返回相同结果,与GET一样可以安全重试
  • 携带请求体:突破了URL长度限制,可以传递复杂结构化查询
  • 只读查询:语义明确,告诉所有阅读代码的人——这个请求只读取数据

二、QUERY方法的RFC语义深度解析

2.1 方法定义(RFC 10008核心条款)

QUERY方法的核心语义规定如下:

QUERY请求的特征:
1. 方法语义:请求服务器根据请求体中的内容执行查询操作
2. 安全性:不会在服务器上产生副作用(即不会修改资源状态)
3. 幂等性:相同请求总产生相同结果
4. 请求体:可以包含任何媒体类型(Content-Type由客户端声明)
5. 响应码:通常返回200 OK,响应体为查询结果
6. 缓存性:响应可缓存(需配合Cache-Control语义)

对比一下三种方法的核心差异:

特性GETPOSTQUERY
安全(无副作用)
幂等(可安全重试)
可携带请求体
可缓存❌(默认)
URL参数传递❌(用请求体)

2.2 状态码语义

QUERY方法的响应状态码遵循标准HTTP语义,但有几个值得注意的点:

200 OK:查询成功,响应体包含查询结果。这是正常情况下的标准响应码。

400 Bad Request:请求格式错误(如无法解析Content-Type,或请求体JSON格式错误)。QUERY方法对请求体格式有明确要求。

404 Not Found:查询目标资源不存在。注意这里有个语义微妙之处——QUERY是"查询"而非"获取",所以404的含义是"查询操作执行了,但找不到匹配的资源"。

409 Conflict:在某些场景下,QUERY操作本身可能与服务器当前状态冲突(例如查询语法与资源当前schema不兼容)。

5xx Server Error:服务器内部错误,与其他方法一致。

2.3 与现有"变通方案"的对比

在QUERY方法出现之前,开发者社区已经发展出多种绕过GET限制的变通方案:

方案一:GET + Base64编码的JSON

GET /api/search?q=eyJmaWx0ZXIiOiAidGVzdCJ9 HTTP/1.1

问题:URL仍然是参数载体,base64编码使长度增加33%,且编码后的字符串容易在日志中产生混淆。

方案二:POST with X-HTTP-Method-Override

POST /api/search HTTP/1.1
X-HTTP-Method-Override: GET
Content-Type: application/json

{"query": "..."}

这是Google推广的方案,通过HTTP头声明实际方法。问题:这是一个约定俗成的非标准方案,需要服务器和所有中间件都理解并支持这个头。幂等性仍然无法被HTTP基础设施识别。

方案三:GraphQL POST端点

POST /graphql HTTP/1.1
Content-Type: application/json

{"query": "..."}

GraphQL的方案其实已经证明了"用POST做查询"的工程价值,但GraphQL是一个完整的查询语言和运行时,不是一个HTTP方法。引入GraphQL意味着引入一套新的生态。

QUERY方法的优雅之处在于:它不需要引入任何新协议,不需要任何约定俗成的约定,直接用标准HTTP语义解决这个具体问题。

三、工程实现:从理论到代码

3.1 Go语言服务器端实现

让我们从零实现一个支持QUERY方法的Go HTTP服务器。首先,我们需要理解QUERY方法在Go中的处理方式:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

// SearchRequest 定义查询请求的结构
type SearchRequest struct {
	Filters struct {
		Status      []string `json:"status"`
		Tags        []string `json:"tags"`
		CreatedAfter string   `json:"created_after"`
	} `json:"filters"`
	Pagination struct {
		Page int `json:"page"`
		Size int `json:"size"`
	} `json:"pagination"`
	Sort []struct {
		Field string `json:"field"`
		Order string `json:"order"`
	} `json:"sort"`
}

// SearchResponse 定义查询响应的结构
type SearchResponse struct {
	Total int                   `json:"total"`
	Page  int                   `json:"page"`
	Items []map[string]any      `json:"items"`
}

// handleQuery 处理QUERY请求
func handleQuery(w http.ResponseWriter, r *http.Request) {
	// 1. 验证HTTP方法
	if r.Method != http.MethodQuery {
		// QUERY在Go标准库中需要自定义注册
		// 或者我们可以使用"POST"并通过header区分
		// 这里演示的是标准QUERY语义
		http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}

	// 2. 验证Content-Type
	contentType := r.Header.Get("Content-Type")
	if contentType == "" {
		http.Error(w, "Content-Type header required", http.StatusBadRequest)
		return
	}

	// 3. 解析请求体
	var req SearchRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
		return
	}

	// 4. 执行查询(模拟)
	// 在真实场景中,这里会连接数据库、执行搜索
	total, items := executeMockSearch(&req)

	// 5. 返回响应
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Cache-Control", "private, max-age=60") // QUERY响应可以设置缓存
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(SearchResponse{
		Total: total,
		Page:  req.Pagination.Page,
		Items: items,
	})
}

// executeMockSearch 模拟搜索执行
func executeMockSearch(req *SearchRequest) (int, []map[string]any) {
	// 这里是模拟数据,实际会查数据库
	return 42, []map[string]any{
		{"id": 1, "title": "示例结果1", "status": "active"},
		{"id": 2, "title": "示例结果2", "status": "pending"},
	}
}

func main() {
	// Go标准库默认不支持QUERY方法注册
	// 需要通过路由库如chi、gorilla/mux或直接手动路由
	mux := http.NewServeMux()

	// 方式一:直接用ServeMux注册,通过方法名区分
	mux.HandleFunc("/search", func(w http.ResponseWriter, r *http.Request) {
		// 手动判断方法
		if r.Method == "QUERY" || r.Header.Get("X-Method") == "QUERY" {
			handleQuery(w, r)
		} else {
			http.Error(w, "Not Found", http.StatusNotFound)
		}
	})

	log.Println("Server listening on :8080")
	log.Fatal(http.ListenAndServe(":8080", mux))
}

3.2 Go标准库对QUERY的支持(Go 1.27+)

Go 1.27(预计2026年8月正式发布)已经为QUERY方法提供了原生支持。让我们看看如何使用标准库实现:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"
)

func main() {
	// Go 1.27+ 中QUERY方法是预定义常量
	// http.MethodQuery == "QUERY"

	mux := http.NewServeMux()

	// 使用原生QUERY方法注册处理器
	mux.HandleFunc("QUERY /api/search", func(w http.ResponseWriter, r *http.Request) {
		// r.Method 已经是 "QUERY"
		// r.Body 直接读取请求体

		var req SearchRequest
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			http.Error(w, "Bad Request", http.StatusBadRequest)
			return
		}

		// 执行查询
		results := performSearch(req)

		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(results)
	})

	// 设置超时(QUERY作为只读操作,也应该设置合理超时)
	srv := &http.Server{
		Addr:         ":8080",
		Handler:      mux,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 30 * time.Second,
	}

	log.Println("Listening on :8080 with native QUERY support")
	log.Fatal(srv.ListenAndServe())
}

type SearchRequest struct {
	Query string `json:"query"`
	Page  int    `json:"page"`
	Size  int    `json:"size"`
}

type SearchResult struct {
	Total int      `json:"total"`
	Items []string `json:"items"`
}

func performSearch(req SearchRequest) SearchResult {
	// 实际场景查数据库
	return SearchResult{
		Total: 100,
		Items: []string{"result1", "result2"},
	}
}

3.3 客户端实现

curl发送QUERY请求:

# 发送QUERY请求(curl 8.10+ 支持METHOD参数)
curl -X QUERY https://api.example.com/search \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "status": ["active"],
      "tags": ["vip"]
    },
    "pagination": {"page": 1, "size": 20}
  }'

# 查看响应头(注意Cache-Control和Content-Type)
curl -X QUERY https://api.example.com/search \
  -H "Content-Type: application/json" \
  -d '{"query": "test"}' \
  -i

Python requests库实现:

import requests

# 发送QUERY请求
response = requests.query(
    "https://api.example.com/search",
    json={
        "filters": {
            "status": ["active", "pending"],
            "created_after": "2026-01-01",
            "tags": ["vip"]
        },
        "pagination": {"page": 1, "size": 20},
        "sort": [{"field": "created_at", "order": "desc"}]
    }
)

print(f"Status: {response.status_code}")
print(f"Cacheable: {'Cache-Control' in response.headers}")
print(f"Results: {response.json()}")

TypeScript / Fetch API实现:

// 浏览器中的QUERY请求
async function searchAPI(params: SearchParams): Promise<SearchResult> {
  const response = await fetch('/api/search', {
    method: 'QUERY',  // 现代浏览器支持QUERY方法
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(params),
    // 注意:credentials和cache的行为与GET一致
    credentials: 'same-origin',
  });

  if (!response.ok) {
    throw new Error(`Search failed: ${response.status}`);
  }

  return response.json();
}

// 对于不支持QUERY方法的旧版浏览器,可以fallback到POST with override
async function searchWithFallback(params: SearchParams): Promise<SearchResult> {
  try {
    // 尝试原生QUERY
    return await searchAPI(params);
  } catch (e) {
    // Fallback到method override方案
    const response = await fetch('/api/search', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-HTTP-Method-Override': 'QUERY',
      },
      body: JSON.stringify(params),
    });
    return response.json();
  }
}

3.4 中间件与网关层支持

作为API网关的维护者,你需要考虑如何处理QUERY请求:

Nginx配置(通过Lua扩展支持QUERY):

server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        # 需要ngx_http_lua_module支持
        access_by_lua_block {
            local method = ngx.req.get_method()
            if method == "QUERY" then
                -- 验证Content-Type
                local ct = ngx.req.get_headers()["content-type"]
                if not ct then
                    ngx.status = ngx.HTTP_BAD_REQUEST
                    ngx.say('{"error": "Content-Type required"}')
                    return ngx.exit(ngx.HTTP_BAD_REQUEST)
                end
                -- 读取body用于日志脱敏
                ngx.req.read_body()
            end
        }

        proxy_pass http://backend;
        # QUERY请求的缓存配置可以与GET类似
        proxy_cache_valid 200 60s;
    }
}

Caddy配置(原生支持):

:8080 {
    # Caddy 3.0+ 原生支持QUERY方法
    @query method QUERY
    handle @query {
        reverse_proxy localhost:9000
        header Cache-Control "private, max-age=60"
    }
}

四、QUERY方法的最佳实践

4.1 Content-Type选择

QUERY方法本身不限定请求体格式,但社区已经形成了初步共识:

application/json:最通用的选择,适合结构化查询表达式。几乎所有现代编程语言都有成熟的JSON解析支持。

{
  "where": {
    "status": {"$in": ["active", "pending"]},
    "created_at": {"$gte": "2026-01-01"}
  },
  "select": ["id", "title", "status"],
  "order_by": [{"field": "created_at", "direction": "desc"}],
  "limit": 20,
  "offset": 0
}

application/x-www-form-urlencoded:兼容传统HTML表单,在简单场景下比JSON更轻量。

application/xml:对于已有XML生态的系统,QUERY也完全支持。

4.2 与GraphQL的对比

QUERY方法和GraphQL解决了一部分重叠的问题,但它们的定位不同:

QUERY方法:作为HTTP协议层面的扩展,适合已经使用REST API、需要处理复杂查询但不想要GraphQL完整复杂度的项目。QUERY不需要引入新的查询语言——你可以继续使用你熟悉的JSON查询表达式。

GraphQL:是一套完整的查询语言+运行时+工具链。引入GraphQL意味着引入schema定义语言、GraphQL服务器、GraphQL客户端库……重量级很多,但也更成熟。

简单来说:QUERY让你用标准HTTP语义做复杂查询,GraphQL让你用专门的查询语言做复杂查询。两者不是非此即彼的选择,而是针对不同场景的工具。

4.3 与OpenAPI规范的集成

QUERY方法正在被纳入OpenAPI规范(OAS 4.0草案中已包含):

openapi: 4.0.0
info:
  title: Query API Example
  version: 1.0.0
paths:
  /search:
    post:  # 当前规范草案中使用POST表示QUERY语义
      operationId: searchResources
      summary: Search resources
      # 未来版本会有专门的方法字段
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'

components:
  schemas:
    SearchRequest:
      type: object
      properties:
        filters:
          type: object
        pagination:
          $ref: '#/components/schemas/Pagination'
    SearchResponse:
      type: object
      properties:
        total:
          type: integer
        items:
          type: array
    Pagination:
      type: object
      properties:
        page:
          type: integer
        size:
          type: integer

4.4 缓存策略

QUERY作为安全且幂等的方法,其响应默认可以被HTTP缓存层缓存。这带来了一个重要的设计决策:查询结果的缓存失效策略

策略一:基于时间的缓存

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=60
ETag: "abc123"

{
  "total": 42,
  "items": [...]
}

适合数据变化不频繁的场景。60秒内相同查询直接返回缓存。

策略二:基于数据版本的缓存

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private, max-age=0, must-revalidate
Last-Modified: Sat, 24 Jul 2026 12:00:00 GMT
Vary: Content-Type

{
  "total": 42,
  "items": [...]
}

适合数据变化频繁的场景,每次都验证数据是否变化。

策略三:CDN层缓存(边缘计算)

QUERY请求配合CDN可以实现边缘查询——在CDN节点上执行查询逻辑,减少回源次数:

// 在CDN边缘节点执行查询(伪代码)
func edgeQueryHandler(c *edge.Context) {
    req := c.ReadJSONBody()

    // 生成缓存key(基于请求体hash)
    cacheKey := fmt.Sprintf("query:%x", sha256.Sum256(req.Body))

    if cached := c.Cache().Get(cacheKey); cached != nil {
        c.WriteJSON(cached)
        return
    }

    // 回源到主数据中心
    result := originQuery(req)
    c.Cache().Set(cacheKey, result, 60*time.Second)
    c.WriteJSON(result)
}

五、性能优化与生产实践

5.1 避免大Body的陷阱

QUERY方法的请求体虽然是可选的,但一旦携带,就面临着和POST一样的性能考量:

问题:请求体的解析和传输会增加延迟。对于简单的过滤条件,URL参数可能比Body更高效。

建议:为请求体大小设置合理的限制。在服务器端配置:

// 限制请求体大小,防止恶意大Body攻击
const MaxBodySize = 10 * 1024 * 1024 // 10MB

mux.HandleFunc("QUERY /search", func(w http.ResponseWriter, r *http.Request) {
    r.Body = http.MaxBytesReader(w, r.Body, MaxBodySize)
    // 继续处理...
})

5.2 超时设置的艺术

QUERY作为只读操作,超时设置需要格外精细:

// 分层超时设置
type TimeoutConfig struct {
    ReadHeader  time.Duration // 读取请求头
    ReadBody   time.Duration // 读取请求体
    Processing time.Duration // 查询处理
    Write      time.Duration // 写入响应
}

func queryHandler(config TimeoutConfig) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        ctx, cancel := context.WithTimeout(r.Context(), config.Processing)
        defer cancel()
        r = r.WithContext(ctx)

        // 设置读取超时
        deadline := time.Now().Add(config.ReadBody)
        r.Body.(interface {
            SetReadDeadline(time.Time) error
        }).SetReadDeadline(deadline)

        // 执行查询...
    }
}

5.3 错误处理的标准化

QUERY方法的错误响应应该与RESTful API的整体错误处理风格保持一致:

// 统一的错误响应结构
type ErrorResponse struct {
    Error struct {
        Code    string `json:"code"`
        Message string `json:"message"`
        Details any    `json:"details,omitempty"`
    } `json:"error"`
}

func writeQueryError(w http.ResponseWriter, code int, errCode, message string, details any) {
    w.Header().Set("Content-Type", "application/problem+json")
    w.WriteHeader(code)
    json.NewEncoder(w).Encode(ErrorResponse{
        Error: struct {
            Code    string `json:"code"`
            Message string `json:"message"`
            Details any    `json:"details,omitempty"`
        }{
            Code:    errCode,
            Message: message,
            Details: details,
        },
    })
}

// 使用示例
writeQueryError(w, http.StatusBadRequest, "INVALID_QUERY",
    "Failed to parse query expression",
    map[string]string{"field": "filters.status", "reason": "expected array"})

六、未来展望:QUERY方法将走向何方

6.1 标准化进程

RFC 10008只是起点。IETF HTTP Working Group已经在讨论以下扩展方向:

Accept-Query头:允许客户端声明自己能够处理哪种查询响应格式,类似Accept头的作用:

QUERY /search HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept-Query: application/json, application/xml

{"query": "..."}

批量QUERY:在单一请求中执行多个查询,减少网络往返:

QUERY /batch HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "queries": [
    {"id": "q1", "endpoint": "/users", "params": {...}},
    {"id": "q2", "endpoint": "/orders", "params": {...}}
  ]
}

6.2 与MCP协议的结合

Model Context Protocol(MCP)是一个新兴的AI Agent工具调用标准。QUERY方法的出现为MCP提供了一种标准化的"只读工具查询"语义:

// MCP工具定义,使用QUERY方法
{
  "tools": [
    {
      "name": "search_database",
      "description": "Execute a complex search query against the database",
      "method": "QUERY",
      "endpoint": "/api/db/search",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sql": {"type": "string"},
          "params": {"type": "object"}
        }
      }
    }
  ]
}

在MCP的上下文中,QUERY的幂等性特别有价值——AI Agent可以安全地重试失败的查询调用,而不用担心重复操作。

6.3 浏览器支持展望

目前主流浏览器已经开始讨论QUERY方法的原生支持。Web Platform Tests(WPT)测试套件已经包含了QUERY方法的测试用例。一旦主流浏览器全面支持,QUERY将进入数百万Web应用的开发实践:

// 未来的浏览器QUERY API(提案)
const result = await fetch('/api/search', {
  method: 'QUERY',
  body: JSON.stringify({ query: '...' }),
  signal: AbortSignal.timeout(10000)
});

// Service Worker中的QUERY支持
self.addEventListener('fetch', event => {
  if (event.request.method === 'QUERY') {
    // 拦截QUERY请求,应用缓存策略
    event.respondWith(handleQueryRequest(event.request));
  }
});

七、总结:QUERY方法的意义

HTTP QUERY方法(RFC 10008)的发布,标志着HTTP协议自1999年(HTTP/1.1 RFC 2616)以来最重大的方法扩展终于落地。它不是一个小修小补的改进,而是对RESTful API设计二十年实践经验的系统性回应。

对API设计者而言:QUERY让API语义更精确。查询就是查询,不需要用POST的"副作用语义"来掩盖一个只读操作。接口文档、代码审查、日志分析——所有环节都将受益于语义的精确表达。

对基础设施而言:QUERY打通了HTTP缓存体系的最后一公里。只读查询现在可以享受与GET一样的CDN缓存、304 Not Modified条件请求、浏览器历史记录等优化。

对开发者体验而言:QUERY让复杂查询不再是URL编码的噩梦。结构化的请求体让查询表达式可读、可维护、可版本控制。

对AI Agent而言:QUERY的幂等性让AI可以安全地重试、探索和优化查询调用,而不用担心"这个操作是否改变了服务器状态"的不确定性。

这不是HTTP的终点,而是API设计进入新阶段的起点。当协议层提供了正确的语义工具,工程实践就会自然涌现出更好的设计模式。


参考资源

  • RFC 10008 - HTTP QUERY Method(https://www.rfc-editor.org/rfc/rfc10008)
  • IETF HTTP Working Group(https://httpwg.org/)
  • Go 1.27 Release Notes(待发布)
  • Web Platform Tests - QUERY Method(https://github.com/web-platform-tests/wpt)

标签:HTTP|QUERY|RFC|API设计|REST|幂等|云原生|Web标准

复制全文 生成海报 HTTP QUERY RFC API设计 REST 幂等 云原生 Web标准

推荐文章

微信小程序热更新
2024-11-18 15:08:49 +0800 CST
Vue3中的JSX有什么不同?
2024-11-18 16:18:49 +0800 CST
Nginx负载均衡详解
2024-11-17 07:43:48 +0800 CST
介绍 Vue 3 中的新的 `emits` 选项
2024-11-17 04:45:50 +0800 CST
阿里云免sdk发送短信代码
2025-01-01 12:22:14 +0800 CST
OpenCV 检测与跟踪移动物体
2024-11-18 15:27:01 +0800 CST
使用临时邮箱的重要性
2025-07-16 17:13:32 +0800 CST
Vue3中的自定义指令有哪些变化?
2024-11-18 07:48:06 +0800 CST
程序员茄子在线接单