@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at upstream/main 85 lines 2.3 kB view raw
1<?php 2 3/** 4 * Responds to a request by proxying an HTTP future. 5 * 6 * NOTE: This is currently very inefficient for large responses, and buffers 7 * the entire response into memory before returning it. It should be updated 8 * to stream the response instead, but we need to complete additional 9 * infrastructure work first. 10 */ 11final class AphrontHTTPProxyResponse extends AphrontResponse { 12 13 private $future; 14 private $headers; 15 private $httpCode; 16 17 public function setHTTPFuture(HTTPSFuture $future) { 18 $this->future = $future; 19 return $this; 20 } 21 22 public function getHTTPFuture() { 23 return $this->future; 24 } 25 26 public function getCacheHeaders() { 27 return array(); 28 } 29 30 public function getHeaders() { 31 $this->readRequestHeaders(); 32 return array_merge( 33 parent::getHeaders(), 34 $this->headers, 35 array( 36 array('X-Phabricator-Proxy', 'true'), 37 )); 38 } 39 40 public function buildResponseString() { 41 // TODO: AphrontResponse needs to support streaming responses. 42 return $this->readRequest(); 43 } 44 45 public function getHTTPResponseCode() { 46 $this->readRequestHeaders(); 47 return $this->httpCode; 48 } 49 50 private function readRequestHeaders() { 51 // TODO: This should read only the headers. 52 $this->readRequest(); 53 } 54 55 private function readRequest() { 56 // TODO: This is grossly inefficient for large requests. 57 58 list($status, $body, $headers) = $this->future->resolve(); 59 $this->httpCode = $status->getStatusCode(); 60 61 // Strip "Transfer-Encoding" headers. Particularly, the server we proxied 62 // may have chunked the response, but cURL will already have un-chunked it. 63 // If we emit the header and unchunked data, the response becomes invalid. 64 65 // See T13517. Strip "Content-Encoding" and "Content-Length" headers, since 66 // they may reflect compressed content. 67 68 foreach ($headers as $key => $header) { 69 list($header_head, $header_body) = $header; 70 $header_head = phutil_utf8_strtolower($header_head); 71 switch ($header_head) { 72 case 'transfer-encoding': 73 case 'content-encoding': 74 case 'content-length': 75 unset($headers[$key]); 76 break; 77 } 78 } 79 80 $this->headers = $headers; 81 82 return $body; 83 } 84 85}