/** * Get an authorization url with expire time * * @param string $bucketName The bucket name. * @param string $object_name The object path. * @param number $timestamp * @param number $expiration_in_seconds The valid time in seconds. * @param mixed $options The extra Http request headers or params. * * @return string */ public function generatePreSignedUrl($bucketName, $key, $options = array()) { list($config, $headers, $params, $signOptions) = $this->parseOptions($options, BosOptions::CONFIG, BosOptions::HEADERS, BosOptions::PARAMS, BosOptions::SIGN_OPTIONS); if (is_null($config)) { $config = $this->config; } else { $config = array_merge($this->config, $config); } if (is_null($params)) { $params = array(); } if (is_null($headers)) { $headers = array(); } $path = $this->getPath($bucketName, $key); list($hostUrl, $hostHeader) = HttpUtils::parseEndpointFromConfig($config); $headers[HttpHeaders::HOST] = $hostHeader; $auth = $this->signer->sign($config[BceClientConfigOptions::CREDENTIALS], HttpMethod::GET, $path, $headers, $params, $signOptions); $params['authorization'] = $auth; $url = $hostUrl . HttpUtils::urlEncodeExceptSlash($path); $queryString = HttpUtils::getCanonicalQueryString($params, false); if ($queryString !== '') { $url .= "?{$queryString}"; } return $url; }
/** * Send request to BCE. * * @param array $config * @param string $httpMethod The Http request method, uppercase. * @param string $path The resource path. * @param string|resource $body The Http request body. * @param array $headers The extra Http request headers. * @param array $params The extra Http url query strings. * @param SignerInterface $signer This function will generate authorization header. * @param resource|string $outputStream Write the Http response to this stream. * * @return \Guzzle\Http\Message\Response body and http_headers * * @throws BceClientException * @throws BceServiceException */ public function sendRequest(array $config, $httpMethod, $path, $body, array $headers, array $params, SignerInterface $signer, $outputStream = null, $options = array()) { $headers[HttpHeaders::USER_AGENT] = sprintf('bce-sdk-php/%s/%s/%s', Bce::SDK_VERSION, php_uname(), phpversion()); if (!isset($headers[HttpHeaders::BCE_DATE])) { $now = new \DateTime(); $now->setTimezone(DateUtils::$UTC_TIMEZONE); $headers[HttpHeaders::BCE_DATE] = DateUtils::formatAlternateIso8601Date($now); } list($hostUrl, $hostHeader) = HttpUtils::parseEndpointFromConfig($config); $headers[HttpHeaders::HOST] = $hostHeader; $url = $hostUrl . HttpUtils::urlEncodeExceptSlash($path); $queryString = HttpUtils::getCanonicalQueryString($params, false); if ($queryString !== '') { $url .= "?{$queryString}"; } if (!isset($headers[HttpHeaders::CONTENT_LENGTH])) { $headers[HttpHeaders::CONTENT_LENGTH] = $this->guessContentLength($body); } $entityBody = null; if ($headers[HttpHeaders::CONTENT_LENGTH] == 0) { //if passing a stream and content length is 0, guzzle will remove //"Content-Length:0" from header, to work around this, we have to //set body to a empty string $entityBody = ""; } else { if (is_resource($body)) { $offset = ftell($body); $original = EntityBody::factory($body); $entityBody = new ReadLimitEntityBody($original, $headers[HttpHeaders::CONTENT_LENGTH], $offset); } else { $entityBody = $body; } } $headers[HttpHeaders::AUTHORIZATION] = $signer->sign($config[BceClientConfigOptions::CREDENTIALS], $httpMethod, $path, $headers, $params, $options); if (LogFactory::isDebugEnabled()) { $this->logger->debug('HTTP method: ' . $httpMethod); $this->logger->debug('HTTP url: ' . $url); $this->logger->debug('HTTP headers: ' . print_r($headers, true)); } $guzzleRequestOptions = array('exceptions' => false); if (isset($config[BceClientConfigOptions::CONNECTION_TIMEOUT_IN_MILLIS])) { $guzzleRequestOptions['connect_timeout'] = $config[BceClientConfigOptions::CONNECTION_TIMEOUT_IN_MILLIS] / 1000.0; } if (isset($config[BceClientConfigOptions::SOCKET_TIMEOUT_IN_MILLIS])) { $guzzleRequestOptions['timeout'] = $config[BceClientConfigOptions::SOCKET_TIMEOUT_IN_MILLIS] / 1000.0; } $guzzleRequest = $this->guzzleClient->createRequest($httpMethod, $url, $headers, $entityBody, $guzzleRequestOptions); if ($outputStream !== null) { $guzzleRequest->setResponseBody($outputStream); } // Send request try { $guzzleResponse = $this->guzzleClient->send($guzzleRequest); } catch (\Exception $e) { throw new BceClientException($e->getMessage()); } if ($guzzleResponse->isInformational()) { throw new BceClientException('Can not handle 1xx Http status code'); } elseif (!$guzzleResponse->isSuccessful()) { $requestId = $guzzleResponse->getHeader(HttpHeaders::BCE_REQUEST_ID); $message = $guzzleResponse->getReasonPhrase(); $code = null; if ($guzzleResponse->isContentType('json')) { try { $responseBody = $guzzleResponse->json(); if (isset($responseBody['message'])) { $message = $responseBody['message']; } if (isset($responseBody['code'])) { $code = $responseBody['code']; } } catch (\Exception $e) { // ignore this error $this->logger->warning('Fail to parse error response body: ' . $e->getMessage()); } } throw new BceServiceException($requestId, $code, $message, $guzzleResponse->getStatusCode()); } if ($outputStream === null) { $body = $guzzleResponse->getBody(true); } else { $body = null; // detach the stream so that it will not be closed when the response // is garbage collected. $guzzleResponse->getBody()->detachStream(); } return array('headers' => $this->parseHeaders($guzzleResponse), 'body' => $body); }