Skip to content

Commit a4e38d8

Browse files
committed
feat: cli download supprot auto proxy by ENV var
1 parent 79fdc85 commit a4e38d8

File tree

3 files changed

+115
-15
lines changed

3 files changed

+115
-15
lines changed

src/Cli.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static function clog(string $msg, array $data = [], string $type = 'info'
102102
$optString = $userOpts ? ' ' . implode(' ', $userOpts) : '';
103103
$dataString = $data ? PHP_EOL . json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) : '';
104104

105-
self::writef('%s [%s]%s %s %s', date('Y/m/d H:i:s'), $type, $optString, trim($msg), $dataString);
105+
self::writef("%s [%s]%s %s %s\n", date('Y/m/d H:i:s'), $type, $optString, trim($msg), $dataString);
106106
}
107107

108108
/*******************************************************************************

src/Traits/WriteMessageTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ trait WriteMessageTrait
4747
*/
4848
public static function writef(string $format, ...$args): int
4949
{
50-
return self::write(sprintf($format, ...$args));
50+
return self::write(sprintf($format, ...$args), false);
5151
}
5252

5353
/**
@@ -60,7 +60,7 @@ public static function writef(string $format, ...$args): int
6060
*/
6161
public static function printf(string $format, ...$args): int
6262
{
63-
return self::write(sprintf($format, ...$args));
63+
return self::write(sprintf($format, ...$args), false);
6464
}
6565

6666
/**

src/Util/Download.php

Lines changed: 112 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,19 @@
1111

1212
use RuntimeException;
1313
use Toolkit\Cli\Cli;
14+
use function array_merge;
1415
use function basename;
1516
use function error_get_last;
1617
use function fclose;
1718
use function file_put_contents;
1819
use function fopen;
1920
use function getcwd;
21+
use function getenv;
2022
use function is_resource;
23+
use function preg_replace;
2124
use function stream_context_create;
2225
use function stream_context_set_params;
26+
use function strpos;
2327
use function trim;
2428
use const STREAM_NOTIFY_AUTH_REQUIRED;
2529
use const STREAM_NOTIFY_AUTH_RESULT;
@@ -41,7 +45,7 @@ final class Download
4145
{
4246
public const PROGRESS_TEXT = 'text';
4347

44-
public const PROGRESS_BAR = 'bar';
48+
public const PROGRESS_BAR = 'bar';
4549

4650
/** @var string */
4751
private $url;
@@ -55,6 +59,19 @@ final class Download
5559
/** @var string */
5660
private $showType;
5761

62+
/**
63+
* @var bool
64+
*/
65+
private $debug = false;
66+
67+
/**
68+
* http context options
69+
*
70+
* @var array
71+
* @link https://www.php.net/manual/en/context.http.php
72+
*/
73+
private $httpCtxOptions = [];
74+
5875
/**
5976
* @param string $url
6077
* @param string $saveAs
@@ -118,14 +135,15 @@ public function start(): self
118135
$this->saveAs = $save;
119136
}
120137

121-
$ctx = stream_context_create();
138+
$ctx = $this->createStreamContext();
122139

123140
// register stream notification callback
141+
// https://www.php.net/manual/en/function.stream-notification-callback.php
124142
stream_context_set_params($ctx, [
125143
'notification' => [$this, 'progressShow']
126144
]);
127145

128-
Cli::write("Download: {$this->url}\nSave As: {$save}\n");
146+
Cli::write("Download: {$this->url}\n Save As: {$save}\n");
129147

130148
$fp = fopen($this->url, 'rb', false, $ctx);
131149

@@ -145,16 +163,71 @@ public function start(): self
145163
return $this;
146164
}
147165

166+
protected function createStreamContext()
167+
{
168+
// https://www.php.net/manual/en/context.http.php
169+
$httpOpts = [
170+
'max_redirects' => '15',
171+
'protocol_version' => '1.1',
172+
'header' => [
173+
'Connection: close', // on 'protocol_version' => '1.1'
174+
],
175+
// 'follow_location' => '1',
176+
// 'timeout' => 0,
177+
// 'proxy' => 'tcp://my-proxy.localhost:3128',
178+
];
179+
180+
if ($this->httpCtxOptions) {
181+
$httpOpts = array_merge($httpOpts, $this->httpCtxOptions);
182+
}
183+
184+
$isHttps = strpos($this->url, 'https') === 0;
185+
186+
if (!isset($httpOpts['proxy'])) {
187+
if ($isHttps) {
188+
$proxyUrl = (string)getenv('https_proxy');
189+
} else {
190+
$proxyUrl = (string)getenv('http_proxy');
191+
}
192+
193+
if ($proxyUrl) {
194+
$this->debugf('Uses proxy ENV variable: http%s_proxy=%s', $isHttps ? 's' : '', $proxyUrl);
195+
196+
// convert 'http://127.0.0.1:10801' to 'tcp://127.0.0.1:10801'
197+
// see https://github.com/guzzle/guzzle/issues/1555#issuecomment-239450114
198+
if (strpos($proxyUrl, 'http') === 0) {
199+
$proxyUrl = preg_replace('/^http[s]?/', 'tcp', $proxyUrl);
200+
}
201+
202+
$httpOpts['proxy'] = $proxyUrl;
203+
// see https://www.php.net/manual/en/context.http.php#110449
204+
$httpOpts['request_fulluri'] = true;
205+
}
206+
}
207+
208+
return stream_context_create([
209+
'http' => $httpOpts,
210+
]);
211+
}
212+
148213
/**
149-
* @param int $notifyCode stream notify code
150-
* @param int $severity severity code
151-
* @param string $message Message text
152-
* @param int $messageCode Message code
153-
* @param int $transferredBytes Have been transferred bytes
154-
* @param int $maxBytes Target max length bytes
214+
* @link https://www.php.net/manual/en/function.stream-notification-callback.php
215+
*
216+
* @param int $notifyCode stream notify code
217+
* @param int $severity severity code
218+
* @param string|null $message Message text
219+
* @param int $messageCode Message code
220+
* @param int $transferredBytes Have been transferred bytes
221+
* @param int $maxBytes Target max length bytes
155222
*/
156-
public function progressShow(int $notifyCode, $severity, string $message, $messageCode, int $transferredBytes, int $maxBytes): void
157-
{
223+
public function progressShow(
224+
int $notifyCode,
225+
int $severity,
226+
?string $message,
227+
$messageCode,
228+
int $transferredBytes,
229+
int $maxBytes
230+
): void {
158231
$msg = '';
159232

160233
switch ($notifyCode) {
@@ -172,7 +245,7 @@ public function progressShow(int $notifyCode, $severity, string $message, $messa
172245
break;
173246

174247
case STREAM_NOTIFY_CONNECT:
175-
$msg = 'Connected ...';
248+
$msg = '> Connected ...';
176249
break;
177250

178251
case STREAM_NOTIFY_FILE_SIZE_IS:
@@ -226,6 +299,17 @@ public function showProgressByType($transferredBytes): string
226299
return '';
227300
}
228301

302+
/**
303+
* @param string $format
304+
* @param mixed ...$args
305+
*/
306+
public function debugf(string $format, ...$args): void
307+
{
308+
if ($this->debug) {
309+
Cli::printf("[DEBUG] $format\n", ...$args);
310+
}
311+
}
312+
229313
/**
230314
* @return string
231315
*/
@@ -273,4 +357,20 @@ public function setSaveAs(string $saveAs): void
273357
{
274358
$this->saveAs = trim($saveAs);
275359
}
360+
361+
/**
362+
* @param bool $debug
363+
*/
364+
public function setDebug(bool $debug): void
365+
{
366+
$this->debug = $debug;
367+
}
368+
369+
/**
370+
* @param array $httpCtxOptions
371+
*/
372+
public function setHttpCtxOptions(array $httpCtxOptions): void
373+
{
374+
$this->httpCtxOptions = $httpCtxOptions;
375+
}
276376
}

0 commit comments

Comments
 (0)