Skip to content

Instantly share code, notes, and snippets.

@nanna-dk
Last active June 24, 2025 09:15
Show Gist options
  • Save nanna-dk/3e64e6c6b6bab4186ded23d713f5ba8a to your computer and use it in GitHub Desktop.
Save nanna-dk/3e64e6c6b6bab4186ded23d713f5ba8a to your computer and use it in GitHub Desktop.
PHP proxy for xml/rss feeds - sets headers (domains and subdomains) to fix CORS issues. Works with POST and GET.
<?php
/*
* PHP Proxy
* Responds to both HTTP GET and POST requests
* Usage:
* https://this-url/parseFeed.php?url=" + encodeURIComponent(external-source) + "&amp;mimeType=application/rss+xml.
*/
$url = $_POST['url'] ?? ($_GET['url'] ?? null);
$mimeType = $_POST['mimeType'] ?? ($_GET['mimeType'] ?? null);
$isPost = isset($_POST['url']);
if ($url) {
$url = filter_var($url, FILTER_SANITIZE_URL);
$url = filter_var($url, FILTER_VALIDATE_URL);
$scheme = parse_url($url, PHP_URL_SCHEME);
// Check for host - file://, ftp:// etc. are not allowed.
if (! in_array($scheme, ['http', 'https'])) {
return;
}
// Initialize cURL session
$ch = curl_init($url);
// Set up custom headers
$headers = [
'X-Custom-Header: Value',
'Content-Type: text/xml'
];
function getCORSHeaderOrigin($allowed, $input)
{
// Function to allow headers from subdomains
if ('*' == $allowed) {
return '*';
}
if (! is_array($allowed)) {
$allowed = [$allowed];
}
foreach ($allowed as &$value) {
$value = preg_quote($value, '/');
if (false !== ($wildcardPos = strpos($value, '\*'))) {
$value = str_replace('\*', '(.*)', $value);
}
}
$regexp = '/^('.implode('|', $allowed).')$/';
$inputHost = parse_url($input, PHP_URL_HOST);
if (null === $inputHost || ! preg_match($regexp, $inputHost, $matches)) {
return 'none';
}
return $input;
}
// If it's a POST, put the POST data in the body
if ($isPost) {
$postvars = '';
while ($element = current($_POST)) {
$postvars .= key($_POST).'='.$element.'&';
next($_POST);
}
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
}
// Apply headers to the cURL request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Set other cURL options as needed
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// Execute the request
$response = curl_exec($ch);
// Check for errors
if (curl_errno($ch)) {
echo 'cURL Error: ' . curl_error($ch);
}
header('Content-Type: '.$mimeType);
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
if (isset($_SERVER['HTTP_ORIGIN'])) {
header('Access-Control-Allow-Origin: '.getCORSHeaderOrigin(['*.yourdomain.com','example.domain.net','localhost'], $_SERVER['HTTP_ORIGIN']));
}
// Output
echo($response);
// Close cURL session
curl_close($ch);
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment