warning http

HTTP 308 Permanent Redirect

Understanding HTTP 308 Permanent Redirect - the resource has permanently moved to a new URL and the request method must not be changed.

What It Means

HTTP 308 Permanent Redirect indicates that the target resource has been assigned a new permanent URI. Unlike 301, the client must not change the request method when following the redirect. If the original request was a POST, the redirected request must also be a POST.

This is the method-preserving equivalent of 301 Moved Permanently. Search engines will update their links to the new URL, just like with 301.

Common Causes

  • Permanent API endpoint changes that need to preserve POST/PUT/DELETE methods
  • Domain migration for API endpoints
  • Permanent URL restructuring for method-sensitive routes
  • Enforcing canonical URLs for API endpoints

How to Fix

Express.js

// Permanent redirect preserving HTTP method
app.all('/api/v1/*', (req, res) => {
  const newPath = req.path.replace('/api/v1/', '/api/v2/');
  res.redirect(308, newPath);
});

Nginx

# Permanent redirect preserving method
location /api/v1/ {
    return 308 https://api.example.com/api/v2/$request_uri;
}

Apache

# Permanent redirect preserving method
Redirect 308 /api/v1 https://api.example.com/api/v2

Choosing the right redirect code

             | Temporary | Permanent
-------------+-----------+----------
May change   |    302    |   301
method       |           |
-------------+-----------+----------
Must keep    |    307    |   308
same method  |           |

Client-side handling

// fetch follows 308 automatically and preserves the method
const response = await fetch('/api/v1/users', {
  method: 'PUT',
  body: JSON.stringify(userData),
  headers: { 'Content-Type': 'application/json' }
});
// The PUT will be re-sent to the new permanent URL
console.log(response.url); // The final URL after redirect

Best practices:

  • Use 308 instead of 301 for API endpoints that accept POST/PUT/DELETE
  • Ensure the Location header contains the new permanent URL
  • Update client code to point to the new URL directly to avoid redirect overhead
  • HTTP 301 - Moved Permanently: Permanent redirect that may change POST to GET.
  • HTTP 302 - Found: Temporary redirect that may change POST to GET.
  • HTTP 307 - Temporary Redirect: Temporary redirect that preserves the request method.