Sendfile
O Sendfile lida com arquivos estáticos, permitindo o uso de autenticação e outros recursos, enquanto o servidor se encarrega de entregar o conteúdo ao usuário final.
Módulos
| Módulo | Servidor Web | Descrição |
|---|---|---|
X-Accel-Redirect |
nginx |
O X-Accel-Redirect é suportado por padrão no nginx. Observação: por questões de segurança, configure-o location {} com a internal diretiva.
|
X-LIGHTTPD-send-file&X-Sendfile2 |
Módulo Lighttpd | https://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file |
X-Sendfile |
Apache | https://tn123.org/mod_xsendfile/ |
Simulador |
Built-in Web Server | O simulador embutido em aplicações Inphinit permite simular parcialmente os headers X-Accel-Redirect e X-Sendfile de forma simples sem precisar ter um servidor completo, facilitando o desenvolvimento. |
módulo nginx
O nginx compara este URI com seus respectivos diretórios, como se fosse uma requisição normal. Em seguida, ele serve o diretório que corresponde à raiz definida e ao URI passado no cabeçalho. Exemplo de configuração:
location / {
...
location ~ \.php$ {
# Replace by your FPM or FastCGI
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
# It helps libraries detect if a resource is available
fastcgi_param MOD_X_ACCEL_REDIRECT_ENABLED on;
set $inphinit_prefix "";
if ($uri != "/index.php") {
set $inphinit_prefix "/public";
}
fastcgi_param SCRIPT_FILENAME $realpath_root$inphinit_prefix$fastcgi_script_name;
}
}
location /protected_files {
root /path/foo/bar;
internal;
}
Também é possível usar um proxy para outro servidor:
location /protected_files {
proxy_pass http://127.0.0.2;
internal;
}
E em scripts você pode usar o cabeçalho, como no exemplo:
$app->action('GET', '/download', function () {
if (isLoggedIn()) {
header("X-Accel-Redirect: /protected_files/sample.txt");
}
});
Utilizando o padrão de rota:
$app->action('GET', '/download/<file:alnum>.txt', function (App $app, array $params) {
if (isLoggedIn()) {
$name = $params['file']; // From <file:alnum>
header("X-Accel-Redirect: /protected_files/{$name}.txt");
}
});
Módulo Lighttpd
Exemplo de como habilitá-lo no lighttpd:
fastcgi.server = {
".php" => {
"127.0.0.1" => {
# ....
"allow-x-send-file" => "enable"
}
}
}
Exemplo de uso:
use Inphinit\Http\Response;
$app->action('GET', '/download/<file:alnum>.txt', function (App $app, array $params) {
if (isLoggedIn()) {
// Content-Disposition
Response::download('download.txt');
header('X-LIGHTTPD-send-file: /path/foo/bar/sample.txt');
}
});
Módulo Apache
Para definir o caminho, é necessário modificar a configuração do servidor, o host virtual e os contextos de diretório. Exemplo:
<VirtualHost ...>
...
XSendFilePath /path/foo/bar
</VirtualHost>
Para habilitá-lo, você pode fazer isso em qualquer contexto, inclusive diretamente no .htaccess arquivo:
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
XSendFile on
# It helps libraries detect if a resource is available
SetEnv MOD_X_SENDFILE_ENABLED 1
...
Exemplo de uso:
use Inphinit\Http\Response;
$app->action('GET', '/download/<file:alnum>.txt', function (App $app, array $params) {
if (isLoggedIn()) {
// Content-Disposition
Response::download('download.txt');
header('X-Sendfile: /path/foo/bar/sample.txt');
}
});
Simulador
Utilizando o servidor web integrado do PHP, é possível simular parcialmente os cabeçalhos X-Accel-Redirect e X-Sendfile. Nenhuma configuração é necessária; basta usar os cabeçalhos. Em seguida, ao iniciar um servidor local, use ./run serve, permitindo o uso de:
$app->action('GET', '/download/<file:alnum>.txt', function (App $app, array $params) {
if (isLoggedIn()) {
$name = $params['file'];
header("X-Accel-Redirect: /path/foo/bar/{$name}.txt");
}
});
Classe FileResponse
A classe Inphinit\Experimental\Http\FileResponse também pode ser usada para servir arquivos, dependendo de variáveis de ambiente para verificar a compatibilidade com o módulo. Normalmente, essas variáveis precisam ser configuradas manualmente.
FileResponse::ACCEL (X-Accel-Redirect):
use Inphinit\Experimental\Http\FileResponse;
$app->action('GET', '/download/<file:alnum>.txt', function (App $app, array $params) {
if (isLoggedIn()) {
$handle = new FileResponse($params['file'], 'output.txt');
try {
// Try serving it with an X-Accel-Redirect header
$handle->send(FileResponse::ACCEL);
} catch (\Exception $ee) {
echo 'Downloads unavailable.';
}
}
});
FileResponse::SENDFILE (X-Sendfile):
$handle = new FileResponse($params['file'], 'output.txt');
try {
// Try serving it with an X-Sendfile header
$handle->send(FileResponse::SENDFILE);
} catch (\Exception $ee) {
echo 'Downloads unavailable.';
}
Avaliando os módulos disponíveis:
$handle = new FileResponse($params['file'], 'output.txt');
try {
// It will try serving with X-Accel-Redirect if available, otherwise it will try using X-Sendfile
$handle->send(FileResponse::ACCEL|FileResponse::SENDFILE);
} catch (\Exception $ee) {
echo 'Downloads unavailable.';
}
Fallback:
O recurso alternativo para Sendfile é um mecanismo que deve ser usado apenas como último recurso e somente quando absolutamente necessário. No exemplo abaixo, o sistema primeiro tenta usar X-Accel-Redirect; se este não estiver disponível, ele recorre a X-Sendfile e, se nenhum dos dois for suportado, ele finalmente serve o arquivo diretamente via PHP:
$handle = new FileResponse($params['file'], 'output.txt');
try {
$handle->send(FileResponse::ACCEL|FileResponse::SENDFILE|FileResponse::FALLBACK);
} catch (\Exception $ee) {
echo 'Downloads unavailable.';
}