Mocks und Fehlerinjektion

Verkehr zu beobachten beantwortet, was eine App tut. Diese Seite handelt von der anderen Hälfte: das Netzwerk etwas antworten zu lassen, was es nie geantwortet hätte, um zu sehen, was die App damit anfängt. Ein Backend, das es noch nicht gibt, ein Endpunkt, der 500 liefert, eine Antwort, die acht Sekunden braucht, eine API, die einfach verschwunden ist.

Alles hier funktioniert auf jeder Plattform, auf der Chute läuft, und alles, was HTTPS berührt, verlangt zuerst Entschlüsselung für diesen Host — eine verschlüsselte Anfrage, die Chute nicht lesen kann, kann es auch nicht beantworten.

Was Chute simulieren kann und was nicht

Chute greift an der Verbindung und an der HTTP-Nachricht ein. Einen Traffic-Shaper hat es nicht:

Kann Einen vorgefertigten Body liefern, einen gewählten Statuscode liefern, vor Anfrage oder Antwort eine feste Verzögerung einlegen, eine Verbindung rundheraus verweigern, HTTP/3-Clients zurück auf TCP zwingen, eine Anfrage an einen anderen Host schicken als den verlangten
Kann nicht Bandbreite begrenzen, Pakete verwerfen oder umsortieren, Jitter hinzufügen, eine Verbindung mittendrin verschlechtern oder eine bestimmte RTT auf Transportebene nachbilden

Es gibt keinen [Throttle]-Abschnitt und nirgends eine Geschwindigkeitsbegrenzung. Wenn Sie eine langsame Leitung brauchen statt einer langsamen Antwort, gehört das zu einem Netzwerk-Conditioner (Apples Network Link Conditioner oder ein Router), nicht zu Chute.

Einen Mechanismus wählen

Zu simulieren Mittel Wo
Ein Antwort-Body, den es noch nicht gibt [Map Local] Mock-Antwort
Genau 503 [URL Rewrite]reject URL-Umschreibung
Ein leeres 200, ein leeres Bild, ein leeres JSON-Objekt reject-200, reject-img, reject-dict URL-Umschreibung
Jeder andere Status — 401, 429, 500 Ein http-request-Skript JS-Skripting
Latenz Ein http-request- oder http-response-Skript JS-Skripting
Ein Endpunkt, der schlicht nicht erreichbar ist Eine REJECT-Regel Eingebaute Richtlinie
Ein Client, der nicht auf TCP zurückfällt block-quic Sonstige Optionen
Ein anderes Backend hinter derselben URL [Host] oder [URL Rewrite] im header-Modus Lokale DNS-Zuordnung

Ein vorgefertigter Antwort-Body

[Map Local] beantwortet eine passende Anfrage aus einer Datei oder aus eingebettetem Base64, ohne den echten Server zu fragen:

[Map Local]
^https://api\.example\.com/v1/profile.* data="/Users/me/mocks/profile.json"
^https://api\.example\.com/v1/flags.* base64="eyJiZXRhIjogdHJ1ZX0="

Drei Dinge entscheiden, ob das funktioniert:

  • Der reguläre Ausdruck muss auf die ganze URL passen, nicht auf einen Teil. Lassen Sie das Muster auf .* enden, sofern Sie nicht ausdrücklich eine URL ganz ohne Query-String treffen wollen.
  • data= liest das Gerät, auf dem Chute läuft. Auf einem Mac ist das praktisch — Datei ändern, und die nächste Anfrage sieht die Änderung. Auf einem Telefon oder einem Apple TV bedeutet ein Pfad von Ihrem Mac nichts; nehmen Sie dort base64=, oder liefern Sie die Datei über HTTP aus und nutzen Sie die URL-Umschreibung.
  • Der Status ist immer 200 OK. [Map Local] hat keine Möglichkeit, einen zu setzen, und nach der Antwort wird die Verbindung geschlossen. Für jeden anderen Status nehmen Sie ein Skript — siehe unten.

Der Body unterstützt die Template-Variablen {{ "{{url}}" }}, {{ "{{host}}" }}, {{ "{{path}}" }}, {{ "{{method}}" }} und {{ "{{ua}}" }}, was für einen Mock reicht, der zurückspiegelt, wonach gefragt wurde.

Ein Fehlerstatus

Für 503 braucht es kein Skript — eine URL-Umschreibung im reject-Modus liefert HTTP/1.1 503:

[URL Rewrite]
^https://api\.example\.com/v1/orders.* _ reject

Die verwandten Modi decken die übrigen Formen von „nichts Brauchbares" ab: reject-200 (200 mit leerem Body), reject-img (ein 1×1-GIF), reject-dict ({} als JSON, 200). Alle greifen bei HTTPS nur, wenn dieser Host gerade entschlüsselt wird.

Für jeden anderen Statuscode kürzt ein http-request-Skript die Anfrage ab:

[Script]
Fail429 = type=http-request, script-path=/Users/me/mocks/fail429.js, pattern=^https://api\.example\.com/v1/orders
// fail429.js — antworten, ohne den Server zu kontaktieren
$done({
    response: {
        status: 429,
        headers: {
            "Content-Type": "application/json",
            "Retry-After": "30"
        },
        body: JSON.stringify({ error: "rate_limited" })
    }
})

Das pattern eines Skripts passt an beliebiger Stelle der URL, anders als bei den Rewrite-Familien — ein Präfix wie ^https://api\.example\.com/v1/orders genügt, ein abschließendes .* ist nicht nötig.

Auf dem HTTP/1.1-Pfad wird die Statuszeile unabhängig vom Code mit der Begründung OK geschrieben (HTTP/1.1 429 OK). Clients lesen die Zahl, nicht den Text, das ist also kosmetisch — aber genau so steht es in einem rohen Mitschnitt.

Latenz

Ein Skript hält die Nachricht auf, bis es $done() aufruft — ein Timer ist also eine Verzögerung:

[Script]
SlowAPI = type=http-response, script-path=/Users/me/mocks/slow.js, pattern=^https://api\.example\.com/v1/, timeout=15
// slow.js — die echte Antwort acht Sekunden zu spät zurückgeben
setTimeout(function () {
    $done({})
}, 8)

Das Budget ist das timeout des Skripts selbst: standardmäßig 5 Sekunden, alles über 30 wird auf 30 gekappt. Ein Skript, das bei Ablauf des Timeouts kein $done() gerufen hat, gilt als Durchreiche — die Nachricht läuft unverändert weiter —, eine Verzögerung länger als das Timeout scheitert also nicht laut, sie verzögert nur nicht mehr. Setzen Sie timeout über die gewünschte Verzögerung, wie im Beispiel.

type=http-request verzögert, bevor der Server kontaktiert wird (die App sieht eine langsame Runde), type=http-response danach (der Server war schnell, die App wartet trotzdem).

Ein Endpunkt, der einfach weg ist

Ein Mock ersetzt eine Antwort; eine REJECT-Regel verweigert die Verbindung. Sie wirkt auf Verbindungsebene, deckt damit jedes Protokoll ab statt nur HTTP, und braucht keine Entschlüsselung:

[Rule]
DOMAIN-SUFFIX,api.example.com,REJECT

REJECT-DROP, REJECT-TINYGIF und REJECT-NO-DROP werden aus Kompatibilitätsgründen akzeptiert und verhalten sich alle wie ein einfaches REJECT. Für HTTP-Anfragen ersetzt show-error-page-for-reject = true die nackte Ablehnung durch eine lesbare Fehlerseite, sodass im Browser sofort klar ist, dass die Blockade Ihre war.

So prüfen Sie auch, ob es überhaupt einen Ausweichpfad gibt — verweigern Sie den primären Host und sehen Sie, ob die App nach dem sekundären greift oder nur dreht.

Einen Client von HTTP/3 herunterholen

QUIC läuft über UDP und Chute kann es nicht entschlüsseln, eine App auf HTTP/3 ist für jeden Mechanismus dieser Seite also unsichtbar. Verweigert man ihre QUIC-Flüsse, versuchen es kompatible Clients erneut über TCP, wo all das funktioniert:

[General]
block-quic = on

auto verweigert QUIC nur, wenn der Fluss zu einem Proxy geht; on verweigert überall, DIRECT eingeschlossen. Für Verkehr, der durch TUN kommt, antwortet Chute auf einen verweigerten QUIC-Fluss mit ICMP Port Unreachable, sodass der Client sofort zurückfällt, statt ein Timeout abzuwarten.

Die Anfrage woandershin schicken

Zwei Wege auf zwei Ebenen:

[Host]
api.example.com = 10.0.0.5

Eine [Host]-Zuordnung beantwortet die DNS-Auflösung mit einer Adresse Ihrer Wahl — einer Staging-Maschine, oder einer Adresse, die nirgendwohin führt, wenn Sie eine Verbindung wollen, die in ein Timeout läuft statt abgewiesen zu werden. Sie gilt für jedes Protokoll und braucht keine Entschlüsselung. Leeren Sie danach den DNS-Cache.

[URL Rewrite]
^https://api\.example\.com/v1/(.*) https://staging.example.com/v1/$1 header

Der header-Modus schreibt die Anfrage an Ort und Stelle um und zieht den Host-Header mit, sodass der Client nie erfährt, dass er umgeleitet wurde. Das ist HTTP-Ebene und braucht bei HTTPS die Entschlüsselung. Lässt sich das Ziel nicht an Ort und Stelle umschreiben, weicht Chute darauf aus, mit einem 307 auf die neue URL zu antworten.

Bestätigen, dass es gegriffen hat

Eine Regel, die nie passt, sieht genauso aus wie eine, die passte und nichts tat — das ist die Art, wie diese ganze Seite scheitert.

  • Rewrites und Mocks: Die Seite Regeln der Web-Konsole listet jede URL-, Header-, Body-Rewrite- und Map-Local-Regel, die in diesem Lauf gegriffen hat, mit Zähler. Nicht in der Liste heißt nie gepasst. Dieselben Daten liegen in rewrite_hits von GET /api/rules.
  • Pro Verbindung: Öffnen Sie die Verbindung in der Konsole oder in Dashboard und lesen Sie ihre Zeilen Angewandte Rewrites, die die Regel in ihren eigenen Worten nennen.
  • Skripte tauchen in dieser Tabelle nicht auf. Der Beleg eines Skripts ist seine eigene Ausgabe: console.log-Zeilen landen im Protokoll, lesbar auf der Seite Protokolle der Konsole oder mit GET /api/logs.

Aufräumen

Regeln, die aus der Konsole, aus Dashboard oder über POST /api/rewrites/:family hinzugefügt wurden, leben im laufenden Kernel und sind beim nächsten Neustart weg — ideal für ein Experiment und ein schlechter Ort für etwas, auf das Sie sich verlassen. Regeln in der Konfigurationsdatei überstehen Neustarts, was sie zu einem guten Ort für einen Mock macht und zu etwas, das man auf keinen Fall vergessen darf: Eine [Map Local]-Zeile, die in einer Konfiguration stehen bleibt, beantwortet Wochen später immer noch Anfragen — und sieht dabei genau aus wie ein kaputter Server.

S. Smart Rabbit LLC © All Rights Reserved            updated 2026-09-05 00:50:49

Diese Seite ist eine Übersetzung der englischen Version. Bei Abweichungen ist die englische Version maßgeblich.

results matching ""

    No results matching ""