workerman/http-client
คำอธิบาย
workerman/http-client เป็นส่วนประกอบลูกค้าสำหรับ HTTP ที่ไม่ซิงโครนัส ทุกคำขอและการตอบสนองเป็นแบบไม่บล็อกแบบอะซิงโครนัส มีการจัดการการเชื่อมต่อแบบในตัวและข้อความคำขอและการตอบสนองปฏิบัติตามมาตรฐาน PSR7
การติดตั้ง:
composer require workerman/http-client
ตัวอย่าง:
การใช้งานคำขอ get และ post
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();
อัปโหลดไฟล์
<?php
use Workerman\Worker;
require_once 'vendor/autoload.php';
$worker = new Worker();
$worker->onWorkerStart = function () {
$http = new Workerman\Http\Client();
// อัปโหลดไฟล์
$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)
<?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('')); // ส่ง chunk ว่างเพื่อระบุว่าการตอบสนองสิ้นสุดลง
},
]);
$connection->send(new Response(200, [
//"Content-Type" => "application/octet-stream",
"Transfer-Encoding" => "chunked",
], ''));
};
Worker::runAll();
ตัวเลือก (Options)
<?php
require __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker();
$worker->onWorkerStart = function(){
$options = [
'max_conn_per_addr' => 128, // จำนวนการเชื่อมต่อพร้อมกันสูงสุดต่อโดเมน
'keepalive_timeout' => 15, // เวลาที่เชื่อมต่อไม่ส่งข้อมูลจะถูกปิด
'connect_timeout' => 30, // เวลารอเชื่อมต่อ
'timeout' => 30, // เวลารอการตอบสนองหลังจากส่งคำขอ
];
$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();
วิธีใช้ Coroutines
หมายเหตุ
การใช้ Coroutines ต้องการ workerman>=5.1, http-client>=3.0, ติดตั้งswooleหรือswowextension หรือ ติดตั้งcomposer require revolt/event-loopเพื่อสนับสนุน Fiber driver
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker();
$worker->eventLoop = \Workerman\Events\Swoole::class; // หรือ \Workerman\Events\Swow::class หรือ \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();
เมื่อไม่มีการตั้งค่าฟังก์ชันการเรียกกลับ ลูกค้าจะกลับคำตอบของคำขอแบบอะซิงโครนัสด้วยวิธีซิงโครนัส กระบวนการคำขอจะไม่บล็อกกระบวนการปัจจุบัน ซึ่งสามารถจัดการคำขอได้พร้อมกัน
หมายเหตุ:
-
โครงการจะต้องโหลด
require __DIR__ . '/vendor/autoload.php';ก่อน -
โค้ดอะซิงโครนัสทั้งหมดสามารถทำงานได้หลังจากที่ Workerman เริ่มทำงานแล้วเท่านั้น
-
รองรับโครงการทั้งหมดที่พัฒนาบน Workerman รวมถึง Webman, GatewayWorker, PHPSocket.io เป็นต้น
-
พยายามเก็บวัตถุ client ไว้เพื่อการใช้งานซ้ำ จะช่วยให้ใช้ประโยชน์จากการจัดการการเชื่อมต่อปรับปรุงประสิทธิภาพ ไม่ควรสร้างวัตถุใหม่ทุกครั้ง
new Workerman\Http\Client()
วิธีใช้ใน Webman
หากต้องการใช้คำขอ HTTP แบบอะซิงโครนัสใน Webman และส่งผลลัพธ์กลับไปยัง front-end ให้ดูตัวอย่างด้านล่าง
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;
class IndexController
{
public function index(Request $request)
{
// เก็บวัตถุ client เพื่อใช้งานซ้ำ เพิ่มประสิทธิภาพได้มาก
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('')); // ส่ง chunk ว่างเพื่อระบุว่าการตอบสนองสิ้นสุดลง
});
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
ตัวอย่างข้างต้นจะส่ง HTTP header ที่มี chunked ให้กับ client ก่อน จากนั้นส่งข้อมูลเป็น chunk ไปยัง client แน่นอนว่าคุณยังสามารถใช้วิธี coroutine ด้านบนได้เช่นกัน
หมายเหตุ
โค้ดข้างต้นจะเก็บวัตถุ client ไว้ในตัวแปรสถิตของขอบเขตวิธีการ ในทางปฏิบัติสามารถเก็บไว้ในสมาชิกสถิตของคลาสหรือในวัตถุทั่ว ๆ ไปก็ได้
การขอ OpenAI API และส่งคืนแบบไหลใน Webman
อ้างอิงจาก https://www.workerman.net/plugin/157