1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688: 689: 690: 691: 692: 693: 694: 695: 696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707: 708: 709: 710: 711: 712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730: 731: 732: 733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763: 764: 765: 766: 767: 768: 769: 770: 771: 772: 773: 774: 775: 776: 777: 778: 779: 780: 781: 782: 783: 784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804: 805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815: 816: 817: 818: 819: 820: 821: 822: 823: 824: 825: 826: 827: 828: 829: 830: 831: 832: 833: 834: 835: 836: 837: 838: 839: 840: 841: 842: 843: 844: 845: 846: 847: 848: 849: 850: 851: 852: 853: 854: 855: 856: 857: 858: 859: 860: 861: 862: 863: 864: 865: 866: 867: 868: 869: 870: 871: 872: 873: 874: 875: 876: 877: 878: 879: 880: 881: 882: 883: 884: 885: 886: 887: 888: 889: 890: 891: 892: 893: 894: 895: 896: 897: 898: 899: 900: 901: 902: 903: 904: 905: 906: 907: 908: 909: 910: 911: 912: 913: 914: 915: 916: 917: 918: 919: 920: 921: 922: 923: 924: 925: 926: 927: 928: 929: 930: 931: 932: 933: 934: 935: 936: 937: 938: 939: 940: 941: 942: 943: 944: 945: 946: 947: 948:
<?php
namespace Guzzle\Tests\Http\Curl;
use Guzzle\Common\Collection;
use Guzzle\Common\Event;
use Guzzle\Http\EntityBody;
use Guzzle\Http\QueryString;
use Guzzle\Http\Client;
use Guzzle\Http\Message\RequestFactory;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Curl\CurlHandle;
class CurlHandleTest extends \Guzzle\Tests\GuzzleTestCase
{
public $requestHandle;
protected function updateForHandle(RequestInterface $request)
{
$that = $this;
$request->getEventDispatcher()->addListener('request.sent', function (Event $e) use ($that) {
$that->requestHandle = $e['handle'];
});
return $request;
}
public function setUp()
{
$this->requestHandle = null;
}
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());
curl_close($handle);
$this->assertFalse($h->isAvailable());
$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));
}
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(
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),
)),
array('TRACE', 'http://www.google.com/', null, null, array(
CURLOPT_CUSTOMREQUEST => 'TRACE'
)),
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),
)),
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
)),
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
)),
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'
)),
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
)),
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
)),
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
)),
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
)),
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' => ''
)),
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
)),
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
)),
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
)
)),
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
)),
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;
}
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();
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 ($expectedHeaders) {
$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();
$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]);
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();
$this->assertTrue($o->has('curl.callback.progress'));
$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();
$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();
$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]']);
$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'));
}
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'));
}
public function testParseCurlConfigConvertsStringKeysToConstantKeys($options, $expected)
{
$actual = CurlHandle::parseCurlConfig($options);
$this->assertEquals($expected, $actual);
}
public function provideCurlConfig()
{
return array(
array(
array(
'CURLOPT_PORT' => 10,
'CURLOPT_TIMEOUT' => 99
),
array(
CURLOPT_PORT => 10,
CURLOPT_TIMEOUT => 99
)
),
array(
array('debug' => true),
array('debug' => true)
),
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');
$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());
}
}