HTTP Sabre (Da Mao Wang), ein PHP-Hochleistungs-HTTP-Client der Swoole人性化组件库
, basiert auf der nativen Coroutine von Swoole, unterstützt mehrere Operationsstile und bietet im Grunde leistungsstarke Lösungen, sodass sich Entwickler auf die Funktionalität konzentrieren können Entwicklung, von traditionell frei von der synchronen Blockierung und umständlichen Konfiguration von Curl.
Englisches Dokument
Die Installation erfolgt am besten über den Composer-Paketmanager:
composer require swlib/saber
Die unterste Schicht von Swoole implementiert die Coroutine-Planung, und die Geschäftsschicht muss sich dessen nicht bewusst sein . Entwickler können synchrones Codeschreiben verwenden, um den Effekt von asynchroner E/A und ultrahoher Leistung zu erzielen, ohne sich dessen bewusst zu sein, wodurch die diskrete Codelogik vermieden wird Übermäßiges Trapping, das durch herkömmliche asynchrone Rückrufe verursacht wird, führt dazu, dass der Code nicht wartbar ist.
Es muss in onRequet
, onReceive
, onConnect
und anderen Ereignisrückruffunktionen verwendet oder mit dem Schlüsselwort go umschlossen werden ( swoole.use_shortname
ist standardmäßig aktiviert).
go ( function () {
echo SaberGM:: get ( ' http://httpbin.org/get ' );
})
Automatische Datenverpackung: Eingehende Daten werden automatisch in das durch den Inhaltstyp angegebene Typformat konvertiert
Der Standardwert ist
x-www-form-urlencoded
und andere Formate wiejson
werden ebenfalls unterstützt.
SaberGM
:= Saber Global Manager
. Wenn Sie der Meinung sind, dass der Klassenname etwas lang ist, können Sie class_alias
selbst einen Alias auswählen. Es wird empfohlen, die Methode zum Generieren von Instanzen im Dienst zu verwenden und SaberGM
als Abkürzung zu verwenden.
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 ' ]);
Anwendbarer API-Proxy-Dienst
$ 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 ' ]);
Die Sitzung speichert automatisch Cookie-Informationen und ihre Implementierung ist auf Browserebene abgeschlossen.
$ 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 ;
Hinweis: Hier wird eine Lösung zur gleichzeitigen Weiterleitungsoptimierung verwendet, die immer gleichzeitig erfolgt und nicht zu einer einzigen Anfrage in der Warteschlange degeneriert.
$ 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 ' ]
]);
Unterstützt derzeit das schnelle Parsen von Daten in vier Formaten: json
, xml
, html
und 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 );
Unterstützt HTTP- und SOCKS5-Proxys
$ 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 ;
Die zugrunde liegende automatische Coroutine-Planung kann das asynchrone Senden sehr großer Dateien und die Übertragung von Breakpoint-Fortsetzungen unterstützen.
Laden Sie drei Dateien gleichzeitig hoch (drei Parameterstile
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
]
]
);
Nachdem Download die Daten empfangen hat, werden diese direkt asynchron auf die Festplatte geschrieben , anstatt den HttpBody im Speicher zu spleißen. Daher benötigt Download nur wenig Speicher, um den Download sehr großer Dateien abzuschließen Festlegen des Offset-Parameters zum Durchführen von Haltepunkt-Downloads.
Asynchroner Download von Sabre-Hintergrundbildern
$ 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-Projekten ist es eine sehr häufige Anforderung, eine fehlgeschlagene Anfrage automatisch erneut zu versuchen, beispielsweise eine erneute Anmeldung nach Ablauf einer Sitzung.
Saber
verfügt über diese integrierte Funktionalität und拦截器
können verwendet werden, um sie zu verbessern.
Wenn retry_time
nicht festgelegt ist, aber ein retry
festgelegt ist, wird retry_time
auf 1 gesetzt. Wenn die Rückrufmethode des retry
false
zurückgibt, wird der Wiederholungsversuch unabhängig von retry_time
beendet, wenn false
zurückgegeben wird.
$ 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 ;
Manchmal ändern sich HTTP-Ressourcen nicht immer, um die Anforderungseffizienz zu beschleunigen, ohne dass die Saber
-Planung dies selbst aufrechterhalten muss Der Server wird ohnehin nicht blockiert, da Saber
stark mit Swoole verwandt ist. Beim Caching können jedoch内存/文件/数据库
und andere Methoden verwendet werden. Obwohl dies noch nicht implementiert ist, wird es in Saber
enthalten sein Die weitere 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 ();
Sie können die zurückgegebene Datenzeichenfolge direkt über die __toString-Methode des websocketFrame-Datenrahmens drucken.
$ websocket = SaberGM:: websocket ( ' ws://127.0.0.1:9999 ' );
while ( true ) {
echo $ websocket -> recv ( 1 ) . "n" ;
$ websocket -> push ( " hello " );
co:: sleep ( 1 );
}
Die Testmaschine ist ein MacBook Pro mit der niedrigsten Konfiguration und der Anforderungsserver ist ein lokaler Echoserver.
6666 Anfragen wurden in 0,9 Sekunden abgeschlossen , mit einer Erfolgsquote von 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 tatsächlichen Projekten werden URL-Listen häufig zum Konfigurieren von Anforderungen verwendet. Daher wird der Einfachheit halber die Listenmethode bereitgestellt:
echo SaberGM:: list ([
' uri ' => [
' https://www.qq.com/ ' ,
' https://www.baidu.com/ ' ,
' https://www.swoole.com/ ' ,
' http://httpbin.org/ '
]
]);
In echten Crawler-Projekten müssen wir oft die Anzahl einzelner gleichzeitiger Anfragen begrenzen, um zu verhindern, dass sie von der Server-Firewall blockiert werden. Ein max_co
-Parameter kann dieses Problem leicht lösen, indem max_co
die Anfragen entsprechend der Obergrenze stapelweise in die Warteschlange schiebt und führen Sie sie aus.
// 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" ;
Stellen Sie bei Verwendung auf einem speicherresidenten Server sicher, dass Sie die Verbindungspooloption manuell aktivieren :
$ swoole = Saber:: create ([
' base_uri ' => ' https://www.swoole.com/ ' ,
' use_pool ' => true
]);
Bei Verwendung über diese Instanz wird die Verbindungspoolfunktion aktiviert, d. h. der zugrunde liegende Verbindungsclient mit der Website www.swoole.com
verwendet für den Zugriff einen globalen Verbindungspool, wodurch der Aufwand für die Erstellung/Verbindung bei jeder Verwendung vermieden wird .
Wenn der Parameter true
ist, ist die Kapazität des Verbindungspools der Website unbegrenzt . Im Allgemeinen gibt es kein Problem und der Verbindungspool mit unbegrenzter Kapazität weist eine bessere Leistung auf.
Wenn Sie es jedoch als Crawler-Proxy-Dienst verwenden und auf eine große Anzahl von Anfragen stoßen, steigt die Anzahl der Clients im Verbindungspool unkontrolliert und schnell an und übersteigt sogar die maximal zulässige Anzahl von Verbindungen, die die von Ihnen angeforderte Quellwebsite zu diesem Zeitpunkt zulässt , Sie müssen use_pool
auf einen idealen Wert (int) einstellen. Zu diesem Zeitpunkt verwendet die unterste Ebene den Kanal als Verbindungspool der auf den Client zugreifen muss, wird gesperrt. Und warten Sie, bis die Coroutine, die den Client verwendet, den Client zurückgibt. Beim Warten und Wechseln der Coroutine entsteht fast kein Leistungsverbrauch, und es handelt sich um eine sehr fortschrittliche Lösung.
Es ist zu beachten, dass der Verbindungspool an服务器IP+端口
gebunden ist, d. h. wenn Sie mehrere Instanzen haben, die auf dieselbe服务器IP+端口
zugreifen, ist auch der zwischen ihnen verwendete Verbindungspool derselbe.
Wenn Sie also wiederholt eine Instanz von服务器IP+端口
erstellen, darf use_pool
den vorherigen Wert überschreiben, d. h. die unterste Ebene des Verbindungspools ändert automatisch ihre Kapazität Die unterste Ebene erstellt einen neuen Verbindungspool und überträgt Kunden. Wenn die Kapazität verringert wird, werden auch die überschüssigen Clients im Verbindungspool zerstört.
Denken Sie nicht nur daran, einen Verbindungspool zu konfigurieren, sondern müssen auch Ihre Programmiergewohnheiten berücksichtigen. Die standardmäßige Ausnahmebehandlung von Saber
ist die gängigste und strengste抛出异常
, aber Saber
unterstützt auch die stille Verwendung von错误码
und状态位
entsprechen möglicherweise eher dem Geschmack vieler Menschen.
SaberGM:: exceptionReport ( 0 ); // 关闭抛出异常报告, 在业务代码之前注册即可全局生效
$ saber -> exceptionReport ( 0 ); //也可以单独设置某个实例
Auf die gleiche Weise kann die gewünschte Konfiguration vor dem Geschäftscode vorkonfiguriert werden, z. B. onWorkerStart
oder sogar vor dem Start von swoole_server
.
SaberGM:: default ([
' exception_report ' => 0
' use_pool ' => true
]);
Wenn Sie Ihre gewünschten Optionen auf diese Weise konfigurieren, können Sie ein besseres Erlebnis erzielen!
go ( function (){
// your code with pool ...
saber_pool_release (); // and this script will exit
});
Wenn Sie einen Verbindungspool in einem einmaligen Skript verwenden, beträgt der Referenzzähler 1 und kann nicht freigegeben werden, da der Coroutine-Client im Pool vorhanden ist. Dies führt dazu, dass sich Swoole immer in der Ereignisschleife befindet und das Skript nicht beendet werden kann Sie müssen saber_pool_release
oder saber_exit
oder swoole_event_exit
manuell aufrufen, um normal zu beenden, oder Sie können Exit verwenden, um das Beenden des aktuellen Skripts zu erzwingen (verwenden Sie Exit nicht auf dem Server).
Das Symbol
|
trennt mehrere optionale Werte
Schlüssel | Typ | Einführung | Beispiel | Bemerkung |
---|---|---|---|---|
Protokollversion | Zeichenfolge | HTTP-Protokollversion | 1.1 | HTTP2 ist noch in Planung |
base_uri | Zeichenfolge | Basispfad | http://httpbin.org | Wird gemäß rfc3986 mit uri zusammengeführt |
uri | Zeichenfolge | Ressourcenkennung | http://httpbin.org/get |. get /get | | Es können sowohl absolute als auch relative Pfade verwendet werden |
uri_query | string|array | Informationen anfordern | ['foo' => 'bar'] | Nicht-Strings werden automatisch konvertiert |
Verfahren | Zeichenfolge | Anfragemethode | get |. post delete head patch put | Die unterste Ebene wird automatisch in Großbuchstaben umgewandelt |
Kopfzeilen | Array | Anforderungsheader | ['DNT' => '1'] |. ['accept' => ['text/html'], ['application/xml']] | Bei Feldnamen wird die Groß-/Kleinschreibung nicht beachtet, aber die ursprünglichen Groß-/Kleinschreibungsregeln bleiben beim Festlegen erhalten. Jeder zugrunde liegende Feldwert wird gemäß PSR-7 automatisch in Arrays unterteilt |
Kekse | array |. string | ['foo '=> 'bar'] |. 'foo=bar; foz=baz' | Die unterste Ebene wird automatisch in ein Cookies-Objekt umgewandelt und ihre Domäne wird auf den aktuellen URI mit vollständigen Attributen auf Browserebene festgelegt. | |
Benutzeragent | Zeichenfolge | Benutzeragent | curl-1.0 | Der Standardwert ist Chrome auf der macOS-Plattform |
Referent | Zeichenfolge | Quelladresse | https://www.google.com | Der Standardwert ist leer |
umleiten | int | Maximale Anzahl an Weiterleitungen | 5 | Der Standardwert ist 3, und wenn er 0 ist, erfolgt keine Umleitung. |
keep_alive | bool | Ob Sie in Verbindung bleiben möchten | true |. false | Der Standardwert ist wahr, die Verbindung wird während der Umleitung automatisch wiederverwendet |
Inhaltstyp | Zeichenfolge | Der gesendete Inhaltskodierungstyp | text/plain |. SwlibHttpContentType::JSON | Der Standardwert ist application/x-www-form-urlencoded |
Daten | array |. string | Daten gesendet | 'foo=bar&dog=cat' |. ['foo' => 'bar'] | Die Daten werden automatisch basierend auf content_type codiert |
vor | callable |. array | Abfangjäger vorab anfordern | function(Request $request){} | Weitere Informationen finden Sie im Abschnitt „Interceptor“. |
nach | callable |. array | Post-Response-Abfangjäger | function(Response $response){} | Weitere Informationen finden Sie im Abschnitt „Interceptor“. |
before_redirect | callable |. array | Post-Redirect-Abfangjäger | function(Request $request, Response $response){} | Weitere Informationen finden Sie im Abschnitt „Interceptor“. |
Time-out | schweben | Time-out | 0,5 | Der Standardwert ist 5 Sekunden, unterstützt Millisekunden-Timeout |
bind_address | Zeichenfolge | Adresse binden | 192.168.1.1 oder eth0 | Nicht standardmäßig festgelegt |
bind_port | int | Bind-Port | 80 | Nicht standardmäßig festgelegt |
Proxy | Zeichenfolge | Schauspiel | http://127.0.0.1:1087 |. socks5://127.0.0.1:1087 | Unterstützen Sie http und sock5 |
SSL | int | Ob die SSL-Verbindung aktiviert werden soll | 0=关闭 1=开启 2=自动 | Standardmäßig automatisch |
cafile | Zeichenfolge | ca-Datei | __DIR__ . '/cacert.pem' | Wird standardmäßig geliefert |
ssl_verify_peer | bool | Überprüfen Sie das serverseitige Zertifikat | false |. true | Standardmäßig deaktiviert |
ssl_allow_self_signed | bool | Selbstsignierte Zertifikate zulassen | true |. false | Standardmäßig zulässig |
ssl_cert_file | Zeichenfolge | Zertifikat | __DIR__ . '/ssl.cert' | Nicht standardmäßig festgelegt |
ssl_key_file | Zeichenfolge | Schlüssel privater Schlüssel | __DIR__ . '/ssl.key' | Nicht standardmäßig festgelegt |
iconv | Array | Geben Sie die Kodierungskonvertierung an | ['gbk', 'utf-8'] | Insgesamt gibt es drei Parameter: from,to,use_mb , die standardmäßig automatisch erkannt werden. |
Ausnahmebericht | int | Ausnahmeberichtsebene | HttpExceptionMask::E_ALL | Melden Sie standardmäßig alle Ausnahmen |
Ausnahme_Handle | aufrufbar|Array | Benutzerdefinierte Ausnahmebehandlungsfunktion | function(Exception $e){} | Fehler können ignoriert werden, wenn die Funktion „true“ zurückgibt |
wiederholen | abrufbar | Automatischer Wiederholungsabfangjäger | function(Request $request, Response $response){} | Nachdem ein Fehler aufgetreten ist und bevor es erneut versucht wird |
retry_time | int | Automatische Wiederholungsversuche | Versuchen Sie es standardmäßig nicht erneut | |
use_pool | bool|int | Verbindungspool | true | false |
pool_key | aufrufbar|Array | Verbindungspoolschlüssel | function(Request $request):string { return $key; } | Der Standardwert ist host:port der angeforderten Adresse |
Aus Gründen der Benutzerfreundlichkeit und Fehlertoleranz verfügen die Schlüsselwerte von Konfigurationselementen über einen Alias-Mechanismus. Es wird empfohlen, so oft wie möglich den Originalnamen zu verwenden:
Schlüssel | alias |
---|---|
Verfahren | 0 |
uri | 1 |. url |
Daten | 2 |. body |
base_uri | base_url |
nach | Rückruf |
Inhaltstyp | content-type |. contentType |
Kekse | Kekse |
Kopfzeilen | Kopfzeile |
umleiten | folgen |
Benutzeragent | ua | user-agent |
Ausnahmebericht | error_report |. report |
before_retry | wiederholen |
Referent | ref |. referrer |
Der Interceptor ist eine sehr leistungsstarke Funktion von Sabre, mit der Sie verschiedene Dinge sehr bequem erledigen können, beispielsweise das Drucken von Entwicklungsprotokollen:
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
Sogar benutzerdefinierte Funktionen und会话
异常自定义处理函数
werden durch Interceptors implementiert.
Es kann mehrere Interceptoren geben, die in der Reihenfolge der Registrierung ausgeführt werden, und Sie können den Interceptor benennen . Sie müssen ihn nur mit einem Array umschließen und den Schlüsselwert angeben. Wenn Sie diesen Interceptor löschen möchten, überschreiben Sie ihn einfach ein Nullwert.
[
' after ' => [
' interceptor_new ' => function (){},
' interceptor_old ' => null
]
]
Interceptoren können auf vier Arten registriert werden (4 PHP-Callback-Funktionen):
callable: function (){}
string: ' function_name '
string: ' ClassName::method_name '
array: [ $ object , ' method_name ' ]
Die Implementierung von Cookies erfolgt auf Browserebene . Sie bezieht sich speziell auf die Implementierung des Chrome-Browsers und folgt dessen relevanten Regeln.
Cookies sind eine Sammlung von Cookies und jedes Cookie hat die folgenden Eigenschaften:
name
, value
, expires
, path
, session
, secure
, httponly
, hostonly
Und die Cookies-Klasse unterstützt die Konvertierung mehrerer Formate, z
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']
Warten Sie, bis das Format an die Cookie-Klasse übertragen wurde oder die Cookie-Klasse in diese Formate serialisiert wurde.
Cookies unterstützen auch die Überprüfung des Domänennamens und des Zeitlimits, ohne dass Informationen verloren gehen. Wenn die Domäne beispielsweise github.com
lautet, wird das Cookie nicht in help.github.com
angezeigt, es sei denn, die Domäne ist nicht hostonly (Platzhalter .github.com
).
Wenn es sich um ein Sitzungscookie handelt (es hat keine Ablaufzeit und läuft ab, wenn der Browser geschlossen wird), wird das Expires-Attribut auf die aktuelle Zeit gesetzt, und Sie können über den Interceptor eine bestimmte Zeit festlegen.
Durch das Lesen der Rohattribute von Cookies können diese problemlos in der Datenbank gespeichert werden, was sich sehr gut für Login-Crawler-Anwendungen eignet.
Weitere Einzelheiten finden Sie in der Dokumentation und den Beispielen der Swlib/Http-Bibliothek.
Sabre folgt der Regel, Geschäft und Fehler zu trennen. Wenn ein Teil der Anfrage fehlschlägt, wird standardmäßig eine Ausnahme ausgelöst .
Das Mächtige ist, dass die Ausnahmebehandlung von Sabre ebenso vielfältig und ebenso vollständig ist wie die native Ausnahmebehandlung von PHP.
Der Ausnahme-Namespace befindet sich in SwlibHttpException
Ausnahme | Einführung | Szene |
---|---|---|
RequestException | Die Anfrage ist fehlgeschlagen | Fehler bei der Anforderungskonfiguration |
ConnectException | Verbindung fehlgeschlagen | Wenn keine Netzwerkverbindung besteht, die DNS-Abfrage fehlschlägt, eine Zeitüberschreitung auftritt usw., entspricht der Wert von errno dem Wert von Linux errno. Mit swoole_strerror können Sie Fehlercodes in Fehlermeldungen umwandeln. |
TooManyRedirectsException | Anzahl der Weiterleitungen überschritten | Die Anzahl der Weiterleitungen überschreitet das festgelegte Limit und die ausgelöste Ausnahme gibt Informationen zur Umleitungsverfolgung aus. |
ClientException | Client-Ausnahme | Der Server hat einen 4xx-Fehlercode zurückgegeben |
ServerException | Serverausnahme | Der Server hat einen 5xx-Fehlercode zurückgegeben |
BadResponseException | Unbekannte Get-Antwort fehlgeschlagen | Der Server hat nicht geantwortet oder einen unbekannten Fehlercode zurückgegeben. |
Zusätzlich zu den allgemeinen Ausnahmemethoden verfügen alle HTTP-Ausnahmeklassen auch über die folgenden Methoden:
Verfahren | Einführung |
---|---|
getRequest | Anforderungsinstanz abrufen |
hasResponse | Ob Sie eine Antwort erhalten möchten |
getResponse | Antwortinstanz abrufen |
getResponseBodySummary | Rufen Sie den zusammenfassenden Inhalt des Antworttexts ab |
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
Gleichzeitig unterstützt Sabre auch den sanften Umgang mit Ausnahmen, um zu verhindern, dass Benutzer in instabilen Netzwerkumgebungen in Panik geraten und den Code bei jedem Schritt mit try umbrechen müssen:
Legen Sie die Fehlerberichtsebene fest, die global wirksam ist und keine Auswirkungen auf erstellte Instanzen hat .
// 启用所有异常但忽略重定向次数过多异常
SaberGM:: exceptionReport (
HttpExceptionMask:: E_ALL ^ HttpExceptionMask:: E_REDIRECT
);
Die folgenden Werte (numerisch oder symbolisch) werden verwendet, um eine Bitmaske zu erstellen, die die zu meldende Fehlermeldung angibt. Sie können bitweise Operatoren verwenden, um diese Werte zu kombinieren oder bestimmte Fehlertypen zu maskieren. Fahnen und Masken
Maske | Wert | Einführung |
---|---|---|
E_NONE | 0 | Ignorieren Sie alle Ausnahmen |
E_REQUEST | 1 | Entspricht RequestException |
E_CONNECT | 2 | Entspricht RequestException |
E_REDIRECT | 4 | Entspricht RequestException |
E_BAD_RESPONSE | 8 | Entspricht BadRException |
E_CLIENT | 16 | Entspricht ClientException |
E_SERVER | 32 | Entspricht ServerException |
E_ALL | 63 | Alle Ausnahmen |
Diese Funktion kann Fehler, die in HTTP-Anfragen generiert werden, auf Ihre eigene Weise behandeln und Sie können die Ausnahmen, die Sie abfangen/ignorieren möchten, freier definieren.
Hinweis: Sofern die Funktion nicht TRUE (oder einen anderen wahren Wert) zurückgibt, wird die Ausnahme weiterhin ausgelöst und nicht von der benutzerdefinierten Funktion abgefangen.
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 !
Datei-Upload | WebSockets | AutoParser | AutoRetry | BigFile-Download | Cache | ClientPool | RandomUA |
---|---|---|---|---|---|---|---|
4 (Hohe Priorität) | 3 | 2 | 1 | .5 | .5 | .5 | .175 |
Der Hauptvorteil von HTTP/2 besteht darin, dass es das Multiplexen vieler Anfragen innerhalb einer einzigen Verbindung ermöglicht, wodurch die Beschränkung der Anzahl gleichzeitiger Anfragen [fast] aufgehoben wird – und bei der Kommunikation mit Ihren eigenen Backends gibt es keine solche Beschränkung wird schlimmer, wenn HTTP/2 für Backends verwendet wird, da eine einzelne TCP-Verbindung anstelle mehrerer verwendet wird, sodass Http2 keine Priorität hat (#ref).
Fügen Sie die Quelldateien dieses Projekts zum Include Path
der IDE hinzu.
(Bei der Installation mit Composer können Sie den gesamten Herstellerordner einschließen, und PHPStorm fügt ihn automatisch ein.)
Durch das gute Schreiben von Kommentaren unterstützt Sabre die automatischen IDE-Eingabeaufforderungen einfach, um alle Objektmethodennamen anzuzeigen. Eine große Anzahl von Methoden folgt der PSR- Spezifikation oder wird durch Verweis darauf implementiert Guzzle-Projekt (danke) .
Für IDE-Eingabeaufforderungen zu zugrunde liegenden Swoole-bezogenen Klassen müssen Sie den Swoole-Helper von eaglewu einführen (Composer wird standardmäßig in der Entwicklungsumgebung installiert). Dieses Projekt wird jedoch manuell verwaltet und ist nicht vollständig -ide-helper oder:
Swooles offizieller Ideengeber.
Willkommen zum Einreichen von Problemen und PRs.
Da Coroutinen (__call, __callStatic) nicht in magischen Methoden verwendet werden können, werden die Methoden im Quellcode manuell definiert.
Zur Vereinfachung der Verwendung wurden für alle unterstützten Anforderungsmethoden Aliase bereitgestellt.
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()