Skip to content

Commit 9a50de7

Browse files
committed
Enhancements in performance and reliability
* Added finer control over general usage settings. * Enhanced usage descriptions for better clarity. * Implemented various performance optimizations for increased efficiency. * Introduced a maximum download size limit to improve stability. * StreamDriver: Resolved issues with HTTP status code detection.
1 parent 3079ee3 commit 9a50de7

File tree

6 files changed

+377
-179
lines changed

6 files changed

+377
-179
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ Temporary Items
4747
.idea/
4848
.vscode/
4949
cache/*
50+
/README.html

README.md

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -83,33 +83,42 @@ html2canvas(document.getElementById('container'), {
8383

8484
Method | Description
8585
--- | ---
86+
`setMaxDownloadSize(int $value): void` | Set the maximum allowed download size
87+
`getMaxDownloadSize(): int` | Get the maximum allowed download size
88+
`setMaxRedirs(int $value): void` | Set the maximum number of HTTP redirects
89+
`getMaxRedirs(): int` | Get the maximum number of HTTP redirects
90+
`setReferer(string $value): void` | Set the Referer request header
91+
`getReferer(): string` | Get the Referer request header
92+
`setTimeout(int $value): void` | Set connection timeout
93+
`getTimeout(): int` | Get connection timeout
94+
`setUserAgent(string $value): void` | Set the User-Agent request header
95+
`getUserAgent(): string` | Get the User-Agent request header
8696
`setDrivers(array $drivers): void` | Set drivers used to download the resource
8797
`setOptions(string $key, mixed $value): void` | Set generic options
8898
`getOptions([string $key]): mixed` | Get generic options
8999
`setAllowedUrls(array $urls): void` | Set allowed URLs
90-
`addAllowedType(string $type, bool $binary): void` | Add content-type to the allowed list
91-
`removeAllowedType(string $type): void` | Remove content-type from the allowed list
100+
`addAllowedType(string $type, bool $binary): void` | Add Content-Type to the allowed list
101+
`removeAllowedType(string $type): void` | Remove Content-Type from the allowed list
102+
`isAllowedType(string $type[, string &$errorMessage])` | Check if Content-Type is allowed
92103
`setTemporary(string $path): void` | Sets temporary handle path, eg.: `/mnt/storage/`, `php://temp`, `php://memory`
93104
`getTemporary(): resource` | Get temporary stream
94105
`download(string $url[, bool $ignoreDownloadError]): void` | Perform download
95106
`setResponseCacheTime(int $seconds): void` | Enable or disable cache for `Proxy::respose()` or `Proxy::jsonp()`
96107
`response(): void` | Dump response to output
97108
`jsonp(string $callback): void` | Output JSONP callback with URL or data URI content
98109
`getContents([int $length[, int $offset]]): string` | If last download was successful, contents will be returned
99-
`getContentType(): string` | If last download was successful, content-type will be returned
110+
`getContentType(): string` | If last download was successful, Content-Type will be returned
100111
`getHttpStatus(): int` | If last download was successful, HTTP status will be returned
101-
`getLastErrorCode(): int` | If last download was failed, error code will be returned
102-
`getLastErrorMessage(): string` | If last download was failed, error message will be returned
112+
`getErrorCode(): int` | If last download was failed, error code will be returned
113+
`getErrorMessage(): string` | If last download was failed, error message will be returned
103114
`reset(): void` | Reset last download
104115

105116
## Generic options
106117

118+
Generic options are primarily used for driver configurations. Since each driver may require different types of settings, the most flexible approach is to allow these options to store any value. This is particularly useful when developing a new driver. Existing options include:
119+
107120
Usage | Description
108121
--- | ---
109-
`setOptions('max_redirs', int $value)` | Set the redirect limit
110-
`setOptions('timeout', int $value)` | Set timeout for connections
111-
`setOptions('user_agent', string $value)` | Set Browser User-Agent
112-
`setOptions('referer', string $value)` | Set request header contains the absolute or partial address from which a resource has been requested
113122
`setOptions('curl', array $value)` | Options for `CurlDriver`. See: https://www.php.net/manual/en/curl.constants.php
114123
`setOptions('stream', array $value)` | Options for `StreamDriver`. See: https://www.php.net/manual/en/context.php
115124

@@ -157,7 +166,7 @@ $proxy->setOptions('stream', [
157166

158167
## Content-Type allowed
159168

160-
When executing the download() method a content-type validation will be performed, by default the following Content-Types are allowed:
169+
When executing the download() method a Content-Type validation will be performed, by default the following Content-Types are allowed:
161170

162171
Content-Type | `Proxy::jsonp()`
163172
--- | ---
@@ -170,7 +179,7 @@ Content-Type | `Proxy::jsonp()`
170179
`image/svg+xml` | URL-encoded
171180
`image/svg-xml` | URL-encoded
172181

173-
You can define another allowed content-type, example:
182+
You can define another allowed Content-Type, example:
174183

175184
```php
176185
$proxy->addAllowedType('image/x-icon', true);
@@ -231,39 +240,35 @@ try {
231240
}
232241
```
233242

234-
If you need to handle content or errors manually, you can use the `Proxy::getContents`, `Proxy::getContentType`, `Proxy::getHttpStatus`, `Proxy::getLastErrorCode`, `Proxy::getLastErrorMessage` methods:
243+
If you need to handle content, you can use the `Proxy::getContents`, `Proxy::getContentType`, `Proxy::getHttpStatus` methods:
235244

236245
```php
237246
use Inphinit\Proxy\Proxy;
238247
use Inphinit\Proxy\Drivers\CurlDriver;
239248
use Inphinit\Proxy\Drivers\StreamDriver;
240249

241-
if (empty($_GET['callback'])) {
242-
die('Missing callback');
243-
}
244-
245250
$proxy = new Proxy();
246251

247252
$proxy->setDrivers([
248253
CurlDriver::class,
249254
StreamDriver::class
250255
]);
251256

252-
$proxy->download($url, true);
253-
254-
$errcode = $proxy->getLastErrorCode();
255-
$httpStatus = $proxy->getHttpStatus();
257+
try {
258+
$proxy->download($url);
256259

257-
if ($errcode) {
258-
echo $code, ': ', $proxy->getLastErrorCode();
259-
} elseif ($httpStatus < 200 && $httpStatus > 299) {
260-
echo 'HTTP request failed:', $httpStatus;
261-
} else {
262-
// Sucesss
263-
$type = $proxy->getContentType();
260+
// Success
264261
$contents = $proxy->getContents();
262+
$contentType = $proxy->getContentType();
263+
$httpStatus = $proxy->getHttpStatus();
265264

266265
...
266+
267+
} catch (Exception $ee) {
268+
$code = $ee->getCode();
269+
$message = $ee->getMessage();
270+
271+
echo 'Error: (', $code, ') ', $message;
267272
}
268273
```
269274

proxy.php

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,42 @@
1717

1818
$proxy = new Proxy();
1919

20+
// Set drivers used for download
21+
$proxy->setDrivers([
22+
//CurlDriver::class,
23+
StreamDriver::class
24+
]);
25+
26+
/*
27+
// PHP 5.4 sintax
28+
$proxy->setDrivers([
29+
'Inphinit\Proxy\Drivers\CurlDriver',
30+
'Inphinit\Proxy\Drivers\StreamDriver',
31+
]);
32+
*/
33+
34+
// Set max download size
35+
// $proxy->setMaxDownloadSize(5242880);
36+
37+
// Set max redirections
38+
// $proxy->setMaxRedirs(3);
39+
40+
// Set current referer
41+
if (isset($_SERVER['HTTP_REFERER'])) {
42+
$proxy->setReferer($_SERVER['HTTP_REFERER']);
43+
}
44+
45+
// Set max timeout connection
46+
// $proxy->setTimeout(10);
47+
48+
// Set current user-agent
49+
if (isset($_SERVER['HTTP_USER_AGENT'])) {
50+
$proxy->setUserAgent($_SERVER['HTTP_USER_AGENT']);
51+
}
52+
53+
// Use specific directory
54+
// $proxy->setTemporary(__DIR__ . '/cache');
55+
2056
// Set allowed URLs
2157
/*
2258
$proxy->setAllowedUrls([
@@ -25,7 +61,7 @@
2561
]);
2662
*/
2763

28-
// Set allowed content-types
64+
// Set allowed Content-Types
2965
// $proxy->addAllowedType('image/ico', true);
3066

3167
// Extra configs for CurlDriver
@@ -44,31 +80,6 @@
4480
]);
4581
*/
4682

47-
// Set max timeout connection
48-
// $proxy->setOptions('timeout', 10);
49-
50-
// Set max redirections from location: header
51-
// $proxy->setOptions('max_redirs', 3);
52-
53-
// Set current user-agent
54-
if (isset($_SERVER['HTTP_USER_AGENT'])) {
55-
$proxy->setOptions('user_agent', $_SERVER['HTTP_USER_AGENT']);
56-
}
57-
58-
// Set current referer
59-
if (isset($_SERVER['HTTP_REFERER'])) {
60-
$proxy->setOptions('referer', $_SERVER['HTTP_REFERER']);
61-
}
62-
63-
// Set drivers used for download
64-
$proxy->setDrivers([
65-
CurlDriver::class,
66-
StreamDriver::class
67-
]);
68-
69-
// Use specific directory
70-
// $proxy->setTemporary(__DIR__ . '/cache');
71-
7283
try {
7384
// Execute download
7485
$proxy->download($url);

src/Drivers/CurlDriver.php

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313

1414
class CurlDriver
1515
{
16-
private $proxy;
17-
private $lastUpdate = 0;
18-
private $timeout = 30;
16+
private $errorMessage;
1917
private $handle;
18+
private $httpStatus;
19+
private $lastUpdate = 0;
20+
private $maxDownloadSize;
21+
private $proxy;
2022

2123
/**
2224
* Create instace
@@ -59,13 +61,13 @@ public function exec($url, &$httpStatus, &$contentType, &$errorCode, &$errorMess
5961
$this->handle = curl_init();
6062

6163
$ch = $this->handle;
62-
$timeout = $this->proxy->getOptions('timeout');
64+
$timeout = $this->proxy->getTimeout();
6365

6466
$options = array(
65-
CURLOPT_CONNECTTIMEOUT => $timeout ? $timeout : $this->timeout,
67+
CURLOPT_CONNECTTIMEOUT => $timeout,
6668
CURLOPT_FOLLOWLOCATION => true,
6769
CURLOPT_HEADER => false,
68-
CURLOPT_MAXREDIRS => $this->proxy->getOptions('max_redirs'),
70+
CURLOPT_MAXREDIRS => $this->proxy->getMaxRedirs(),
6971
CURLOPT_RETURNTRANSFER => false
7072
);
7173

@@ -77,18 +79,34 @@ public function exec($url, &$httpStatus, &$contentType, &$errorCode, &$errorMess
7779

7880
curl_setopt_array($ch, $options);
7981

80-
$referer = $this->proxy->getOptions('referer');
82+
$referer = $this->proxy->getReferer();
8183

8284
if ($referer) {
8385
curl_setopt($ch, CURLOPT_REFERER, $referer);
8486
}
8587

86-
$userAgent = $this->proxy->getOptions('user_agent');
88+
$userAgent = $this->proxy->getUserAgent();
8789

8890
if ($userAgent) {
8991
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
9092
}
9193

94+
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
95+
96+
$this->maxDownloadSize = $this->proxy->getMaxDownloadSize();
97+
98+
if (PHP_VERSION_ID < 50500) {
99+
$progressCallback = function ($download_size, $downloaded, $upload_size, $uploaded) {
100+
return $this->abort($downloaded);
101+
};
102+
} else {
103+
$progressCallback = function ($resource, $download_size, $downloaded, $upload_size, $uploaded) {
104+
return $this->abort($downloaded);
105+
};
106+
}
107+
108+
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $progressCallback);
109+
92110
$temp = $this->proxy->getTemporary();
93111

94112
if (defined('CURLOPT_WRITEFUNCTION')) {
@@ -110,10 +128,40 @@ public function exec($url, &$httpStatus, &$contentType, &$errorCode, &$errorMess
110128

111129
if ($code !== 0) {
112130
$errorCode = $code;
113-
$errorMessage = 'cURL: ' . curl_error($ch);
114-
} else {
115-
$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
116-
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
131+
$errorMessage = $this->errorMessage ? $this->errorMessage : ('cURL: ' . curl_error($ch));
132+
133+
if ($this->httpStatus !== null) {
134+
$httpStatus = $this->httpStatus;
135+
}
136+
137+
return false;
117138
}
139+
140+
$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
141+
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
142+
143+
return true;
144+
}
145+
146+
private function abort($downloaded)
147+
{
148+
if ($downloaded > $this->maxDownloadSize) {
149+
return 1;
150+
}
151+
152+
$code = curl_getinfo($this->handle, CURLINFO_HTTP_CODE);
153+
154+
if ($code >= 100 && ($code < 200 || $code >= 300)) {
155+
$this->httpStatus = $code;
156+
return 1;
157+
}
158+
159+
$contentType = curl_getinfo($this->handle, CURLINFO_CONTENT_TYPE);
160+
161+
if ($contentType && $this->proxy->isAllowedType($contentType, $this->errorMessage) === false) {
162+
return 1;
163+
}
164+
165+
return 0;
118166
}
119167
}

0 commit comments

Comments
 (0)