Skip to main content

API 設計拿資料要透過 POST,會有什麼問題嗎?

問題一:違反 RESTful 設計原則

  • 說明:在 RESTful API 設計中,HTTP 方法有明確的語義:

    • GET:用於查詢或獲取資源,應該是安全的(不改變伺服器狀態)且具冪等性(多次請求結果相同)。

    • POST:通常用於創建資源或執行非冪等操作(例如提交表單、創建新資料)。 使用 POST 來拿資料違反了這些語義,可能會讓 API 的設計顯得不直觀,增加其他開發者的困惑。

  • 問題影響

    • 前端工程師或後端工程師在維護或使用 API 時,可能會誤解 API 的用途。

    • 其他使用你 API 的開發者(例如第三方)可能會因為不符合 RESTful 規範而感到混亂。

  • 解決方法

    • 使用 GET 方法來處理純資料查詢。例如,假設你要查詢用戶資料:

      // GET 請求範例
      fetch("https://api.example.com/users?userId=123", {
      method: "GET",
      headers: {
      "Content-Type": "application/json",
      },
      })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("錯誤:", error));

問題二:無法利用快取機制

  • 說明:GET 請求可以被瀏覽器、CDN 或代理伺服器快取,這能減少伺服器的負載並提升效能。POST 請求通常不會被快取,因為它被認為是動態的、非冪等的操作。

  • 問題影響

    • 如果你用 POST 來查詢資料,每次請求都會直接發送到伺服器,無法利用快取,增加伺服器負擔,特別是在高流量場景下。

    • 這可能導致前端頁面載入速度變慢,影響使用者體驗。

  • 解決方法

    • 使用 GET 並在請求中添加適當的查詢參數(Query Parameters)。例如:

      // 使用 GET 查詢多個條件
      fetch("https://api.example.com/products?category=electronics&price=1000", {
      method: "GET",
      headers: {
      "Content-Type": "application/json",
      },
      })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("錯誤:", error));
    • 如果需要快取,確保後端 API 設置適當的快取頭(Cache-Control)。


問題三:安全性問題

  • 說明:POST 請求通常用於傳送敏感資料(例如表單資料),因為它的資料放在請求主體(Body)中,不會顯示在 URL 中。然而,如果用 POST 來查詢資料,可能會誤導開發者認為查詢操作需要隱藏參數,這可能導致不必要的複雜性。

  • 問題影響

    • 如果查詢參數並不敏感,卻使用 POST,可能會讓 API 設計顯得過於複雜。

    • 如果查詢參數確實敏感(例如包含個人資料),將參數放在 POST 的 Body 中確實比 GET 的 URL 安全,但這不是 POST 的主要用途,可能會讓其他開發者誤解 API 的意圖。

  • 解決方法

    • 如果查詢不涉及敏感資料,使用 GET 並將參數放在 URL 的查詢字串中。

    • 如果涉及敏感資料,考慮使用 GET 並透過 HTTPS 加密傳輸,或者在特殊情況下使用 POST,但需清楚註明這是為了安全考量。例如:

      // 使用 POST 傳送敏感查詢(不建議作為標準做法)
      fetch("https://api.example.com/secure-data", {
      method: "POST",
      headers: {
      "Content-Type": "application/json",
      },
      body: JSON.stringify({
      userId: "123",
      token: "abc123",
      }),
      })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("錯誤:", error));

問題四:開發與除錯困難

  • 說明:GET 請求的查詢參數會顯示在 URL 中,這使得前端工程師在開發或除錯時更容易檢查請求內容。POST 請求的參數放在 Body 中,必須透過工具(例如 Postman 或瀏覽器的開發者工具)才能看到,增加了除錯的複雜度。

  • 問題影響

    • 前端工程師在測試 API 時,可能需要額外設置 Body 內容,增加操作步驟。

    • 如果 API 文件沒有清楚說明 POST 的 Body 格式,可能會導致前端與後端溝通成本上升。

  • 解決方法

    • 將查詢操作改用 GET 方法,讓參數直接顯示在 URL 中,方便除錯。例如:

      // GET 請求,參數直接在 URL 中
      fetch("https://api.example.com/users?name=John&age=30", {
      method: "GET",
      headers: {
      "Content-Type": "application/json",
      },
      })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("錯誤:", error));
    • 如果必須使用 POST,確保後端提供清晰的 API 文件,說明 Body 的格式,例如使用 JSON Schema 或範例。


問題五:SEO 和書籤問題

  • 說明:如果你的應用程式涉及網頁前端,且查詢結果需要被搜尋引擎索引(例如搜尋頁面),GET 請求的 URL 可以被搜尋引擎輕易抓取並索引,而 POST 請求無法做到這一點。

  • 問題影響

    • 使用 POST 查詢可能導致搜尋引擎無法正確索引你的頁面內容,影響 SEO(搜尋引擎最佳化)。

    • 使用者也無法將查詢結果的 URL 儲存為書籤或分享,因為 POST 請求的參數不在 URL 中。

  • 解決方法

    • 使用 GET 請求,讓查詢參數成為 URL 的一部分,方便分享和索引。例如:

      // GET 請求,URL 可分享
      fetch("https://api.example.com/search?query=javascript", {
      method: "GET",
      headers: {
      "Content-Type": "application/json",
      },
      })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error("錯誤:", error));

什麼情況下可以用 POST 來拿資料?

雖然不建議使用 POST 來查詢資料,但在某些特殊場景下,POST 可能是合理的選擇:

  1. 查詢參數過長:GET 請求的 URL 長度受限(通常是 2048 個字元,視瀏覽器而定)。如果查詢參數非常複雜或長度過長,POST 可以將參數放在 Body 中,繞過這個限制。

    // POST 處理大量參數
    fetch("https://api.example.com/complex-query", {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    },
    body: JSON.stringify({
    filters: {
    category: "electronics",
    priceRange: [500, 2000],
    brands: ["brandA", "brandB", "brandC"],
    },
    }),
    })
    .then((response) => response.json())
    .then((data) => console.log(data))
    .catch((error) => console.error("錯誤:", error));
  2. 敏感資料:如果查詢涉及敏感資料(例如身份驗證 token),POST 的 Body 比 GET 的 URL 更安全。

  3. 非 RESTful API:如果你的 API 不遵循 RESTful 規範(例如某些舊系統或特殊設計),POST 可能被用來處理查詢。


總結與建議

  • 建議:盡量使用 GET 方法來處理資料查詢,因為它符合 RESTful 規範、支援快取、易於除錯且對 SEO 友善。

  • 操作步驟

    1. 確認查詢是否涉及敏感資料或大量參數。

    2. 如果是簡單查詢,使用 GET 並將參數放在 URL 的查詢字串中。

    3. 如果必須使用 POST,確保後端提供清晰的文件,說明 Body 格式,並在前端使用 fetch 或 axios 正確傳送請求。

    4. 測試時使用瀏覽器的開發者工具(F12)檢查請求是否正確發送。