diff options
author | Bill Pirkle <bpirkle@wikimedia.org> | 2019-01-02 16:16:44 -0600 |
---|---|---|
committer | Krinkle <krinklemail@gmail.com> | 2019-01-24 22:05:10 +0000 |
commit | e8cb9f5f83534dac16bedb8a3af6cdf0f0fd617f (patch) | |
tree | de3a59a8027d8c5586f1f45b2a6bca5b32976ce4 /includes/http/GuzzleHttpRequest.php | |
parent | cd0860616a21ac611f4a78e686a6871d80542aec (diff) | |
download | mediawikicore-e8cb9f5f83534dac16bedb8a3af6cdf0f0fd617f.tar.gz mediawikicore-e8cb9f5f83534dac16bedb8a3af6cdf0f0fd617f.zip |
http: Support callback functions in GuzzleHttpRequest
Provide backward compatibility for callback functions in
GuzzleHttpRequest, which was missing in T202110, and restore
GuzzleHttpRequest as the default provided by HttpRequestFactory.
Bug: T212175
Depends-On: I4b45e79d35252d13f714f3271b87301ca515121a
Change-Id: I60d1a034b44874f6d24a04058db264eeb565f5e1
Diffstat (limited to 'includes/http/GuzzleHttpRequest.php')
-rw-r--r-- | includes/http/GuzzleHttpRequest.php | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/includes/http/GuzzleHttpRequest.php b/includes/http/GuzzleHttpRequest.php index db8a09b97094..ef7046724fbf 100644 --- a/includes/http/GuzzleHttpRequest.php +++ b/includes/http/GuzzleHttpRequest.php @@ -25,8 +25,10 @@ use GuzzleHttp\Psr7\Request; * MWHttpRequest implemented using the Guzzle library * * Differences from the CurlHttpRequest implementation: - * 1) the MWHttpRequest 'callback" option is unsupported. Instead, use the 'sink' option to - * send a filename/stream (see http://docs.guzzlephp.org/en/stable/request-options.html#sink) + * 1) a new 'sink' option is available as an alternative to callbacks. See: + * http://docs.guzzlephp.org/en/stable/request-options.html#sink) + * The 'callback' option remains available as well. If both 'sink' and 'callback' are + * specified, 'sink' is used. * 2) callers may set a custom handler via the 'handler' option. * If this is not set, Guzzle will use curl (if available) or PHP streams (otherwise) * 3) setting either sslVerifyHost or sslVerifyCert will enable both. Guzzle does not allow @@ -49,7 +51,7 @@ class GuzzleHttpRequest extends MWHttpRequest { * @throws Exception */ public function __construct( - $url, array $options = [], $caller = __METHOD__, $profiler = null + $url, array $options = [], $caller = __METHOD__, Profiler $profiler = null ) { parent::__construct( $url, $options, $caller, $profiler ); @@ -62,6 +64,48 @@ class GuzzleHttpRequest extends MWHttpRequest { } /** + * Set a read callback to accept data read from the HTTP request. + * By default, data is appended to an internal buffer which can be + * retrieved through $req->getContent(). + * + * To handle data as it comes in -- especially for large files that + * would not fit in memory -- you can instead set your own callback, + * in the form function($resource, $buffer) where the first parameter + * is the low-level resource being read (implementation specific), + * and the second parameter is the data buffer. + * + * You MUST return the number of bytes handled in the buffer; if fewer + * bytes are reported handled than were passed to you, the HTTP fetch + * will be aborted. + * + * This function overrides any 'sink' or 'callback' constructor option. + * + * @param callable|null $callback + * @throws InvalidArgumentException + */ + public function setCallback( $callback ) { + $this->sink = null; + $this->doSetCallback( $callback ); + } + + /** + * Worker function for setting callbacks. Calls can originate both internally and externally + * via setCallback). Defaults to the internal read callback if $callback is null. + * + * If a sink is already specified, this does nothing. This causes the 'sink' constructor + * option to override the 'callback' constructor option. + * + * @param $callback|null $callback + * @throws InvalidArgumentException + */ + protected function doSetCallback( $callback ) { + if ( !$this->sink ) { + parent::doSetCallback( $callback ); + $this->sink = new MWCallbackStream( $this->callback ); + } + } + + /** * @see MWHttpRequest::execute * * @return Status @@ -124,11 +168,9 @@ class GuzzleHttpRequest extends MWHttpRequest { $request = new Request( $this->method, $this->url ); $response = $client->send( $request ); $this->headerList = $response->getHeaders(); - $this->content = $response->getBody()->getContents(); $this->respVersion = $response->getProtocolVersion(); $this->respStatus = $response->getStatusCode() . ' ' . $response->getReasonPhrase(); - } catch ( GuzzleHttp\Exception\ConnectException $e ) { // ConnectException is thrown for several reasons besides generic "timeout": // Connection refused @@ -179,6 +221,11 @@ class GuzzleHttpRequest extends MWHttpRequest { return Status::wrap( $this->status ); // TODO B/C; move this to callers } + protected function prepare() { + $this->doSetCallback( $this->callback ); + parent::prepare(); + } + /** * @return bool */ @@ -189,7 +236,7 @@ class GuzzleHttpRequest extends MWHttpRequest { /** * Guzzle provides headers as an array. Reprocess to match our expectations. Guzzle will - * have already parsed and removed the status line (in EasyHandle::createResponse)z. + * have already parsed and removed the status line (in EasyHandle::createResponse). */ protected function parseHeader() { // Failure without (valid) headers gets a response status of zero |