Skip to content

Commit 3c4063e

Browse files
committed
Some renaming and improvements
1 parent f2b35bd commit 3c4063e

File tree

3 files changed

+116
-70
lines changed

3 files changed

+116
-70
lines changed

bin/proxy

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,9 @@ if (php_sapi_name() !== 'cli') {
1212
require __DIR__ . '/../src/Proxy.php';
1313

1414
$proxy = new Proxy();
15-
$proxy->setUrl($argv[1]);
16-
$proxy->execute();
15+
16+
if (isset($argv[1])) {
17+
$proxy->setUrl($argv[1]);
18+
}
19+
20+
$proxy->execute(true);

src/Proxy.php

Lines changed: 107 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -15,53 +15,55 @@ class Proxy
1515
protected $method = 'GET';
1616

1717
/** @var string */
18-
protected $data = '';
18+
protected $body = '';
1919

2020
/** @var array<string, string> */
21-
protected $header = [
21+
protected $headers = [
2222
'user-agent' => 'SempertonProxy/1.0.0 (+https://github.com/semperton/proxy)'
2323
];
2424

2525
/** @var array<string, string> */
26-
protected $responseHeader = [];
26+
protected $responseHeaders = [];
2727

2828
/** @var bool */
29-
protected $return = false;
29+
protected $echo = false;
3030

3131
/** @var bool */
32-
protected $isHttp2 = false;
32+
protected $isHttp1 = false;
3333

3434
/**
35-
* @param array<string, string> $header
35+
* @param array<string, string> $headers
3636
*/
37-
public function __construct(string $url = '', string $method = 'GET', string $data = '', array $header = [])
37+
public function __construct(string $url = '', string $method = 'GET', string $body = '', array $headers = [])
3838
{
3939
$this->setUrl($url);
4040
$this->setMethod($method);
41-
$this->setData($data);
42-
$this->setHeader($header);
43-
44-
if (
45-
php_sapi_name() === 'cli' ||
46-
(isset($_SERVER['SERVER_PROTOCOL']) && stripos($_SERVER['SERVER_PROTOCOL'], 'http/2') !== false)
47-
) {
48-
$this->isHttp2 = true;
49-
}
41+
$this->setBody($body);
42+
$this->setHeaders($headers);
43+
44+
$this->isHttp1 = self::getServerHttpVersion() === 1;
5045
}
5146

5247
public static function createFromGlobals(): Proxy
5348
{
54-
if (php_sapi_name() === 'cli') {
55-
return new self();
49+
$proxy = new self();
50+
51+
if (isset($_SERVER['REQUEST_METHOD'])) {
52+
$proxy->setMethod((string)$_SERVER['REQUEST_METHOD']);
5653
}
5754

58-
$url = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']) + 1);
59-
$method = $_SERVER['REQUEST_METHOD'];
60-
$data = @file_get_contents('php://input');
61-
$header = getallheaders();
55+
if (in_array($proxy->getMethod(), ['POST', 'PUT', 'PATCH'])) {
56+
$data = file_get_contents('php://input');
57+
$proxy->setBody($data);
58+
}
59+
60+
$headers = function_exists('getallheaders') ? getallheaders() : self::getServerHeaders();
61+
$proxy->setHeaders($headers);
6262

63-
$proxy = new self($url, $method, $data, $header);
64-
$proxy->removeHeader('host');
63+
if (isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME'])) {
64+
$url = substr((string)$_SERVER['REQUEST_URI'], strlen((string)$_SERVER['SCRIPT_NAME']) + 1);
65+
$proxy->setUrl($url)->removeHeader('host');
66+
}
6567

6668
return $proxy;
6769
}
@@ -96,28 +98,28 @@ public function getMethod(): string
9698
return $this->method;
9799
}
98100

99-
public function setData(string $data): self
101+
public function setBody(string $data): self
100102
{
101-
$this->data = $data;
103+
$this->body = $data;
102104

103105
return $this;
104106
}
105107

106-
public function getData(): string
108+
public function getBody(): string
107109
{
108-
return $this->data;
110+
return $this->body;
109111
}
110112

111113
/**
112-
* @param array<string, string> $header
114+
* @param array<string, string> $headers
113115
*/
114-
public function setHeader(array $header): self
116+
public function setHeaders(array $headers): self
115117
{
116-
foreach ($header as $key => $val) {
118+
foreach ($headers as $key => $val) {
117119

118120
$key = strtolower($key);
119121

120-
$this->header[$key] = $val;
122+
$this->headers[$key] = $val;
121123
}
122124

123125
return $this;
@@ -127,15 +129,15 @@ public function getHeader(string $name): ?string
127129
{
128130
$name = strtolower($name);
129131

130-
return isset($this->header[$name]) ? $this->header[$name] : null;
132+
return isset($this->headers[$name]) ? $this->headers[$name] : null;
131133
}
132134

133135
/**
134136
* @return array<string, string>
135137
*/
136138
public function getAllHeaders(): array
137139
{
138-
return $this->header;
140+
return $this->headers;
139141
}
140142

141143
/**
@@ -152,7 +154,7 @@ public function removeHeader($header): self
152154

153155
$key = strtolower($key);
154156

155-
unset($this->header[$key]);
157+
unset($this->headers[$key]);
156158
}
157159

158160
return $this;
@@ -161,18 +163,17 @@ public function removeHeader($header): self
161163
/**
162164
* @return array|void
163165
*/
164-
public function execute(bool $return = false)
166+
public function execute(bool $echo = false)
165167
{
166-
$this->return = $return;
167-
$this->responseHeader = [];
168+
$this->echo = $echo;
169+
$this->responseHeaders = [];
168170

169171
$ch = curl_init($this->url);
170172

171173
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
172174

173175
if (in_array($this->method, ['POST', 'PUT', 'PATCH'])) {
174-
175-
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->data);
176+
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body);
176177
}
177178

178179
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
@@ -187,12 +188,11 @@ public function execute(bool $return = false)
187188

188189
curl_setopt($ch, CURLOPT_HEADERFUNCTION, [$this, 'onCurlHeader']);
189190

190-
if (!$this->return) {
191+
if ($this->echo) {
191192

192193
curl_setopt($ch, CURLOPT_WRITEFUNCTION, [$this, 'onCurlWrite']);
193194

194-
if (!$this->isHttp2) {
195-
195+
if ($this->isHttp1) {
196196
header('Transfer-Encoding: chunked');
197197
}
198198
}
@@ -202,21 +202,15 @@ public function execute(bool $return = false)
202202

203203
curl_close($ch);
204204

205-
if (!$this->return) {
206-
207-
if (!$this->isHttp2) {
208-
209-
echo "0\r\n\r\n";
210-
flush();
211-
}
212-
213-
die();
205+
if ($this->echo && $this->isHttp1) {
206+
echo "0\r\n\r\n";
207+
flush();
214208
}
215209

216210
return [
217211

218212
'info' => $responseInfo,
219-
'header' => $this->responseHeader,
213+
'header' => $this->responseHeaders,
220214
'body' => $responseBody
221215
];
222216
}
@@ -228,10 +222,10 @@ protected function onCurlWrite($ch, string $data): int
228222
{
229223
$length = strlen($data);
230224

231-
if ($this->isHttp2) {
232-
echo $data;
233-
} else {
225+
if ($this->isHttp1) {
234226
echo dechex($length) . "\r\n$data\r\n";
227+
} else {
228+
echo $data;
235229
}
236230

237231
flush();
@@ -246,23 +240,21 @@ protected function onCurlHeader($ch, string $header): int
246240
// we follow redirects, so we need to reset the headers...
247241
if (stripos($header, 'http') === 0) {
248242

249-
$this->responseHeader = [];
243+
$this->responseHeaders = [];
250244
} else {
251245

252-
if ($this->return) {
253-
246+
if ($this->echo) {
247+
header($header);
248+
} else {
254249
$col = strpos($header, ':');
255250

256251
if ($col) { // not false and > 0
257252

258253
$key = strtolower(substr($header, 0, $col));
259254
$val = substr($header, $col + 1);
260255

261-
$this->responseHeader[trim($key)] = trim($val);
256+
$this->responseHeaders[trim($key)] = trim($val);
262257
}
263-
} else {
264-
265-
header($header);
266258
}
267259
}
268260

@@ -276,17 +268,67 @@ protected function getHeaderArray(): array
276268
{
277269
$header = [];
278270

279-
foreach ($this->header as $key => $val) {
271+
foreach ($this->headers as $key => $val) {
280272

281273
$header[] = $key . ':' . $val;
282274
}
283275

284276
return $header;
285277
}
278+
279+
protected static function getServerHttpVersion(): int
280+
{
281+
if (isset($_SERVER['SERVER_PROTOCOL'])) {
282+
283+
$proto = (string)$_SERVER['SERVER_PROTOCOL'];
284+
$pos = stripos($proto, 'http/');
285+
286+
if ($pos !== false) {
287+
return (int)substr($proto, $pos + 1, 1);
288+
}
289+
}
290+
291+
return 0;
292+
}
293+
294+
/**
295+
* laminas-diactoros/src/functions/marshal_headers_from_sapi.php
296+
* @return array<string, string>
297+
*/
298+
protected static function getServerHeaders(): array
299+
{
300+
$headers = [];
301+
foreach ($_SERVER as $key => $value) {
302+
303+
$key = (string)$key;
304+
305+
if (0 === strpos($key, 'REDIRECT_')) {
306+
$key = substr($key, 9);
307+
308+
if (array_key_exists($key, $_SERVER)) {
309+
continue;
310+
}
311+
}
312+
313+
if ($value && 0 === strpos($key, 'HTTP_')) {
314+
$name = strtr(strtolower(substr($key, 5)), '_', '-');
315+
$headers[$name] = (string)$value;
316+
continue;
317+
}
318+
319+
if ($value && 0 === strpos($key, 'CONTENT_')) {
320+
$name = 'content-' . strtolower(substr($key, 8));
321+
$headers[$name] = (string)$value;
322+
continue;
323+
}
324+
}
325+
326+
return $headers;
327+
}
286328
}
287329

288330
// allow standalone usage
289331
if (get_included_files()[0] === __FILE__) {
290332

291-
Proxy::createFromGlobals()->execute();
333+
Proxy::createFromGlobals()->execute(true);
292334
}

tests/ProxyTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@ final class ProxyTest extends TestCase
1010
public function testHttp(): void
1111
{
1212
$proxy = new Proxy('http://httpbin.org/get');
13-
$response = $proxy->execute(true);
13+
$response = $proxy->execute();
1414

1515
$this->assertEquals('HTTP', $response['info']['scheme']);
1616
}
1717

1818
public function testHttps(): void
1919
{
2020
$proxy = new Proxy('https://httpbin.org/get');
21-
$response = $proxy->execute(true);
21+
$response = $proxy->execute();
2222

2323
$this->assertEquals('HTTPS', $response['info']['scheme']);
2424
}
2525

2626
public function testEncoding(): void
2727
{
2828
$proxy = new Proxy('https://httpbin.org/gzip');
29-
$response = $proxy->execute(true);
29+
$response = $proxy->execute();
3030

3131
$this->assertEquals('gzip', $response['header']['content-encoding']);
3232

0 commit comments

Comments
 (0)