In der Kategorie Fuckup der Woche geht es heute um ein Beispiel, das zeigt, wie viel Zeit man in etwas scheinbar Simples wie eine Proxy-Konfiguration investieren kann – und warum das am Ende lehrreich war.
Problem: Ein Proxy für eine API sollte lokale Anfragen weiterleiten, und dabei traten wiederholt 403 Forbidden-Fehler auf. Die Ursache? Ein unscheinbarer Origin-Header, den wir (fast) übersehen hätten.

Unser Setup basierte auf Vite, einem beliebten Build-Tool für moderne Frontend-Entwicklung. Die Herausforderung bestand darin, einen Proxy zu konfigurieren, der Anfragen von einem lokalen Frontend an einen entfernten Server (TARGET_URL) weiterleitet, ohne an selbstsignierten SSL-Zertifikaten oder Cross-Origin Resource Sharing (CORS)-Problemen zu scheitern. Der Proxy sollte:
secure: false setzen, um Zertifikatsfehler zu umgehen.OPTIONS) unterstützen und die richtigen Header setzen.^/centerdevice-rest-server/v2/ai-search sollten umgeleitet und die Basispfade korrekt angepasst werden.Mit unserer Proxy-Konfiguration standen wir am Anfang vor einem ständigen 403 Forbidden-Fehler. Trotz gefühlt endloser Anpassungen von changeOrigin, secure, und rewrite, konnte der Proxy die Anfrage einfach nicht durchbringen. Der Server lehnte die Anfrage weiterhin ab, als ob wir an ein unsichtbares Hindernis stießen.
Was wir ausprobiert haben:
403-Fehler durch fehlende CORS-Header verursacht wurde. Also ergänzten wir Access-Control-Allow-Origin, Access-Control-Allow-Methods, und Access-Control-Allow-Headers.OPTIONS-Antwort hinzu, um den Browser zufriedenzustellen, der jedes Mal mit einem Preflight-Test das Feld abfragte.changeOrigin: true, damit der Proxy alle Anfragen so weiterleitete, als ob sie vom Ziel-Host kämen. Doch der Server blieb stur.Origin-Header entfernenNach einer ausgiebigen Inspektion von curl-Befehlen und einer genauen Überprüfung der Proxy-Req-Header fiel uns ein unscheinbarer Verdächtiger auf: der Origin-Header. Anders als curl, das ohne diesen Header arbeitet, schickte der Proxy ihn hartnäckig mit. Das Problem: Der entfernte Server akzeptierte die Anfragen nur, wenn der Origin-Header weggelassen wurde. Eine Regel, die in der API-Dokumentation nicht erwähnt war und die nur durch Ausschlussverfahren herauszufinden war.
Also: proxyReq.removeHeader("origin");
Sobald wir den Origin-Header entfernt hatten, war der Weg frei. Kein 403 mehr. Die Anfrage ging durch, als wäre nie etwas gewesen.
Hier ist der endgültige Proxy-Setup in vite.config.js, der das Problem umgeht, indem der Origin-Header explizit entfernt wird und alle notwendigen CORS- und Fehler-Handler berücksichtigt:
import { defineConfig } from "vite";
import dotenv from "dotenv";
dotenv.config();
export default defineConfig({
server: {
port: process.env.PORT || 5000,
proxy: {
"^/derkuba-rest-server/v2/ai-search": {
target: process.env.TARGET_URL,
changeOrigin: true,
secure: false,
rewrite: (path) =>
path.replace(/^\/derkuba-rest-server\/v2\/ai-search/, ""),
configure: (proxy) => {
// Setzt CORS-Header für jede Anfrage
proxy.on("proxyReq", (proxyReq, req, res) => {
proxyReq.removeHeader("origin"); // Entfernt den Origin-Header
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS",
);
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization",
);
console.log(
`[Incoming Request] ${req.method} ${req.url}`,
);
console.log(
`[Outgoing Request] ${proxyReq.method} ${proxyReq.getHeader("host")}${proxyReq.path}`,
);
});
// Preflight-Anfragen für CORS beantworten
proxy.on("proxyRes", (proxyRes, req, res) => {
if (req.method === "OPTIONS") {
res.writeHead(200, {
"Content-Type": "text/plain",
});
res.end();
}
});
// Fehler-Handler mit CORS und Content-Type
proxy.on("error", (err, req, res) => {
console.error(`Proxy error: ${err.message}`);
if (res && !res.headersSent) {
res.writeHead(500, {
"Content-Type": "text/plain",
"Access-Control-Allow-Origin": "*",
});
res.end("Something went wrong with the proxy.");
}
});
},
},
},
},
});
Der Origin-Header mag unscheinbar sein, kann aber bei serverseitigen API-Beschränkungen den Unterschied zwischen Erfolg und einem 403 Forbidden-Fehler machen. Der heutige Fuckup der Woche ist eine Erinnerung daran, dass die kleinen Details oft die entscheidenden sind. Manchmal liegt die Lösung in der genauen Untersuchung des Request-Formats und in der geduldigen Fehlersuche – und nicht immer in großen Codeänderungen.
Für Feedback bin ich immer dankbar. Gerne an jacob@derkuba.de
Viele Grüße
Euer Kuba