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_fopen must be set to 1 on php.ini to use StreamDriver
  • 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 ]);
You can also limit the URLs that the proxy can access:
$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
Go to homepage
Star us on Github