first commit.
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Libs;
|
||||
|
||||
/**
|
||||
* PHP Proxy - DuckBrain
|
||||
*
|
||||
* Proxy is a library to create a PHP proxy.
|
||||
* It allows controlling the headers that will be returned to the client,
|
||||
* in addition to placing filters on the resulting HTML code.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
*/
|
||||
class Proxy
|
||||
{
|
||||
public static $proxied_headers = [
|
||||
'Set-Cookie',
|
||||
'Content-Type',
|
||||
'Cookie',
|
||||
'Location',
|
||||
];
|
||||
public static $proxy_base_url_canonical = '/';
|
||||
public static $destination_host = SOURCE_URL;
|
||||
protected static $filters = [];
|
||||
|
||||
/**
|
||||
* Adds a callable (AKA filter) that will receive the content
|
||||
* and should return a string.
|
||||
*
|
||||
* @param callable $cb
|
||||
* Function that will modify the content.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add_filter(callable $cb): void
|
||||
{
|
||||
static::$filters[] = $cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the filters configured with add_filter.
|
||||
*
|
||||
* @param string $content
|
||||
* Content on which the filters will be applied.
|
||||
*
|
||||
* @return mixed
|
||||
* It would be correct to return a string, but
|
||||
* since the filters might not return correctly,
|
||||
* to avoid a design error, we specify that it returns mixed.
|
||||
*/
|
||||
protected static function apply_filters(string $content): mixed
|
||||
{
|
||||
foreach (static::$filters as $filter) {
|
||||
$content = call_user_func($filter, $content);
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the proxy process.
|
||||
*
|
||||
* @param string|null $proxy_request_uri
|
||||
* The address to which the proxy will be applied.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function run(?string $proxy_request_uri = null): void
|
||||
{
|
||||
// Get the URI if not defined
|
||||
if (is_null($proxy_request_uri)) {
|
||||
$proxy_request_uri = substr($_SERVER['REQUEST_URI'], strlen(static::$proxy_base_url_canonical));
|
||||
} elseif (substr($proxy_request_uri, 0, 1) == '/') {
|
||||
$proxy_request_uri = substr($proxy_request_uri, 1);
|
||||
}
|
||||
|
||||
// Generate the final URL
|
||||
$proxy_request_url = static::$destination_host . $proxy_request_uri;
|
||||
|
||||
// cURL initialization
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $proxy_request_url);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
|
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
|
||||
|
||||
// Capture client cookies
|
||||
$hdrs = [];
|
||||
if (isset($_SERVER['HTTP_COOKIE'])) {
|
||||
$hdrs[] = "Cookie: " . $_SERVER['HTTP_COOKIE'];
|
||||
}
|
||||
|
||||
// Capture client browser (User-Agent)
|
||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||
$hdrs[] = "User-Agent: " . $_SERVER['HTTP_USER_AGENT'];
|
||||
}
|
||||
|
||||
// Add captured headers
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $hdrs);
|
||||
|
||||
// Capture all client headers
|
||||
$hdrs = [];
|
||||
foreach (\getallheaders() as $name => $value) {
|
||||
$hdrs[] = "$name: $value";
|
||||
}
|
||||
|
||||
// Add captured headers to the request
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $hdrs);
|
||||
|
||||
// Add POST parameters
|
||||
if (sizeof($_POST) > 0) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
|
||||
}
|
||||
|
||||
// Execute the request
|
||||
$res = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// Parse the response
|
||||
list($headers, $body) = explode("\r\n\r\n", $res, 2);
|
||||
$headers = str_replace(static::$destination_host, '/', $headers);
|
||||
|
||||
$headers = explode("\r\n", $headers);
|
||||
$hs = [];
|
||||
|
||||
foreach ($headers as $header) {
|
||||
if (false !== strpos($header, ': ')) {
|
||||
list($h, $v) = explode(': ', $header);
|
||||
$hs[$h][] = $v;
|
||||
} else {
|
||||
$header1 = $header;
|
||||
}
|
||||
}
|
||||
|
||||
// Define headers in the client
|
||||
list($proto, $code, $text) = explode(' ', $header1);
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' ' . $code . ' ' . $text);
|
||||
|
||||
foreach (static::$proxied_headers as $hname) {
|
||||
if (isset($hs[$hname])) {
|
||||
foreach ($hs[$hname] as $v) {
|
||||
if ($hname === 'Set-Cookie') {
|
||||
header($hname . ": " . $v, false);
|
||||
} else {
|
||||
header($hname . ": " . $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
die(static::apply_filters($body));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user