From b260e1e5b7977e2ea6ec37a2641c57e3ea263ba9 Mon Sep 17 00:00:00 2001 From: Brandon Payton Date: Wed, 23 Oct 2024 00:26:55 -0400 Subject: [PATCH 1/3] Update CORS proxy to respond with no-cache --- packages/playground/php-cors-proxy/cors-proxy.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/playground/php-cors-proxy/cors-proxy.php b/packages/playground/php-cors-proxy/cors-proxy.php index 1909e8357d..9738ce6740 100644 --- a/packages/playground/php-cors-proxy/cors-proxy.php +++ b/packages/playground/php-cors-proxy/cors-proxy.php @@ -99,7 +99,7 @@ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); $httpcode_sent = false; curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use($targetUrl, &$httpcode_sent, $ch) { - if(!$httpcode_sent) { + if (!$httpcode_sent) { // Set the response code from the target server $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); http_response_code($httpCode); @@ -129,7 +129,8 @@ header('Location: ' . $newLocation, true); } else if ( stripos($header, 'Set-Cookie:') !== 0 && - stripos($header, 'Authorization:') !== 0 + stripos($header, 'Authorization:') !== 0 && + stripos($header, 'Cache-Control:') !== 0 ) { header($header, false); } @@ -158,8 +159,11 @@ http_response_code(502); echo "Bad Gateway – curl_exec error: " . curl_error($ch); } else { - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - @http_response_code($httpCode); + if (!$httpcode_sent) { + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + @http_response_code($httpCode); + } + @header('Cache-Control: no-cache'); } // Close cURL session curl_close($ch); From 137cf6dda135ddd5eaf07c870491c69d0a41b148 Mon Sep 17 00:00:00 2001 From: Brandon Payton Date: Wed, 23 Oct 2024 11:32:46 -0400 Subject: [PATCH 2/3] Add why comment --- packages/playground/php-cors-proxy/cors-proxy.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/playground/php-cors-proxy/cors-proxy.php b/packages/playground/php-cors-proxy/cors-proxy.php index 9738ce6740..00ee40b5a5 100644 --- a/packages/playground/php-cors-proxy/cors-proxy.php +++ b/packages/playground/php-cors-proxy/cors-proxy.php @@ -86,7 +86,7 @@ "Host: $host", // @TODO: Consider relaying client IP with the following reasoning: // Let's not take full credit for the proxied request. - // This is a CORS proxy, not an IP anonymizer. + // This is a CORS proxy, not an IP anonymizer. // NOTE: We cannot do this reliably based on X-Forwarded-For unless // we trust the reverse proxy, so it cannot be done unconditionally // in this script because we do not control where others deploy it. @@ -122,13 +122,13 @@ // Adjust the redirection URL to go back to the proxy script $locationUrl = trim(substr($header, 9)); $newLocation = rewrite_relative_redirect( - $targetUrl, - $locationUrl, + $targetUrl, + $locationUrl, CURRENT_SCRIPT_URI ); header('Location: ' . $newLocation, true); } else if ( - stripos($header, 'Set-Cookie:') !== 0 && + stripos($header, 'Set-Cookie:') !== 0 && stripos($header, 'Authorization:') !== 0 && stripos($header, 'Cache-Control:') !== 0 ) { @@ -163,6 +163,7 @@ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); @http_response_code($httpCode); } + // For now, let's clearly avoid the possibility of stale, cached responses. @header('Cache-Control: no-cache'); } // Close cURL session From e191846a7ea867eb7fcc7afc48cf926d8ad9c643 Mon Sep 17 00:00:00 2001 From: Brandon Payton Date: Wed, 23 Oct 2024 12:30:33 -0400 Subject: [PATCH 3/3] Fix Cache-Control header to always be sent --- .../playground/php-cors-proxy/cors-proxy.php | 101 ++++++++++-------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/packages/playground/php-cors-proxy/cors-proxy.php b/packages/playground/php-cors-proxy/cors-proxy.php index 00ee40b5a5..9fb854f391 100644 --- a/packages/playground/php-cors-proxy/cors-proxy.php +++ b/packages/playground/php-cors-proxy/cors-proxy.php @@ -62,6 +62,21 @@ $ch = curl_init($targetUrl); +$relay_http_code_and_initial_headers_if_not_already_sent = function () use ($ch) { + static $http_code_sent = false; + + if (!$http_code_sent) { + // Set the response code from the target server + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + http_response_code($http_code); + + // For now, let's clearly avoid the possibility of stale, cached responses. + header('Cache-Control: no-cache'); + + $http_code_sent = true; + } +}; + // Pin the hostname resolution to an IP we've resolved earlier curl_setopt($ch, CURLOPT_RESOLVE, [ "$host:80:$resolvedIp", @@ -98,44 +113,51 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); $httpcode_sent = false; -curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use($targetUrl, &$httpcode_sent, $ch) { - if (!$httpcode_sent) { - // Set the response code from the target server - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - http_response_code($httpCode); - $httpcode_sent = true; - } - $len = strlen($header); - $colonPos = strpos($header, ':'); - $name = strtolower(substr($header, 0, $colonPos)); - $value = trim(substr($header, $colonPos + 1)); - - if($name === 'content-length') { - $content_length = intval($value); - if ($content_length >= MAX_RESPONSE_SIZE) { - http_response_code(413); - echo "Response Too Large"; - exit; - } - } - if (stripos($header, 'Location:') === 0) { - // Adjust the redirection URL to go back to the proxy script - $locationUrl = trim(substr($header, 9)); - $newLocation = rewrite_relative_redirect( - $targetUrl, - $locationUrl, - CURRENT_SCRIPT_URI - ); - header('Location: ' . $newLocation, true); - } else if ( - stripos($header, 'Set-Cookie:') !== 0 && - stripos($header, 'Authorization:') !== 0 && - stripos($header, 'Cache-Control:') !== 0 +curl_setopt( + $ch, + CURLOPT_HEADERFUNCTION, + function( + $curl, + $header + ) use ( + $targetUrl, + $relay_http_code_and_initial_headers_if_not_already_sent ) { - header($header, false); + $relay_http_code_and_initial_headers_if_not_already_sent(); + + $len = strlen($header); + $colonPos = strpos($header, ':'); + $name = strtolower(substr($header, 0, $colonPos)); + $value = trim(substr($header, $colonPos + 1)); + + if($name === 'content-length') { + $content_length = intval($value); + if ($content_length >= MAX_RESPONSE_SIZE) { + http_response_code(413); + echo "Response Too Large"; + exit; + } + } + if (stripos($header, 'Location:') === 0) { + // Adjust the redirection URL to go back to the proxy script + $locationUrl = trim(substr($header, 9)); + $newLocation = rewrite_relative_redirect( + $targetUrl, + $locationUrl, + CURRENT_SCRIPT_URI + ); + header('Location: ' . $newLocation, true); + } else if ( + stripos($header, 'Set-Cookie:') !== 0 && + stripos($header, 'Authorization:') !== 0 && + stripos($header, 'Cache-Control:') !== 0 + ) { + header($header, false); + } + return $len; } - return $len; -}); +); + curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) { echo $data; @ob_flush(); @@ -159,12 +181,7 @@ http_response_code(502); echo "Bad Gateway – curl_exec error: " . curl_error($ch); } else { - if (!$httpcode_sent) { - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - @http_response_code($httpCode); - } - // For now, let's clearly avoid the possibility of stale, cached responses. - @header('Cache-Control: no-cache'); + @$relay_http_code_and_initial_headers_if_not_already_sent(); } // Close cURL session curl_close($ch);