You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firefox扩展PUT请求携带凭证问题:模拟沃尔玛加购请求

Hey there, let's figure out why your PUT request to Walmart's cart API isn't working from your Firefox extension's content script. The issue is almost certainly missing critical request headers that the site requires to authenticate the request—just setting withCredentials=true isn't enough for most modern e-commerce APIs. Here's how to fix it:

1. Capture all required request headers from a successful manual request

When you click the "Add to Cart" button manually, your browser sends a bunch of headers that Walmart uses to verify the request is legitimate. You need to replicate all of these in your XHR call.

Open Firefox DevTools (F12), go to the Network tab, filter for the PUT request to /api/v3/cart/:GCRT/items, then check the "Headers" tab. Look for headers like:

  • Authorization (usually a Bearer token)
  • X-Csrf-Token or similar anti-forgery token
  • User-Agent (must match your browser's exact user agent string)
  • Accept (matches the content types the API expects)
  • Any custom Walmart-specific headers (like X-Walmart-* or similar)

Your current code only sets Content-Type—you need to add all these missing headers with their exact values from the successful request.

2. Dynamically fetch dynamic tokens (don't hardcode!)

Tokens like the CSRF token or cart ID (:GCRT in the URL) are dynamic and change per session/user. You can't hardcode them—you need to extract them from the page:

  • Cart ID: Look for it in the page's URL, DOM elements (like a data attribute), or in a previous API response stored in localStorage/sessionStorage.
  • CSRF Token: Check the page's <meta> tags (common for frameworks like React/Angular) or extract it from a cookie. For example:
    // Fetch CSRF token from meta tag
    const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
    // Or from a cookie (use a helper function to parse cookies)
    function getCookie(name) {
      const value = `; ${document.cookie}`;
      const parts = value.split(`; ${name}=`);
      if (parts.length === 2) return parts.pop().split(';').shift();
    }
    const csrfToken = getCookie('csrfToken');
    

3. Fix your extension's permissions

Make sure your manifest.json includes the necessary host permissions to send requests to Walmart's API. Add this line:

"permissions": [
  "https://grocery.walmart.com/*",
  "cookies" // If you need to access cookies directly
]

Without these permissions, Firefox will block your request even if the headers are correct.

4. Consider using a background script instead of content script

Content scripts run in the page's context and have some limitations around cross-origin requests (even same-origin can have restrictions for certain headers). A background script has more permissions and can handle requests more reliably:

  1. Send a message from your content script to the background script with the cart item details.
  2. The background script sends the PUT request with all necessary headers and credentials.

Example background script code:

browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'addToCart') {
    fetch(`https://grocery.walmart.com/api/v3/cart/${message.cartId}/items`, {
      method: 'PUT',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json; charset=utf-8',
        'Authorization': message.authToken,
        'X-Csrf-Token': message.csrfToken,
        'User-Agent': navigator.userAgent
        // Add all other required headers here
      },
      body: JSON.stringify(message.cartItems)
    })
    .then(res => res.json())
    .then(data => sendResponse(data))
    .catch(err => sendResponse({ error: err.message }));
    return true; // Keep the message channel open for async response
  }
});

5. Verify your request URL

The :GCRT in your URL is a placeholder—you need to replace it with the actual cart ID for the logged-in user. You can find this ID in the manual request's URL (from DevTools) or extract it from the page's state.

Modified Content Script Example

Here's how your content script might look after adding all these fixes:

(function() {
  // 1. Extract dynamic values from the page
  const cartId = document.querySelector('[data-cart-id]')?.dataset.cartId; // Example DOM extraction
  const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
  const authToken = localStorage.getItem('walmart_auth_token'); // Example storage extraction

  if (!cartId || !csrfToken || !authToken) {
    console.error('Missing required tokens/cart ID');
    return;
  }

  const params = {"cartItems":[{"offerId":"8E5AE39B44CD467DAC4AAA3A0042110F","quantity":3}]};
  
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4) {
      if (this.status == 200) {
        const res = JSON.parse(xhttp.responseText);
        console.log('Success:', res);
      } else {
        console.error('Request failed:', this.status, this.responseText);
      }
    }
  };

  xhttp.open("PUT", `https://grocery.walmart.com/api/v3/cart/${cartId}/items`, true);
  xhttp.withCredentials = true;
  
  // Add all required headers
  xhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8");
  xhttp.setRequestHeader("Authorization", `Bearer ${authToken}`);
  xhttp.setRequestHeader("X-Csrf-Token", csrfToken);
  xhttp.setRequestHeader("User-Agent", navigator.userAgent);
  // Add other headers from your manual request here

  xhttp.send(JSON.stringify(params));
})();

The key takeaway is that modern APIs rely on multiple layers of authentication (cookies + tokens + custom headers) to prevent abuse. You need to replicate the exact request the browser sends when you click the button—every header, every dynamic value.

内容的提问来源于stack exchange,提问作者Vlada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:56:54