コード例 #1
0
ファイル: Request.php プロジェクト: keekinc/s3-client
 /**
  * Get the S3 response
  *
  * @return  Response
  */
 public function getResponse()
 {
     $this->processParametersIntoResource();
     $schema = 'http://';
     if ($this->configuration->isSSL()) {
         $schema = 'https://';
     }
     $url = $schema . $this->headers['Host'] . $this->uri;
     // Basic setup
     $curl = curl_init();
     curl_setopt($curl, CURLOPT_USERAGENT, 'keek/s3-client');
     curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
     curl_setopt($curl, CURLOPT_TIMEOUT, 5);
     if ($this->configuration->isSSL()) {
         // Set the CA certificate cache location
         $caCert = $this->getCaCertLocation();
         if (!empty($caCert)) {
             if (is_dir($caCert)) {
                 @curl_setopt($curl, CURLOPT_CAPATH, $caCert);
             } else {
                 @curl_setopt($curl, CURLOPT_CAINFO, $caCert);
             }
         }
         // Verify the host name in the certificate and the certificate itself. However, if your bucket contains dots
         // we have to turn off host verification. Sorry, that's a limitation of Amazon S3. Since they recommend
         // always using virtual hosting style hostnames while their SSL certificate is set up to only allow
         // subdomains (bucket names) without dots the direct implication is that if you want to use SSL you MUST NOT
         // use dots in your bucket name. Of course this contradicts another part of their documentation which
         // suggests using bucket names with dots (same as your domain name) but YOU CAN'T MAKE SENSE OF THEIR BLOODY
         // DOCS, CAN YOU? For what is worth their own SDK uses path-style access which they tell everyone else to
         // not use.
         //
         // TL;DR: Amazon is a bunch of jerks.
         $isAmazonS3 = substr($this->headers['Host'], -14) == '.amazonaws.com';
         $tooManyDots = substr_count($this->headers['Host'], '.') > 3;
         $verifyHost = $isAmazonS3 && $tooManyDots ? 0 : 2;
         curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $verifyHost);
         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
     }
     curl_setopt($curl, CURLOPT_URL, $url);
     $signer = Signature::getSignatureObject($this, $this->configuration->getSignatureMethod());
     $signer->preProcessHeaders($this->headers, $this->amzHeaders);
     // Headers
     $headers = array();
     foreach ($this->amzHeaders as $header => $value) {
         if (strlen($value) > 0) {
             $headers[] = $header . ': ' . $value;
         }
     }
     foreach ($this->headers as $header => $value) {
         if (strlen($value) > 0) {
             $headers[] = $header . ': ' . $value;
         }
     }
     $headers[] = 'Authorization: ' . $signer->getAuthorizationHeader();
     curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
     curl_setopt($curl, CURLOPT_HEADER, false);
     curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
     curl_setopt($curl, CURLOPT_WRITEFUNCTION, array($this, '__responseWriteCallback'));
     curl_setopt($curl, CURLOPT_HEADERFUNCTION, array($this, '__responseHeaderCallback'));
     curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
     // Optimize the Object Store Request Caching
     if (!in_array($this->verb, ['PUT', 'POST'])) {
         curl_setopt($curl, CURLOPT_FRESH_CONNECT, false);
         curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 1000);
         // Disabled execution timeout to allow streaming to complete
         //curl_setopt($curl, CURLOPT_TIMEOUT_MS, 8000);
         curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 604800);
     }
     // Request types
     switch ($this->verb) {
         case 'GET':
             break;
         case 'PUT':
         case 'POST':
             if (!is_object($this->input) || !$this->input instanceof Input) {
                 $this->input = new Input();
             }
             $size = $this->input->getSize();
             $type = $this->input->getInputType();
             if ($type == Input::INPUT_DATA) {
                 curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
                 $data = $this->input->getDataReference();
                 if (strlen($data)) {
                     curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
                 }
                 if ($size > 0) {
                     curl_setopt($curl, CURLOPT_BUFFERSIZE, $size);
                 }
             } else {
                 curl_setopt($curl, CURLOPT_PUT, true);
                 curl_setopt($curl, CURLOPT_INFILE, $this->input->getFp());
                 if ($size > 0) {
                     curl_setopt($curl, CURLOPT_INFILESIZE, $size);
                 }
             }
             break;
         case 'HEAD':
             curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD');
             curl_setopt($curl, CURLOPT_NOBODY, true);
             break;
         case 'DELETE':
             curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
             break;
         default:
             break;
     }
     // Execute, grab errors
     $this->response->resetBody();
     if (curl_exec($curl)) {
         $this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
     } else {
         $this->response->error = new Error(curl_errno($curl), curl_error($curl), $this->resource);
     }
     @curl_close($curl);
     // Set the body data
     $this->response->finaliseBody();
     // Clean up file resources
     if (!is_null($this->fp) && is_resource($this->fp)) {
         fclose($this->fp);
     }
     return $this->response;
 }
コード例 #2
0
ファイル: Connector.php プロジェクト: keekinc/s3-client
 /**
  * Finalizes the multi-part upload. The $input object should contain two keys, etags an array of ETags of the
  * uploaded parts and UploadID the multipart upload ID.
  *
  * @param   Input   $input   The array of input elements
  * @param   string  $bucket  The bucket where the object is being stored
  * @param   string  $uri     The key (path) to the object
  *
  * @return  void
  */
 public function finalizeMultipart(Input $input, $bucket, $uri)
 {
     $etags = $input->getEtags();
     $UploadID = $input->getUploadID();
     if (empty($etags)) {
         throw new CannotPutFile(__METHOD__ . '(): No ETags array specified');
     }
     if (empty($UploadID)) {
         throw new CannotPutFile(__METHOD__ . '(): No UploadID specified');
     }
     // Create the message
     $message = "<CompleteMultipartUpload>\n";
     $part = 0;
     foreach ($etags as $etag) {
         $part++;
         $message .= "\t<Part>\n\t\t<PartNumber>{$part}</PartNumber>\n\t\t<ETag>\"{$etag}\"</ETag>\n\t</Part>\n";
     }
     $message .= "</CompleteMultipartUpload>";
     // Get a request query
     $reqInput = Input::createFromData($message);
     $request = new Request('POST', $bucket, $uri, $this->configuration);
     $request->setParameter('uploadId', $UploadID);
     $request->setInput($reqInput);
     // Do post
     $request->setHeader('Content-Type', 'application/xml');
     // Even though the Amazon API doc doesn't mention it, it's required... :(
     $response = $request->getResponse();
     if (!$response->error->isError() && $response->code != 200) {
         $response->error = new Error($response->code, "Unexpected HTTP status {$response->code}");
     }
     if ($response->error->isError()) {
         if ($response->error->getCode() == 'RequestTimeout') {
             return;
         }
         throw new CannotPutFile(sprintf(__METHOD__ . "(): [%s] %s\n\nDebug info:\n%s", $response->error->getCode(), $response->error->getMessage(), print_r($response->body, true)));
     }
 }