workerman/http-client

Beschreibung

workerman/http-client ist ein asynchrones HTTP-Client-Komponente. Alle Anfragen und Antworten sind asynchron und nicht blockierend, mit einem integrierten Verbindungs-Pool. Anfragen und Antworten entsprechen dem PSR7-Standard.

Installation:

composer require workerman/http-client

Beispiel:

Verwendung von GET- und POST-Anfragen

use Workerman\Worker;

require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker();
$worker->onWorkerStart = function () {
    $http = new Workerman\Http\Client();

    $http->get('https://example.com/', function ($response) {
        var_dump($response->getStatusCode());
        echo $response->getBody();
    }, function ($exception) {
        echo $exception;
    });

    $http->post('https://example.com/', ['key1' => 'value1', 'key2' => 'value2'], function ($response) {
        var_dump($response->getStatusCode());
        echo $response->getBody();
    }, function ($exception) {
        echo $exception;
    });

    $http->request('https://example.com/', [
        'method' => 'POST',
        'version' => '1.1',
        'headers' => ['Connection' => 'keep-alive'],
        'data' => ['key1' => 'value1', 'key2' => 'value2'],
        'success' => function ($response) {
            echo $response->getBody();
        },
        'error' => function ($exception) {
            echo $exception;
        }
    ]);
};
Worker::runAll();

Datei hochladen

<?php
use Workerman\Worker;

require_once 'vendor/autoload.php';

$worker = new Worker();
$worker->onWorkerStart = function () {
    $http = new Workerman\Http\Client();
    // Datei hochladen
    $multipart = new \Workerman\Psr7\MultipartStream([
        [
            'name' => 'file',
            'contents' => fopen(__FILE__, 'r')
        ],
        [
            'name' => 'json',
            'contents' => json_encode(['a'=>1, 'b'=>2])
        ]
    ]);
    $boundary = $multipart->getBoundary();
    $http->request('http://127.0.0.1:8787', [
        'method' => 'POST',
        'version' => '1.1',
        'headers' => ['Connection' => 'keep-alive', 'Content-Type' => "multipart/form-data; boundary=$boundary"],
        'data' => $multipart,
        'success' => function ($response) {
            echo $response->getBody();
        },
        'error' => function ($exception) {
            echo $exception;
        }
    ]);
};

Worker::runAll();

Progress-Streaming-Antwort

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Workerman\Connection\TcpConnection;
use Workerman\Http\Client;
use Workerman\Protocols\Http\Chunk;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
use Workerman\Worker;

$worker = new Worker('http://0.0.0.0:1234');
$worker->onMessage = function (TcpConnection $connection, Request $request) {
    $http = new Client();
    $http->request('https://api.ai.com/v1/chat/completions', [
        'method' => 'POST',
        'data' => json_encode([
            'model' => 'gpt-3.5-turbo',
            'temperature' => 1,
            'stream' => true,
            'messages' => [['role' => 'user', 'content' => 'hello']],
        ]),
        'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer sk-xxx',
        ],
        'progress' => function($buffer) use ($connection) {
            $connection->send(new Chunk($buffer));
        },
        'success' => function($response) use ($connection) {
            $connection->send(new Chunk('')); // Ein leeres Chunk senden, um das Ende der Antwort zu signalisieren
        },
    ]);
    $connection->send(new Response(200, [
        //"Content-Type" => "application/octet-stream",
        "Transfer-Encoding" => "chunked",
    ], ''));
};
Worker::runAll();

Optionen

<?php
require __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker();
$worker->onWorkerStart = function(){
    $options = [
        'max_conn_per_addr' => 128, // Maximale Anzahl an gleichzeitigen Verbindungen pro Domain
        'keepalive_timeout' => 15,  // Zeit, nach der die Verbindung ohne Kommunikation geschlossen wird
        'connect_timeout'   => 30,  // Zeitüberschreitung für die Verbindung
        'timeout'           => 30,  // Zeitüberschreitung für das Warten auf eine Antwort nach der Anfrage
    ];
    $http = new Workerman\Http\Client($options);

    $http->get('http://example.com/', function($response){
        var_dump($response->getStatusCode());
        echo $response->getBody();
    }, function($exception){
        echo $exception;
    });
};
Worker::runAll();

Verwendung von Coroutinen

Hinweis
Die Verwendung von Coroutinen erfordert workerman>=5.1, http-client>=3.0, die Installation der swoole oder swow Erweiterung, oder die Installation von composer require revolt/event-loop, um den Fiber-Treiber zu unterstützen.

use Workerman\Worker;

require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker();
$worker->eventLoop = \Workerman\Events\Swoole::class; // Oder \Workerman\Events\Swow::class oder \Workerman\Events\Fiber::class
$worker->onWorkerStart = function () {
    $http = new Workerman\Http\Client();

    $response = $http->get('https://example.com/');
    var_dump($response->getStatusCode());
    echo $response->getBody();

    $response = $http->post('https://example.com/', ['key1' => 'value1', 'key2' => 'value2']);
    var_dump($response->getStatusCode());
    echo $response->getBody();

    $response = $http->request('https://example.com/', [
        'method' => 'POST',
        'version' => '1.1',
        'headers' => ['Connection' => 'keep-alive'],
        'data' => ['key1' => 'value1', 'key2' => 'value2'],
    ]);
    echo $response->getBody();
};
Worker::runAll();

Wenn keine Rückruffunktionen festgelegt sind, wird das Ergebnis der asynchronen Anfrage synchron zurückgegeben; der Anfrageprozess blockiert den aktuellen Prozess nicht und es können mehrere Anfragen gleichzeitig bearbeitet werden.

Hinweise:

  1. Das Projekt muss zuerst require __DIR__ . '/vendor/autoload.php'; laden.

  2. Alle asynchronen Codes dürfen nur in der Laufzeitumgebung nach dem Start von workerman ausgeführt werden.

  3. Alle Projekte, die auf Workerman basieren, werden unterstützt, einschließlich Webman, GatewayWorker, PHPSocket.io usw.

  4. Versuchen Sie, das Client-Objekt wiederzuverwenden, um die Nutzung des Verbindungs-Pools zur Leistungsverbesserung zu maximieren, und erstellen Sie nicht bei jeder Anfrage ein neues Workerman\Http\Client()-Objekt.

Verwendung in Webman

Wenn Sie asynchrone HTTP-Anfragen in Webman verwenden und die Ergebnisse an die Frontend zurückgeben möchten, siehe die folgende Verwendung.

<?php
namespace app\controller;

use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;

class IndexController
{
    public function index(Request $request)
    {
        // Client-Objekt speichern und wiederverwenden, kann die Leistung erheblich verbessern
        static $http;
        $connection = $request->connection;
        $http = $http ?: new \Workerman\Http\Client();
        $http->get('https://example.com/', function ($response) use ($connection) {
            $connection->send(new Chunk($response->getBody()));
            $connection->send(new Chunk('')); // Ein leeres Chunk senden, um das Ende der Antwort zu signalisieren
        });
        return response()->withHeaders([
            "Transfer-Encoding" => "chunked",
        ]);
    }
}

Die obige Verwendung gibt dem Client zunächst einen HTTP-Header mit Chunked zurück und sendet dann die Daten in Chunk-Form an den Client; Sie können auch die oben beschriebenene Verwendung von Coroutinen in Betracht ziehen.

Hinweis
Der obige Code speichert das Client-Objekt in einer statischen Variablen im Methodenbereich, es kann jedoch auch in einer statischen Mitglieder oder einem globalen Objekt gespeichert werden.

Anfordern der OpenAI-Schnittstelle in Webman und Streaming-Rückgabe

Siehe https://www.workerman.net/plugin/157