APICatcher Skript-Funktion Benutzerhandbuch
APICatcher verfügt über eine integrierte JavaScript-basierte Skript-Engine, mit der Sie benutzerdefinierte Skripte schreiben können, um HTTP/HTTPS-Anforderungen und -Antworten abzufangen und zu ändern. Die Skriptfunktion ist leistungsstark und flexibel und eignet sich für das Entwicklungs-Debugging, API-Tests, Datensimulation und andere Szenarien.
Inhaltsverzeichnis
- Schnellstart
- Grundlegende Struktur des Skripts
- Anforderungsabfangfunktion interceptRequest
- Antwortabfangfunktion interceptResponse
- Eingebaute API
- Praktische Beispiele
- Hinweise
Schnellstart
- Öffnen Sie APICatcher und rufen Sie die Verwaltungsseite "Skripte" auf.
- Klicken Sie auf "Skript hinzufügen". Das System füllt den Vorlagencode automatisch aus.
- Legen Sie die Übereinstimmungsbedingungen des Skripts (z. B. Host, Path usw.) fest, um zu bestimmen, für welche Anforderungen das Skript wirksam ist.
- Schreiben Sie Ihre Abfanglogik.
- Nach dem Aktivieren des Skripts beginnen Sie mit der Paketerfassung, damit es wirksam wird.
Grundlegende Struktur des Skripts
Jedes Skript kann zwei Funktionen enthalten:
// Anforderungsabfangen (Optional)
function interceptRequest(request) {
// Ihre Logik
return { action: 'passthrough' };
}
// Antwortabfangen (Optional)
function interceptResponse(request, response) {
// Ihre Logik
return { action: 'passthrough' };
}
- Sie können nur eine davon oder beide definieren.
- Die Skripte werden in der Reihenfolge ihrer Priorität und Erstellungszeit ausgeführt.
- Sobald ein Skript ein anderes Ergebnis als
passthroughzurückgibt, werden nachfolgende Skripte nicht mehr ausgeführt.
Anforderungsabfangfunktion interceptRequest
Wenn eine übereinstimmende HTTP-Anforderung eintrifft, wird die Funktion interceptRequest aufgerufen.
Parameter: request-Objekt
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
method | string | HTTP-Methode (GET, POST, PUT, DELETE usw.) |
url | string | Vollständige URL |
host | string | Hostname |
port | number | Portnummer |
path | string | Anforderungspfad |
scheme | string | Protokoll (http / https) |
headers | object | Anforderungsheader (Key-Value-Objekt) |
body | string | Anforderungstext-Zeichenfolge |
queryParams | object | URL-Abfrageparameter (Key-Value-Objekt) |
Rückgabewert
Gibt ein Objekt zurück, das ein action-Feld enthält, um zu bestimmen, wie die Anforderung verarbeitet werden soll:
1. Anforderung durchlassen (passthrough)
return { action: 'passthrough' };
Nimmt keine Änderungen vor, die Anforderung wird normal gesendet.
2. Anforderung ändern (modify)
request.headers['Authorization'] = 'Bearer my-token';
request.body = JSON.stringify({ modified: true });
return { action: 'modify', request: request };
Fährt mit dem Senden nach Änderung des Anforderungsinhalts fort.
3. Antwort simulieren (mock)
return {
action: 'mock',
response: {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ success: true, data: 'mocked' })
}
};
Sendet keine echte Anforderung, sondern gibt die simulierte Antwort direkt zurück.
4. Umleiten (redirect)
return {
action: 'redirect',
url: 'https://new-api.example.com' + request.path,
statusCode: 302 // Optional, standardmäßig 302
};
Leitet die Anforderung an eine andere URL um.
5. Anforderung verwerfen (drop)
return { action: 'drop' };
Verwirft die Anforderung direkt, ohne sie zu senden oder zu antworten.
Antwortabfangfunktion interceptResponse
Nachdem der Server eine Antwort zurückgegeben hat, wird die Funktion interceptResponse aufgerufen.
Parameter
- request: Informationen zur ursprünglichen Anforderung (wie oben)
- response: Antwortinformationen
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
statusCode | number | HTTP-Statuscode |
headers | object | Antwortheader (Key-Value-Objekt) |
body | string | Antworttext-Zeichenfolge |
Rückgabewert
1. Antwort durchlassen (passthrough)
return { action: 'passthrough' };
2. Antwort ändern (modify)
var data = JSON.parse(response.body);
data.injected = true;
response.body = JSON.stringify(data);
return { action: 'modify', response: response };
3. Antwort verzögern (delay)
return {
action: 'delay',
response: response,
delay: 3000 // 3000 Millisekunden verzögern
};
4. Antwort verwerfen (drop)
return { action: 'drop' };
Eingebaute API
Die folgenden globalen Objekte sind in der Skriptumgebung voreingestellt und können direkt in interceptRequest und interceptResponse verwendet werden.
httpClient — HTTP-Anforderungen
Starten Sie HTTP/HTTPS-Anforderungen innerhalb des Skripts. Der Aufruf ist synchron, das Skript wartet, bis die Anforderung abgeschlossen ist, bevor die Ausführung fortgesetzt wird. Die für jede Anforderung aufgewendete Zeit wird automatisch im Protokoll aufgezeichnet, um die Fehlerbehebung bei Leistungsproblemen zu erleichtern.
Methoden
// GET-Anforderung
httpClient.get(url)
httpClient.get(url, headers)
// POST-Anforderung
httpClient.post(url)
httpClient.post(url, body)
httpClient.post(url, body, headers)
// PUT-Anforderung
httpClient.put(url)
httpClient.put(url, body)
httpClient.put(url, body, headers)
// DELETE-Anforderung
httpClient.delete(url)
httpClient.delete(url, headers)
Parameterbeschreibung
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
url | string | ✅ | Vollständige Anforderungs-URL (http:// oder https://) |
body | string | ❌ | Anforderungstext-Zeichenfolge (für JSON verwenden Sie JSON.stringify()) |
headers | object | ❌ | Anforderungsheader-Objekt |
Rückgabewert
Alle Methoden geben ein Antwortobjekt mit derselben Struktur zurück:
{
statusCode: 200, // HTTP-Statuscode (-1, wenn die Anforderung fehlschlägt)
headers: { ... }, // Antwortheader-Objekt
body: "...", // Antworttext-Zeichenfolge
error: "" // Fehlermeldung (leere Zeichenfolge bei Erfolg)
}
Beispiel
// Einfache GET-Anforderung
var resp = httpClient.get('https://api.example.com/status');
console.log('Status: ' + resp.statusCode);
// GET-Anforderung mit Headern
var resp = httpClient.get('https://api.example.com/user', {
'Authorization': 'Bearer my-token'
});
// JSON-Daten mit POST senden
var resp = httpClient.post(
'https://api.example.com/data',
JSON.stringify({ name: 'test', value: 123 }),
{ 'Content-Type': 'application/json' }
);
// Überprüfen, ob die Anforderung erfolgreich war
if (resp.error) {
console.error('Anforderung fehlgeschlagen: ' + resp.error);
} else {
var data = JSON.parse(resp.body);
console.log('Antwortdaten: ' + JSON.stringify(data));
}
Automatische Protokollierung des Zeitaufwands
Jedes Mal, wenn ein httpClient-Aufruf abgeschlossen ist, gibt die Engine automatisch ein Protokoll aus:
[Script] httpClient.get https://api.example.com/status -> 200 (156ms)
[Script] httpClient.post https://api.example.com/data -> 201 (342ms)
Sie können diese Informationen im Protokollfenster von APICatcher anzeigen, um langsame Anforderungen zu lokalisieren.
⚠️ Hinweis: Aufrufe an httpClient sind synchron und blockieren die Ausführung des Skripts, bis die HTTP-Anforderung abgeschlossen ist (Zeitlimit 15 Sekunden). Wenn Sie im Skript eine zeitaufwändige HTTP-Anforderung starten, kann dies zu einer Verzögerung bei der Antwort auf die ursprünglich abgefangene Anforderung führen. Bitte beachten Sie die im Protokoll angegebenen Zeitangaben.
localStore — Lokaler Speicher
Bietet einfachen lokalen, persistenten Schlüssel-Wert-Speicher (Key-Value). Die Daten werden in den UserDefaults der App gespeichert, und alle Skripte teilen sich denselben Speicherplatz. Wenn Sie Daten nach Host oder anderen Dimensionen isolieren müssen, fügen Sie dem Schlüssel selbst ein Präfix hinzu (z. B. request.host + '_token').
Methoden
// Daten schreiben
localStore.write(key, value)
// Daten lesen
localStore.read(key) // Gibt string oder null zurück
// Daten löschen
localStore.remove(key)
Parameterbeschreibung
| Parameter | Typ | Beschreibung |
|---|---|---|
key | string | Der Name des zu speichernden Schlüssels |
value | any | Der zu speichernde Wert (wird automatisch in eine Zeichenfolge konvertiert) |
Speicherbeschreibung
- Alle Skripte teilen sich denselben Speicherplatz
- Die Daten werden in der Sandbox der App (lokaler Speicher) aufbewahrt und sind auch nach einem Neustart der App noch vorhanden
- Wenn Sie nach Host isolieren müssen, fügen Sie die Host-Informationen in den Schlüssel ein, z. B.:
// Manuelle Isolation nach Host
var key = request.host + '_token';
localStore.write(key, 'my-token');
Beispiel
// Grundlegendes Lesen und Schreiben
localStore.write('counter', '1');
var count = localStore.read('counter'); // '1'
console.log('Count: ' + count);
// JSON-Objekt speichern
var config = { debug: true, maxRetry: 3 };
localStore.write('config', JSON.stringify(config));
// JSON-Objekt lesen
var raw = localStore.read('config');
if (raw) {
var config = JSON.parse(raw);
console.log('Debug mode: ' + config.debug);
}
// Daten löschen
localStore.remove('counter');
var v = localStore.read('counter'); // null
console — Protokollausgabe
Wird verwendet, um Protokolle innerhalb des Skripts auszugeben, die im Protokollfenster von API Catcher angezeigt werden können.
console.log('Normales Protokoll'); // Informationsebene
console.warn('Warnprotokoll'); // Warnstufe
console.error('Fehlerprotokoll'); // Fehlerebene
Unterstützt mehrere Parameter, und Objekte werden automatisch in JSON serialisiert:
console.log('Anforderungsinformationen:', request.method, request.url);
console.log('Antwortdaten:', { status: response.statusCode, body: response.body });
Praktische Beispiele
Beispiel 1: Automatische Injektion des Authentifizierungstokens
Fangen Sie alle Anforderungen an api.myserver.com ab und fügen Sie automatisch den Authorization-Header hinzu. Das Token wird von der Login-API bezogen und im localStore zwischengespeichert.
function interceptRequest(request) {
// Nur den Zielserver verarbeiten
if (!request.host.includes('api.myserver.com')) {
return { action: 'passthrough' };
}
// Versuchen, das Token aus dem Cache zu lesen
var token = localStore.read('auth_token');
var tokenExpiry = localStore.read('auth_token_expiry');
// Überprüfen, ob das Token abgelaufen ist (unter Verwendung des Zeitstempels in Sekunden)
var now = Math.floor(Date.now() / 1000);
if (!token || !tokenExpiry || now > parseInt(tokenExpiry)) {
// Das Token ist nicht vorhanden oder abgelaufen, melden Sie sich erneut an, um es zu erhalten
console.log('Token expired, re-authenticating...');
var loginResp = httpClient.post(
'https://api.myserver.com/auth/login',
JSON.stringify({ username: 'testuser', password: 'testpass' }),
{ 'Content-Type': 'application/json' }
);
if (loginResp.statusCode === 200) {
var loginData = JSON.parse(loginResp.body);
token = loginData.token;
// Token zwischenspeichern, so einstellen, dass es nach 1 Stunde abläuft
localStore.write('auth_token', token);
localStore.write('auth_token_expiry', String(now + 3600));
console.log('New token cached successfully');
} else {
console.error('Login failed: ' + loginResp.statusCode);
return { action: 'passthrough' };
}
}
// Authorization-Header injizieren
request.headers['Authorization'] = 'Bearer ' + token;
return { action: 'modify', request: request };
}
Beispiel 2: Weiterleitung von API-Daten/Protokollierung
Melden Sie die abgefangenen Anforderungs- und Antwortinformationen an Ihren Protokollanalyseserver.
function interceptResponse(request, response) {
// Nur APIs bestimmter Pfade melden
if (!request.path.startsWith('/api/v2/')) {
return { action: 'passthrough' };
}
// Anforderungs- und Antwortinformationen sammeln
var logData = {
timestamp: new Date().toISOString(),
request: {
method: request.method,
url: request.url,
headers: request.headers
},
response: {
statusCode: response.statusCode,
body: response.body
}
};
// An den Protokollserver melden (Hinweis: Die Anforderung ist synchron und blockiert die Rückgabe der aktuellen Antwort)
var reportResp = httpClient.post(
'https://log.myserver.com/api/collect',
JSON.stringify(logData),
{ 'Content-Type': 'application/json' }
);
if (reportResp.error) {
console.warn('Log report failed: ' + reportResp.error);
}
// Die ursprüngliche Antwort durchlassen
return { action: 'passthrough' };
}
Beispiel 3: A/B-Tests — Antworten dynamisch ändern
Verwenden Sie einen Zähler, um eine einfache A/B-Aufteilung zu implementieren, die abwechselnd unterschiedliche simulierte Daten zurückgibt.
function interceptRequest(request) {
if (request.path !== '/api/recommend') {
return { action: 'passthrough' };
}
// Den alternativen Zähler aus localStore lesen
var count = parseInt(localStore.read('ab_counter') || '0');
count++;
localStore.write('ab_counter', String(count));
// Abwechselnd unterschiedliche Versionen für gerade und ungerade Zahlen zurückgeben
var version = (count % 2 === 0) ? 'A' : 'B';
if (version === 'A') {
return {
action: 'mock',
response: {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
version: 'A',
items: [{ id: 1, name: 'Empfehlungsplan A-1' }, { id: 2, name: 'Empfehlungsplan A-2' }]
})
}
};
} else {
return {
action: 'mock',
response: {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
version: 'B',
items: [{ id: 3, name: 'Empfehlungsplan B-1' }, { id: 4, name: 'Empfehlungsplan B-2' }]
})
}
};
}
}
Beispiel 4: Schutz vor Ratenbegrenzung bei Anforderungen
Zeichnen Sie die Anforderungshäufigkeit derselben API auf und geben Sie einen 429-Fehler zurück, wenn der Schwellenwert überschritten wird.
function interceptRequest(request) {
if (!request.path.startsWith('/api/')) {
return { action: 'passthrough' };
}
var key = 'rate_' + request.path;
var now = Math.floor(Date.now() / 1000);
// Die Zeit und Anzahl der letzten Anforderung lesen
var rawData = localStore.read(key);
var data = rawData ? JSON.parse(rawData) : { count: 0, windowStart: now };
// Wenn das Zeitfenster 60 Sekunden überschreitet, den Zähler zurücksetzen
if (now - data.windowStart > 60) {
data = { count: 0, windowStart: now };
}
data.count++;
localStore.write(key, JSON.stringify(data));
// Maximal 10 Mal pro Minute
if (data.count > 10) {
console.warn('Rate limit exceeded for ' + request.path);
return {
action: 'mock',
response: {
statusCode: 429,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
error: 'Too Many Requests',
retryAfter: 60 - (now - data.windowStart)
})
}
};
}
return { action: 'passthrough' };
}
Hinweise
-
httpClient ist ein synchroner Aufruf: HTTP-Anforderungen, die im Skript gestartet werden, blockieren die Ausführung des Skripts, bis die Anforderung abgeschlossen ist oder das Zeitlimit (15 Sekunden) erreicht ist. Dies wirkt sich auf die Verarbeitungsgeschwindigkeit der ursprünglichen Anforderung aus. Bitte achten Sie auf die in den Protokollen automatisch ausgegebenen Informationen zum Zeitaufwand der Anforderung.
-
Gemeinsamer Speicher localStore: Alle Skripte teilen sich denselben Speicherplatz. Wenn Sie Daten nach Host isolieren müssen, fügen Sie dem Schlüssel selbst ein Präfix hinzu.
-
Reihenfolge der Skriptausführung: Mehrere Skripte werden nach Priorität sortiert und ausgeführt. Sobald ein Skript ein anderes Ergebnis als
passthroughzurückgibt, werden nachfolgende Skripte übersprungen. -
Remote-Skripte: Unterstützt das Laden von Skripten von URLs. Der Inhalt des Remote-Skripts wird beim Starten der Paketerfassung automatisch abgerufen. Wenn der Abruf fehlschlägt, wird das Skript übersprungen.
-
JSON-Verarbeitung: Der Textkörper der Anforderungen/Antworten besteht aus Zeichenfolgen. Wenn Sie JSON-Daten verarbeiten müssen, verwenden Sie
JSON.parse()zum Parsen undJSON.stringify()zur Serialisierung. -
Fehlerbehandlung: Es wird empfohlen,
try-catchin der Schlüssellogik zu verwenden und Ausnahmen überconsole.error()zu protokollieren, um zu vermeiden, dass die Abfangkette aufgrund eines Skriptabsturzes unterbrochen wird. -
Hilfsfunktionen: Die Engine verfügt über zwei integrierte Hilfsfunktionen:
safeJsonParse(str)— Sicheres JSON-Parsen, gibt im Fehlerfall null zurückdeepClone(obj)— Tiefe Kopie von Objekten