คำอธิบาย
workerman เริ่มเสริมการสนับสนุน HTTP ตั้งแต่เวอร์ชัน 4.x โดยได้มีการแนะนำคลาสคำขอ คลาสการตอบสนอง คลาสเซสชัน และSSE หากคุณต้องการใช้บริการ HTTP ของ workerman ขอแนะนำอย่างยิ่งให้ใช้ workerman เวอร์ชัน 4.x หรือเวอร์ชันที่สูงกว่านี้
โปรดทราบว่า ข้างล่างนี้เป็นวิธีการใช้งานของ workerman เวอร์ชัน 4.x ซึ่งไม่รองรับ workerman เวอร์ชัน 3.x
หมายเหตุ
- ยกเว้นการส่งเป็น chunk หรือการตอบสนองแบบ SSE ไม่อนุญาตให้ส่งการตอบสนองหลายครั้งในคำร้องเดียว ซึ่งหมายความว่าไม่อนุญาตให้เรียกใช้
$connection->send()หลายครั้งในคำร้องเดียว - คำร้องแต่ละคำร้องจะต้องเรียกใช้
$connection->send()เพื่อส่งการตอบสนอง มิฉะนั้นไคลเอนต์จะรอคอยตลอดไป
การตอบสนองอย่างรวดเร็ว
เมื่อไม่จำเป็นต้องเปลี่ยนรหัสสถานะ HTTP (ค่าเริ่มต้นคือ 200) หรือกำหนด header, cookie ด้วยตนเอง สามารถส่งสตริงไปยังไคลเอนต์เพื่อทำการตอบสนองได้โดยตรง
ตัวอย่าง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
// ส่ง this is body ให้กับไคลเอนต์โดยตรง
$connection->send("this is body");
};
// เรียกใช้งาน worker
Worker::runAll();
การเปลี่ยนรหัสสถานะ
เมื่อจำเป็นต้องกำหนดรหัสสถานะ, header, cookie ด้วยตนเอง จะต้องใช้คลาสการตอบสนอง Workerman\Protocols\Http\Response ตัวอย่างด้านล่างนี้จะส่งรหัสสถานะ 404 เมื่อเข้าถึงpath/404 โดยมีเนื้อหาของแพ็กเกจเป็น <h1>ขอโทษ, ไม่พบไฟล์</h1>
ตัวอย่าง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
if ($request->path() === '/404') {
$connection->send(new Response(404, [], '<h1>ขอโทษ, ไม่พบไฟล์</h1>'));
} else {
$connection->send('this is body');
}
};
// เรียกใช้งาน worker
Worker::runAll();
เมื่อคลาส Response ถูกสร้างแล้ว หากต้องการเปลี่ยนรหัสสถานะให้ใช้วิธีด้านล่างนี้
$response = new Response(200);
$response->withStatus(404);
$connection->send($response);
การส่ง header
เช่นเดียวกัน การส่ง header จะต้องใช้คลาสการตอบสนอง Workerman\Protocols\Http\Response
ตัวอย่าง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
$response = new Response(200, [
'Content-Type' => 'text/html',
'X-Header-One' => 'Header Value'
], 'this is body');
$connection->send($response);
};
// เรียกใช้งาน worker
Worker::runAll();
เมื่อคลาส Response ถูกสร้างแล้ว หากต้องการเพิ่มหรือเปลี่ยนแปลง header ให้ใช้วิธีด้านล่างนี้
$response = new Response(200);
// เพิ่มหรือเปลี่ยนแปลง header หนึ่งอัน
$response->header('Content-Type', 'text/html');
// เพิ่มหรือเปลี่ยนแปลง header หลายอัน
$response->withHeaders([
'Content-Type' => 'application/json',
'X-Header-One' => 'Header Value'
]);
$connection->send($response);
การเปลี่ยนเส้นทาง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
$location = '/test_location';
$response = new Response(302, ['Location' => $location]);
$connection->send($response);
};
Worker::runAll();
การส่ง cookie
เช่นเดียวกัน การส่ง cookie จะต้องใช้คลาสการตอบสนอง Workerman\Protocols\Http\Response
ตัวอย่าง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
$response = new Response(200, [], 'this is body');
$response->cookie('name', 'tom');
$connection->send($response);
};
// เรียกใช้งาน worker
Worker::runAll();
การส่งไฟล์
เช่นเดียวกัน การส่งไฟล์จะต้องใช้คลาสการตอบสนอง Workerman\Protocols\Http\Response
ในการส่งไฟล์ให้ใช้วิธีนี้
$response = (new Response())->withFile($file);
$connection->send($response);
- workerman รองรับการส่งไฟล์ขนาดใหญ่
- สำหรับไฟล์ขนาดใหญ่ (เกิน 2M) workerman จะไม่อ่านไฟล์ทั้งหมดในหน่วยความจำพร้อมกัน แต่จะอ่านไฟล์แยกตามช่วงเวลาที่เหมาะสมและส่งข้อมูล
- workerman จะปรับปรุงความเร็วในการอ่านไฟล์ตามความเร็วในการรับของไคลเอนต์เพื่อส่งไฟล์อย่างรวดเร็วพร้อมลดการใช้หน่วยความจำให้น้อยที่สุด
- การส่งข้อมูลเป็นแบบไม่บล็อก จะไม่ส่งผลกระทบต่อการจัดการคำร้องอื่น ๆ
- การส่งไฟล์จะเพิ่ม header
Last-Modifiedโดยอัตโนมัติ เพื่อให้เซิร์ฟเวอร์ตัดสินใจว่าจะส่งการตอบสนอง 304 เพื่อประหยัดการถ่ายโอนไฟล์และเพิ่มประสิทธิภาพ - ไฟล์ที่ถูกส่งจะถูกส่งไปยังเบราว์เซอร์ด้วย header
Content-Typeที่เหมาะสม - หากไฟล์ไม่ถูกพบ จะถูกเปลี่ยนเป็นการตอบสนอง 404 โดยอัตโนมัติ
ตัวอย่าง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
$file = '/your/path/of/file';
// ตรวจสอบ if-modified-since header เพื่อดูว่าไฟล์มีการเปลี่ยนแปลงหรือไม่
if (!empty($if_modified_since = $request->header('if-modified-since'))) {
$modified_time = date('D, d M Y H:i:s', filemtime($file)) . ' ' . \date_default_timezone_get();
// หากไฟล์ไม่เปลี่ยนแปลง ให้ส่ง 304
if ($modified_time === $if_modified_since) {
$connection->send(new Response(304));
return;
}
}
// ส่งไฟล์หากมีการเปลี่ยนแปลงหรือไม่มี if-modified-since header
$response = (new Response())->withFile($file);
$connection->send($response);
};
// เรียกใช้งาน worker
Worker::runAll();
การส่งข้อมูล http chunk
- ต้องส่งการตอบสนอง Response ที่มี header
Transfer-Encoding: chunkedก่อน - ข้อมูล chunk ที่ตามมาจะใช้งาน
Workerman\Protocols\Http\Chunkคลาส - ต้องส่ง chunk ว่างเพื่อสิ้นสุดการตอบสนอง
ตัวอย่าง
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
use Workerman\Protocols\Http\Chunk;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
// ส่ง Response ที่มี Transfer-Encoding: chunked header ก่อน
$connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
// ส่งข้อมูล Chunk ต่อไปด้วย Workerman\Protocols\Http\Chunk คลาส
$connection->send(new Chunk('ข้อมูลช่วงแรก'));
$connection->send(new Chunk('ข้อมูลช่วงที่สอง'));
$connection->send(new Chunk('ข้อมูลช่วงที่สาม'));
// ส่ง chunk ว่างเพื่อสิ้นสุดการตอบสนอง
$connection->send(new Chunk(''));
};
// เรียกใช้งาน worker
Worker::runAll();