From 8df3db566a3a937b45ebf11adb90d265e6f5e2d4 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 17 Nov 2019 20:45:02 +0100 Subject: initial checking of customized version 1.0rc9 --- .../Guzzle/Tests/Http/Curl/CurlHandleTest.php | 947 +++++++++++++++++++++ 1 file changed, 947 insertions(+) create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php (limited to 'vendor/guzzle/guzzle/tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php') diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php new file mode 100644 index 0000000..5bf28de --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Http/Curl/CurlHandleTest.php @@ -0,0 +1,947 @@ +getEventDispatcher()->addListener('request.sent', function (Event $e) use ($that) { + $that->requestHandle = $e['handle']; + }); + + return $request; + } + + public function setUp() + { + $this->requestHandle = null; + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testConstructorExpectsCurlResource() + { + $h = new CurlHandle(false, array()); + } + + public function testConstructorExpectsProperOptions() + { + $h = curl_init($this->getServer()->getUrl()); + try { + $ha = new CurlHandle($h, false); + $this->fail('Expected InvalidArgumentException'); + } catch (\InvalidArgumentException $e) { + } + + $ha = new CurlHandle($h, array( + CURLOPT_URL => $this->getServer()->getUrl() + )); + $this->assertEquals($this->getServer()->getUrl(), $ha->getOptions()->get(CURLOPT_URL)); + + $ha = new CurlHandle($h, new Collection(array( + CURLOPT_URL => $this->getServer()->getUrl() + ))); + $this->assertEquals($this->getServer()->getUrl(), $ha->getOptions()->get(CURLOPT_URL)); + } + + public function testConstructorInitializesObject() + { + $handle = curl_init($this->getServer()->getUrl()); + $h = new CurlHandle($handle, array( + CURLOPT_URL => $this->getServer()->getUrl() + )); + $this->assertSame($handle, $h->getHandle()); + $this->assertInstanceOf('Guzzle\\Http\\Url', $h->getUrl()); + $this->assertEquals($this->getServer()->getUrl(), (string) $h->getUrl()); + $this->assertEquals($this->getServer()->getUrl(), $h->getOptions()->get(CURLOPT_URL)); + } + + public function testStoresStdErr() + { + $request = RequestFactory::getInstance()->create('GET', 'http://test.com'); + $request->getCurlOptions()->set('debug', true); + $h = CurlHandle::factory($request); + $this->assertEquals($h->getStderr(true), $h->getOptions()->get(CURLOPT_STDERR)); + $this->assertInternalType('resource', $h->getStderr(true)); + $this->assertInternalType('string', $h->getStderr(false)); + $r = $h->getStderr(true); + fwrite($r, 'test'); + $this->assertEquals('test', $h->getStderr(false)); + } + + public function testStoresCurlErrorNumber() + { + $h = new CurlHandle(curl_init('http://test.com'), array(CURLOPT_URL => 'http://test.com')); + $this->assertEquals(CURLE_OK, $h->getErrorNo()); + $h->setErrorNo(CURLE_OPERATION_TIMEOUTED); + $this->assertEquals(CURLE_OPERATION_TIMEOUTED, $h->getErrorNo()); + } + + public function testAccountsForMissingStdErr() + { + $handle = curl_init('http://www.test.com/'); + $h = new CurlHandle($handle, array( + CURLOPT_URL => 'http://www.test.com/' + )); + $this->assertNull($h->getStderr(false)); + } + + public function testDeterminesIfResourceIsAvailable() + { + $handle = curl_init($this->getServer()->getUrl()); + $h = new CurlHandle($handle, array()); + $this->assertTrue($h->isAvailable()); + + // Mess it up by closing the handle + curl_close($handle); + $this->assertFalse($h->isAvailable()); + + // Mess it up by unsetting the handle + $handle = null; + $this->assertFalse($h->isAvailable()); + } + + public function testWrapsErrorsAndInfo() + { + if (!defined('CURLOPT_TIMEOUT_MS')) { + $this->markTestSkipped('Update curl'); + } + + $settings = array( + CURLOPT_PORT => 123, + CURLOPT_CONNECTTIMEOUT_MS => 1, + CURLOPT_TIMEOUT_MS => 1 + ); + + $handle = curl_init($this->getServer()->getUrl()); + curl_setopt_array($handle, $settings); + $h = new CurlHandle($handle, $settings); + @curl_exec($handle); + + $errors = array( + "couldn't connect to host", + 'timeout was reached', + 'connection time-out', + 'connect() timed out!', + 'failed connect to 127.0.0.1:123; connection refused', + 'failed to connect to 127.0.0.1 port 123: connection refused' + ); + $this->assertTrue(in_array(strtolower($h->getError()), $errors), $h->getError() . ' was not the error'); + + $this->assertTrue($h->getErrorNo() > 0); + + $this->assertEquals($this->getServer()->getUrl(), $h->getInfo(CURLINFO_EFFECTIVE_URL)); + $this->assertInternalType('array', $h->getInfo()); + + curl_close($handle); + $this->assertEquals(null, $h->getInfo('url')); + } + + public function testGetInfoWithoutDebugMode() + { + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + $client = new Client($this->getServer()->getUrl()); + $request = $client->get($this->getServer()->getUrl()); + $response = $request->send(); + + $info = $response->getInfo(); + $this->assertFalse(empty($info)); + $this->assertEquals($this->getServer()->getUrl(), $info['url']); + } + + public function testWrapsCurlOptions() + { + $handle = curl_init($this->getServer()->getUrl()); + $h = new CurlHandle($handle, array( + CURLOPT_AUTOREFERER => true, + CURLOPT_BUFFERSIZE => 1024 + )); + + $this->assertEquals(true, $h->getOptions()->get(CURLOPT_AUTOREFERER)); + $this->assertEquals(1024, $h->getOptions()->get(CURLOPT_BUFFERSIZE)); + } + + /** + * Data provider for factory tests + * + * @return array + */ + public function dataProvider() + { + $testFile = __DIR__ . '/../../../../../phpunit.xml.dist'; + + $postBody = new QueryString(array('file' => '@' . $testFile)); + $qs = new QueryString(array( + 'x' => 'y', + 'z' => 'a' + )); + + $client = new Client(); + $userAgent = $client->getDefaultUserAgent(); + $auth = base64_encode('michael:123'); + $testFileSize = filesize($testFile); + + $tests = array( + // Send a regular GET + array('GET', 'http://www.google.com/', null, null, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_HTTPHEADER => array('Accept:', 'Host: www.google.com', 'User-Agent: ' . $userAgent), + )), + // Test that custom request methods can be used + array('TRACE', 'http://www.google.com/', null, null, array( + CURLOPT_CUSTOMREQUEST => 'TRACE' + )), + // Send a GET using a port + array('GET', 'http://127.0.0.1:8080', null, null, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_PORT => 8080, + CURLOPT_HTTPHEADER => array('Accept:', 'Host: 127.0.0.1:8080', 'User-Agent: ' . $userAgent), + )), + // Send a HEAD request + array('HEAD', 'http://www.google.com/', null, null, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_HTTPHEADER => array('Accept:', 'Host: www.google.com', 'User-Agent: ' . $userAgent), + CURLOPT_NOBODY => 1 + )), + // Send a GET using basic auth + array('GET', 'https://michael:123@127.0.0.1/index.html?q=2', null, null, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_HTTPHEADER => array( + 'Accept:', + 'Host: 127.0.0.1', + 'Authorization: Basic ' . $auth, + 'User-Agent: ' . $userAgent + ), + CURLOPT_PORT => 443 + )), + // Send a GET request with custom headers + array('GET', 'http://127.0.0.1:8124/', array( + 'x-test-data' => 'Guzzle' + ), null, array( + CURLOPT_PORT => 8124, + CURLOPT_HTTPHEADER => array( + 'Accept:', + 'Host: 127.0.0.1:8124', + 'x-test-data: Guzzle', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'x-test-data' => 'Guzzle' + )), + // Send a POST using a query string + array('POST', 'http://127.0.0.1:8124/post.php', null, $qs, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_POSTFIELDS => 'x=y&z=a', + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'Content-Type: application/x-www-form-urlencoded; charset=utf-8', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Length' => '7', + '!Expect' => null, + 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8', + '!Transfer-Encoding' => null + )), + // Send a PUT using raw data + array('PUT', 'http://127.0.0.1:8124/put.php', null, EntityBody::factory(fopen($testFile, 'r+')), array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_READFUNCTION => 'callback', + CURLOPT_INFILESIZE => filesize($testFile), + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + '!Expect' => null, + 'Content-Length' => $testFileSize, + '!Transfer-Encoding' => null + )), + // Send a POST request using an array of fields + array('POST', 'http://127.0.0.1:8124/post.php', null, array( + 'x' => 'y', + 'a' => 'b' + ), array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_POST => 1, + CURLOPT_POSTFIELDS => 'x=y&a=b', + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'Content-Type: application/x-www-form-urlencoded; charset=utf-8', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Length' => '7', + '!Expect' => null, + 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8', + '!Transfer-Encoding' => null + )), + // Send a POST request with raw POST data and a custom content-type + array('POST', 'http://127.0.0.1:8124/post.php', array( + 'Content-Type' => 'application/json' + ), '{"hi":"there"}', array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_UPLOAD => true, + CURLOPT_INFILESIZE => 14, + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'Content-Type: application/json', + 'User-Agent: ' . $userAgent + ), + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Type' => 'application/json', + '!Expect' => null, + 'Content-Length' => '14', + '!Transfer-Encoding' => null + )), + // Send a POST request with raw POST data, a custom content-type, and use chunked encoding + array('POST', 'http://127.0.0.1:8124/post.php', array( + 'Content-Type' => 'application/json', + 'Transfer-Encoding' => 'chunked' + ), '{"hi":"there"}', array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_UPLOAD => true, + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'Transfer-Encoding: chunked', + 'Content-Type: application/json', + 'User-Agent: ' . $userAgent + ), + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Type' => 'application/json', + '!Expect' => null, + 'Transfer-Encoding' => 'chunked', + '!Content-Length' => '' + )), + // Send a POST request with no body + array('POST', 'http://127.0.0.1:8124/post.php', null, '', array( + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Length' => '0', + '!Transfer-Encoding' => null + )), + // Send a POST request with empty post fields + array('POST', 'http://127.0.0.1:8124/post.php', null, array(), array( + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Length' => '0', + '!Transfer-Encoding' => null + )), + // Send a PATCH request + array('PATCH', 'http://127.0.0.1:8124/patch.php', null, 'body', array( + CURLOPT_INFILESIZE => 4, + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'User-Agent: ' . $userAgent + ) + )), + // Send a DELETE request with a body + array('DELETE', 'http://127.0.0.1:8124/delete.php', null, 'body', array( + CURLOPT_CUSTOMREQUEST => 'DELETE', + CURLOPT_INFILESIZE => 4, + CURLOPT_HTTPHEADER => array ( + 'Expect:', + 'Accept:', + 'Host: 127.0.0.1:8124', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Length' => '4', + '!Expect' => null, + '!Transfer-Encoding' => null + )), + + /** + * Send a request with empty path and a fragment - the fragment must be + * stripped out before sending it to curl + * + * @issue 453 + * @link https://github.com/guzzle/guzzle/issues/453 + */ + array('GET', 'http://www.google.com#head', null, null, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_HTTPHEADER => array('Accept:', 'Host: www.google.com', 'User-Agent: ' . $userAgent), + )), + ); + + $postTest = array('POST', 'http://127.0.0.1:8124/post.php', null, $postBody, array( + CURLOPT_RETURNTRANSFER => 0, + CURLOPT_HEADER => 0, + CURLOPT_CONNECTTIMEOUT => 150, + CURLOPT_WRITEFUNCTION => 'callback', + CURLOPT_HEADERFUNCTION => 'callback', + CURLOPT_POST => 1, + CURLOPT_POSTFIELDS => array( + 'file' => '@' . $testFile . ';filename=phpunit.xml.dist;type=application/octet-stream' + ), + CURLOPT_HTTPHEADER => array ( + 'Accept:', + 'Host: 127.0.0.1:8124', + 'Content-Type: multipart/form-data', + 'Expect: 100-Continue', + 'User-Agent: ' . $userAgent + ) + ), array( + 'Host' => '*', + 'User-Agent' => '*', + 'Content-Length' => '*', + 'Expect' => '100-Continue', + 'Content-Type' => 'multipart/form-data; boundary=*', + '!Transfer-Encoding' => null + )); + + if (version_compare(phpversion(), '5.5.0', '>=')) { + $postTest[4][CURLOPT_POSTFIELDS] = array( + 'file' => new \CurlFile($testFile, 'application/octet-stream', 'phpunit.xml.dist') + ); + } + + $tests[] = $postTest; + + return $tests; + } + + /** + * @dataProvider dataProvider + */ + public function testFactoryCreatesCurlBasedOnRequest($method, $url, $headers, $body, $options, $expectedHeaders = null) + { + $client = new Client(); + $request = $client->createRequest($method, $url, $headers, $body); + $request->getCurlOptions()->set('debug', true); + + $originalRequest = clone $request; + $curlTest = clone $request; + $handle = CurlHandle::factory($curlTest); + + $this->assertInstanceOf('Guzzle\\Http\\Curl\\CurlHandle', $handle); + $o = $handle->getOptions()->getAll(); + + // Headers are case-insensitive + if (isset($o[CURLOPT_HTTPHEADER])) { + $o[CURLOPT_HTTPHEADER] = array_map('strtolower', $o[CURLOPT_HTTPHEADER]); + } + if (isset($options[CURLOPT_HTTPHEADER])) { + $options[CURLOPT_HTTPHEADER] = array_map('strtolower', $options[CURLOPT_HTTPHEADER]); + } + + $check = 0; + foreach ($options as $key => $value) { + $check++; + $this->assertArrayHasKey($key, $o, '-> Check number ' . $check); + if ($key != CURLOPT_HTTPHEADER && $key != CURLOPT_POSTFIELDS && (is_array($o[$key])) || $o[$key] instanceof \Closure) { + $this->assertEquals('callback', $value, '-> Check number ' . $check); + } else { + $this->assertTrue($value == $o[$key], '-> Check number ' . $check . ' - ' . var_export($value, true) . ' != ' . var_export($o[$key], true)); + } + } + + // If we are testing the actual sent headers + if ($expectedHeaders) { + + // Send the request to the test server + $client = new Client($this->getServer()->getUrl()); + $request->setClient($client); + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + $request->send(); + + // Get the request that was sent and create a request that we expected + $requests = $this->getServer()->getReceivedRequests(true); + $this->assertEquals($method, $requests[0]->getMethod()); + + $test = $this->compareHeaders($expectedHeaders, $requests[0]->getHeaders()); + $this->assertFalse($test, $test . "\nSent: \n" . $request . "\n\n" . $requests[0]); + + // Ensure only one Content-Length header is sent + if ($request->getHeader('Content-Length')) { + $this->assertEquals((string) $request->getHeader('Content-Length'), (string) $requests[0]->getHeader('Content-Length')); + } + } + } + + public function testFactoryUsesSpecifiedProtocol() + { + $request = RequestFactory::getInstance()->create('GET', 'http://127.0.0.1:8124/'); + $request->setProtocolVersion('1.1'); + $handle = CurlHandle::factory($request); + $options = $handle->getOptions(); + $this->assertEquals(CURL_HTTP_VERSION_1_1, $options[CURLOPT_HTTP_VERSION]); + } + + public function testUploadsPutData() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi"); + + $client = new Client($this->getServer()->getUrl()); + $request = $client->put('/'); + $request->getCurlOptions()->set('debug', true); + $request->setBody(EntityBody::factory('test'), 'text/plain', false); + $request->getCurlOptions()->set('progress', true); + + $o = $this->getWildcardObserver($request); + $request->send(); + + // Make sure that the events were dispatched + $this->assertTrue($o->has('curl.callback.progress')); + + // Ensure that the request was received exactly as intended + $r = $this->getServer()->getReceivedRequests(true); + $this->assertFalse($r[0]->hasHeader('Transfer-Encoding')); + $this->assertEquals(4, (string) $r[0]->getHeader('Content-Length')); + $sent = strtolower($r[0]); + $this->assertContains('put / http/1.1', $sent); + $this->assertContains('host: 127.0.0.1', $sent); + $this->assertContains('user-agent:', $sent); + $this->assertContains('content-type: text/plain', $sent); + } + + public function testUploadsPutDataUsingChunkedEncodingWhenLengthCannotBeDetermined() + { + $this->getServer()->flush(); + $this->getServer()->enqueue(array( + "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n", + "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi" + )); + $client = new Client($this->getServer()->getUrl()); + $request = $client->put('/'); + $request->setBody(EntityBody::factory(fopen($this->getServer()->getUrl(), 'r')), 'text/plain'); + $request->send(); + + $r = $this->getServer()->getReceivedRequests(true); + $this->assertEquals('chunked', $r[1]->getHeader('Transfer-Encoding')); + $this->assertFalse($r[1]->hasHeader('Content-Length')); + } + + public function testUploadsPutDataUsingChunkedEncodingWhenForced() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi"); + + $client = new Client($this->getServer()->getUrl()); + $request = $client->put('/', array('Transfer-Encoding' => 'chunked'), 'hi!'); + $request->send(); + + $r = $this->getServer()->getReceivedRequests(true); + $this->assertEquals('chunked', $r[0]->getHeader('Transfer-Encoding')); + $this->assertFalse($r[0]->hasHeader('Content-Length')); + $this->assertEquals('hi!', $r[0]->getBody(true)); + } + + public function testSendsPostRequestsWithFields() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi"); + + $request = RequestFactory::getInstance()->create('POST', $this->getServer()->getUrl()); + $request->getCurlOptions()->set('debug', true); + $request->setClient(new Client()); + $request->addPostFields(array( + 'a' => 'b', + 'c' => 'ay! ~This is a test, isn\'t it?' + )); + $request->send(); + + // Make sure that the request was sent correctly + $r = $this->getServer()->getReceivedRequests(true); + $this->assertEquals('a=b&c=ay%21%20~This%20is%20a%20test%2C%20isn%27t%20it%3F', (string) $r[0]->getBody()); + $this->assertFalse($r[0]->hasHeader('Transfer-Encoding')); + $this->assertEquals(56, (string) $r[0]->getHeader('Content-Length')); + $sent = strtolower($r[0]); + $this->assertContains('post / http/1.1', $sent); + $this->assertContains('content-type: application/x-www-form-urlencoded; charset=utf-8', $sent); + } + + public function testSendsPostRequestsWithFiles() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nhi"); + + $request = RequestFactory::getInstance()->create('POST', $this->getServer()->getUrl()); + $request->getCurlOptions()->set('debug', true); + $request->setClient(new Client()); + $request->addPostFiles(array( + 'foo' => __FILE__, + )); + $request->addPostFields(array( + 'bar' => 'baz', + 'arr' => array('a' => 1, 'b' => 2), + )); + $this->updateForHandle($request); + $request->send(); + + // Ensure the CURLOPT_POSTFIELDS option was set properly + $options = $this->requestHandle->getOptions()->getAll(); + if (version_compare(phpversion(), '5.5.0', '<')) { + $this->assertContains('@' . __FILE__ . ';filename=CurlHandleTest.php;type=text/x-', $options[CURLOPT_POSTFIELDS]['foo']); + } else{ + $this->assertInstanceOf('CURLFile', $options[CURLOPT_POSTFIELDS]['foo']); + } + $this->assertEquals('baz', $options[CURLOPT_POSTFIELDS]['bar']); + $this->assertEquals('1', $options[CURLOPT_POSTFIELDS]['arr[a]']); + $this->assertEquals('2', $options[CURLOPT_POSTFIELDS]['arr[b]']); + // Ensure that a Content-Length header was sent by cURL + $this->assertTrue($request->hasHeader('Content-Length')); + } + + public function testCurlConfigurationOptionsAreSet() + { + $request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl()); + $request->setClient(new Client('http://www.example.com')); + $request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT, 99); + $request->getCurlOptions()->set('curl.fake_opt', 99); + $request->getCurlOptions()->set(CURLOPT_PORT, 8181); + $handle = CurlHandle::factory($request); + $this->assertEquals(99, $handle->getOptions()->get(CURLOPT_CONNECTTIMEOUT)); + $this->assertEquals(8181, $handle->getOptions()->get(CURLOPT_PORT)); + $this->assertNull($handle->getOptions()->get('curl.fake_opt')); + $this->assertNull($handle->getOptions()->get('fake_opt')); + } + + public function testEnsuresRequestsHaveResponsesWhenUpdatingFromTransfer() + { + $request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl()); + $handle = CurlHandle::factory($request); + $handle->updateRequestFromTransfer($request); + } + + public function testCanSendBodyAsString() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + $client = new Client($this->getServer()->getUrl()); + $request = $client->put('/', null, 'foo'); + $request->getCurlOptions()->set('body_as_string', true); + $request->send(); + $requests = $this->getServer()->getReceivedRequests(false); + $this->assertContains('PUT /', $requests[0]); + $this->assertContains("\nfoo", $requests[0]); + $this->assertContains('content-length: 3', $requests[0]); + $this->assertNotContains('content-type', $requests[0]); + } + + public function testCanSendPostBodyAsString() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + $client = new Client($this->getServer()->getUrl()); + $request = $client->post('/', null, 'foo'); + $request->getCurlOptions()->set('body_as_string', true); + $request->send(); + $requests = $this->getServer()->getReceivedRequests(false); + $this->assertContains('POST /', $requests[0]); + $this->assertContains("\nfoo", $requests[0]); + $this->assertContains('content-length: 3', $requests[0]); + $this->assertNotContains('content-type', $requests[0]); + } + + public function testAllowsWireTransferInfoToBeEnabled() + { + $request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl()); + $request->getCurlOptions()->set('debug', true); + $handle = CurlHandle::factory($request); + $this->assertNotNull($handle->getOptions()->get(CURLOPT_STDERR)); + $this->assertNotNull($handle->getOptions()->get(CURLOPT_VERBOSE)); + } + + public function testAddsCustomCurlOptions() + { + $request = RequestFactory::getInstance()->create('PUT', $this->getServer()->getUrl()); + $request->getCurlOptions()->set(CURLOPT_TIMEOUT, 200); + $handle = CurlHandle::factory($request); + $this->assertEquals(200, $handle->getOptions()->get(CURLOPT_TIMEOUT)); + } + + public function testSendsPostUploadsWithContentDispositionHeaders() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\n\r\nContent-Length: 0\r\n\r\n"); + + $fileToUpload = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'TestData' . DIRECTORY_SEPARATOR . 'test_service.json'; + + $client = new Client($this->getServer()->getUrl()); + $request = $client->post(); + $request->addPostFile('foo', $fileToUpload, 'application/json'); + $request->addPostFile('foo', __FILE__); + + $request->send(); + $requests = $this->getServer()->getReceivedRequests(true); + $body = (string) $requests[0]->getBody(); + + $this->assertContains('Content-Disposition: form-data; name="foo[0]"; filename="', $body); + $this->assertContains('Content-Type: application/json', $body); + $this->assertContains('Content-Type: text/x-', $body); + $this->assertContains('Content-Disposition: form-data; name="foo[1]"; filename="', $body); + } + + public function requestMethodProvider() + { + return array(array('POST'), array('PUT'), array('PATCH')); + } + + /** + * @dataProvider requestMethodProvider + */ + public function testSendsRequestsWithNoBodyUsingContentLengthZero($method) + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + $client = new Client($this->getServer()->getUrl()); + $client->createRequest($method)->send(); + $requests = $this->getServer()->getReceivedRequests(true); + $this->assertFalse($requests[0]->hasHeader('Transfer-Encoding')); + $this->assertTrue($requests[0]->hasHeader('Content-Length')); + $this->assertEquals('0', (string) $requests[0]->getHeader('Content-Length')); + } + + /** + * @dataProvider provideCurlConfig + */ + public function testParseCurlConfigConvertsStringKeysToConstantKeys($options, $expected) + { + $actual = CurlHandle::parseCurlConfig($options); + $this->assertEquals($expected, $actual); + } + + /** + * Data provider for curl configurations + * + * @return array + */ + public function provideCurlConfig() + { + return array( + // Conversion of option name to constant value + array( + array( + 'CURLOPT_PORT' => 10, + 'CURLOPT_TIMEOUT' => 99 + ), + array( + CURLOPT_PORT => 10, + CURLOPT_TIMEOUT => 99 + ) + ), + // Keeps non constant options + array( + array('debug' => true), + array('debug' => true) + ), + // Conversion of constant names to constant values + array( + array('debug' => 'CURLPROXY_HTTP'), + array('debug' => CURLPROXY_HTTP) + ) + ); + } + + public function testSeeksToBeginningOfStreamWhenSending() + { + $this->getServer()->flush(); + $this->getServer()->enqueue(array( + "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n", + "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n" + )); + + $client = new Client($this->getServer()->getUrl()); + $request = $client->put('/', null, 'test'); + $request->send(); + $request->send(); + + $received = $this->getServer()->getReceivedRequests(true); + $this->assertEquals(2, count($received)); + $this->assertEquals('test', (string) $received[0]->getBody()); + $this->assertEquals('test', (string) $received[1]->getBody()); + } + + public function testAllowsCurloptEncodingToBeSet() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + + $client = new Client($this->getServer()->getUrl()); + $request = $client->get('/', null); + $request->getCurlOptions()->set(CURLOPT_ENCODING, ''); + $this->updateForHandle($request); + $request->send(); + $options = $this->requestHandle->getOptions()->getAll(); + $this->assertSame('', $options[CURLOPT_ENCODING]); + $received = $this->getServer()->getReceivedRequests(false); + $this->assertContainsIns('accept: */*', $received[0]); + $this->assertContainsIns('accept-encoding: ', $received[0]); + } + + public function testSendsExpectHeaderWhenSizeIsGreaterThanCutoff() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + $client = new Client($this->getServer()->getUrl()); + $request = $client->put('/', null, 'test'); + // Start sending the expect header to 2 bytes + $this->updateForHandle($request); + $request->setExpectHeaderCutoff(2)->send(); + $options = $this->requestHandle->getOptions()->getAll(); + $this->assertContains('Expect: 100-Continue', $options[CURLOPT_HTTPHEADER]); + $received = $this->getServer()->getReceivedRequests(false); + $this->assertContainsIns('expect: 100-continue', $received[0]); + } + + public function testSetsCurloptEncodingWhenAcceptEncodingHeaderIsSet() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\ndata"); + $client = new Client($this->getServer()->getUrl()); + $request = $client->get('/', array( + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip, deflate', + )); + $this->updateForHandle($request); + $request->send(); + $options = $this->requestHandle->getOptions()->getAll(); + $this->assertSame('gzip, deflate', $options[CURLOPT_ENCODING]); + $received = $this->getServer()->getReceivedRequests(false); + $this->assertContainsIns('accept: application/json', $received[0]); + $this->assertContainsIns('accept-encoding: gzip, deflate', $received[0]); + } + + public function testSendsPostFieldsForNonPostRequests() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\n\r\nContent-Length: 0\r\n\r\n"); + + $client = new Client(); + $request = $client->put($this->getServer()->getUrl(), null, array( + 'foo' => 'baz', + 'baz' => 'bar' + )); + + $request->send(); + $requests = $this->getServer()->getReceivedRequests(true); + $this->assertEquals('PUT', $requests[0]->getMethod()); + $this->assertEquals( + 'application/x-www-form-urlencoded; charset=utf-8', + (string) $requests[0]->getHeader('Content-Type') + ); + $this->assertEquals(15, (string) $requests[0]->getHeader('Content-Length')); + $this->assertEquals('foo=baz&baz=bar', (string) $requests[0]->getBody()); + } + + public function testSendsPostFilesForNonPostRequests() + { + $this->getServer()->flush(); + $this->getServer()->enqueue("HTTP/1.1 200 OK\r\n\r\nContent-Length: 0\r\n\r\n"); + + $client = new Client(); + $request = $client->put($this->getServer()->getUrl(), null, array( + 'foo' => '@' . __FILE__ + )); + + $request->send(); + $requests = $this->getServer()->getReceivedRequests(true); + $this->assertEquals('PUT', $requests[0]->getMethod()); + $this->assertContains('multipart/form-data', (string) $requests[0]->getHeader('Content-Type')); + $this->assertContains('testSendsPostFilesForNonPostRequests', (string) $requests[0]->getBody()); + } +} -- cgit v1.2.3-54-g00ecf