This commit is contained in:
2025-09-03 15:57:56 +02:00
parent a3f5b5a0cf
commit bd32f43c9e
441 changed files with 54487 additions and 256 deletions

View File

@ -0,0 +1,4 @@
.idea/
.vscode/
vendor/

24
api/vendor/zounar/php-proxy/LICENSE vendored Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

470
api/vendor/zounar/php-proxy/Proxy.php vendored Normal file
View File

@ -0,0 +1,470 @@
<?php
namespace Zounar\PHPProxy;
use CURLFile;
use Exception;
use RuntimeException;
/**
* @author Robin Zounar <https://github.com/zounar>
* @license http://unlicense.org
* @package Zounar\PHPProxy
*
* Credits to:
* https://github.com/cowboy/php-simple-proxy/
* https://gist.github.com/iovar
*
* Usage:
* To call this script two headers must be sent
* HTTP_PROXY_AUTH Access key for the proxy (should be changed)
* HTTP_PROXY_TARGET_URL URL to be called by this script
*
* Debug:
* To debug, send HTTP_PROXY_DEBUG header with any non-zero value
*
* Compatibility:
* PHP >=5.6
* libcurl
* gzip
* PHP safe_mode disabled
*/
class Proxy
{
/**
* Your private auth key. It is recommended to change it.
* If you installed the package via composer, call `Proxy::$AUTH_KEY = '<your-new-key>';` before running the proxy.
* If you copied this file, change the value here in place.
* @var string
*/
public static $AUTH_KEY = 'Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2';
/**
* Set this to false to disable authorization. Useful for debugging, not recommended in production.
* @var bool
*/
public static $ENABLE_AUTH = true;
/**
* If true, PHP safe mode compatibility will not be checked
* (you may not need it if no POST files are sent over proxy)
* @var bool
*/
public static $IGNORE_SAFE_MODE = false;
/**
* Enable debug mode (you can do it by sending Proxy-Debug header as well).
* This value overrides any value specified in Proxy-Debug header.
* @var bool
*/
public static $DEBUG = false;
/**
* When set to false the fetched header is not included in the result
* @var bool
*/
public static $CURLOPT_HEADER = true;
/**
* When set to false the fetched result is echoed immediately instead of waiting for the fetch to complete first
* @var bool
*/
public static $CURLOPT_RETURNTRANSFER = true;
/**
* Target URL is set via Proxy-Target-URL header. For debugging purposes you might set it directly here.
* This value overrides any value specified in Proxy-Target-URL header.
* @var string
*/
public static $TARGET_URL = '';
/**
* Name of remote debug header
* @var string
*/
public static $HEADER_HTTP_PROXY_DEBUG = 'HTTP_PROXY_DEBUG';
/**
* Name of the proxy auth key header
* @var string
*/
public static $HEADER_HTTP_PROXY_AUTH = 'HTTP_PROXY_AUTH';
/**
* Name of the target url header
* @var string
*/
public static $HEADER_HTTP_PROXY_TARGET_URL = 'HTTP_PROXY_TARGET_URL';
/**
* Line break for debug purposes
* @var string
*/
protected static $HR = PHP_EOL . PHP_EOL . '----------------------------------------------' . PHP_EOL . PHP_EOL;
/**
* @return string[]
*/
protected static function getSkippedHeaders()
{
return [
static::$HEADER_HTTP_PROXY_TARGET_URL,
static::$HEADER_HTTP_PROXY_AUTH,
static::$HEADER_HTTP_PROXY_DEBUG,
'HTTP_HOST',
'HTTP_ACCEPT_ENCODING'
];
}
/**
* Return variable or default value if not set
* @param mixed $variable
* @param mixed|null $default
* @return mixed
* @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection
*/
protected static function ri(&$variable, $default = null)
{
if (isset($variable)) {
return $variable;
} else {
return $default;
}
}
/**
* @param string $message
*/
protected static function exitWithError($message)
{
http_response_code(500);
echo 'PROXY ERROR: ' . $message;
exit(500);
}
/**
* @return bool
*/
public static function isInstalledWithComposer()
{
$autoloaderPath = join(DIRECTORY_SEPARATOR, [dirname(dirname(__DIR__)), 'autoload.php']);
return is_readable($autoloaderPath);
}
/**
* @return void
*/
public static function registerErrorHandlers()
{
set_error_handler(function ($code, $message, $file, $line) {
Proxy::exitWithError("($code) $message in $file at line $line");
}, E_ALL);
set_exception_handler(function (Exception $ex) {
Proxy::exitWithError("{$ex->getMessage()} in {$ex->getFile()} at line {$ex->getLine()}");
});
}
/**
* @return void
*/
public static function checkCompatibility()
{
if (!static::$IGNORE_SAFE_MODE && function_exists('ini_get') && ini_get('safe_mode')) {
throw new RuntimeException('Safe mode is enabled, this may cause problems with uploading files');
}
if (!function_exists('curl_init')) {
throw new RuntimeException('libcurl is not installed on this server');
}
if (!function_exists('gzdecode')) {
throw new RuntimeException('gzip is not installed on this server');
}
}
/**
* @return bool
*/
protected static function hasCURLFileSupport()
{
return class_exists('CURLFile');
}
/**
* @param string $headerString
* @return string[]
*/
protected static function splitResponseHeaders($headerString)
{
$results = [];
$headerLines = preg_split('/[\r\n]+/', $headerString);
foreach ($headerLines as $headerLine) {
if (empty($headerLine)) {
continue;
}
// Header contains HTTP version specification and path
if (strpos($headerLine, 'HTTP/') === 0) {
// Reset the output array as there may by multiple response headers
$results = [];
continue;
}
$results[] = "$headerLine";
}
return $results;
}
/**
* Returns true if response code matches 2xx or 3xx
* @param int $responseCode
* @return bool
*/
public static function isResponseCodeOk($responseCode)
{
return preg_match('/^[23]\d\d$/', $responseCode) === 1;
}
/**
* @return string
*/
protected static function getTargetUrl()
{
if (!empty(static::$TARGET_URL)) {
$targetURL = static::$TARGET_URL;
} else {
$targetURL = static::ri($_SERVER[static::$HEADER_HTTP_PROXY_TARGET_URL]);
}
if (empty($targetURL)) {
throw new RuntimeException(static::$HEADER_HTTP_PROXY_TARGET_URL . ' header is empty');
}
if (filter_var($targetURL, FILTER_VALIDATE_URL) === false) {
throw new RuntimeException(static::$HEADER_HTTP_PROXY_TARGET_URL . ' "' . $targetURL . '" is invalid');
}
return $targetURL;
}
/**
* @return bool
*/
protected static function isDebug()
{
return static::$DEBUG || !empty($_SERVER[static::$HEADER_HTTP_PROXY_DEBUG]);
}
/**
* @return bool
*/
protected static function isAuthenticated()
{
return !static::$ENABLE_AUTH || static::ri($_SERVER[static::$HEADER_HTTP_PROXY_AUTH]) === static::$AUTH_KEY;
}
/**
* @param string[] $skippedHeaders
* @return string[]
*/
protected static function getIncomingRequestHeaders($skippedHeaders = [])
{
$results = [];
foreach ($_SERVER as $key => $value) {
if (in_array($key, $skippedHeaders)) {
continue;
}
$loweredKey = strtolower($key);
if (strpos($loweredKey, 'http_') === 0) {
// Remove prefix
$key = substr($loweredKey, strlen('http_'));
// Replace underscores with dashes
$key = str_replace('_', '-', $key);
// Capital each word
$key = ucwords($key, '-');
$results[] = "$key: $value";
}
}
return $results;
}
/**
* @param string $targetURL
* @return false|resource
*/
protected static function createRequest($targetURL)
{
$request = curl_init($targetURL);
// Set input data
$requestMethod = strtoupper(static::ri($_SERVER['REQUEST_METHOD']));
if ($requestMethod === "PUT" || $requestMethod === "PATCH") {
curl_setopt($request, CURLOPT_POSTFIELDS, file_get_contents('php://input'));
} elseif ($requestMethod === "POST") {
$data = array();
if (!empty($_FILES)) {
if (!static::hasCURLFileSupport()) {
curl_setopt($request, CURLOPT_SAFE_UPLOAD, false);
}
foreach ($_FILES as $fileName => $file) {
$filePath = realpath($file['tmp_name']);
if (static::hasCURLFileSupport()) {
$data[$fileName] = new CURLFile($filePath, $file['type'], $file['name']);
} else {
$data[$fileName] = '@' . $filePath;
}
}
}
curl_setopt($request, CURLOPT_POSTFIELDS, $data + $_POST);
}
$headers = static::getIncomingRequestHeaders(static::getSkippedHeaders());
curl_setopt_array($request, [
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HEADER => static::$CURLOPT_HEADER,
CURLOPT_RETURNTRANSFER => static::$CURLOPT_RETURNTRANSFER,
CURLINFO_HEADER_OUT => true,
CURLOPT_HTTPHEADER => $headers
]);
return $request;
}
/**
* @return int HTTP response code (200, 404, 500, etc.)
*/
public static function run()
{
if (!static::isAuthenticated()) {
throw new RuntimeException(static::$HEADER_HTTP_PROXY_AUTH . ' header is invalid');
}
$debug = static::isDebug();
$targetURL = static::getTargetUrl();
$request = static::createRequest($targetURL);
// Get response
$response = curl_exec($request);
$headerSize = curl_getinfo($request, CURLINFO_HEADER_SIZE);
$responseHeader = substr($response, 0, $headerSize);
$responseBody = substr($response, $headerSize);
$responseInfo = curl_getinfo($request);
$responseCode = static::ri($responseInfo['http_code'], 500);
$redirectCount = static::ri($responseInfo['redirect_count'], 0);
$requestHeaders = preg_split('/[\r\n]+/', static::ri($responseInfo['request_header'], ''));
if ($responseCode === 0) {
$responseCode = 404;
}
$finalRequestURL = curl_getinfo($request, CURLINFO_EFFECTIVE_URL);
if ($redirectCount > 0 && !empty($finalRequestURL)) {
$finalRequestURLParts = parse_url($finalRequestURL);
$effectiveURL = static::ri($finalRequestURLParts['scheme'], 'http') . '://' .
static::ri($finalRequestURLParts['host']) . static::ri($finalRequestURLParts['path'], '');
}
curl_close($request);
//----------------------------------
// Split header text into an array.
$responseHeaders = static::splitResponseHeaders($responseHeader);
// Pass headers to output
foreach ($responseHeaders as $header) {
$headerParts = preg_split('/:\s+/', $header, 2);
if (count($headerParts) !== 2) {
throw new RuntimeException("Can not parse header \"$header\"");
}
$headerName = $headerParts[0];
$loweredHeaderName = strtolower($headerName);
$headerValue = $headerParts[1];
$loweredHeaderValue = strtolower($headerValue);
// Pass following headers to response
if (in_array($loweredHeaderName,
['content-type', 'content-language', 'content-security', 'server'])) {
header("$headerName: $headerValue");
} elseif (strpos($loweredHeaderName, 'x-') === 0) {
header("$headerName: $headerValue");
} // Replace cookie domain and path
elseif ($loweredHeaderName === 'set-cookie') {
$newValue = preg_replace('/((?>domain)\s*=\s*)[^;\s]+/', '\1.' . $_SERVER['HTTP_HOST'], $headerValue);
$newValue = preg_replace('/\s*;?\s*path\s*=\s*[^;\s]+/', '', $newValue);
header("$headerName: $newValue", false);
} // Decode response body if gzip encoding is used
elseif ($loweredHeaderName === 'content-encoding' && $loweredHeaderValue === 'gzip') {
$responseBody = gzdecode($responseBody);
}
}
http_response_code($responseCode);
//----------------------------------
if ($debug) {
echo 'Headers sent to proxy' . PHP_EOL . PHP_EOL;
echo implode(PHP_EOL, static::getIncomingRequestHeaders());
echo static::$HR;
if (!empty($_GET)) {
echo '$_GET sent to proxy' . PHP_EOL . PHP_EOL;
print_r($_GET);
echo static::$HR;
}
if (!empty($_POST)) {
echo '$_POST sent to proxy' . PHP_EOL . PHP_EOL;
print_r($_POST);
echo static::$HR;
}
echo 'Headers sent to target' . PHP_EOL . PHP_EOL;
echo implode(PHP_EOL, $requestHeaders);
echo static::$HR;
if (isset($effectiveURL) && $effectiveURL !== $targetURL) {
echo "Request was redirected from \"$targetURL\" to \"$effectiveURL\"";
echo static::$HR;
}
echo 'Headers received from target' . PHP_EOL . PHP_EOL;
echo $responseHeader;
echo static::$HR;
echo 'Headers sent from proxy to client' . PHP_EOL . PHP_EOL;
echo implode(PHP_EOL, headers_list());
echo static::$HR;
echo 'Body sent from proxy to client' . PHP_EOL . PHP_EOL;
}
echo $responseBody;
return $responseCode;
}
}
if (!Proxy::isInstalledWithComposer()) {
Proxy::checkCompatibility();
Proxy::registerErrorHandlers();
$responseCode = Proxy::run();
if (Proxy::isResponseCodeOk($responseCode)) {
exit(0);
} else {
exit($responseCode);
}
}

118
api/vendor/zounar/php-proxy/README.md vendored Normal file
View File

@ -0,0 +1,118 @@
# Simple PHP Proxy
This proxy script allows you to forward all HTTP/HTTPS requests to another server. Works for all common request types
including GET, POST requests with files, PATCH and PUT requests. It has minimal set of requirements
(PHP >=5.6, libcurl, gzip) which are available even on the smallest free hostings and has its own simple authorization
and cookie support.
## How to use
* Copy the [Proxy.php](Proxy.php) script to publicly-accessible folder of a PHP web server (the script is standalone and has no PHP dependencies)
* Make a cURL request targeting this script
* Add **Proxy-Auth** header with auth key [found here](https://github.com/zounar/php-proxy/blob/master/Proxy.php#L40)
* Add **Proxy-Target-URL** header with URL to be requested by the proxy
* (Optional) Add **Proxy-Debug** header for debug mode
In order to protect using proxy by unauthorized users, consider changing `Proxy-Auth` token in [proxy source file](https://github.com/zounar/php-proxy/blob/master/Proxy.php#L40) and in all your requests.
## How to use (via composer)
This might be useful when you want to redirect requests coming into your app.
* Run `composer require zounar/php-proxy`
* Add `Proxy::run();` line to where you want to execute it (usually into a controller action)
* In this example, the script is in `AppController` - `actionProxy`:
```
use Zounar\PHPProxy\Proxy;
class AppController extends Controller {
public function actionProxy() {
Proxy::$AUTH_KEY = '<your-new-key>';
// Do your custom logic before running proxy
$responseCode = Proxy::run();
// Do your custom logic after running proxy
// You can utilize HTTP response code returned from the run() method
}
}
```
* Make a cURL request to your web
* In the example, it would be `http://your-web.com/app/proxy`
* Add **Proxy-Auth** header with auth key [found here](https://github.com/zounar/php-proxy/blob/master/Proxy.php#L40)
* Add **Proxy-Target-URL** header with URL to be requested by the proxy
* (Optional) Add **Proxy-Debug** header for debug mode
In order to protect using proxy by unauthorized users, consider changing `Proxy-Auth` token by calling
`Proxy::$AUTH_KEY = '<your-new-key>';` before `Proxy::run()`. Then change the token in all your requests.
## Usage example
Following example shows how to execute GET request to https://www.github.com. Proxy script is at http://www.foo.bar/Proxy.php. All proxy settings are kept default, the response is automatically echoed.
```php
$request = curl_init('http://www.foo.bar/Proxy.php');
curl_setopt($request, CURLOPT_HTTPHEADER, array(
'Proxy-Auth: Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2',
'Proxy-Target-URL: https://www.github.com'
));
curl_exec($request);
```
## Debugging
In order to show some debug info from the proxy, add `Proxy-Debug: 1` header into the request. This will show debug info in plain-text containing request headers, response headers and response body.
```php
$request = curl_init('http://www.foo.bar/Proxy.php');
curl_setopt($request, CURLOPT_HTTPHEADER, array(
'Proxy-Auth: Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2',
'Proxy-Target-URL: https://www.github.com',
'Proxy-Debug: 1'
));
curl_exec($request);
```
## Specifying User-Agent
Some sites may return different content for different user agents. In such case add `User-Agent` header to cURL request, it will be automatically passed to the request for target site. In this case it's Firefox 70 for Ubuntu.
```php
$request = curl_init('http://www.foo.bar/Proxy.php');
curl_setopt($request, CURLOPT_HTTPHEADER, array(
'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0',
'Proxy-Auth: Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2',
'Proxy-Target-URL: https://www.github.com'
));
curl_exec($request);
```
## Error 301 Moved permanently
It might occur that there's a redirection when calling the proxy (not the target site), eg. during `http -> https` redirection. You can either modify/fix the proxy URL (which is recommended), or add `CURLOPT_FOLLOWLOCATION` option before `curl_exec`.
```php
$request = curl_init('http://www.foo.bar/Proxy.php');
curl_setopt($request, CURLOPT_FOLLOWLOCATION, true );
curl_setopt($request, CURLOPT_HTTPHEADER, array(
'Proxy-Auth: Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2',
'Proxy-Target-URL: https://www.github.com'
));
curl_exec($request);
```
## Save response into variable
The default cURL behavior is to echo the response of `curl_exec`. In order to save response into variable, all you have to do is to add `CURLOPT_RETURNTRANSFER` cURL option.
```php
$request = curl_init('http://www.foo.bar/Proxy.php');
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_HTTPHEADER, array(
'Proxy-Auth: Bj5pnZEX6DkcG6Nz6AjDUT1bvcGRVhRaXDuKDX9CjsEs2',
'Proxy-Target-URL: https://www.github.com'
));
$response = curl_exec($request);
```

View File

@ -0,0 +1,39 @@
{
"name": "zounar/php-proxy",
"description": "Forward your HTTP/HTTPS requests to another server.",
"type": "library",
"keywords": [
"php-proxy",
"proxy-script",
"php",
"proxy",
"http",
"http-proxy",
"curl",
"curlphp"
],
"homepage": "https://github.com/zounar/php-proxy",
"readme": "README.md",
"require": {
"php": ">=5.6.0",
"ext-curl": "*",
"ext-zlib": "*"
},
"license": "unlicense",
"authors": [
{
"name": "Robin Zounar",
"homepage": "https://zounar.me"
}
],
"support": {
"issues": "https://github.com/zounar/php-proxy/issues",
"source": "https://github.com/zounar/php-proxy",
"docs": "https://github.com/zounar/php-proxy/blob/master/README.md"
},
"autoload": {
"psr-4": {
"Zounar\\PHPProxy\\": "./"
}
}
}

22
api/vendor/zounar/php-proxy/composer.lock generated vendored Normal file
View File

@ -0,0 +1,22 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "a101b9e5b9b0bff50de607452cc30901",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.6.0",
"ext-curl": "*",
"ext-zlib": "*"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
}

View File

@ -0,0 +1,11 @@
version: "2"
services:
proxy:
# image: webdevops/php-nginx:8.0
# image: webdevops/php-nginx:7.4
image: webdevops/php-nginx:5.6
ports:
- 80:80
- 443:443
volumes:
- ./:/app