public function __construct(Request $request = null, Response $response = null, Exception $previous = null)
 {
     $message = $previous ? $previous->getMessage() : 'Unknown error';
     $status = 0;
     $this->request = $request;
     $this->response = $response;
     if ($response) {
         $message = $response->getError();
         $status = $response->getStatus();
         //TODO Add status text
     }
     parent::__construct($message, $status, $previous);
 }
 public function testMultipart()
 {
     $goodMultipartMixedResponse = "Content-Type: multipart/mixed; boundary=Boundary_1245_945802293_1394135045248\n" . "\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\r\n" . "\r\n" . "{\n" . "  \"response\" : [ {\n" . "    \"status\" : 200\n" . "  }, {\n" . "    \"status\" : 200\n" . "  } ]\n" . "}\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"foo\" : \"bar\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"baz\" : \"qux\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248--\n";
     $multipartMixedResponseWithErrorPart = "Content-Type: multipart/mixed; boundary=Boundary_1245_945802293_1394135045248\n" . "\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"response\" : [ {\n" . "    \"status\" : 200\n" . "  }, {\n" . "    \"status\" : 404\n" . "  }, {\n" . "    \"status\" : 200\n" . "  } ]\n" . "}\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"foo\" : \"bar\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"message\" : \"object not found\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"baz\" : \"qux\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248--\n";
     $badMultipartMixedResponse = "Content-Type: multipart/mixed; boundary=Boundary_1245_945802293_1394135045248\n" . "\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "THIS IS JUNK AND CANNOT BE PARSED AS JSON\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"foo\" : \"bar\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248\n" . "Content-Type: application/json\n" . "\n" . "{\n" . "  \"baz\" : \"qux\"\n" . "}\n" . "--Boundary_1245_945802293_1394135045248--\n";
     $r1 = new Response(207, $goodMultipartMixedResponse);
     $this->assertEquals(2, count($r1->getResponses()));
     $rr1 = $r1->getResponses();
     $this->assertEquals('bar', $rr1[0]->getJson()->foo);
     $this->assertEquals('qux', $rr1[1]->getJson()->baz);
     $r2 = new Response(207, $multipartMixedResponseWithErrorPart);
     $rr2 = $r2->getResponses();
     $this->assertEquals('bar', $rr2[0]->getJson()->foo);
     $this->assertEquals('object not found', $rr2[1]->getError());
     $this->assertEquals('qux', $rr2[2]->getJson()->baz);
     $r3 = new Response(207, $badMultipartMixedResponse);
     $caught = false;
     try {
         $r3->getResponses();
     } catch (Exception $e) {
         $caught = true;
     }
     $this->assertTrue($caught);
 }
 /**
  * @return $this
  * @throws HttpException
  * @codeCoverageIgnore
  */
 public function send()
 {
     $ch = curl_init();
     $response = null;
     try {
         curl_setopt($ch, CURLOPT_URL, $this->getUrlWithQueryString());
         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->getMethod());
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
         curl_setopt($ch, CURLOPT_HEADER, true);
         curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getHeadersArray());
         if ($this->isPut() || $this->isPost()) {
             curl_setopt($ch, CURLOPT_POST, true);
             curl_setopt($ch, CURLOPT_POSTFIELDS, $this->getEncodedBody());
         }
         $res = curl_exec($ch);
         $response = new Response(curl_getinfo($ch, CURLINFO_HTTP_CODE), $res);
         if (!$response->checkStatus()) {
             throw new Exception('Response has unsuccessful status');
         }
     } catch (Exception $e) {
         curl_close($ch);
         throw new HttpException($this, $response, $e);
     }
     curl_close($ch);
     return $response;
 }
 /**
  * @return Response[]
  * @throws Exception
  */
 public function getResponses()
 {
     if (!$this->isMultipart()) {
         throw new Exception('Response is not multipart');
     }
     $contentType = $this->getHeader('content-type');
     if (!stristr($contentType, 'multipart/mixed')) {
         throw new Exception('Response is not multipart/mixed');
     }
     $body = $this->getBody();
     //TODO Read stream as stream
     // Step 1. Split boundaries
     preg_match(self::BOUNDARY_REGEXP, $contentType, $matches);
     $boundary = $matches[1];
     $parts = explode(self::BOUNDARY_SEPARATOR . $boundary, $body);
     // First empty part out
     if (!$parts[0] || !trim($parts[0])) {
         array_shift($parts);
     }
     // Last "--" part out
     if (trim($parts[sizeof($parts) - 1]) == self::BOUNDARY_SEPARATOR) {
         array_pop($parts);
     }
     // Step 2. Create status info object
     $statusInfoObj = new Response($this->getStatus(), array_shift($parts));
     $statusInfo = $statusInfoObj->getJson()->response;
     // Step 3. Parse all parts into Response objects
     $responses = array();
     foreach ($parts as $i => $part) {
         $partInfo = $statusInfo[$i];
         $responses[] = new Response($partInfo->status, $part);
     }
     return $responses;
 }