Inphinit Proxy
Inphinit Proxy is a proxy library intended for use with html2canvas or similar client-side tools that require bypassing CORS restrictions.
Although developed as part of the Inphinit framework, this library is fully standalone and compatible with any framework — or even plain PHP.
System requirements
- cURL PHP extension to use the CurlDriver
allow_url_fopenmust be set to1onphp.inito useStreamDriver- Composer (Optional)
Installing
You can install via composer:
composer require inphinit/proxy
If you're not using a framework, you can download the release from https://github.com/inphinit/inphinit-php-proxy/archive/refs/tags/2.0.0-rc.2.zip, then extract it, move it to your web server, and optionally rename the folder, for example
mv "inphinit-php-proxy-2.0.0-rc.2" proxy
How to use
Then include this in your script or controller:
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;
}
Without autoload and composer-autoload is needed manualy include classes:
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();
...
To return the download response directly to the browser, use the Proxy::response() method:
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();
If you want to use the JSONP format, replace the Proxy::response() method with Proxy::jsonp(). In this example, the callback will return and receive the content in DATA URI format:
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) {
}
If you need to handle content, you can use the Proxy::getContents(), Proxy::getContentType(), Proxy::getHttpStatus() methods:
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;
}
In the examples so far, CurlDriver takes priority, and uses StreamDriver as a fallback, but you can change this, in a hypothetical example, if you only want to use StreamDriver:
$proxy->setDrivers([
StreamDriver::class
]);
$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);
Generic options allow you to customize driver behavior through their native configuration mechanisms (cURL options or stream contexts). Since each driver may require different types of settings, the most flexible approach is to allow these options to store any value. This is particularly useful when developing a new driver.
To configure the cURL driver, use 'curl' as the first parameter, for example $proxy->setOptions('curl', [ ... ]), an example to change the SSL version:
$proxy->setOptions('curl', [
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_3
]);
An example to disable SSL verification (for local testing, don't use in a production environment):
$proxy->setOptions('curl', [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => false
]);
For more constants options to be used with $proxy->setOptions('curl', [ ... ]), see: https://www.php.net/manual/en/curl.constants.php
To configure the StreamDriver, use 'stream' as the first parameter in setOptions(),
an example to set the HTTP protocol version:
$proxy->setOptions('stream', [
'http' => [
'protocol_version' => 1.0,
]
]);
Example SSL configuration:
$proxy->setOptions('stream', [
'ssl' => [
'verify_peer' => true,
'cafile' => '/foo/bar/baz/cacert.pem',
'verify_depth' => 5,
'CN_match' => 'secure.example.com'
]
]);
Content-Type allowed
When executing the download() method, a Content-Type validation will be performed, by default the following Content-Types are allowed:
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 |
URL-encoded |
image/svg-xml |
URL-encoded |
You can define additional allowed Content-Types, for example:
$proxy->addAllowedType('image/x-icon', true);
$proxy->addAllowedType('image/vnd.microsoft.icon', true);
The method's second parameter specifies whether Proxy::jsonp() should use URL encoding or Base64 encoding in the data URI scheme.
To remove an allowed Content-Type use the Proxy::removeAllowedType() method, example:
$proxy->removeAllowedType('image/apng');
API
| Method | Description |
|---|---|
setMaxDownloadSize(int $value): void |
Set the maximum allowed download size |
getMaxDownloadSize(): int |
Get the maximum allowed download size |
setMaxRedirs(int $value): void |
Set the maximum number of HTTP redirects |
getMaxRedirs(): int |
Get the maximum number of HTTP redirects |
setReferer(string $value): void |
Set the Referer: request header |
getReferer(): string |
Get the Referer: request header |
setTimeout(int $value): void |
Set the connection timeout in seconds |
getTimeout(): int |
Get the connection timeout in seconds |
setUserAgent(string $value): void |
Set the User-Agent: request header |
getUserAgent(): string |
Get the User-Agent: request header |
setDrivers(array $drivers): void |
Set the list of driver class names used for downloading resources |
setControlAllowOrigin(string $origin): void |
Set the Access-Control-Allow-Origin: header |
setControlAllowHeaders(array $headers): void |
Set the list of allowed headers |
setOptions(string $key, mixed $value): void |
Set generic options |
getOptions([string $key]): mixed |
Get generic options |
getOptionsUpdate(): int |
Returns an internal incremental counter used to determine whether driver options have changed |
setAllowedUrls(array $urls): void |
Set the list of allowed URLs for download |
addAllowedType(string $type, bool $binary): void |
Add a Content-Type to the allowed list, true = Base64 encoding, false = URL encoding |
removeAllowedType(string $type): void |
Remove a Content-Type from the allowed list |
isAllowedType(string $type, string &$errorMessage): bool |
Check if a given Content-Type is allowed (this method will be used by drivers) |
setTemporary(string $path): void |
Set the temporary storage path or stream for downloaded content (e.g., /mnt/storage/, php://temp, php://memory) |
getTemporary(): resource|null |
Get the temporary stream resource used for downloaded content |
download(string $url): void |
Perform the download |
setResponseCacheTime(int $seconds): void |
Set the cache duration (in seconds) or disable cache for Proxy::response() or Proxy::jsonp() |
response(): void |
Dump response to output |
jsonp(string $callback): void |
Output JSONP callback with URL or data URI content |
getContents([int $length[, int $offset]]): string|null |
If last download was successful, contents will be returned |
getContentType(): string|null |
If last download was successful, Content-Type will be returned |
getHttpStatus(): int|null |
If last download was successful, HTTP status will be returned |
reset(): void |
Reset last download |