Eine Support-Request-API erstellen

CloudflareBeginner
Jetzt üben

Einführung

Ein Supportformular benötigt eine API, die eine gültige Anfrage von ungültigem JSON, einer fehlenden Route und einem nicht verfügbaren Ticketdienst unterscheidet. Sie erstellen diese HTTP-Schnittstelle mit JavaScript, testen sie lokal und stellen sie anschließend zusammen mit einem temporären Upstream-Worker bereit.

Verwenden Sie Ihr eigenes Cloudflare-Lernkonto sowie das Wissen zur Geräteautorisierung aus dem Verbindungs-Lab. Dieses Lab startet in einer frischen VM mit Node.js 22.22.0 und lokal im Projekt installiertem Wrangler 4.131.1 unter /home/labex/project/support-api. Grundkenntnisse zu JavaScript-Funktionen, Objekten und Modulen werden vorausgesetzt. Das Verhalten von HTTP und asynchrone Anfragen werden hier erklärt. Die beiden öffentlichen Worker verwenden ausschließlich synthetische Daten. Der bereitgestellte Upstream bestätigt Anfragen, speichert jedoch nichts: Es handelt sich nicht um ein dauerhaftes Ticketsystem. Workers Free und eine workers.dev-Subdomain reichen aus; für diese kleine Übung benötigen Sie weder eine Datenbank noch eine gekaufte Domain oder ein kostenpflichtiges Upgrade. Anfragen werden auf die Workers-Nutzung Ihres Kontos angerechnet.

Sie entfernen beide Worker und melden sich ab, bevor Sie das Lab beenden. Lassen Sie dasselbe Terminal geöffnet, damit die Shell-Variablen für Ressourcennamen und URLs erhalten bleiben.

Anfragen nach Pfad und Methode routen

In diesem Schritt weisen Sie jeder unterstützten URL explizit eine Methode und eine Antwort zu. Ein Pfad bezeichnet die Operation, eine Methode beschreibt die Aktion. GET /health prüft die Verfügbarkeit, und POST /requests nimmt eine Supportanfrage entgegen.

Wechseln Sie in das vorbereitete Projekt und prüfen Sie die Werkzeuge:

cd /home/labex/project/support-api
node --version
npx wrangler --version

Erwartet werden Node v22.22.0 und Wrangler 4.131.1. Die Installation ist bereits abgeschlossen. Installieren Sie auf Ihrem eigenen Computer Node und verwenden Sie in einem Projekt npm install --save-dev wrangler@4.131.1. Wenn Sie ein Projekt anhand seiner Lockdatei reproduzieren, verwenden Sie npm ci.

Erzeugen Sie einen eindeutigen temporären Namen. openssl rand -hex 6 gibt 12 zufällige hexadezimale Zeichen aus. $(...) fügt diese Ausgabe ein, und die Shell-Zuweisung speichert sie für spätere Befehle.

WORKER_NAME="labex-support-$(openssl rand -hex 6)"

Schreiben Sie die standardmäßige Wrangler-Konfiguration. cat > file <<MARKER schreibt die folgenden Zeilen bis zur abschließenden Markierung. Die nicht quotierte Markierung erlaubt der Shell, $WORKER_NAME zu ersetzen.

cat > wrangler.jsonc <<CONFIG
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-09-14",
  "workers_dev": true,
  "preview_urls": false,
  "vars": {"UPSTREAM_URL": "http://127.0.0.1:8081"}
}
CONFIG

main bezeichnet den Handler, compatibility_date legt das Laufzeitverhalten fest, und vars stellt über env eine nicht geheime Upstream-Adresse bereit. Zunächst verweist sie auf ein lokales Testsystem, das später gestartet wird. Öffentliche Vorschau-URLs sind deaktiviert, damit die Ressourcenübersicht übersichtlich bleibt.

Schreiben Sie den Handler. Die quotierte Markierung JS bewahrt den JavaScript-Inhalt unverändert. new URL(...).pathname extrahiert die Route. Der ternäre Ausdruck wählt die zulässige Methode aus. HTTP 405 kündigt diese Methode zusätzlich in Allow an. Response.json serialisiert ein Objekt und setzt den passenden Content-Type. Der async-Handler kann in späteren Schritten asynchrone Arbeit mit await ausführen.

cat > src/index.js <<'JS'
export default {
  async fetch(request, env) {
    const path = new URL(request.url).pathname;
    if (path !== '/health' && path !== '/requests') {
      return Response.json({error: 'not_found'}, {status: 404});
    }
    const allowed = path === '/health' ? 'GET' : 'POST';
    if (request.method !== allowed) {
      return Response.json({error: 'method_not_allowed'}, {
        status: 405, headers: {Allow: allowed}
      });
    }
    if (path === '/health') return Response.json({status: 'ok'});
    return Response.json({error: 'not_implemented'}, {status: 501});
  }
};
JS

Starten Sie den lokalen Wrangler-Prozess im Hintergrund. > leitet die Ausgabe um, 2>&1 schließt Fehlermeldungen ein, und & gibt die Terminal-Eingabeaufforderung zurück, während der Server läuft.

npx wrangler dev --port 8080 > api.log 2>&1 &
cat api.log

Warten Sie, bis das Log die Bereitschaft an Port 8080 meldet. Führen Sie cat api.log erneut aus, falls der Start noch läuft. curl -i zeigt den HTTP-Status und die Header an:

curl -i http://127.0.0.1:8080/health
curl -i http://127.0.0.1:8080/missing
curl -i http://127.0.0.1:8080/requests

Erwartet werden jeweils 200 mit {"status":"ok"}, 404 mit {"error":"not_found"} und 405 mit {"error":"method_not_allowed"} sowie Allow: POST. Diese Fehlerantworten sind beabsichtigt. Verwenden Sie die Schaltfläche zur Überprüfung, solange der Server noch läuft.

JSON-Eingaben analysieren und validieren

In diesem Schritt weisen Sie fehlerhafte Eingaben zurück, bevor ein Upstream-Dienst aufgerufen wird. HTTP 415 bedeutet, dass der Medientyp nicht unterstützt wird, 400 bedeutet, dass JSON nicht analysiert werden kann, und 422 bedeutet, dass die analysierten Daten den Vertrag nicht erfüllen. Ein Betreff muss eine Zeichenkette mit 1–80 Zeichen nach dem Entfernen von Leerzeichen am Anfang und Ende sein.

Ersetzen Sie den Handler durch diese vollständige Version. headers.get liest den angegebenen Medientyp. Durch das Aufteilen bei ; wird ein Charset-Parameter erlaubt. await request.json() wartet auf die Analyse und liest den Body einmal. Ein try/catch wandelt eine Analyseausnahme in eine vorhersehbare Antwort um. JSON kann auch null, Arrays oder Zahlen darstellen. Deshalb prüft die Validierung zunächst die Struktur, bevor Zeichenkettenmethoden verwendet werden. trim() vereinheitlicht den akzeptierten Betreff.

cat > src/index.js <<'JS'
export default {
  async fetch(request, env) {
    const path = new URL(request.url).pathname;
    if (path !== '/health' && path !== '/requests') {
      return Response.json({error: 'not_found'}, {status: 404});
    }
    const allowed = path === '/health' ? 'GET' : 'POST';
    if (request.method !== allowed) {
      return Response.json({error: 'method_not_allowed'}, {
        status: 405, headers: {Allow: allowed}
      });
    }
    if (path === '/health') return Response.json({status: 'ok'});
    const mediaType = (request.headers.get('content-type') || '').split(';')[0].trim().toLowerCase();
    if (mediaType !== 'application/json') {
      return Response.json({error: 'unsupported_media_type'}, {status: 415});
    }
    let body;
    try {
      body = await request.json();
    } catch {
      return Response.json({error: 'invalid_json'}, {status: 400});
    }
    if (!body || Array.isArray(body) || typeof body.subject !== 'string' ||
        body.subject.trim().length < 1 || body.subject.trim().length > 80) {
      return Response.json({error: 'invalid_subject'}, {status: 422});
    }
    const subject = body.subject.trim();
    return Response.json({subject}, {status: 201});
  }
};
JS

Wrangler lädt die Anwendung neu, sobald sich der Quellcode ändert. Prüfen Sie cat api.log auf Kompilierungsfehler. Senden Sie eine gültige Anfrage. -H setzt einen Header, und --data übergibt den Body und verwendet POST. Einfache Anführungszeichen bewahren die doppelten Anführungszeichen des JSON in der Shell.

curl -i http://127.0.0.1:8080/requests -H "Content-Type: application/json" --data '{"subject":"  Printer offline  "}'

Erwartet werden 201 und {"subject":"Printer offline"}. Dies ist nur eine Bestätigung im Arbeitsspeicher, kein gespeichertes Ticket. Testen Sie drei verschiedene Ablehnungsfälle:

curl -i http://127.0.0.1:8080/requests -H "Content-Type: application/json" --data '{'
curl -i http://127.0.0.1:8080/requests -H "Content-Type: application/json" --data '{"subject":"   "}'
curl -i http://127.0.0.1:8080/requests -H "Content-Type: text/plain" --data 'hello'

Erwartet werden 400 invalid_json, 422 invalid_subject und 415 unsupported_media_type. Testen Sie außerdem JSON null, [] und {"subject":5}. Jede dieser Eingaben muss 422 zurückgeben, ohne eine Ausnahme auszulösen. Verwenden Sie die Schaltfläche zur Überprüfung. Sie prüft diese Grenzen und erhält das Verhalten für Health-Check und Routing.

Einen Upstream aufrufen und seine Fehler abfangen

In diesem Schritt verbinden Sie die API mit einem bereitgestellten Simulator für einen Ticketdienst. Ein Upstream ist eine Abhängigkeit, die von Ihrem Dienst aufgerufen wird. Der Simulator gibt für normale Betreffzeilen ein synthetisches Ticket zurück und für den speziellen Betreff simulate-outage HTTP 503. Er speichert niemals Anfragen.

Sehen Sie sich den bereitgestellten Quellcode an, um das Testsystem zu verstehen, und konfigurieren Sie anschließend eine eigene eindeutige Worker-Identität:

cat upstream/index.js
cat > upstream/wrangler.jsonc <<CONFIG
{
  "name": "${WORKER_NAME}-upstream",
  "main": "index.js",
  "compatibility_date": "2026-09-14",
  "workers_dev": true,
  "preview_urls": false
}
CONFIG

Mit --config wählen Sie diese zweite Konfiguration aus. Verwenden Sie Port 8081 und einen separaten Inspector-Port, damit beide lokalen Worker gleichzeitig laufen können:

npx wrangler dev --config upstream/wrangler.jsonc --port 8081 --inspector-port 9230 > upstream.log 2>&1 &
cat upstream.log
curl -i http://127.0.0.1:8081/health

Warten Sie, bis der Dienst bereit ist. Erwartet werden 200 und {"service":"support-upstream","status":"ok"}. Ersetzen Sie nun den Haupthandler durch die vollständige Integration. Die globale Funktion fetch sendet eine ausgehende Anfrage. JSON.stringify codiert den validierten Betreff. await wartet auf die Antwort. HTTP-Fehler lösen keine Ausnahme aus. Deshalb prüft upstream.ok den Status ausdrücklich. catch behandelt getrennt eine fehlgeschlagene Verbindung oder eine nicht lesbare JSON-Antwort. HTTP 502 teilt unserem Client mit, dass die Abhängigkeit fehlgeschlagen ist, ohne deren internen Antwort-Body offenzulegen.

cat > src/index.js <<'JS'
export default {
  async fetch(request, env) {
    const path = new URL(request.url).pathname;
    if (path !== '/health' && path !== '/requests') {
      return Response.json({error: 'not_found'}, {status: 404});
    }
    const allowed = path === '/health' ? 'GET' : 'POST';
    if (request.method !== allowed) {
      return Response.json({error: 'method_not_allowed'}, {
        status: 405, headers: {Allow: allowed}
      });
    }
    if (path === '/health') return Response.json({status: 'ok'});
    const mediaType = (request.headers.get('content-type') || '').split(';')[0].trim().toLowerCase();
    if (mediaType !== 'application/json') {
      return Response.json({error: 'unsupported_media_type'}, {status: 415});
    }
    let body;
    try {
      body = await request.json();
    } catch {
      return Response.json({error: 'invalid_json'}, {status: 400});
    }
    if (!body || Array.isArray(body) || typeof body.subject !== 'string' ||
        body.subject.trim().length < 1 || body.subject.trim().length > 80) {
      return Response.json({error: 'invalid_subject'}, {status: 422});
    }
    const subject = body.subject.trim();
    try {
      const upstream = await fetch(`${env.UPSTREAM_URL}/tickets`, {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({subject})
      });
      if (!upstream.ok) {
        return Response.json({error: 'upstream_unavailable'}, {status: 502});
      }
      const ticket = await upstream.json();
      return Response.json({ticket: ticket.ticket, subject}, {status: 201});
    } catch {
      return Response.json({error: 'upstream_unavailable'}, {status: 502});
    }
  }
};
JS
curl -i http://127.0.0.1:8080/requests -H "Content-Type: application/json" --data '{"subject":"Printer offline"}'
curl -i http://127.0.0.1:8080/requests -H "Content-Type: application/json" --data '{"subject":"simulate-outage"}'

Erwartet werden zunächst 201 mit {"ticket":"demo-1001","subject":"Printer offline"} und anschließend 502 mit {"error":"upstream_unavailable"}. Die interne Diagnose des Simulators darf nicht erscheinen. Der Betreff ist synthetisch, und dieser Endpunkt hat keine dauerhaften Nebenwirkungen. Verwenden Sie die Schaltfläche zur Überprüfung, während beide lokalen Server laufen.

In diesem Lab verwenden Sie gewöhnliches HTTP, um eine Grenze zu einem externen Dienst zu üben. Ein späteres Lab behandelt Service Bindings für interne Worker-zu-Worker-Aufrufe. Zeitlimits und ausführlichere Diagnosen werden in „Worker-Fehler diagnostizieren“ behandelt. Der Fixture liefert kleine, begrenzte Antworten. Eine Produktions-API muss außerdem die Größen nicht vertrauenswürdiger Anfragen und Antworten begrenzen.

Die öffentliche API bereitstellen und testen

In diesem Schritt stellen Sie beide Worker im selben Lernkonto bereit und ersetzen die lokale Upstream-Adresse durch ihre öffentliche URL. Stoppen Sie zuerst beide lokalen Prozesse. Prüfen Sie jobs und verwenden Sie jeweils die tatsächliche Jobnummer. Die Beispiele gehen davon aus, dass die API Job 1 und der Upstream Job 2 ist.

jobs
kill %1 %2

Autorisieren Sie diese frische VM. Die Genehmigung identifiziert Ihr Konto und erlaubt die Bereitstellung und Löschung von Workern. Die Berechtigung am Ende entspricht der Genehmigung aus der Bereitstellungslektion, obwohl dieses Lab keinen Log-Stream benötigt.

npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_tail:read

Öffnen Sie den angezeigten Browser-Link, geben Sie den aktuellen Gerätecode ein, prüfen Sie die Wrangler-Berechtigungen einschließlich des erforderlichen Background Access, wählen Sie ausschließlich Ihr Lernkonto aus und autorisieren Sie den Zugriff. Kehren Sie zum Terminal zurück und warten Sie, bis der Vorgang abgeschlossen ist.

npx wrangler whoami --json

Bestätigen Sie loggedIn: true, den Kontonamen und die tatsächliche ID unter accounts. Ersetzen Sie YOUR_ACCOUNT_ID weiter unten durch diese ID. Behalten Sie die in Schritt 1 erzeugten Namen bei. Falls eine Variable verloren gegangen ist, lesen Sie die gespeicherte Konfiguration und stellen Sie die Variable daraus wieder her, anstatt einen weiteren Ressourcennamen zu erzeugen.

cat > upstream/wrangler.jsonc <<CONFIG
{
  "name": "${WORKER_NAME}-upstream",
  "main": "index.js",
  "compatibility_date": "2026-09-14",
  "workers_dev": true,
  "preview_urls": false,
  "account_id": "YOUR_ACCOUNT_ID"
}
CONFIG
npx wrangler deploy --config upstream/wrangler.jsonc

Kopieren Sie die exakte workers.dev-URL aus der Bereitstellungsausgabe. Verwenden Sie die bereits vorhandene Subdomain des Kontos. Falls Wrangler zur erstmaligen Registrierung einer Subdomain auffordert, wählen Sie einen verfügbaren Namen und folgen Sie der Bestätigung. Ändern Sie keine vorhandene Account-Subdomain.

Schreiben Sie nun die Hauptkonfiguration neu. Ersetzen Sie beide Platzhalter durch Ihre Account-ID und die Upstream-URL ohne abschließenden Schrägstrich. global_fetch_strictly_public sorgt dafür, dass ausgehende Aufrufe mit fetch() über das öffentliche Internet geroutet werden, einschließlich des anderen Workers auf der workers.dev-Subdomain dieses Kontos. Ohne diese Einstellung kann dieser HTTP-Aufruf innerhalb derselben Zone fehlschlagen, obwohl beide Worker unabhängig voneinander funktionieren. Dieses Flag gehört in die bereitgestellte API-Konfiguration; das frühere lokale Loopback-Testsystem benötigt es nicht. Weitere Informationen finden Sie in der Fetch-API-Dokumentation.

cat > wrangler.jsonc <<CONFIG
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-09-14",
  "compatibility_flags": ["global_fetch_strictly_public"],
  "workers_dev": true,
  "preview_urls": false,
  "account_id": "YOUR_ACCOUNT_ID",
  "vars": {"UPSTREAM_URL": "YOUR_UPSTREAM_URL"}
}
CONFIG
cat wrangler.jsonc
npx wrangler deploy

Kopieren Sie die URL der Haupt-API aus der Bereitstellungsausgabe in die folgende Variable:

API_URL="https://YOUR_API.YOUR_SUBDOMAIN.workers.dev"
curl -i "$API_URL/health"
curl -i "$API_URL/requests" -H "Content-Type: application/json" --data '{"subject":"Printer offline"}'
curl -i "$API_URL/requests" -H "Content-Type: application/json" --data '{"subject":"simulate-outage"}'
curl -i "$API_URL/requests" -H "Content-Type: application/json" --data '{'

Erwartet werden dieselben Verträge wie lokal: 200 für den Health-Check, 201 für das synthetische Ticket, 502 für den Upstream-Fehler und 400 für fehlerhaftes JSON. Warten Sie bei Verbindungsfehlern, bis der Hostname propagiert wurde, bevor Sie den Zugriff erneut testen. Wählen Sie im Dashboard dasselbe Lernkonto aus und öffnen Sie Compute → Workers & Pages. Suchen Sie die beiden exakten Namen und vergleichen Sie ihre Adressen mit der Bereitstellungsausgabe. Dies ist ein schreibgeschützter Kontrollpunkt. Erstellen Sie dort keine doppelten Anwendungen.

Das folgende Beispiel zeigt die Haupt-API und den zugehörigen Dienst mit dem Suffix -upstream. Klappen Sie in der linken Seitenleiste Compute auf und wählen Sie Workers & Pages. Verwenden Sie Search applications, wenn Ihr Konto weitere Projekte enthält. Vergleichen Sie die vollständigen generierten Namen und die darunter angezeigten Adressen mit Ihren beiden Bereitstellungsausgaben. Ihr zufälliges Suffix und die Account-Subdomain unterscheiden sich von diesem Beispiel.

Workers and Pages mit der Support-API und dem zugehörigen Upstream-Worker

Beide Ressourcen sollten im ausgewählten Konto erscheinen. Ihr Vorhandensein bestätigt, wo sie bereitgestellt wurden. Die HTTP-Antworten oben zeigen, ob die API funktioniert. Falls ein Name fehlt, prüfen Sie die Kontomauswahl und die Bereitstellungsausgabe, bevor Sie es erneut versuchen. Verwenden Sie Create application nicht, um eine CLI-Bereitstellung zu duplizieren.

Verwenden Sie die Schaltfläche zur Überprüfung. Sie prüft unabhängig die Besitzverhältnisse beider Worker, die bereitgestellte Upstream-Anbindung sowie positive und negative öffentliche Antworten. Sie sendet ausschließlich synthetische, zustandslose Anfragen an den Simulator dieses Labs.

Beide temporären Worker entfernen

In diesem Schritt entfernen Sie die API und ihren Upstream, solange die Autorisierung noch verfügbar ist, um das Ergebnis zu überprüfen. Dies sind die einzigen Cloud-Ressourcen, die dieses Lab erstellt. Prüfen Sie beide Konfigurationen vor dem Löschen:

cat wrangler.jsonc
cat upstream/wrangler.jsonc

Bestätigen Sie den Namen labex-support-... der Hauptanwendung und das passende Suffix -upstream sowie dieselbe ID des Lernkontos. Löschen Sie zuerst die Haupt-API und anschließend den Upstream. Prüfen Sie bei jeder Eingabeaufforderung den exakten Namen und drücken Sie die einzelne Taste y.

npx wrangler delete
npx wrangler delete --config upstream/wrangler.jsonc

Wrangler 4.131.1 kann einen Worker entfernen und anschließend beim Prüfen von KV-Daten aus älteren Workers-Sites einen Authentifizierungsfehler ausgeben, weil diese Genehmigung keinen KV-Zugriff umfasst. Diese spezifische Diagnose beweist weder den Erfolg noch den Fehlschlag der Löschung. Erteilen Sie nicht mehr Berechtigungen, nur um sie zu unterdrücken. Aktualisieren Sie Workers & Pages und verwenden Sie die Schaltfläche zur Überprüfung. Eine erfolgreiche autorisierte Bestandsprüfung muss bestätigen, dass beide Namen fehlen. Netzwerk- oder Autorisierungsfehler sind nicht eindeutig. Beheben Sie sie, bevor Sie fortfahren. Lassen Sie andere Anwendungen, Ihr Lernkonto und dessen Subdomain unverändert.

Die VM abmelden

In diesem Schritt entfernen Sie die Wrangler-Autorisierung dieser VM, nachdem die Bereinigung beider Ressourcen erfolgreich überprüft wurde. Das Abmelden löscht keine Worker. Deshalb wurde die Bereinigung zuerst durchgeführt.

npx wrangler logout
npx wrangler whoami --json

Erwartet wird ausdrücklich "loggedIn": false. Ein nicht authentifizierter Statusbefehl kann mit einem Fehlercode beendet werden. Das ist erwartungsgemäß, wenn sein strukturiertes Ergebnis eindeutig die Abmeldung meldet. Ein Netzwerkfehler ist nicht gleichbedeutend damit. Verwenden Sie die Schaltfläche zur Überprüfung und beenden Sie anschließend die LabEx-Umgebung. Ihre Browser-Anmeldung und Ihr Lernkonto bleiben für spätere Labs verfügbar. Jede neue VM fordert ihre eigene Autorisierung an.

Zusammenfassung

Sie haben eine HTTP-API mit methodenabhängigem Routing erstellt, JSON analysiert und validiert, akzeptierte Daten vereinheitlicht und einen Upstream-Fehler in einen vorhersehbaren öffentlichen Fehler übersetzt. Sie haben normale und abgelehnte Anfragen lokal und auf Cloudflare getestet, den Besitz beider Bereitstellungen geprüft, die temporären Ressourcen entfernt und die VM abgemeldet.

Weitere Informationen finden Sie in der offiziellen Request API, Response API und Fetch API.