{"id":28412502,"url":"https://github.com/inphinit/inphinit-php-proxy","last_synced_at":"2025-06-24T13:31:03.170Z","repository":{"id":9879572,"uuid":"11881973","full_name":"inphinit/inphinit-php-proxy","owner":"inphinit","description":"PHP Proxy html2canvas","archived":false,"fork":false,"pushed_at":"2025-06-07T07:53:04.000Z","size":295,"stargazers_count":137,"open_issues_count":0,"forks_count":78,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-06-07T08:27:55.247Z","etag":null,"topics":["html2canvas","html2canvas-proxy","php","proxy-server"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inphinit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2013-08-04T17:15:59.000Z","updated_at":"2025-06-07T07:53:09.000Z","dependencies_parsed_at":"2025-05-29T04:22:45.820Z","dependency_job_id":"be268b1a-e980-4c3a-bf00-66c57c3e451c","html_url":"https://github.com/inphinit/inphinit-php-proxy","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inphinit%2Finphinit-php-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inphinit%2Finphinit-php-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inphinit%2Finphinit-php-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inphinit%2Finphinit-php-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inphinit","download_url":"https://codeload.github.com/inphinit/inphinit-php-proxy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inphinit%2Finphinit-php-proxy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258930973,"owners_count":22779982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["html2canvas","html2canvas-proxy","php","proxy-server"],"created_at":"2025-06-02T22:33:33.838Z","updated_at":"2025-06-24T13:31:03.157Z","avatar_url":"https://github.com/inphinit.png","language":"PHP","readme":"## About Inphinit Proxy\n\nUntil version 1.x, this project primarily served as a proxy solution for the *html2canvas* library. Version 2.0 marked a significant expansion, introducing extensive configuration and adaptation options that enable its use for a wide variety of needs and objectives.\n\nAlthough developed as part of the Inphinit framework, the project operates completely independently. This means you can readily use it with any PHP framework or in a stand-alone application. While the project is modular, consider adopting the Inphinit framework itself for your new projects. For more details: https://inphinit.github.io\n\n## Proxies for other scripting languages\n\nYou do not use PHP, but need html2canvas working with proxy, see other proxies:\n\n* [html2canvas proxy in asp.net (csharp)](https://github.com/brcontainer/html2canvas-csharp-proxy)\n* [html2canvas proxy in asp classic (vbscript)](https://github.com/brcontainer/html2canvas-asp-vbscript-proxy)\n* [html2canvas proxy in python (work any framework)](https://github.com/brcontainer/html2canvas-proxy-python)\n\n## Requirements\n\n1. PHP 8 (https://www.php.net/supported-versions.php)\n    * Minimal _PHP 5.4_ (backward compatibility is maintained for users with upgrade limitations)\n1. cURL PHP extension to use `CurlDriver`\n1. `allow_url_fopen` must be set to `1` on `php.ini` to use `StreamDriver`\n\n## Installing\n\nYou can install via composer:\n\n```bash\ncomposer require inphinit/proxy\n```\n\nThen add this to your script or controller:\n\n```php\nuse Inphinit\\Proxy\\Proxy;\nuse Inphinit\\Proxy\\Drivers\\CurlDriver;\nuse Inphinit\\Proxy\\Drivers\\StreamDriver;\n\n$proxy = new Proxy();\n\n// Set drivers used for download\n$proxy-\u003esetDrivers([\n    CurlDriver::class,\n    StreamDriver::class\n]);\n\n// Execute download\n$proxy-\u003edownload($_GET['url']);\n\n// Display raw output\n$proxy-\u003eresponse();\n```\n\nIf you are not using web frameworks, you can download the release from https://github.com/inphinit/inphinit-php-proxy/releases, then extract the contents and move it to the web server and rename the folder, like this (optional):\n\n```bash\nmv inphinit-php-proxy-2.0.0 proxy\n```\n\n## Configure html2canvas\n\nIf you are using a web framework, simply point to the address of the route you configured to use the proxy, for example:\n\n```javascript\nhtml2canvas(document.getElementById('container'), {\n    logging: true,\n    proxy: '/proxy'\n}).then((canvas) =\u003e {\n    canvas.toBlob((blob) =\u003e { });\n});\n```\n\nIf you have manually downloaded it to use on your server, you can use the `proxy.php` script, a example:\n\n```javascript\nhtml2canvas(document.getElementById('container'), {\n    logging: true,\n    proxy: '/proxy/proxy.php'\n}).then((canvas) =\u003e {\n    canvas.toBlob((blob) =\u003e { });\n});\n```\n\n## Setup proxy\n\nMethod | Description\n--- | ---\n`setMaxDownloadSize(int $value): void` | Set the maximum allowed download size\n`getMaxDownloadSize(): int` | Get the maximum allowed download size\n`setMaxRedirs(int $value): void` | Set the maximum number of HTTP redirects\n`getMaxRedirs(): int` | Get the maximum number of HTTP redirects\n`setReferer(string $value): void` | Set the Referer request header\n`getReferer(): string` | Get the Referer request header\n`setTimeout(int $value): void` | Set connection timeout\n`getTimeout(): int` | Get connection timeout\n`setUserAgent(string $value): void` | Set the User-Agent request header\n`getUserAgent(): string` | Get the User-Agent request header\n`setDrivers(array $drivers): void` | Set drivers used to download the resource\n`setOptions(string $key, mixed $value): void` | Set generic options\n`getOptions([string $key]): mixed` | Get generic options\n`setAllowedUrls(array $urls): void` | Set allowed URLs\n`addAllowedType(string $type, bool $binary): void` | Add Content-Type to the allowed list\n`removeAllowedType(string $type): void` | Remove Content-Type from the allowed list\n`isAllowedType(string $type[, string \u0026$errorMessage])` | Check if Content-Type is allowed\n`setTemporary(string $path): void` | Sets temporary handle path, eg.: `/mnt/storage/`, `php://temp`, `php://memory`\n`getTemporary(): resource` | Get temporary stream\n`download(string $url[, bool $ignoreDownloadError]): void` | Perform download\n`setResponseCacheTime(int $seconds): void` | Enable or disable cache for `Proxy::respose()` or `Proxy::jsonp()`\n`response(): void` | Dump response to output\n`jsonp(string $callback): void` | Output JSONP callback with URL or data URI content\n`getContents([int $length[, int $offset]]): string` | If last download was successful, contents will be returned\n`getContentType(): string` | If last download was successful, Content-Type will be returned\n`getHttpStatus(): int` | If last download was successful, HTTP status will be returned\n`getErrorCode(): int` | If last download was failed, error code will be returned\n`getErrorMessage(): string` | If last download was failed, error message will be returned\n`reset(): void` | Reset last download\n\n## Generic options\n\nGeneric options are primarily used for driver configurations. 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. Existing options include:\n\nUsage | Description\n--- | ---\n`setOptions('curl', array $value)` | Options for `CurlDriver`. See: https://www.php.net/manual/en/curl.constants.php\n`setOptions('stream', array $value)` | Options for `StreamDriver`. See: https://www.php.net/manual/en/context.php\n\nSetup cURL driver use generic options with `'curl'` in first param, eg.: `$proxy-\u003esetOptions('curl', [ ... ]);`, a sample for change SSL version:\n\n```php\n$proxy-\u003esetOptions('curl', [\n    CURLOPT_SSLVERSION =\u003e CURL_SSLVERSION_TLSv1_3\n]);\n```\n\nA example for disable SSL verify (for local tests):\n\n```php\n$proxy-\u003esetOptions('curl', [\n    CURLOPT_SSL_VERIFYHOST =\u003e 0,\n    CURLOPT_SSL_VERIFYPEER =\u003e false\n]);\n```\n\nFor more constants options for use with `$proxy-\u003esetOptions('curl', [ ... ])`, see: https://www.php.net/manual/en/curl.constants.php\n\nFor setup Stream driver use generic options with `'stream'` in first param, eg.: `$proxy-\u003esetOptions('stream', [ ... ])`, a sample for set HTTP protocol version:\n\n```php\n$proxy-\u003esetOptions('stream', [\n    'http' =\u003e [\n        'protocol_version' =\u003e 1.0,\n    ]\n]);\n```\n\nAn example SSL configuration:\n\n```php\n$proxy-\u003esetOptions('stream', [\n    'ssl' =\u003e [\n        'verify_peer'   =\u003e true,\n        'cafile'        =\u003e '/foo/bar/baz/cacert.pem',\n        'verify_depth'  =\u003e 5,\n        'CN_match'      =\u003e 'secure.example.com'\n    ]\n]);\n```\n\n## Content-Type allowed\n\nWhen executing the download() method a Content-Type validation will be performed, by default the following Content-Types are allowed:\n\nContent-Type | `Proxy::jsonp()`\n--- | ---\n`image/apng` | base64\n`image/png` | base64\n`image/avif` | base64\n`image/webp` | base64\n`image/gif` | base64\n`image/jpeg` | base64\n`image/svg+xml` | URL-encoded\n`image/svg-xml` | URL-encoded\n\nYou can define another allowed Content-Type, example:\n\n```php\n$proxy-\u003eaddAllowedType('image/x-icon', true);\n$proxy-\u003eaddAllowedType('image/vnd.microsoft.icon', true);\n```\n\nSecond parameter of the method specifies whether the `Proxy::jsonp()` should use URL encoding or Base64 encoding in the data URI scheme.\n\nTo remove an allowed Content-Type use the `Proxy::removeAllowedType()` method, example:\n\n```php\n$proxy-\u003eremoveAllowedType('image/apng');\n```\n\n## How to use\n\nTo return the download response directly to the browser, use the `Proxy::response()` method:\n\n```php\nuse Inphinit\\Proxy\\Proxy;\nuse Inphinit\\Proxy\\Drivers\\CurlDriver;\nuse Inphinit\\Proxy\\Drivers\\StreamDriver;\n\n$proxy = new Proxy();\n\n$proxy-\u003esetDrivers([\n    CurlDriver::class,\n    StreamDriver::class\n]);\n\n$proxy-\u003edownload($url);\n\n$proxy-\u003eresponse();\n```\n\nIf 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:\n\n```php\nuse Inphinit\\Proxy\\Proxy;\nuse Inphinit\\Proxy\\Drivers\\CurlDriver;\nuse Inphinit\\Proxy\\Drivers\\StreamDriver;\n\nif (empty($_GET['callback'])) {\n    die('Missing callback');\n}\n\n$proxy = new Proxy();\n\n$proxy-\u003esetDrivers([\n    CurlDriver::class,\n    StreamDriver::class\n]);\n\ntry {\n    $proxy-\u003edownload($url);\n    $proxy-\u003ejsonp($_GET['callback']);\n} catch (Exception $ee) {\n}\n```\n\nIf you need to handle content, you can use the `Proxy::getContents`, `Proxy::getContentType`, `Proxy::getHttpStatus` methods:\n\n```php\nuse Inphinit\\Proxy\\Proxy;\nuse Inphinit\\Proxy\\Drivers\\CurlDriver;\nuse Inphinit\\Proxy\\Drivers\\StreamDriver;\n\n$proxy = new Proxy();\n\n$proxy-\u003esetDrivers([\n    CurlDriver::class,\n    StreamDriver::class\n]);\n\ntry {\n    $proxy-\u003edownload($url);\n\n    // Success\n    $contents = $proxy-\u003egetContents();\n    $contentType = $proxy-\u003egetContentType();\n    $httpStatus = $proxy-\u003egetHttpStatus();\n\n    ...\n\n} catch (Exception $ee) {\n    $code = $ee-\u003egetCode();\n    $message = $ee-\u003egetMessage();\n\n    echo 'Error: (', $code, ') ', $message;\n}\n```\n\nIn 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`:\n\n```php\n$proxy-\u003esetDrivers([\n    StreamDriver::class\n]);\n```\n\nYou can also limit the URLs that the proxy can access:\n\n```php\n$proxy-\u003eurls([\n    'https://domain1.com/',        // Allows requests on any path to https://domain1.com\n    'https://domain2.com/images/', // Allows requests from the path /images/ on https://domain1.com\n    'https://*.mainsite.io/',      // Allows requests on subdomains of mainsite.io\n    'https://foo.io:8000/',        // Allows requests to foo.io with port 8000\n    '*://other.io/',               // Allows HTTPS and HTTP requests to other.io\n]);\n\n$proxy-\u003edownload($url);\n```\n\n## Writing your own driver\n\nThe following methods are required to write an `Inphinit\\Proxy` compatible driver\n\nMethod | Description\n--- | ---\n`__construct(Proxy $proxy)` | It will receive the `Proxy` instance\n`available(): bool` | It will inform if the server has support\n`exec(string $url, int \u0026$httpStatus, string \u0026$contentType, int \u0026$errorCode, string \u0026$errorMessage): void` | It will execute the driver and fill in the references\n\n*Optionally* you can use `InterfaceDriver` to avoid errors when writing:\n\n```php\nuse Inphinit\\Proxy\\Drivers\\InterfaceDriver;\nuse Inphinit\\Proxy\\Proxy;\n\nclass CustomDriver implements InterfaceDriver\n{\n    public function __construct(Proxy $proxy)\n    {\n        ...\n    }\n\n    public function available()\n    {\n        ...\n    }\n\n    public function exec($url, \u0026$httpStatus, \u0026$contentType, \u0026$errorCode, \u0026$errorMessage)\n    {\n        ...\n    }\n}\n```\n\nOnce created you can use it like this:\n\n```php\n$proxy-\u003esetDrivers([\n    CustomDriver::class\n]);\n```\n\n## Common issues and solutions\n\nWhen adding an image that belongs to another domain in `\u003ccanvas\u003e` and after that try to export the canvas\nfor a new image, a security error occurs (actually occurs is a security lock), which can return the error:\n\n\u003e SecurityError: DOM Exception 18\n\u003e\n\u003e Error: An attempt was made to break through the security policy of the user agent.\n\nIf using Google Maps (or google maps static) you can get this error in console:\n\n\u003e Google Maps API error: MissingKeyMapError\n\nYou need get a API Key in: https://developers.google.com/maps/documentation/javascript/get-api-key\n\nIf you get this error:\n\n\u003e Access to Image at 'file:///...' from origin 'null' has been blocked by CORS policy: Invalid response. Origin 'null' is therefore not allowed access.\n\nMeans that you are not using an HTTP server, html2canvas does not work over the `file:///` protocol, use Apache, Nginx or IIS with PHP for work.\n\n## Debuging with Web Console from DevTools\n\nIf you have any issue is recommend to analyze the log with the Web Console tab and requests with Network tab from your browser, see documentations:\n\n* Firefox: https://firefox-source-docs.mozilla.org/devtools-user/\n* Chrome: https://developer.chrome.com/docs/devtools\n* Microsoft Edge: https://learn.microsoft.com/pt-br/microsoft-edge/devtools-guide-chromium/landing/\n\nAn alternative is to debug issues by accessing the link directly:\n\n`http://[DOMAIN]/[PATH]/proxy?url=http%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fstaticmap%3Fcenter%3D40.714728%2C-73.998672%26zoom%3D12%26size%3D800x600%26maptype%3Droadmap%26sensor%3Dfalse%261\u0026callback=html2canvas_0`\n\nReplace `[DOMAIN]` by your domain (eg. 127.0.0.1) and replace `[PATH]` by your project folder (eg.: `project-1/test`), something like:\n\n`http://localhost/project-1/test/proxy?url=http%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fstaticmap%3Fcenter%3D40.714728%2C-73.998672%26zoom%3D12%26size%3D800x600%26maptype%3Droadmap%26sensor%3Dfalse%261\u0026callback=html2canvas_0`\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finphinit%2Finphinit-php-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finphinit%2Finphinit-php-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finphinit%2Finphinit-php-proxy/lists"}