คำอธิบาย

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();