[PYTHON] Ich habe einen HTTP-Proxy erstellt, der HTTP-Antworten aufzeichnen und wiedergeben kann

Wie der Titel schon sagt, haben wir einen HTTP-Proxy erstellt, der HTTP-Antworten aufzeichnen und wiedergeben kann.

Was ich wollte

Ich entwickle einen Crawler bei der Arbeit und wollte schon immer etwas, um einen externen Dienst zu verspotten und eine HTTP-Antwort zurückzugeben, um einen systemweiten E2E-Test mit dem Crawler zu schreiben.

Ich habe nach den folgenden vier Funktionen gesucht. ** 1. Sie können eine HTTP-Antwort aufzeichnen und basierend auf den aufgezeichneten Daten antworten ** ** 2. Die aufgezeichneten Daten können einfach bearbeitet werden, um eine HTTP-Antwort zu simulieren ** ** 3. Kann als HTTP-Proxy verwendet werden, um es unabhängig von einer bestimmten Sprache oder einem bestimmten Testframework zu machen ** ** 4. Unterstützt HTTPS **

Es gab eine Bibliothek, die einen HTTP-Client verspottete, der zu Testzwecken verwendet werden kann, und eine Antwort zurückgab, und es gab verschiedene Dinge, die durch Simulation einer API-Antwort eine Verspottung erzeugen konnten, aber ich konnte nicht diejenige finden, die genau verwendet werden konnte, und entschied mich daher, eine zu erstellen. Hat.

Übrigens, obwohl es den Zweck dieser Zeit nicht erfüllte, gibt es ein OSS namens mountebank, das zum Testen von Microservices verwendet werden kann, und es scheint wahnsinnig praktisch zu sein, da es auch beliebige Antworten abspielen kann. war. Es gibt auch eine von netflix erstellte Bibliothek namens Polly.JS, die auf JavaScript (browser, node.js) beschränkt ist und ein HTTP-Server ist. Sie können einen Stub erstellen, um eine beliebige Antwort zurückzugeben, und Sie können die Antwortzeit anpassen, was sehr praktisch erscheint. Ich möchte beide eines Tages verwenden, wenn es einen passenden Zweck gibt.

Wie es funktioniert

Nach vielen Recherchen habe ich eine großartige HTTP-Proxy-Software namens mitmproxy gefunden, die für diesen Zweck geeignet ist. Das "Mitm" von Mitmproxy stammt von * Man In The Middle Attack *, und durch Beenden der SSL-Kommunikation mit diesem Proxy ist es möglich, den Inhalt auch mit HTTPS-Anforderungsantwort zu manipulieren. Toller HTTP-Proxy! (Unheimlich)

Obwohl Mitmproxy selbst nicht die Funktion hat, HTTP-Antworten aufzuzeichnen und wiederzugeben, hat es eine sehr bequeme Funktion, beliebige Python-Skripte an verschiedenen Stellen einzufügen, z. B. beim Empfangen einer Anfrage und beim Senden einer Antwort, damit diese erweitert werden kann. Daher habe ich ein Plug-In erstellt, um HTTP-Antworten mithilfe dieses Mechanismus aufzuzeichnen und wiederzugeben.

image.png

Der Quellcode ist hier verfügbar. https://github.com/Chanmoro/record-and-replay-proxy

Wir haben ein Docker-Image zur einfachen Verwendung veröffentlicht. https://hub.docker.com/r/chanmoro/record-and-replay-proxy

Wie benutzt man

Das Docker-Image wird auf Docker Hub (https://hub.docker.com/r/chanmoro/record-and-replay-proxy) veröffentlicht, sodass es einfach zu verwenden ist.

1. Zeichnen Sie die HTTP-Antwort auf

Starten Sie den HTTP-Proxy im Aufnahmemodus mit dem folgenden Befehl:

$ docker run -it --rm -p 8080:8080 -v ${PWD}/response_data:/app/response_data chanmoro/record-and-replay-proxy record

Die hier aufgezeichnete Antwort wird in / app / response_data gespeichert. Hängen Sie also das lokale Verzeichnis ein, damit die Daten erhalten bleiben.

2. HTTP-Anfrage senden (Datensatz)

Hier als Beispiel speichern wir die Antwort, wenn Sie mit curl auf https://github.com/ zugreifen.

$ curl -k -x localhost:8080 https://github.com/

Zu diesem Zeitpunkt verwendet curl das von mitmproxy ausgestellte Selbstzertifikat für die SSL-Kommunikation. Wenn Sie eine Anforderung im Standardzustand senden, tritt bei der SSL-Gültigkeitsprüfung ein Fehler auf. Deaktivieren Sie ihn daher.

Aufgezeichnete HTTP-Antwort

Die aufgezeichnete HTTP-Antwort wird in response_data im aktuellen Verzeichnis gespeichert, das auf dem Docker-Container bereitgestellt ist.

$ tree response_data
response_data
└── https%3A%2F%2Fgithub.com%2F #Die Anforderungs-URL wird zum Verzeichnisnamen
    └── GET                     #HTTP-Methode
        ├── metadata            #HTTP-Methode, Anforderungs-URL, HTTP-Antwortstatus
        ├── response_body       #Antwortkörper
        └── response_header     #Antwortheader

metadata speichert die HTTP-Methode, die Anforderungs-URL und den HTTP-Antwortstatus der aufgezeichneten Anforderung.

metadata


{
    "url": "https://github.com/",
    "method": "GET",
    "status": 200
}

Der Antworttext wird in "response_body" aufgezeichnet.

response_body


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com">
  <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com">
  <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com">
  <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
...

Der Antwortheader wird in response_header aufgezeichnet.

response_header


Date: Thu, 12 Dec 2019 10:20:49 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Server: GitHub.com
Status: 200 OK
Vary: X-PJAX
...

3. Spielen Sie die aufgezeichnete HTTP-Antwort ab

Starten Sie den HTTP-Proxy im Wiedergabemodus, um die aufgezeichnete HTTP-Antwort abzuspielen. Das Verzeichnis, das in / app / response_data gemountet werden soll, gibt das Verzeichnis an, das die aufgezeichneten Antwortdaten enthält.

$ docker run -it --rm -p 8080:8080 -v ${PWD}/response_data:/app/response_data chanmoro/record-and-replay-proxy replay

4. HTTP-Anfrage senden (Wiedergabe)

Wenn Sie eine HTTP-Anforderung auf dieselbe Weise senden wie bei der Aufzeichnung mit dem HTTP-Proxy, der im Wiedergabemodus ausgeführt wird, wird die aufgezeichnete Antwort zurückgegeben. Im Wiedergabemodus greift der Proxy nicht auf "https: // github.com /" zu, sodass er offline verwendet werden kann.

$ curl -k -x localhost:8080 https://github.com/

Lassen Sie uns die Antwortdaten bearbeiten, damit wir bestätigen können, dass sie wiedergegeben wurden. Bearbeiten Sie die Daten auf den folgenden Inhalt.

metadata


{
    "url": "https://github.com/",
    "method": "GET",
    "status": 500
}

response_body


This is recorded response!

response_header


Date: Thu, 12 Dec 2019 10:20:49 GMT
Status: 500 Error
Hoge: This is Hoge header.

Lassen Sie uns überprüfen, ob die Antwort als bearbeitet zurückgegeben wird.

$ curl -v -k -x localhost:8080 https://github.com/
...
> GET / HTTP/1.1
> Host: github.com
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 500 Internal Server Error
< Date: Thu, 12 Dec 2019 10:20:49 GMT
< Status: 500 Error
< Hoge: This is Hoge header.
< content-length: 26
< 
* Connection #0 to host localhost left intact
This is recorded response!

Sie können sehen, dass der HTTP-Status, der Antwortheader und der Antworttext genau das sind, was Sie bearbeitet haben. Das beste!

Zusammenfassung

In diesem Artikel werden die Funktionen und die Verwendung des HTTP-Proxys (Record-and-Replay-Proxy) (https://github.com/Chanmoro/record-and-replay-proxy) vorgestellt, mit dem die erstellte HTTP-Antwort aufgezeichnet und wiedergegeben werden kann. Hat.

Auf diese Weise können Sie problemlos auf externe Dienste und APIs zugreifen.

Bitte benutzen Sie es!

Recommended Posts

Ich habe einen HTTP-Proxy erstellt, der HTTP-Antworten aufzeichnen und wiedergeben kann
Richten Sie einen FTP-Server ein, der sofort erstellt und zerstört werden kann (in Python).
Verwenden Sie den Befehl pip in einer HTTP-Proxy-Umgebung, für die eine Authentifizierung erforderlich ist