Mimic CURLOPT_POST in GuzzleHttpRequest
[lhc/web/wiklou.git] / tests / phpunit / includes / http / GuzzleHttpRequestTest.php
1 <?php
2
3 use GuzzleHttp\Handler\MockHandler;
4 use GuzzleHttp\HandlerStack;
5 use GuzzleHttp\Middleware;
6 use GuzzleHttp\Psr7\Response;
7 use GuzzleHttp\Psr7\Request;
8
9 /**
10 * class for tests of GuzzleHttpRequest
11 *
12 * No actual requests are made herein - all external communications are mocked
13 *
14 * @covers GuzzleHttpRequest
15 * @covers MWHttpRequest
16 */
17 class GuzzleHttpRequestTest extends MediaWikiTestCase {
18 /**
19 * Placeholder url to use for various tests. This is never contacted, but we must use
20 * a url of valid format to avoid validation errors.
21 * @var string
22 */
23 protected $exampleUrl = 'http://www.example.test';
24
25 /**
26 * Minimal example body text
27 * @var string
28 */
29 protected $exampleBodyText = 'x';
30
31 /**
32 * For accumulating callback data for testing
33 * @var string
34 */
35 protected $bodyTextReceived = '';
36
37 /**
38 * Callback: process a chunk of the result of a HTTP request
39 *
40 * @param mixed $req
41 * @param string $buffer
42 * @return int Number of bytes handled
43 */
44 public function processHttpDataChunk( $req, $buffer ) {
45 $this->bodyTextReceived .= $buffer;
46 return strlen( $buffer );
47 }
48
49 public function testSuccess() {
50 $handler = HandlerStack::create( new MockHandler( [ new Response( 200, [
51 'status' => 200,
52 ], $this->exampleBodyText ) ] ) );
53 $r = new GuzzleHttpRequest( $this->exampleUrl, [ 'handler' => $handler ] );
54 $r->execute();
55
56 $this->assertEquals( 200, $r->getStatus() );
57 $this->assertEquals( $this->exampleBodyText, $r->getContent() );
58 }
59
60 public function testSuccessConstructorCallback() {
61 $this->bodyTextReceived = '';
62 $handler = HandlerStack::create( new MockHandler( [ new Response( 200, [
63 'status' => 200,
64 ], $this->exampleBodyText ) ] ) );
65 $r = new GuzzleHttpRequest( $this->exampleUrl, [
66 'callback' => [ $this, 'processHttpDataChunk' ],
67 'handler' => $handler,
68 ] );
69 $r->execute();
70
71 $this->assertEquals( 200, $r->getStatus() );
72 $this->assertEquals( $this->exampleBodyText, $this->bodyTextReceived );
73 }
74
75 public function testSuccessSetCallback() {
76 $this->bodyTextReceived = '';
77 $handler = HandlerStack::create( new MockHandler( [ new Response( 200, [
78 'status' => 200,
79 ], $this->exampleBodyText ) ] ) );
80 $r = new GuzzleHttpRequest( $this->exampleUrl, [
81 'handler' => $handler,
82 ] );
83 $r->setCallback( [ $this, 'processHttpDataChunk' ] );
84 $r->execute();
85
86 $this->assertEquals( 200, $r->getStatus() );
87 $this->assertEquals( $this->exampleBodyText, $this->bodyTextReceived );
88 }
89
90 /**
91 * use a callback stream to pipe the mocked response data to our callback function
92 */
93 public function testSuccessSink() {
94 $this->bodyTextReceived = '';
95 $handler = HandlerStack::create( new MockHandler( [ new Response( 200, [
96 'status' => 200,
97 ], $this->exampleBodyText ) ] ) );
98 $r = new GuzzleHttpRequest( $this->exampleUrl, [
99 'handler' => $handler,
100 'sink' => new MWCallbackStream( [ $this, 'processHttpDataChunk' ] ),
101 ] );
102 $r->execute();
103
104 $this->assertEquals( 200, $r->getStatus() );
105 $this->assertEquals( $this->exampleBodyText, $this->bodyTextReceived );
106 }
107
108 public function testBadUrl() {
109 $r = new GuzzleHttpRequest( '' );
110 $s = $r->execute();
111 $errorMsg = $s->getErrorsByType( 'error' )[0]['message'];
112
113 $this->assertSame( 0, $r->getStatus() );
114 $this->assertEquals( 'http-invalid-url', $errorMsg );
115 }
116
117 public function testConnectException() {
118 $handler = HandlerStack::create( new MockHandler( [ new GuzzleHttp\Exception\ConnectException(
119 'Mock Connection Exception', new Request( 'GET', $this->exampleUrl )
120 ) ] ) );
121 $r = new GuzzleHttpRequest( $this->exampleUrl, [ 'handler' => $handler ] );
122 $s = $r->execute();
123 $errorMsg = $s->getErrorsByType( 'error' )[0]['message'];
124
125 $this->assertSame( 0, $r->getStatus() );
126 $this->assertEquals( 'http-request-error', $errorMsg );
127 }
128
129 public function testTimeout() {
130 $handler = HandlerStack::create( new MockHandler( [ new GuzzleHttp\Exception\RequestException(
131 'Connection timed out', new Request( 'GET', $this->exampleUrl )
132 ) ] ) );
133 $r = new GuzzleHttpRequest( $this->exampleUrl, [ 'handler' => $handler ] );
134 $s = $r->execute();
135 $errorMsg = $s->getErrorsByType( 'error' )[0]['message'];
136
137 $this->assertSame( 0, $r->getStatus() );
138 $this->assertEquals( 'http-timed-out', $errorMsg );
139 }
140
141 public function testNotFound() {
142 $handler = HandlerStack::create( new MockHandler( [ new Response( 404, [
143 'status' => '404',
144 ] ) ] ) );
145 $r = new GuzzleHttpRequest( $this->exampleUrl, [ 'handler' => $handler ] );
146 $s = $r->execute();
147 $errorMsg = $s->getErrorsByType( 'error' )[0]['message'];
148
149 $this->assertEquals( 404, $r->getStatus() );
150 $this->assertEquals( 'http-bad-status', $errorMsg );
151 }
152
153 /*
154 * Test of POST requests header
155 */
156 public function testPostBody() {
157 $container = [];
158 $history = Middleware::history( $container );
159 $stack = HandlerStack::create();
160 $stack->push( $history );
161 $client = new GuzzleHttpRequest( $this->exampleUrl, [
162 'method' => 'POST',
163 'handler' => $stack,
164 'post' => 'key=value',
165 ] );
166 $client->execute();
167
168 $request = $container[0]['request'];
169 $this->assertEquals( 'POST', $request->getMethod() );
170 $this->assertEquals( 'application/x-www-form-urlencoded',
171 $request->getHeader( 'Content-Type' )[0] );
172 }
173 }