Introdução
A partir da versão 4.x, o workerman reforçou o suporte ao serviço HTTP. Introduziu classes de requisição, resposta, sessão e SSE. Se você deseja usar o serviço HTTP do workerman, é altamente recomendável usar a versão 4.x ou posterior.
Observe que os seguintes exemplos são para uso da versão 4.x do workerman e não são compatíveis com a versão 3.x.
Atenção
- A menos que esteja enviando uma resposta em chunks ou SSE, não é permitido enviar a resposta várias vezes em uma única solicitação, ou seja, não é permitido chamar
$connection->send()
várias vezes em uma única solicitação. - Cada solicitação deve chamar
$connection->send()
pelo menos uma vez para enviar a resposta, caso contrário o cliente ficará aguardando indefinidamente.
Resposta Rápida
Quando não for necessário alterar o código de status HTTP (padrão 200), ou personalizar cabeçalhos e cookies, você pode enviar uma string diretamente para o cliente para concluir 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)
{
// Envie diretamente "this is body" para o cliente
$connection->send("this is body");
};
// Executar o worker
Worker::runAll();
Alterando o Código de Status
Quando for necessário personalizar o código de status, cabeçalhos e cookies, é necessário usar a classe de resposta Workerman\Protocols\Http\Response
. Por exemplo, no seguinte exemplo, ao acessar o caminho /404
, o código de status 404 será retornado com o conteúdo <h1>Desculpe, o arquivo não existe</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, o arquivo não existe</h1>'));
} else {
$connection->send('this is body');
}
};
// Executar o worker
Worker::runAll();
Depois que a classe Response
é inicializada, é possível modificar o código de status usando o método abaixo.
$response = new Response(200);
$response->withStatus(404);
$connection->send($response);
Enviando Cabeçalhos
Da mesma forma, para enviar cabeçalhos é necessário 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' => 'Valor do Cabeçalho'
], 'this is body');
$connection->send($response);
};
// Executar o worker
Worker::runAll();
Depois que a classe Response
é inicializada, é possível adicionar ou modificar cabeçalhos usando o método abaixo.
$response = new Response(200);
// Adicionar ou modificar um cabeçalho
$response->header('Content-Type', 'text/html');
// Adicionar ou modificar vários cabeçalhos
$response->withHeaders([
'Content-Type' => 'application/ json',
'X-Header-One' => 'Valor do Cabeçalho'
]);
$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)
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function($connection, $request)
{
$location = '/test_location';
$response = new Response(302, ['Location' => $location]);
$connection->send($response);
};
Worker::runAll();
Enviando Cookie
Da mesma forma, para enviar um cookie é necessário 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();
Enviando Arquivo
Da mesma forma, para enviar um arquivo é necessário usar a classe de resposta Workerman\Protocols\Http\Response
.
Para enviar um arquivo, use o seguinte método
$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 o lê e envia em partes no momento apropriado.
- O workerman otimiza a velocidade de leitura e envio do arquivo com base na velocidade de recebimento do cliente, garantindo o envio mais rápido do arquivo enquanto reduz o uso de memória ao mínimo.
- A transmissão de dados é não-bloqueante e não afeta o processamento de outras solicitações.
- Ao enviar um arquivo, o cabeçalho
Last-Modified
é automaticamente adicionado para que o servidor possa decidir se enviar uma resposta 304 na próxima solicitação, poupando a transmissão do arquivo e melhorando o desempenho. - O arquivo enviado automaticamente utilizará o cabeçalho
Content-Type
apropriado para enviar ao navegador. - Se o arquivo não existir, será automaticamente tratado como 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 = '/seu/caminho/do/arquivo';
// Verifique se o cabeçalho if-modified-since para verificar 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, retorne 304
if ($modified_time === $if_modified_since) {
$connection->send(new Response(304));
return;
}
}
// Se o arquivo foi modificado ou o cabeçalho if-modified-since está ausente, envie o arquivo
$response = (new Response())->withFile($file);
$connection->send($response);
};
// Executar o worker
Worker::runAll();
Enviar dados de chunk HTTP
- É necessário enviar uma resposta inicial com cabeçalho
Transfer-Encoding: chunked
para o cliente. - Para enviar dados de chunk subsequentes, use a classe
Workerman\Protocols\Http\Chunk
. - No final, é necessário 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)
{
// Envie inicialmente uma resposta com o cabeçalho Transfer-Encoding: chunked
$connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
// Use a classe Workerman\Protocols\Http\Chunk para enviar dados de chunk subsequentes
$connection->send(new Chunk('Dados do primeiro bloco'));
$connection->send(new Chunk('Dados do segundo bloco'));
$connection->send(new Chunk('Dados do terceiro bloco'));
// Finalmente, é necessário enviar um chunk vazio para encerrar a resposta
$connection->send(new Chunk(''));
};
// Executar o worker
Worker::runAll();