warning http

HTTP 307 Temporary Redirect

Understanding HTTP 307 Temporary Redirect - the resource temporarily resides at a different URL and the request method must not be changed.

What It Means

HTTP 307 Temporary Redirect indicates that the target resource resides temporarily under a different URI. Unlike 302, 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 302 Found.

Common Causes

  • Temporary API endpoint changes that need to preserve POST/PUT/DELETE methods
  • HTTPS enforcement that preserves request methods
  • Temporary load balancing or failover routing
  • API versioning with method-sensitive endpoints
  • Temporary maintenance redirects for non-GET endpoints

How to Fix

Express.js

// Redirect POST while preserving method
app.post('/api/v1/submit', (req, res) => {
  res.redirect(307, '/api/v2/submit');
  // The client will re-send the POST to /api/v2/submit
});

// HTTPS enforcement preserving method
app.use((req, res, next) => {
  if (!req.secure) {
    return res.redirect(307, `https://${req.headers.host}${req.url}`);
  }
  next();
});

Nginx

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

Python Flask

from flask import redirect

@app.route('/api/v1/data', methods=['POST', 'PUT', 'DELETE'])
def old_api():
    return redirect('/api/v2/data', code=307)

When to use 307 vs 302

302 Found:
  - Browser MAY change POST to GET (most do)
  - Use for redirects after form submission (PRG pattern)
  - Use when method change is acceptable

307 Temporary Redirect:
  - Browser MUST keep the same method
  - Use for API redirects where method matters
  - Use when POST/PUT/DELETE must be preserved

Client-side handling

// fetch follows 307 automatically and preserves the method
const response = await fetch('/api/v1/submit', {
  method: 'POST',
  body: JSON.stringify(data),
  headers: { 'Content-Type': 'application/json' }
});
// If 307, fetch will re-POST to the new URL automatically
  • HTTP 301 - Moved Permanently: Permanent redirect that may change POST to GET.
  • HTTP 302 - Found: Temporary redirect that may change POST to GET.
  • HTTP 308 - Permanent Redirect: Permanent redirect that preserves the request method.