Summary: Ref T13517. See that task for details about the underlying issue here. Currently, we may decode a compressed response, then retransmit it with leftover "Content-Encoding" and "Content-Length" headers. Instead, strip these headers. Test Plan: - In a clustered repository setup, cloned a Git repository over HTTP. - Before: Error while processing content unencoding: invalid stored block lengths - After: Clean clone. Maniphest Tasks: T13517 Differential Revision: https://secure.phabricator.com/D21167
86 lines
2.2 KiB
PHP
86 lines
2.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Responds to a request by proxying an HTTP future.
|
|
*
|
|
* NOTE: This is currently very inefficient for large responses, and buffers
|
|
* the entire response into memory before returning it. It should be updated
|
|
* to stream the response instead, but we need to complete additional
|
|
* infrastructure work first.
|
|
*/
|
|
final class AphrontHTTPProxyResponse extends AphrontResponse {
|
|
|
|
private $future;
|
|
private $headers;
|
|
private $httpCode;
|
|
|
|
public function setHTTPFuture(HTTPSFuture $future) {
|
|
$this->future = $future;
|
|
return $this;
|
|
}
|
|
|
|
public function getHTTPFuture() {
|
|
return $this->future;
|
|
}
|
|
|
|
public function getCacheHeaders() {
|
|
return array();
|
|
}
|
|
|
|
public function getHeaders() {
|
|
$this->readRequestHeaders();
|
|
return array_merge(
|
|
parent::getHeaders(),
|
|
$this->headers,
|
|
array(
|
|
array('X-Phabricator-Proxy', 'true'),
|
|
));
|
|
}
|
|
|
|
public function buildResponseString() {
|
|
// TODO: AphrontResponse needs to support streaming responses.
|
|
return $this->readRequest();
|
|
}
|
|
|
|
public function getHTTPResponseCode() {
|
|
$this->readRequestHeaders();
|
|
return $this->httpCode;
|
|
}
|
|
|
|
private function readRequestHeaders() {
|
|
// TODO: This should read only the headers.
|
|
$this->readRequest();
|
|
}
|
|
|
|
private function readRequest() {
|
|
// TODO: This is grossly inefficient for large requests.
|
|
|
|
list($status, $body, $headers) = $this->future->resolve();
|
|
$this->httpCode = $status->getStatusCode();
|
|
|
|
// Strip "Transfer-Encoding" headers. Particularly, the server we proxied
|
|
// may have chunked the response, but cURL will already have un-chunked it.
|
|
// If we emit the header and unchunked data, the response becomes invalid.
|
|
|
|
// See T13517. Strip "Content-Encoding" and "Content-Length" headers, since
|
|
// they may reflect compressed content.
|
|
|
|
foreach ($headers as $key => $header) {
|
|
list($header_head, $header_body) = $header;
|
|
$header_head = phutil_utf8_strtolower($header_head);
|
|
switch ($header_head) {
|
|
case 'transfer-encoding':
|
|
case 'content-encoding':
|
|
case 'content-length':
|
|
unset($headers[$key]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->headers = $headers;
|
|
|
|
return $body;
|
|
}
|
|
|
|
}
|