@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
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}