@@ -15,53 +15,55 @@ class Proxy
15
15
protected $ method = 'GET ' ;
16
16
17
17
/** @var string */
18
- protected $ data = '' ;
18
+ protected $ body = '' ;
19
19
20
20
/** @var array<string, string> */
21
- protected $ header = [
21
+ protected $ headers = [
22
22
'user-agent ' => 'SempertonProxy/1.0.0 (+https://github.com/semperton/proxy) '
23
23
];
24
24
25
25
/** @var array<string, string> */
26
- protected $ responseHeader = [];
26
+ protected $ responseHeaders = [];
27
27
28
28
/** @var bool */
29
- protected $ return = false ;
29
+ protected $ echo = false ;
30
30
31
31
/** @var bool */
32
- protected $ isHttp2 = false ;
32
+ protected $ isHttp1 = false ;
33
33
34
34
/**
35
- * @param array<string, string> $header
35
+ * @param array<string, string> $headers
36
36
*/
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 = [])
38
38
{
39
39
$ this ->setUrl ($ url );
40
40
$ 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 ;
50
45
}
51
46
52
47
public static function createFromGlobals (): Proxy
53
48
{
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 ' ]);
56
53
}
57
54
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 );
62
62
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
+ }
65
67
66
68
return $ proxy ;
67
69
}
@@ -96,28 +98,28 @@ public function getMethod(): string
96
98
return $ this ->method ;
97
99
}
98
100
99
- public function setData (string $ data ): self
101
+ public function setBody (string $ data ): self
100
102
{
101
- $ this ->data = $ data ;
103
+ $ this ->body = $ data ;
102
104
103
105
return $ this ;
104
106
}
105
107
106
- public function getData (): string
108
+ public function getBody (): string
107
109
{
108
- return $ this ->data ;
110
+ return $ this ->body ;
109
111
}
110
112
111
113
/**
112
- * @param array<string, string> $header
114
+ * @param array<string, string> $headers
113
115
*/
114
- public function setHeader (array $ header ): self
116
+ public function setHeaders (array $ headers ): self
115
117
{
116
- foreach ($ header as $ key => $ val ) {
118
+ foreach ($ headers as $ key => $ val ) {
117
119
118
120
$ key = strtolower ($ key );
119
121
120
- $ this ->header [$ key ] = $ val ;
122
+ $ this ->headers [$ key ] = $ val ;
121
123
}
122
124
123
125
return $ this ;
@@ -127,15 +129,15 @@ public function getHeader(string $name): ?string
127
129
{
128
130
$ name = strtolower ($ name );
129
131
130
- return isset ($ this ->header [$ name ]) ? $ this ->header [$ name ] : null ;
132
+ return isset ($ this ->headers [$ name ]) ? $ this ->headers [$ name ] : null ;
131
133
}
132
134
133
135
/**
134
136
* @return array<string, string>
135
137
*/
136
138
public function getAllHeaders (): array
137
139
{
138
- return $ this ->header ;
140
+ return $ this ->headers ;
139
141
}
140
142
141
143
/**
@@ -152,7 +154,7 @@ public function removeHeader($header): self
152
154
153
155
$ key = strtolower ($ key );
154
156
155
- unset($ this ->header [$ key ]);
157
+ unset($ this ->headers [$ key ]);
156
158
}
157
159
158
160
return $ this ;
@@ -161,18 +163,17 @@ public function removeHeader($header): self
161
163
/**
162
164
* @return array|void
163
165
*/
164
- public function execute (bool $ return = false )
166
+ public function execute (bool $ echo = false )
165
167
{
166
- $ this ->return = $ return ;
167
- $ this ->responseHeader = [];
168
+ $ this ->echo = $ echo ;
169
+ $ this ->responseHeaders = [];
168
170
169
171
$ ch = curl_init ($ this ->url );
170
172
171
173
curl_setopt ($ ch , CURLOPT_CUSTOMREQUEST , $ this ->method );
172
174
173
175
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 );
176
177
}
177
178
178
179
curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , 0 );
@@ -187,12 +188,11 @@ public function execute(bool $return = false)
187
188
188
189
curl_setopt ($ ch , CURLOPT_HEADERFUNCTION , [$ this , 'onCurlHeader ' ]);
189
190
190
- if (! $ this ->return ) {
191
+ if ($ this ->echo ) {
191
192
192
193
curl_setopt ($ ch , CURLOPT_WRITEFUNCTION , [$ this , 'onCurlWrite ' ]);
193
194
194
- if (!$ this ->isHttp2 ) {
195
-
195
+ if ($ this ->isHttp1 ) {
196
196
header ('Transfer-Encoding: chunked ' );
197
197
}
198
198
}
@@ -202,21 +202,15 @@ public function execute(bool $return = false)
202
202
203
203
curl_close ($ ch );
204
204
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 ();
214
208
}
215
209
216
210
return [
217
211
218
212
'info ' => $ responseInfo ,
219
- 'header ' => $ this ->responseHeader ,
213
+ 'header ' => $ this ->responseHeaders ,
220
214
'body ' => $ responseBody
221
215
];
222
216
}
@@ -228,10 +222,10 @@ protected function onCurlWrite($ch, string $data): int
228
222
{
229
223
$ length = strlen ($ data );
230
224
231
- if ($ this ->isHttp2 ) {
232
- echo $ data ;
233
- } else {
225
+ if ($ this ->isHttp1 ) {
234
226
echo dechex ($ length ) . "\r\n$ data \r\n" ;
227
+ } else {
228
+ echo $ data ;
235
229
}
236
230
237
231
flush ();
@@ -246,23 +240,21 @@ protected function onCurlHeader($ch, string $header): int
246
240
// we follow redirects, so we need to reset the headers...
247
241
if (stripos ($ header , 'http ' ) === 0 ) {
248
242
249
- $ this ->responseHeader = [];
243
+ $ this ->responseHeaders = [];
250
244
} else {
251
245
252
- if ($ this ->return ) {
253
-
246
+ if ($ this ->echo ) {
247
+ header ($ header );
248
+ } else {
254
249
$ col = strpos ($ header , ': ' );
255
250
256
251
if ($ col ) { // not false and > 0
257
252
258
253
$ key = strtolower (substr ($ header , 0 , $ col ));
259
254
$ val = substr ($ header , $ col + 1 );
260
255
261
- $ this ->responseHeader [trim ($ key )] = trim ($ val );
256
+ $ this ->responseHeaders [trim ($ key )] = trim ($ val );
262
257
}
263
- } else {
264
-
265
- header ($ header );
266
258
}
267
259
}
268
260
@@ -276,17 +268,67 @@ protected function getHeaderArray(): array
276
268
{
277
269
$ header = [];
278
270
279
- foreach ($ this ->header as $ key => $ val ) {
271
+ foreach ($ this ->headers as $ key => $ val ) {
280
272
281
273
$ header [] = $ key . ': ' . $ val ;
282
274
}
283
275
284
276
return $ header ;
285
277
}
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
+ }
286
328
}
287
329
288
330
// allow standalone usage
289
331
if (get_included_files ()[0 ] === __FILE__ ) {
290
332
291
- Proxy::createFromGlobals ()->execute ();
333
+ Proxy::createFromGlobals ()->execute (true );
292
334
}
0 commit comments