HTTP Saber (Da Mao Wang), a PHP high-performance HTTP client of Swoole人性化组件库
, is based on Swoole's native coroutine, supports multiple styles of operations, and provides high-performance solutions at the bottom, allowing developers to focus on functional development, from traditional Free from the synchronous blocking and cumbersome configuration of Curl.
English Document
The best way to install is through the Composer package manager:
composer require swlib/saber
The bottom layer of Swoole implements coroutine scheduling, and the business layer does not need to be aware . Developers can use synchronous code writing to achieve the effect of asynchronous IO and ultra-high performance without being aware of it, avoiding the discrete code logic and excessive trapping caused by traditional asynchronous callbacks. Layer callbacks cause the code to be unmaintainable.
It needs to be used in onRequet
, onReceive
, onConnect
and other event callback functions, or wrapped with the go keyword ( swoole.use_shortname
is enabled by default).
go ( function () {
echo SaberGM:: get ( ' http://httpbin.org/get ' );
})
Automatic data packaging: Incoming data will be automatically converted into the type format specified by content-type
The default is
x-www-form-urlencoded
, and other formats such asjson
are also supported.
SaberGM
:= Saber Global Manager
. If you think the class name is a bit long, you can use class_alias
to give it your own alias. It is recommended to use the method of generating instances in the service and use SaberGM
as a shortcut.
SaberGM:: get ( ' http://httpbin.org/get ' );
SaberGM:: delete ( ' http://httpbin.org/delete ' );
SaberGM:: post ( ' http://httpbin.org/post ' , [ ' foo ' => ' bar ' ]);
SaberGM:: put ( ' http://httpbin.org/put ' , [ ' foo ' => ' bar ' ]);
SaberGM:: patch ( ' http://httpbin.org/patch ' , [ ' foo ' => ' bar ' ]);
Applicable API proxy service
$ saber = Saber:: create ([
' base_uri ' => ' http://httpbin.org ' ,
' headers ' => [
' Accept-Language ' => ' en,zh-CN;q=0.9,zh;q=0.8 ' ,
' Content-Type ' => ContentType:: JSON ,
' DNT ' => ' 1 ' ,
' User-Agent ' => null
]
]);
echo $ saber -> get ( ' /get ' );
echo $ saber -> delete ( ' /delete ' );
echo $ saber -> post ( ' /post ' , [ ' foo ' => ' bar ' ]);
echo $ saber -> patch ( ' /patch ' , [ ' foo ' => ' bar ' ]);
echo $ saber -> put ( ' /put ' , [ ' foo ' => ' bar ' ]);
Session will automatically save cookie information, and its implementation is complete at the browser level.
$ session = Saber:: session ([
' base_uri ' => ' http://httpbin.org ' ,
' redirect ' => 0
]);
$ session -> get ( ' /cookies/set?foo=bar&k=v&apple=banana ' );
$ session -> get ( ' /cookies/delete?k ' );
echo $ session -> get ( ' /cookies ' )-> body ;
Note: A concurrent redirect optimization solution is used here. Multiple redirects are always concurrent and will not degenerate into a single request in the queue.
$ responses = SaberGM:: requests ([
[ ' uri ' => ' http://github.com/ ' ],
[ ' uri ' => ' http://github.com/ ' ],
[ ' uri ' => ' https://github.com/ ' ]
]);
echo " multi-requests [ { $ responses -> success_num } ok, { $ responses -> error_num } error ]: n" . " consuming-time: { $ responses -> time } s n" ;
// multi - requests [ 3 ok , 0 error ] :
// consuming - time : 0 . 79090881347656s
// 别名机制可以省略参数书写参数名
$ saber = Saber:: create ([ ' base_uri ' => ' http://httpbin.org ' ]);
echo $ saber -> requests ([
[ ' get ' , ' /get ' ],
[ ' post ' , ' /post ' ],
[ ' patch ' , ' /patch ' ],
[ ' put ' , ' /put ' ],
[ ' delete ' , ' /delete ' ]
]);
Currently supports rapid parsing of data in four formats: json
, xml
, html
, and url-query
[ $ json , $ xml , $ html ] = SaberGM:: list ([
' uri ' => [
' http://httpbin.org/get ' ,
' http://www.w3school.com.cn/example/xmle/note.xml ' ,
' http://httpbin.org/html '
]
]);
var_dump ( $ json -> getParsedJsonArray ());
var_dump ( $ json -> getParsedJsonObject ());
var_dump ( $ xml -> getParsedXmlArray ());
var_dump ( $ xml -> getParsedXmlObject ( true ));
var_dump ( $ html -> getParsedDomObject ()-> getElementsByTagName ( ' h1 ' )-> item ( 0 )-> textContent );
Supports HTTP and SOCKS5 proxies
$ uri = ' http://myip.ipip.net/ ' ;
echo SaberGM:: get ( $ uri , [ ' proxy ' => ' http://127.0.0.1:1087 ' ])-> body ;
echo SaberGM:: get ( $ uri , [ ' proxy ' => ' socks5://127.0.0.1:1086 ' ])-> body ;
The underlying automatic coroutine scheduling can support asynchronous sending of very large files and resume uploading at breakpoints.
Upload three files at the same time (three parameter styles
string
|array
|object
)
$ file1 = __DIR__ . ' /black.png ' ;
$ file2 = [
' path ' => __DIR__ . ' /black.png ' ,
' name ' => ' white.png ' ,
' type ' => ContentType:: MAP [ ' png ' ],
' offset ' => null , // re - upload from break
' size ' => null //upload a part of the file
];
$ file3 = new SwUploadFile (
__DIR__ . ' /black.png ' ,
' white.png ' ,
ContentType:: MAP [ ' png ' ]
);
echo SaberGM:: post ( ' http://httpbin.org/post ' , null , [
' files ' => [
' image1 ' => $ file1 ,
' image2 ' => $ file2 ,
' image3 ' => $ file3
]
]
);
After Download receives the data, it will write it directly to the disk asynchronously instead of splicing the HttpBody in the memory. Therefore, download only uses a small amount of memory to complete the download of very large files . It also supports breakpoint resume downloading by setting the offset parameter. to perform breakpoint downloads.
Asynchronous download of Saber wallpapers
$ download_dir = ' /tmp/saber.jpg ' ;
$ response = SaberGM:: download (
' https://ws1.sinaimg.cn/large/006DQdzWly1fsr8jt2botj31hc0wxqfs.jpg ' ,
$ download_dir
);
if ( $ response -> success ) {
exec ( ' open ' . $ download_dir );
}
In crawler projects, it is a very common requirement to automatically retry a failed request, such as logging in again after a session expires.
Saber
has this functionality built-in, and拦截器
can be used to enhance it.
If retry_time
is not set but a retry
interceptor is set, retry_time
will be set to 1. If the callback method of the retry
interceptor returns false
, no matter what retry_time
is, the retry will be terminated when false
is returned.
$ uri = ' http://eu.httpbin.org/basic-auth/foo/bar ' ;
$ res = SaberGM:: get (
$ uri , [
' exception_report ' => 0 ,
' retry_time ' => 3 ,
' retry ' => function ( Saber Request $ request ) {
echo " retry... n" ;
$ request -> withBasicAuth ( ' foo ' , ' bar ' ); //发现失败后添加验证信息
if ( ' i don not want to retry again ' ) {
return false ; // shutdown
}
}
]
);
echo $ res ;
Sometimes HTTP resources do not always change. We can learn how browsers cache resources that do not change to speed up request efficiency. Saber
automatically completes this without having to maintain caching logic (CURD or file reading and writing) by itself. Coroutines Scheduling ensures that it will not block the server anyway. Saber
does not use a middleware mechanism because it is strongly related to Swoole, but caching can use内存/文件/数据库
and other methods, so although it has not yet been implemented, it will Included in Saber
’s subsequent roadmap.
$ bufferStream = new BufferStream ();
$ bufferStream -> write ( json_encode ([ ' foo ' => ' bar ' ]));
$ response = SaberGM:: psr ()
-> withMethod ( ' POST ' )
-> withUri ( new Uri ( ' http://httpbin.org/post?foo=bar ' ))
-> withQueryParams ([ ' foo ' => ' option is higher-level than uri ' ])
-> withHeader ( ' content-type ' , ContentType:: JSON )
-> withBody ( $ bufferStream )
-> exec ()-> recv ();
echo $ response -> getBody ();
You can directly print the returned data string through the __toString method of the websocketFrame data frame.
$ websocket = SaberGM:: websocket ( ' ws://127.0.0.1:9999 ' );
while ( true ) {
echo $ websocket -> recv ( 1 ) . "n" ;
$ websocket -> push ( " hello " );
co:: sleep ( 1 );
}
The test machine is a MacBook Pro with the lowest configuration, and the request server is a local echo server.
Completed 6666 requests in 0.9 seconds , with a success rate of 100%.
co:: set ([ ' max_coroutine ' => 8191 ]);
go ( function () {
$ requests = [];
for ( $ i = 6666 ; $ i --;) {
$ requests [] = [ ' uri ' => ' http://127.0.0.1 ' ];
}
$ res = SaberGM:: requests ( $ requests );
echo " use { $ res -> time } s n" ;
echo " success: $ res -> success_num , error: $ res -> error_num " ;
});
// on MacOS
// use 0 . 91531705856323s
// success : 6666 , error : 0
In actual projects, URL lists are often used to configure requests, so the list method is provided for convenience:
echo SaberGM:: list ([
' uri ' => [
' https://www.qq.com/ ' ,
' https://www.baidu.com/ ' ,
' https://www.swoole.com/ ' ,
' http://httpbin.org/ '
]
]);
In actual crawler projects, we often have to limit the number of single concurrent requests to prevent being blocked by the server firewall, and a max_co
parameter can easily solve this problem. max_co
will push the requests into the queue in batches according to the upper limit and execute them. Receive package.
// max_co is the max number of concurrency request once , it ' s very useful to prevent server - waf limit .
$ requests = array_fill ( 0 , 10 , [ ' uri ' => ' https://www.qq.com/ ' ]);
echo SaberGM:: requests ( $ requests , [ ' max_co ' => 5 ])-> time . "n" ;
echo SaberGM:: requests ( $ requests , [ ' max_co ' => 1 ])-> time . "n" ;
When used in a memory-resident server, be sure to manually enable the connection pool option :
$ swoole = Saber:: create ([
' base_uri ' => ' https://www.swoole.com/ ' ,
' use_pool ' => true
]);
When used through this instance, the connection pool feature will be enabled, that is, the underlying connection client with the www.swoole.com
website will use a global connection pool to access, avoiding the overhead of creating/connecting each time it is used.
When the parameter is true
, the website's connection pool capacity is unlimited . Generally, there is no problem, and the connection pool with unlimited capacity has better performance.
But if you use it as a crawler proxy service and encounter a large number of requests , the number of clients in the connection pool will increase uncontrollably and rapidly, even exceeding the maximum number of connections allowed by the source website you requested. At this time, you need to use_pool
is set to an ideal value (int). At this time, the bottom layer will use Channel as the connection pool. When the number of clients created by the connection pool exceeds the number and is not enough, the coroutine that needs to access the client will be suspended. And wait for the coroutine that is using the client to return the client. There is almost no performance consumption in coroutine waiting and switching, and it is a very advanced solution.
It should be noted that the connection pool is bound to服务器IP+端口
, that is, if you have multiple instances facing the same服务器IP+端口
, the connection pool used between them is also the same.
So when you repeatedly create an instance of服务器IP+端口
, use_pool
specified by the newly created instance is allowed to overwrite the previous value, that is, the bottom layer of the connection pool automatically changes its capacity. When the capacity increases, the bottom layer will re-create a new connection pool and transfer customers. When the capacity is reduced, the excess clients in the connection pool will also be destroyed.
In addition to remembering to configure a connection pool, the method of exception handling also needs to be in line with your programming habits. Saber
's default exception handling is the most mainstream and rigorous抛出异常
, but Saber
also supports the silent use of错误码
and状态位
, may be more in line with many people's tastes.
SaberGM:: exceptionReport ( 0 ); // 关闭抛出异常报告, 在业务代码之前注册即可全局生效
$ saber -> exceptionReport ( 0 ); //也可以单独设置某个实例
In the same way, the configuration you want can be pre-configured before the business code, such as onWorkerStart
or even before swoole_server
is started.
SaberGM:: default ([
' exception_report ' => 0
' use_pool ' => true
]);
Configuring your desired options like this can give you a better experience!
go ( function (){
// your code with pool ...
saber_pool_release (); // and this script will exit
});
If you use a connection pool in a one-time script, since the coroutine client exists in the pool, the reference count is 1 and cannot be released, which will cause swoole to always be in the event loop and the script cannot exit. You need to manually call saber_pool_release
Or saber_exit
or swoole_event_exit
to exit normally, or you can use exit to force exit the current script (do not use exit in the server).
|
symbol separates multiple optional values
key | type | introduction | example | remark |
---|---|---|---|---|
protocol_version | string | HTTP protocol version | 1.1 | HTTP2 is still under planning |
base_uri | string | base path | http://httpbin.org | Will be merged with uri according to rfc3986 |
uri | string | resource identifier | http://httpbin.org/get | /get | get | Both absolute and relative paths can be used |
uri_query | string|array | request information | ['foo' => 'bar'] | Non-strings are automatically converted |
method | string | Request method | get | post | head | patch | put | delete | The bottom layer is automatically converted to uppercase |
headers | array | request header | ['DNT' => '1'] | ['accept' => ['text/html'], ['application/xml']] | Field names are not case-sensitive, but the original case rules during setting will be retained. Each underlying field value will be automatically divided into arrays according to PSR-7 |
cookies | array | string | ['foo '=> 'bar'] | 'foo=bar; foz=baz' | The bottom layer is automatically converted into a Cookies object, and its domain is set to the current URI, with complete attributes at the browser level. | |
useragent | string | user agent | curl-1.0 | The default is chrome on macos platform |
referer | string | Source address | https://www.google.com | Default is empty |
redirect | int | Maximum number of redirects | 5 | The default is 3, and when it is 0, there is no redirection. |
keep_alive | bool | Whether to keep connected | true | false | The default is true, the connection will be automatically reused during redirection |
content_type | string | Content encoding type sent | text/plain | SwlibHttpContentType::JSON | The default is application/x-www-form-urlencoded |
data | array | string | data sent | 'foo=bar&dog=cat' | ['foo' => 'bar'] | Data will be automatically encoded based on content_type |
before | callable | array | Pre-request interceptor | function(Request $request){} | Please refer to the Interceptor section for details. |
after | callable | array | Post-response interceptor | function(Response $response){} | Please refer to the Interceptor section for details. |
before_redirect | callable | array | Post-redirect interceptor | function(Request $request, Response $response){} | Please refer to the Interceptor section for details. |
timeout | float | timeout | 0.5 | Default is 5s, supports millisecond timeout |
bind_address | string | Bind address | 192.168.1.1 or eth0 | Not set by default |
bind_port | int | Bind port | 80 | Not set by default |
proxy | string | acting | http://127.0.0.1:1087 | socks5://127.0.0.1:1087 | Support http and socks5 |
ssl | int | Whether to enable ssl connection | 0=关闭 1=开启 2=自动 | Default automatic |
cafile | string | ca file | __DIR__ . '/cacert.pem' | Comes with default |
ssl_verify_peer | bool | Verify server-side certificate | false | true | Off by default |
ssl_allow_self_signed | bool | Allow self-signed certificates | true | false | Allowed by default |
ssl_cert_file | string | cert certificate | __DIR__ . '/ssl.cert' | Not set by default |
ssl_key_file | string | key private key | __DIR__ . '/ssl.key' | Not set by default |
iconv | array | Specify encoding conversion | ['gbk', 'utf-8'] | There are three parameters in total: from,to,use_mb , which are automatically recognized by default. |
exception_report | int | Exception reporting level | HttpExceptionMask::E_ALL | Report all exceptions by default |
exception_handle | callable|array | Exception custom handling function | function(Exception $e){} | Errors can be ignored when the function returns true |
retry | callable | Automatic retry interceptor | function(Request $request, Response $response){} | After an error occurs and before retrying |
retry_time | int | Number of automatic retries | Do not retry by default | |
use_pool | bool|int | connection pool | true | false |
pool_key | callable|array | Connection pool key | function(Request $request):string { return $key; } | The default is host:port of the requested address |
For ease of use and fault tolerance, the key values of configuration items have an alias mechanism. It is recommended to use the original name as much as possible:
key | alias |
---|---|
method | 0 |
uri | 1 | url |
data | 2 | body |
base_uri | base_url |
after | callback |
content_type | content-type | contentType |
cookies | cookies |
headers | header |
redirect | follow |
useragent | ua | user-agent |
exception_report | error_report | report |
before_retry | retry |
referer | ref | referrer |
The interceptor is a very powerful feature of Saber, which allows you to handle various things very conveniently, such as printing dev logs:
SaberGM:: get ( ' http://twosee.cn/ ' , [
' before ' => function ( Saber Request $ request ) {
$ uri = $ request -> getUri ();
echo " log: request $ uri now... n" ;
},
' after ' => function ( Saber Response $ response ) {
if ( $ response -> success ) {
echo " log: success! n" ;
} else {
echo " log: failed n" ;
}
echo " use { $ response -> time } s " ;
}
]);
// log : request http : // twosee . cn / now...
// log : success !
// use 0 . 52036285400391s
Even异常自定义处理函数
and会话
are implemented through interceptors.
There can be multiple interceptors, which will be executed in the order of registration, and you can name the interceptor . You only need to wrap it with an array and specify the key value. If you want to delete this interceptor, just overwrite it with a null value.
[
' after ' => [
' interceptor_new ' => function (){},
' interceptor_old ' => null
]
]
Interceptors can be registered in four ways (4 PHP callback functions):
callable: function (){}
string: ' function_name '
string: ' ClassName::method_name '
array: [ $ object , ' method_name ' ]
The implementation of Cookie is complete at the browser level . It specifically refers to the implementation of the Chrome browser and follows its relevant rules.
Cookies are a collection of cookies, and each cookie has the following properties:
name
, value
, expires
, path
, session
, secure
, httponly
, hostonly
And the Cookies class supports the conversion of multiple formats, such as
foo=bar; foz=baz; apple=banana
Set-Cookie: logged_in=no; domain=.github.com; path=/; expires=Tue, 06 Apr 2038 00:00:00 -0000; secure; HttpOnly
['foo'=>'bar', 'foz'=>'baz']
Wait for the format to be transferred to the Cookie class, or the Cookie class to be serialized into these formats.
Cookies also support domain name and time limit verification without losing any information. For example, if the domain is github.com
, the cookie will not appear in help.github.com
unless the domain is not hostonly ( .github.com
wildcard).
If it is a session-cookie (it has no expiration time and expires when the browser is closed), the expires attribute will be set to the current time, and you can set a specific time through the interceptor .
By reading the raw attribute of Cookies, it can be easily persisted to the database , which is very suitable for login crawler applications.
For more details, please refer to the Swlib/Http library documentation and examples.
Saber follows the rule of separating business from errors . When any part of the request fails, an exception will be thrown by default .
What's powerful is that Saber's exception handling is also diverse and as complete as PHP's native exception handling.
The exception namespace is located in SwlibHttpException
Exception | Intro | scene |
---|---|---|
RequestException | Request failed | Request configuration error |
ConnectException | Connection failed | If there is no network connection, DNS query fails, timeout, etc., the value of errno is equal to Linux errno. You can use swoole_strerror to convert error codes into error messages. |
TooManyRedirectsException | Number of redirects exceeded | The number of redirections exceeds the set limit, and the exception thrown will print redirect tracking information. |
ClientException | Client exception | The server returned a 4xx error code |
ServerException | Server exception | The server returned a 5xx error code |
BadResponseException | Unknown get response failed | The server did not respond or returned an unrecognized error code. |
In addition to the general exception methods, all HTTP exception classes also have the following methods:
Method | Intro |
---|---|
getRequest | Get request instance |
hasResponse | Whether to get a response |
getResponse | Get response instance |
getResponseBodySummary | Get the summary content of the response body |
try {
echo SaberGM:: get ( ' http://httpbin.org/redirect/10 ' );
} catch ( TooManyRedirectsException $ e ) {
var_dump ( $ e -> getCode ());
var_dump ( $ e -> getMessage ());
var_dump ( $ e -> hasResponse ());
echo $ e -> getRedirectsTrace ();
}
// int ( 302)
// string ( 28) "Too many redirects occurred ! "
// bool ( true )
#0 http : // httpbin . org / redirect/10
#1 http : // httpbin . org / relative - redirect/9
#2 http : // httpbin . org / relative - redirect/8
At the same time, Saber also supports handling exceptions in a gentle way, so as to prevent users from falling into panic in unstable network environments and having to wrap code with try at every step:
Set the errorReport level, which is globally effective and will not take effect on created instances .
// 启用所有异常但忽略重定向次数过多异常
SaberGM:: exceptionReport (
HttpExceptionMask:: E_ALL ^ HttpExceptionMask:: E_REDIRECT
);
The following values (numeric or symbolic) are used to create a bitmask that specifies the error message to be reported. You can use bitwise operators to combine these values or to mask certain types of errors. Flags and masks
Mask | Value | Intro |
---|---|---|
E_NONE | 0 | ignore all exceptions |
E_REQUEST | 1 | Corresponds to RequestException |
E_CONNECT | 2 | Corresponds to RequestException |
E_REDIRECT | 4 | Corresponds to RequestException |
E_BAD_RESPONSE | 8 | Corresponds to BadRException |
E_CLIENT | 16 | Corresponds to ClientException |
E_SERVER | 32 | Corresponds to ServerException |
E_ALL | 63 | All exceptions |
This function can handle errors generated in HTTP requests in your own way, and you can define the exceptions you want to catch/ignore more freely.
Note: Unless the function returns TRUE (or other true value), the exception will continue to be thrown instead of being caught by the custom function.
SaberGM:: exceptionHandle ( function ( Exception $ e ) {
echo get_class ( $ e ) . " is caught! " ;
return true ;
});
SaberGM:: get ( ' http://httpbin.org/redirect/10 ' );
//output : Swlib Http E xceptionTooManyRedirectsException is caught !
File Upload | WebSockets | AutoParser | AutoRetry | BigFile Download | Cache | ClientPool | RandomUA |
---|---|---|---|---|---|---|---|
4 (High-priority) | 3 | 2 | 1 | .5 | .5 | .5 | .175 |
As the main HTTP/2 benefit is that it allows multiplexing many requests within a single connection, thus [almost] removing the limit on number of simultaneous requests - and there is no such limit when talking to your own backends. Moreover, things may even become worse when using HTTP/2 to backends, due to single TCP connection being used instead of multiple ones, so Http2 Will not be a priority. (#ref)
Add the source files of this project to the IDE's Include Path
.
(If installed using composer, you can include the entire vendor folder, and PHPStorm will automatically include it)
Good comment writing makes Saber perfectly support IDE automatic prompts. Just write the arrow symbol after the object to view all object method names. The names are very easy to understand. A large number of methods follow the PSR specification or are implemented by referring to the Guzzle project (thanks) .
For IDE prompts on underlying Swoole-related classes, you need to introduce eaglewu's swoole-ide-helper (composer will be installed by default in the dev environment). However, this project is manually maintained and is not complete. You can also use swoft-ide-helper or:
Swoole's official ide-helper.
Welcome to submit issues and PRs.
Since coroutines (__call, __callStatic) cannot be used in magic methods, the methods in the source code are manually defined.
For ease of use, aliases have been provided for all supported request methods.
public static function psr( array $ options = []): Swlib Saber Request
public static function wait(): Swlib Saber
public static function request( array $ options = [])
public static function get (string $ uri , array $ options = [])
public static function delete (string $ uri , array $ options = [])
public static function head (string $ uri , array $ options = [])
public static function options (string $ uri , array $ options = [])
public static function post (string $ uri , $ data = null , array $ options = [])
public static function put (string $ uri , $ data = null , array $ options = [])
public static function patch (string $ uri , $ data = null , array $ options = [])
public static function download (string $ uri , string $ dir , int $ offset , array $ options = [])
public static function requests (array $ requests , array $ default_options = []): Swlib Saber ResponseMap
public static function list(array $ options , array $ default_options = []): Swlib Saber ResponseMap
public static function websocket (string $ uri )
public static function default (?array $ options = null ): array
public static function exceptionReport (?int $ level = null ): int
public static function exceptionHandle (callable $ handle ): void
public static function create( array $ options = []): self
public static function session( array $ options = []): self
public static function websocket( string $ uri ): WebSocket
public function request( array $ options )
public function get( string $ uri , array $ options = [])
public function delete( string $ uri , array $ options = [])
public function head( string $ uri , array $ options = [])
public function options( string $ uri , array $ options = [])
public function post( string $ uri , $ data = null , array $ options = [])
public function put( string $ uri , $ data = null , array $ options = [])
public function patch( string $ uri , $ data = null , array $ options = [])
public function download( string $ uri , string $ dir , int $ offset , array $ options = [])
public function requests( array $ requests , array $ default_options = []): ResponseMap
public function list( array $ options , array $ default_options = []): ResponseMap
public function upgrade(? string $ path = null ): WebSocket
public function psr( array $ options = []): Request
public function wait(): self
public function exceptionReport(? int $ level = null ): int
public function exceptionHandle( callable $ handle ): void
public static function getAliasMap(): array
public function setOptions( array $ options = [], ? Swlib Saber Request $ request = null ): self
public static function getDefaultOptions(): array
public static function setDefaultOptions( array $ options = [])
public function getExceptionReport(): int
public function setExceptionReport( int $ level ): self
public function isWaiting(): bool
public function getPool()
public function withPool( $ bool_or_max_size ): self
public function tryToRevertClientToPool( bool $ connect_failed = false )
public function getSSL(): int
public function withSSL( int $ mode = 2 ): self
public function getCAFile(): string
public function withCAFile( string $ ca_file = __DIR__ . ' /cacert.pem ' ): self
public function getSSLCertFile(): string
public function withSSLCertFile( string $ cert_file ): self
public function getSSLKeyFile(): string
public function withSSLKeyFile( string $ key_file ): self
public function withSSLVerifyPeer( bool $ verify_peer = false , ? string $ ssl_host_name = '' ): self
public function withSSLAllowSelfSigned( bool $ allow = true ): self
public function getSSLConf()
public function getKeepAlive()
public function withKeepAlive( bool $ enable ): self
public function withBasicAuth(? string $ username = null , ? string $ password = null ): self
public function withXHR( bool $ enable = true )
public function getProxy(): array
public function withProxy( string $ host , int $ port ): self
public function withSocks5( string $ host , int $ port , ? string $ username , ? string $ password ): self
public function withoutProxy(): self
public function getBindAddress(): ? string
public function withBindAddress( string $ address ): self
public function getBindPort(): ? int
public function withBindPort( int $ port ): self
public function getTimeout(): float
public function withTimeout( float $ timeout ): self
public function getRedirect(): int
public function getName()
public function withName( $ name ): self
public function withRedirect( int $ time ): self
public function isInQueue(): bool
public function withInQueue( bool $ enable ): self
public function getRetryTime(): int
public function withRetryTime( int $ time ): self
public function withAutoIconv( bool $ enable ): self
public function withExpectCharset( string $ source = ' auto ' , string $ target = ' utf-8 ' , bool $ use_mb = false ): self
public function withDownloadDir( string $ dir ): self
public function withDownloadOffset( int $ offset ): self
public function resetClient( $ client )
public function exec()
public function recv()
public function getRequestTarget(): string
public function withRequestTarget( $ requestTarget ): self
public function getMethod(): string
public function withMethod( $ method ): self
public function getUri(): Psr Http Message UriInterface
public function withUri(? Psr Http Message UriInterface $ uri , $ preserveHost = false ): self
public function getCookieParams(): array
public function getCookieParam( string $ name ): string
public function withCookieParam( string $ name , ? string $ value ): self
public function withCookieParams( array $ cookies ): self
public function getQueryParam( string $ name ): string
public function getQueryParams(): array
public function withQueryParam( string $ name , ? string $ value ): self
public function withQueryParams( array $ query ): self
public function getParsedBody(? string $ name = null )
public function withParsedBody( $ data ): self
public function getUploadedFile( string $ name ): Psr Http Message UploadedFileInterface
public function getUploadedFiles(): array
public function withUploadedFile( string $ name , ? Psr Http Message UploadedFileInterface $ uploadedFile ): self
public function withoutUploadedFile( string $ name ): self
public function withUploadedFiles( array $ uploadedFiles ): self
public function __toString()
public function getProtocolVersion(): string
public function withProtocolVersion( $ version ): self
public function hasHeader( $ name ): bool
public function getHeader( $ name ): array
public function getHeaderLine( $ name ): string
public function getHeaders( bool $ implode = false , bool $ ucwords = false ): array
public function getHeadersString( bool $ ucwords = true ): string
public function withHeader( $ raw_name , $ value ): self
public function withHeaders( array $ headers ): self
public function withAddedHeaders( array $ headers ): self
public function withAddedHeader( $ raw_name , $ value ): self
public function withoutHeader( $ name ): self
public function getBody(): Psr Http Message StreamInterface
public function withBody(? Psr Http Message StreamInterface $ body ): self
public function getCookies()
public function setCookie( array $ options ): self
public function unsetCookie( string $ name , string $ path = '' , string $ domain = '' ): self
public function withInterceptor( string $ name , array $ interceptor )
public function withAddedInterceptor( string $ name , array $ functions ): self
public function withoutInterceptor( string $ name ): self
public function callInterceptor( string $ name , $ arguments )
public function getSpecialMark( string $ name = ' default ' )
public function withSpecialMark( $ mark , string $ name = ' default ' ): self
public function isSuccess(): bool
public function getUri(): Psr Http Message UriInterface
public function getTime(): float
public function getRedirectHeaders(): array
public function getStatusCode()
public function withStatus( $ code , $ reasonPhrase = '' )
public function getReasonPhrase()
public function __toString()
public function getProtocolVersion(): string
public function withProtocolVersion( $ version ): self
public function hasHeader( $ name ): bool
public function getHeader( $ name ): array
public function getHeaderLine( $ name ): string
public function getHeaders( bool $ implode = false , bool $ ucwords = false ): array
public function getHeadersString( bool $ ucwords = true ): string
public function withHeader( $ raw_name , $ value ): self
public function withHeaders( array $ headers ): self
public function withAddedHeaders( array $ headers ): self
public function withAddedHeader( $ raw_name , $ value ): self
public function withoutHeader( $ name ): self
public function getBody(): Psr Http Message StreamInterface
public function withBody(? Psr Http Message StreamInterface $ body ): self
public function getCookies()
public function setCookie( array $ options ): self
public function unsetCookie( string $ name , string $ path = '' , string $ domain = '' ): self
public function getSpecialMark( string $ name = ' default ' )
public function withSpecialMark( $ mark , string $ name = ' default ' ): self
public function getParsedJsonArray( bool $ reParse = false ): array
public function getParsedJsonObject( bool $ reParse = false ): object
public function getParsedQueryArray( bool $ reParse = false ): array
public function getParsedXmlArray( bool $ reParse = false ): array
public function getParsedXmlObject( bool $ reParse = false ): SimpleXMLElement
public function getParsedDomObject( bool $ reParse = false ): DOMDocument
public function getDataRegexMatch( string $ regex , $ group = null , int $ fill_size )
public function getDataRegexMatches( string $ regex , int $ flag ): array
public function isExistInData( string $ needle , int $ offset )
public function enqueue( $ request )
public function getMaxConcurrency(): int
public function withMaxConcurrency( int $ num = - 1 ): self
public function recv(): Swlib Saber ResponseMap
public function withInterceptor( string $ name , array $ interceptor )
public function withAddedInterceptor( string $ name , array $ functions ): self
public function withoutInterceptor( string $ name ): self
public function callInterceptor( string $ name , $ arguments )
public $ time = 0.0 ;
public $ status_map = [];
public $ success_map = [];
public $ success_num = 0 ;
public $ error_num = 0 ;
public function offsetSet( $ index , $ response )
public function __toString()
public function withMock( bool $ ssl ): self
public function recv( float $ timeout = - 1 )
public function push( string $ data , int $ opcode = 1 , bool $ finish = true ): bool
public function close(): bool
public $ finish = true ;
public $ opcode = null ;
public $ data = null ;
public function getOpcodeDefinition()
public function getOpcode()
public function getData()
public function __toString()