Descrição
O Workerman a partir da versão 4.x reforçou o suporte ao serviço HTTP. Introduziu classes de requisição, classe de resposta, classe de sessão e SSE. Se você deseja utilizar o serviço HTTP do Workerman, é altamente recomendado usar a versão 4.x ou uma versão superior.
Observe que todos os exemplos a seguir são para a versão 4.x do Workerman, não são compatíveis com a versão 3.x.
Atenção
- A menos que a resposta seja um chunk ou uma resposta SSE, não é permitido enviar múltiplas respostas em uma única requisição, ou seja, não é permitido chamar
$connection->send()várias vezes em uma única requisição. - Cada requisição deve finalizar chamando
$connection->send()para enviar uma resposta, caso contrário, o cliente ficará esperando indefinidamente.
Resposta rápida
Quando não é necessário alterar o código de status HTTP (padrão 200), ou personalizar headers ou cookies, você pode simplesmente enviar uma string diretamente para o cliente para completar a resposta.
Exemplo
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)
{
// Enviar diretamente "this is body" para o cliente
$connection->send("this is body");
};
// Executar o worker
Worker::runAll();
Alterar código de status
Quando é necessário personalizar o código de status, headers ou cookies, você deve usar a classe de resposta Workerman\Protocols\Http\Response. Por exemplo, o exemplo abaixo retorna um código 404 quando o caminho acessado é /404, com o corpo da resposta como <h1>Desculpe, arquivo não encontrado</h1>.
Exemplo
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>Desculpe, arquivo não encontrado</h1>'));
} else {
$connection->send('this is body');
}
};
// Executar o worker
Worker::runAll();
Quando a classe Response já estiver inicializada, você pode alterar o código de status usando o método abaixo.
$response = new Response(200);
$response->withStatus(404);
$connection->send($response);
Enviar headers
Da mesma forma, para enviar headers, você precisa usar a classe de resposta Workerman\Protocols\Http\Response.
Exemplo
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);
};
// Executar o worker
Worker::runAll();
Quando a classe Response já estiver inicializada, você pode adicionar ou alterar headers usando o método abaixo.
$response = new Response(200);
// Adicionar ou alterar um header
$response->header('Content-Type', 'text/html');
// Adicionar ou alterar múltiplos headers
$response->withHeaders([
'Content-Type' => 'application/json',
'X-Header-One' => 'Header Value'
]);
$connection->send($response);
Redirecionamento
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);
};
// Executar o worker
Worker::runAll();
Enviar cookies
Da mesma forma, para enviar cookies, você precisa usar a classe de resposta Workerman\Protocols\Http\Response.
Exemplo
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);
};
// Executar o worker
Worker::runAll();
Enviar arquivos
Da mesma forma, para enviar arquivos, você precisa usar a classe de resposta Workerman\Protocols\Http\Response.
Para enviar um arquivo, use a seguinte abordagem:
$response = (new Response())->withFile($file);
$connection->send($response);
- O Workerman suporta o envio de arquivos muito grandes.
- Para arquivos grandes (maiores que 2M), o Workerman não carrega o arquivo inteiro na memória de uma vez, mas lê e envia o arquivo em partes no momento adequado.
- O Workerman otimiza a velocidade de leitura e envio de arquivos com base na velocidade de recebimento do cliente, garantindo o envio mais rápido possível do arquivo enquanto reduz ao mínimo o uso da memória.
- O envio de dados é não bloqueante e não afeta o processamento de outras requisições.
- Ao enviar arquivos, o cabeçalho
Last-Modifiedserá automaticamente adicionado, para que em solicitações futuras o servidor possa determinar se deve enviar uma resposta 304 para economizar na transferência de arquivos e melhorar o desempenho. - Os arquivos enviados automaticamente usarão o cabeçalho
Content-Typeapropriado ao serem enviados para o navegador. - Se o arquivo não existir, será automaticamente convertido para uma resposta 404.
Exemplo
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';
// Verificar o cabeçalho if-modified-since para determinar se o arquivo foi modificado
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();
// Se o arquivo não foi modificado, retorna 304
if ($modified_time === $if_modified_since) {
$connection->send(new Response(304));
return;
}
}
// Se o arquivo foi modificado ou não há cabeçalho if-modified-since, envia o arquivo
$response = (new Response())->withFile($file);
$connection->send($response);
};
// Executar o worker
Worker::runAll();
Enviar dados HTTP chunk
- Primeiro, deve-se enviar uma resposta que contenha o cabeçalho
Transfer-Encoding: chunkedpara o cliente. - Os dados chunk subsequentes são enviados usando a classe
Workerman\Protocols\Http\Chunk. - Finalmente, deve-se enviar um chunk vazio para encerrar a resposta.
Exemplo
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)
{
// Primeiro, envia uma resposta com o cabeçalho Transfer-Encoding: chunked
$connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
// Os dados Chunk subsequentes são enviados com a classe Workerman\Protocols\Http\Chunk
$connection->send(new Chunk('Primeiro pedaço de dados'));
$connection->send(new Chunk('Segundo pedaço de dados'));
$connection->send(new Chunk('Terceiro pedaço de dados'));
// Finalmente, é necessário enviar um chunk vazio para encerrar a resposta
$connection->send(new Chunk(''));
};
// Executar o worker
Worker::runAll();