private function performRequest($action, array $converted, $dataHandle = null, $contentMd5 = null) {

    $curlOptions = $this->configureCurlOptions($action, $converted, $dataHandle, $contentMd5);

    if (is_null($curlOptions[CURLOPT_RETURNTRANSFER]) || !$curlOptions[CURLOPT_RETURNTRANSFER]) {
      $curlOptions[CURLOPT_RETURNTRANSFER] = true;
    }

    $this->curlClient = curl_init();
    curl_setopt_array($this->curlClient, $curlOptions);

    $this->headerContents = @fopen('php://memory', 'rw+');
    $this->errorResponseBody = @fopen('php://memory', 'rw+');

    $httpResponse = curl_exec($this->curlClient);

    rewind($this->headerContents);
    $header = stream_get_contents($this->headerContents);

    $parsedHeader = $this->parseHttpHeader($header);

    require_once('MarketplaceWebService/Model/ResponseHeaderMetadata.php');
    $responseHeaderMetadata = new MarketplaceWebService_Model_ResponseHeaderMetadata(
              $parsedHeader['x-mws-request-id'],
              $parsedHeader['x-mws-response-context'],
              $parsedHeader['x-mws-timestamp']);

    $code = (int) curl_getinfo($this->curlClient, CURLINFO_HTTP_CODE);
    
    // Only attempt to verify the Content-MD5 value if the request was successful.
    if (RequestType::getRequestType($action) === RequestType::POST_DOWNLOAD) {
    	if ($code != 200) {
    	  rewind($this->errorResponseBody);
        $httpResponse =  stream_get_contents($this->errorResponseBody);	
    	} else {
        $this->verifyContentMd5($this->getParsedHeader($parsedHeader,'Content-MD5'), $dataHandle);
        $httpResponse = $this->getDownloadResponseDocument($action, $parsedHeader);
    	}
    }
    
    // Cleanup open streams and cURL instance.
    @fclose($this->headerContents);
    @fclose($this->errorResponseBody);
    curl_close($this->curlClient);

    
    return array (
        'Status' => $code, 
        'ResponseBody' => $httpResponse,
        'ResponseHeaderMetadata' => $responseHeaderMetadata);
  }