🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

So beheben Sie einen Fehler bei der CORS Preflight OPTIONS-Anfrage in der Produktion

⏱️5 min read  ·  889 words

Ihre API funktioniert in der Entwicklung, schlägt jedoch in der Produktion mitfehl CORS-Preflight-Anfrage besteht die Zugriffskontrollprüfung nicht oder die OPTIONS-Anfrage gibt 404/405 zurück. Preflight-Fehler sind ein häufiges CORS-Problem, das nur in der Produktion auftritt. Hier erfahren Sie, wie Sie sie diagnostizieren und beheben können.

Was ist eine Preflight-Anfrage?

Bei „nicht einfachen“ Anfragen (PUT, DELETE, benutzerdefinierte Header oder JSON-Inhaltstyp) sendet der Browser einOPTIONEN Anfrage zuerst – der „Preflight“ – um den Server zu fragen, ob die echte Anfrage zulässig ist. Wenn der Preflight fehlschlägt, wird die eigentliche Anfrage nie ausgeführt. Preflight-Fehler treten aufgrund unterschiedlicher Serverkonfigurationen häufig nur in der Produktion auf.

# Browser automatically sends this before your POST:
OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization

# Server MUST respond with matching CORS headers and 2xx status

Ursache 1: Server verarbeitet OPTIONS

// 🐛 Express route only handles POST, not OPTIONS preflight
app.post('/api/users', createUser);
// The OPTIONS preflight hits no handler → 404/405 → preflight fails

// ✅ Use the cors middleware which handles OPTIONS automatically
const cors = require('cors');
app.use(cors({
  origin: 'https://app.example.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
}));
// cors() responds to preflight OPTIONS requests before your routes

nicht Ursache 2: Reverse Proxy entfernt oder blockiert OPTIONEN

# nginx — explicitly handle OPTIONS preflight
location /api/ {
    # Handle preflight
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Max-Age' 86400 always;
        add_header 'Content-Length' 0;
        return 204;   # respond to preflight with 204 No Content
    }

    proxy_pass http://localhost:3000;
    add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
}

Ursache 3: Wildcard-Ursprung mit Anmeldeinformationen

// 🐛 Wildcard origin CANNOT be used with credentials
app.use(cors({
  origin: '*',              // ❌ fails when credentials: true
  credentials: true,
}));
// Browser error: "Access-Control-Allow-Origin cannot be '*' when
// credentials mode is 'include'"

// ✅ Specify the exact origin
app.use(cors({
  origin: 'https://app.example.com',   // exact origin, not *
  credentials: true,
}));

// ✅ For multiple origins, echo the matching one
const allowed = ['https://app.example.com', 'https://admin.example.com'];
app.use(cors({
  origin: (origin, cb) => {
    if (!origin || allowed.includes(origin)) cb(null, true);
    else cb(new Error('Not allowed by CORS'));
  },
  credentials: true,
}));

Ursache 4: Fehlende zulässige Header

// The preflight lists headers the real request will send.
// The server must allow ALL of them, or preflight fails.

// 🐛 Real request sends Authorization but server doesn't allow it
allowedHeaders: ['Content-Type'],   // missing Authorization

// ✅ Allow every custom header your client sends
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'X-API-Key'],

// Check the browser's preflight to see what's requested:
// Access-Control-Request-Headers: authorization, content-type
// The server's Access-Control-Allow-Headers must include all of these

Ursache 5: Authentifizierungs-Middleware wird vor CORS ausgeführt

// 🐛 Auth middleware rejects the OPTIONS preflight (no auth header on preflight!)
app.use(authenticate);   // blocks OPTIONS with 401
app.use(cors());

// ✅ CORS must come BEFORE auth so preflight passes
app.use(cors({ origin: 'https://app.example.com', credentials: true }));
app.use(authenticate);   // preflight already handled by cors()
// Preflight OPTIONS requests carry no credentials by design —
// they must not be blocked by auth

Debuggen von Preflight-Fehlern

# Simulate the preflight with curl to see the server response
curl -X OPTIONS https://api.example.com/users \
  -H "Origin: https://app.example.com" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: Content-Type, Authorization" \
  -i

# Check the response has:
# HTTP/1.1 204 (or 200)  ← must be 2xx
# Access-Control-Allow-Origin: https://app.example.com  ← matches
# Access-Control-Allow-Methods: ...POST...  ← includes your method
# Access-Control-Allow-Headers: ...content-type, authorization...

Häufig gestellte Fragen

F: Warum funktioniert es in der Entwicklung, schlägt aber in der Produktion fehl?
A: Die Entwicklung verwendet häufig einen Proxy (Vite/CRA), der CORS vollständig vermeidet, oder eine freizügige Entwickler-CORS-Konfiguration. Die Produktion verfügt über einen echten Reverse-Proxy (Nginx) und eine strengere Konfiguration, bei der die Preflight-Behandlung explizit sein muss.

F: Warum gibt meine OPTIONS-Anfrage 401 zurück?
A: Ihre Authentifizierungs-Middleware läuft vor CORS und lehnt den Preflight ab (der standardmäßig keine Anmeldeinformationen enthält). Platzieren Sie CORS-Middleware vor der Authentifizierung, damit Preflight-Anfragen durchgelassen werden.

F: Welchen Statuscode sollte der Preflight zurückgeben?
A: 204 (Kein Inhalt) oder 200. Alle 2xx funktionieren. Eine 404, 405 oder 401 bedeutet, dass der Preflight fehlgeschlagen ist und der Browser die eigentliche Anfrage blockiert.

F: Soll ich CORS-Header in Nginx oder in der App festlegen – nicht in beiden?
A: Wählen Sie einen Ort aus. DuplizierenAccess-Control-Allow-Origin Header (sowohl von Nginx als auch von Express) führen dazu, dass der Browser die Antwort ablehnt. Verwenden Sie Nginx ODER die App, nicht beides.

F: Wie erlaube ich ursprungsübergreifende Anmeldeinformationen (Cookies)?
A: SetzeAccess-Control-Allow-Credentials: true UND geben Sie einen genauen Ursprung (nicht ) auf dem Server an und verwenden Sie* im Client-Abruf. Alle drei sind zusammen erforderlich.credentials: 'include'Fazit

CORS-Preflight-Fehler in der Produktion sind in der Regel darauf zurückzuführen, dass der Server OPTIONS nicht verarbeitet, ein Reverse-Proxy dies blockiert, ein Wildcard-Ursprung mit Anmeldeinformationen, fehlende zulässige Header oder Authentifizierungs-Middleware, die den Preflight ablehnt. Die Korrekturen:

Verwenden Sie Middleware (oder explizite Nginx-OPTIONS-Verarbeitung), geben Sie bei der Verwendung von Anmeldeinformationen genaue Ursprünge an, lassen Sie jeden Header zu, den Ihr Client sendet, und setzen Sie CORS vor Authentifizierungs-Middlewarecors. Debuggen Sie mit einem Anfrage, um genau zu sehen, was der Server zurückgibt – der Preflight muss 2xx mit passenden CORS-Headern antworten.curl -X OPTIONS Anfrage, um genau zu sehen, was der Server zurückgibt – der Preflight muss 2xx mit passenden CORS-Headern antworten.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা