Inphinit Proxy
É uma biblioteca proxy destinada ao uso com html2canvas e similares do lado do cliente que exigem a superação das restrições CORS.
Embora desenvolvida como parte do framework Inphinit, esta biblioteca é totalmente independente e compatível com qualquer framework — ou mesmo com PHP puro.
Requisitos do sistema
- Extensão cURL PHP para usar o
CurlDriver allow_url_fopendeve ser definido com o valor1nophp.inipara pode usar oStreamDriver- (Opcional) Composer
Instalação
Você pode instalar via Composer:
composer require inphinit/proxy
Se você não estiver usando um framework, pode baixar a versão de https://github.com/inphinit/inphinit-php-proxy/archive/refs/tags/2.0.0-rc.2.zip, extraí-la, movê-la para o seu servidor web e, opcionalmente, renomear a pasta, por exemplo.
mv "inphinit-php-proxy-2.0.0-rc.2" proxy
Como usar
Em seguida, inclua isso em seu script ou controlador:
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;
$proxy = new Proxy();
// Set drivers used for download
$proxy->setDrivers([
CurlDriver::class,
StreamDriver::class
]);
try {
// Execute download
$proxy->download($_GET['url']);
// Display raw output
$proxy->response();
} catch (Exception $ee) {
$code = $ee->getCode();
$message = $ee->getMessage();
echo 'Error: (', $code, ') ', $message;
}
Sem o autoload e o composer-autoload, é necessário incluir as classes manualmente:
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;
require_once '/path/proxy/src/CurlDriver.php';
require_once '/path/proxy/src/StreamDriver.php';
require_once '/path/proxy/src/Proxy.php';
$proxy = new Proxy();
...
Para retornar a resposta do download diretamente para o navegador, use o método Proxy::response():
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;
$proxy = new Proxy();
$proxy->setDrivers([
CurlDriver::class,
StreamDriver::class
]);
$proxy->download($url);
$proxy->response();
Se você deseja usar o formato JSONP, substitua o método Proxy::response() por Proxy::jsonp(). Neste exemplo, o callback retornará e receberá o conteúdo no formato DATA URI:
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;
if (empty($_GET['callback'])) {
http_response_code(400);
die('Missing callback');
}
$proxy = new Proxy();
$proxy->setDrivers([
CurlDriver::class,
StreamDriver::class
]);
try {
$proxy->download($url);
$proxy->jsonp($_GET['callback']);
} catch (Exception $ee) {
}
Se você precisar manipular conteúdo, pode usar os métodos Proxy::getContents(), Proxy::getContentType() e Proxy::getHttpStatus():
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;
$proxy = new Proxy();
$proxy->setDrivers([
CurlDriver::class,
StreamDriver::class
]);
try {
$proxy->download($url);
// Success
$contents = $proxy->getContents();
$contentType = $proxy->getContentType();
$httpStatus = $proxy->getHttpStatus();
...
} catch (Exception $ee) {
$code = $ee->getCode();
$message = $ee->getMessage();
echo 'Error: (', $code, ') ', $message;
}
Nos exemplos apresentados até agora, CurlDriver tem prioridade enquanto StreamDriver é usado como altertiva, mas você pode alterar isso. Em um exemplo hipotético, por exemplo, se você quiser usar apenas StreamDriver faça:
$proxy->setDrivers([
StreamDriver::class
]);
Você também pode limitar os URLs que o proxy pode acessar:
$proxy->setAllowedUrls([
'https://domain1.com/', // Allows requests on any path to https://domain1.com
'https://domain2.com/images/', // Allows requests from the path /images/ on https://domain2.com
'https://*.mainsite.io/', // Allows requests on subdomains of mainsite.io
'https://foo.io:8000/', // Allows requests to foo.io with port 8000
'*://other.io/', // Allows HTTPS and HTTP requests to other.io
]);
$proxy->download($url);
As opções genéricas permitem personalizar o comportamento do driver por meio de seus mecanismos de configuração nativos (opções cURL ou contextos de fluxo). Como cada driver pode exigir diferentes tipos de configurações, a abordagem mais flexível é permitir que essas opções armazenem qualquer valor. Isso é particularmente útil ao desenvolver um novo driver.
Para configurar o driver cURL, use 'curl' como primeiro parâmetro, por exemplo $proxy->setOptions('curl', [ ... ]), um exemplo para alterar a versão SSL:
$proxy->setOptions('curl', [
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_3
]);
Exemplo de como desativar a verificação SSL (para testes locais, não utilize em ambiente de produção):
$proxy->setOptions('curl', [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => false
]);
Para mais opções de constantes a serem usadas com $proxy->setOptions('curl', [ ... ]), consulte: https://www.php.net/manual/en/curl.constants.php
Para configurar o StreamDriver, use 'stream' como primeiro parâmetro em setOptions(), um exemplo para definir a versão do protocolo HTTP:
$proxy->setOptions('stream', [
'http' => [
'protocol_version' => 1.0,
]
]);
Exemplo de configuração SSL:
$proxy->setOptions('stream', [
'ssl' => [
'verify_peer' => true,
'cafile' => '/foo/bar/baz/cacert.pem',
'verify_depth' => 5,
'CN_match' => 'secure.example.com'
]
]);
Tipo de conteúdo permitido
Ao executar o método download(), será realizada uma validação do tipo de conteúdo (Content-Type). Por padrão, os seguintes tipos de conteúdo são permitidos:
Content-Type |
Proxy::jsonp() |
|---|---|
image/apng |
base64 |
image/png |
base64 |
image/avif |
base64 |
image/webp |
base64 |
image/gif |
base64 |
image/jpeg |
base64 |
image/svg+xml |
codificado em URL |
image/svg-xml |
codificado em URL |
Você pode definir tipos de conteúdo adicionais permitidos, por exemplo:
$proxy->addAllowedType('image/x-icon', true);
$proxy->addAllowedType('image/vnd.microsoft.icon', true);
O segundo parâmetro do método especifica se Proxy::jsonp() deve ser usada a codificação URL ou a codificação Base64 no esquema URI de dados.
Para remover um Content-Type permitido, use o Proxy::removeAllowedType() método, por exemplo:
$proxy->removeAllowedType('image/apng');
API
| Método | Descrição |
|---|---|
setMaxDownloadSize(int $value): void |
Defina o tamanho máximo permitido para download. |
getMaxDownloadSize(): int |
Obtenha o tamanho máximo de download permitido |
setMaxRedirs(int $value): void |
Defina o número máximo de redirecionamentos HTTP. |
getMaxRedirs(): int |
Obtenha o número máximo de redirecionamentos HTTP. |
setReferer(string $value): void |
Defina o Referer: cabeçalho da solicitação. |
getReferer(): string |
Obtenha o Referer: cabeçalho da solicitação |
setTimeout(int $value): void |
Defina o tempo limite de conexão em segundos. |
getTimeout(): int |
Obtenha o tempo limite de conexão em segundos. |
setUserAgent(string $value): void |
Defina o User-Agent: cabeçalho da solicitação. |
getUserAgent(): string |
Obtenha o User-Agent: cabeçalho da solicitação |
setDrivers(array $drivers): void |
Defina a lista de nomes de classes de driver usadas para baixar recursos. |
setControlAllowOrigin(string $origin): void |
Defina o Access-Control-Allow-Origin: cabeçalho |
setControlAllowHeaders(array $headers): void |
Defina a lista de cabeçalhos permitidos. |
setOptions(string $key, mixed $value): void |
Defina opções genéricas |
getOptions([string $key]): mixed |
Obtenha opções genéricas |
getOptionsUpdate(): int |
Retorna um contador incremental interno usado para determinar se as opções do driver foram alteradas. |
setAllowedUrls(array $urls): void |
Defina a lista de URLs permitidas para download. |
addAllowedType(string $type, bool $binary): void |
Adicione um Content-Type à lista de permitidos, true= codificação Base64, false= codificação de URL |
removeAllowedType(string $type): void |
Remover um Content-Type da lista de permitidos |
isAllowedType(string $type, string &$errorMessage): bool |
Verificar se uma determinada ação Content-Type é permitida (este método será usado pelos motoristas) |
setTemporary(string $path): void |
Defina o caminho ou fluxo de armazenamento temporário para o conteúdo baixado (por exemplo, /mnt/storage/, php://temp, php://memory) |
getTemporary(): resource|null |
Obtenha o recurso de fluxo temporário usado para o conteúdo baixado. |
download(string $url): void |
Efetue o download |
setResponseCacheTime(int $seconds): void |
Defina a duração do cache (em segundos) ou desative o cache para Proxy::response() ou Proxy::jsonp() |
response(): void |
Despejar resposta para saída |
jsonp(string $callback): void |
Saída de retorno JSONP com conteúdo de URL ou URI de dados |
getContents([int $length[, int $offset]]): string|null |
Se o último download foi bem-sucedido, o conteúdo será retornado. |
getContentType(): string|null |
Se o último download foi bem-sucedido, Content-Type o valor será retornado. |
getHttpStatus(): int|null |
Se o último download foi bem-sucedido, o status HTTP será retornado. |
reset(): void |
Redefinir último download |