Giới thiệu

Workerman từ phiên bản 4.x đã tăng cường hỗ trợ cho dịch vụ HTTP. Đã giới thiệu các lớp yêu cầu, lớp phản hồi, lớp phiên và SSE. Nếu bạn muốn sử dụng dịch vụ HTTP của Workerman, chúng tôi khuyên bạn nên sử dụng Workerman 4.x hoặc phiên bản cao hơn.

Lưu ý rằng tất cả các cú pháp dưới đây đều dành cho phiên bản Workerman 4.x, không tương thích với Workerman 3.x.

Lưu ý

  • Trừ khi gửi phản hồi chunk hoặc phản hồi SSE, nếu không không được phép gửi nhiều phản hồi trong một yêu cầu, tức là không được gọi \$connection->send() nhiều lần trong một yêu cầu.
  • Mỗi yêu cầu cuối cùng phải gọi một lần \$connection->send() để gửi phản hồi, nếu không, khách hàng sẽ chờ mãi.

Phản hồi nhanh

Khi không cần thay đổi mã trạng thái HTTP (mặc định là 200), hoặc header, cookie tùy chỉnh, bạn có thể gửi một chuỗi trực tiếp cho khách hàng để hoàn thành phản hồi.

Ví dụ

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)
{
    // Gửi trực tiếp this is body cho khách hàng
    $connection->send("this is body");
};

// Chạy worker
Worker::runAll();

Thay đổi mã trạng thái

Khi cần tùy chỉnh mã trạng thái, header, cookie, cần sử dụng lớp phản hồi Workerman\Protocols\Http\Response. Ví dụ dưới đây trả về mã trạng thái 404 khi truy cập đường dẫn /404, nội dung gói là <h1>Xin lỗi, tệp không tồn tại</h1>.

Ví dụ

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>Xin lỗi, tệp không tồn tại</h1>'));
    } else {
        $connection->send('this is body');
    }
};

// Chạy worker
Worker::runAll();

Khi lớp Response đã được khởi tạo, để thay đổi mã trạng thái, sử dụng phương pháp dưới đây.

$response = new Response(200);
$response->withStatus(404);
$connection->send($response);

Gửi header

Tương tự, để gửi header cần sử dụng lớp phản hồi Workerman\Protocols\Http\Response.

Ví dụ

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

// Chạy worker
Worker::runAll();

Khi lớp Response đã được khởi tạo, để thêm hoặc thay đổi header, sử dụng phương pháp dưới đây.

$response = new Response(200);
// Thêm hoặc thay đổi một header
$response->header('Content-Type', 'text/html');
// Thêm hoặc thay đổi nhiều header
$response->withHeaders([
    'Content-Type' => 'application/ json',
    'X-Header-One' => 'Header Value'
]);
$connection->send($response);

Chuyển hướng

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

// Chạy worker
Worker::runAll();

Gửi cookie

Tương tự, để gửi cookie cần sử dụng lớp phản hồi Workerman\Protocols\Http\Response.

Ví dụ

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

// Chạy worker
Worker::runAll();

Gửi tệp

Tương tự, để gửi tệp cần sử dụng lớp phản hồi Workerman\Protocols\Http\Response.

Gửi tệp bằng cách sau

$response = (new Response())->withFile($file);
$connection->send($response);
  • Workerman hỗ trợ gửi các tệp lớn.
  • Đối với tệp lớn (trên 2M), Workerman sẽ không đọc toàn bộ tệp vào bộ nhớ một lần mà sẽ đọc tệp theo phân đoạn trong thời điểm thích hợp và gửi.
  • Workerman sẽ tối ưu tốc độ đọc tệp và gửi dựa trên tốc độ tiếp nhận của khách hàng, đảm bảo gửi tệp nhanh nhất trong khi giảm thiểu việc sử dụng bộ nhớ.
  • Việc gửi dữ liệu diễn ra không đồng bộ, không ảnh hưởng đến việc xử lý yêu cầu khác.
  • Khi gửi tệp sẽ tự động thêm header Last-Modified, để lần yêu cầu tiếp theo, máy chủ có thể xác định có gửi phản hồi 304 hay không nhằm tiết kiệm băng thông truyền tải tệp và cải thiện hiệu suất.
  • Tệp gửi đi sẽ tự động sử dụng header Content-Type phù hợp để gửi cho trình duyệt.
  • Nếu tệp không tồn tại, sẽ tự động chuyển thành phản hồi 404.

Ví dụ

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';
    // Kiểm tra header if-modified-since để xác định tệp có bị sửa đổi không
    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();
        // Nếu tệp không thay đổi thì trả về 304
        if ($modified_time === $if_modified_since) {
            $connection->send(new Response(304));
            return;
        }
    }
    // Nếu tệp đã thay đổi hoặc không có header if-modified-since thì gửi tệp
    $response = (new Response())->withFile($file);
    $connection->send($response);
};

// Chạy worker
Worker::runAll();

Gửi dữ liệu http chunk

  • Phải gửi một phản hồi có header Transfer-Encoding: chunked trước cho khách hàng.
  • Gửi dữ liệu chunk sau đó sử dụng lớp Workerman\Protocols\Http\Chunk.
  • Cuối cùng bắt buộc phải gửi một chunk trống để kết thúc phản hồi.

Ví dụ

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)
{
    // Đầu tiên gửi một phản hồi với header Transfer-Encoding: chunked
    $connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
    // Gửi dữ liệu chunk sau đó sử dụng lớp Workerman\Protocols\Http\Chunk
    $connection->send(new Chunk('Phân đoạn đầu tiên'));
    $connection->send(new Chunk('Phân đoạn thứ hai'));
    $connection->send(new Chunk('Phân đoạn thứ ba'));
    // Cuối cùng phải gửi một chunk trống để kết thúc phản hồi
    $connection->send(new Chunk(''));
};

// Chạy worker
Worker::runAll();