Skip to content

Commit

Permalink
[CORS Proxy] Support chunked encoding when running in Apache/Nginx/etc (
Browse files Browse the repository at this point in the history
#2114)

Adds support for `transfer-encoding: chunked` on Apache, Nginx, and
other web servers.

#2077 added support for `transfer-encoding: chunked` in a way that works
on a local PHP dev server. The proxy manually chunks the output bytes
and outputs each chunk's header, separator, body, and trailer.

However, it doesn't work on playground.wordpress.net because the web
server there handles the chunked encoding on its own. The bytes echoed
by cors-proxy.php are treated as body bytes, which messes up the
response body.

This PR restricts the manual chunking to a local CLI dev server.

## Testing instructions

Run cors-proxy.php in Apache or so and confirm that requesting resources
served with chunked encoding works with this patch but not without it.
One such URL is https://adamadam.blog/feed/.
  • Loading branch information
adamziel authored Jan 9, 2025
1 parent 5fa2cfa commit 4f810db
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions packages/playground/php-cors-proxy/cors-proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,33 @@
};

function send_response_chunk($data) {
global $is_chunked_response;
if ($is_chunked_response) {
if (should_send_as_chunked_response()) {
// We need to manually chunk the response when running in the PHP
// built-in server. It won't handle that for us.
echo sprintf("%s\r\n%s\r\n", dechex(strlen($data)), $data);
} else {
// When running behing an Apache or Nginx or another webserver,
// it will handle the chunking for us. Manually sending the chunk
// header, \r\n separator, body, and \r\n trailer isn't just
// unnecessary, but it would actually include those bytes in the
// response body.
echo $data;
}
@ob_flush();
@flush();
}

/**
* We need to manually chunk the response when running the PHP
* dev server AND the transfer-encoding header is set to chunked.
*
* Apache, Nginx, etc. will handle the chunking for us.
*/
function should_send_as_chunked_response() {
global $is_chunked_response;
return $is_chunked_response && php_sapi_name() === 'cli-server';
}

// Pin the hostname resolution to an IP we've resolved earlier
curl_setopt($ch, CURLOPT_RESOLVE, [
"$host:80:$resolvedIp",
Expand Down Expand Up @@ -255,7 +272,9 @@ function(
// Close cURL session
curl_close($ch);

// Only send chunked transfer encoding footer if we're using chunked encoding
if ($is_chunked_response) {
// Only send chunked transfer encoding footer if we're using chunked encoding.
// We need to manually send the footer when running in the PHP built-in server
// because, unlike apache or nginx, it won't handle that for us.
if (should_send_as_chunked_response()) {
echo "0\r\n\r\n";
}

0 comments on commit 4f810db

Please sign in to comment.