/** * Generate BCE Authorization Signature * * @param string $method HTTP Request Method. * @param string $resource The resource path. * @param array $params The query strings. * @param array $headers The extra http request headers. * @param number $timestamp The customized timestamp, if it's 0, the will use time() instead. * @param number $expiration_in_seconds The valid time in seconds. * @param array $headers_to_sign The extra http request headers will be included in the signature * * @return string */ public function generateAuthorization($method, $resource, $params = array(), $headers = array(), $timestamp = 0, $expiration_in_seconds = 1800, $headers_to_sign = null) { $raw_session_key = sprintf("bce-auth-v1/%s/%s/%d", $this->credentials->access_key_id, Time::bceTimeNow($timestamp), $expiration_in_seconds); $session_key = hash_hmac("sha256", $raw_session_key, $this->credentials->secret_access_key, false); $canonical_uri = Coder::urlEncodeExceptSlash($resource); $canonical_query_string = $this->queryStringCanonicalization($params); list($canonical_headers, $signed_headers) = $this->headersCanonicalization($headers, $headers_to_sign); $raw_signature = $method . "\n" . $canonical_uri . "\n" . $canonical_query_string . "\n" . $canonical_headers; $signature = hash_hmac("sha256", $raw_signature, $session_key, false); if (count($signed_headers) > 0) { return sprintf('%s/%s/%s', $raw_session_key, implode(';', $signed_headers), $signature); } return sprintf('%s//%s', $raw_session_key, $signature); }
/** * Send request to BCE. * * @param string $http_method The http request method, uppercase. * @param string $path The resource path. * @param string $body The http request body. * @param mixed $headers The extra http request headers. * @param mixed $params The extra http url query strings. * @param mixed $sign_function This function will genenrate authorization header. * @param mixed $output_stream Write the http response to this stream. * * @return mixed body and http_headers */ public function sendRequest($http_method, $path, $body = null, $headers = array(), $params = array(), $sign_function = null, $output_stream = null) { $curl_handle = \curl_init(); curl_setopt($curl_handle, CURLOPT_URL, $this->getRequestUrl($path, $params)); curl_setopt($curl_handle, CURLOPT_NOPROGRESS, true); curl_setopt($curl_handle, CURLINFO_HEADER_OUT, true); if (isset($this->config['connection_timeout_in_mills'])) { curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT_MS, $this->config['connection_timeout_in_mills']); } if (!isset($headers[HttpHeaders::CONTENT_LENGTH])) { $content_length = $this->guessContentLength($body); $headers[HttpHeaders::CONTENT_LENGTH] = $content_length; } $parsed_url = parse_url($this->config['endpoint']); $default_headers = array(HttpHeaders::USER_AGENT => sprintf("bce-sdk-php/%s/%s/%s", Bce::SDK_VERSION, PHP_OS, phpversion()), HttpHeaders::BCE_DATE => Time::bceTimeNow(), HttpHeaders::BCE_REQUEST_ID => BceTools::genUUid(), HttpHeaders::EXPECT => '', HttpHeaders::TRANSFER_ENCODING => '', HttpHeaders::CONTENT_TYPE => HttpContentTypes::JSON, HttpHeaders::HOST => preg_replace('/(\\w+:\\/\\/)?([^\\/]+)\\/?/', '$2', $this->config['endpoint'])); $headers = array_merge($default_headers, $headers); if (!is_null($sign_function)) { $headers[HttpHeaders::AUTHORIZATION] = call_user_func($sign_function, $this->config['credentials'], $http_method, $path, $params, $headers); } // Handle Http Request Headers $request_headers = $this->generateRequestHeaders($headers); curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $request_headers); curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $http_method); if ($http_method === HttpMethod::HEAD) { curl_setopt($curl_handle, CURLOPT_NOBODY, true); } // Handle Http Request Body // Read everything from stream interface, if $body's type is string, wrapp is as a stream. if (!is_null($body)) { $input_stream = is_string($body) ? fopen('php://memory', 'r+') : $body; if (is_string($body)) { fwrite($input_stream, $body); rewind($input_stream); } curl_setopt($curl_handle, CURLOPT_POST, true); $read_callback = function ($_1, $_2, $size) use($input_stream) { if (is_resource($input_stream)) { return fread($input_stream, $size); } else { if (method_exists($input_stream, 'read')) { return $input_stream->read($size); } } // EOF return ''; }; curl_setopt($curl_handle, CURLOPT_READFUNCTION, $read_callback); } // Handle Http Response Headers $http_response_headers = array(); $read_response_headers_callback = function ($_1, $str) use(&$http_response_headers) { array_push($http_response_headers, $str); return strlen($str); }; curl_setopt($curl_handle, CURLOPT_HEADERFUNCTION, $read_response_headers_callback); curl_setopt($curl_handle, CURLOPT_HEADER, false); // Handle Http Response Body if (!is_null($output_stream)) { $write_callback = function ($_1, $str) use($output_stream) { if (is_resource($output_stream)) { return fwrite($output_stream, $str); } else { if (method_exists($output_stream, 'write')) { return $output_stream->write($str); } } // EOF return false; }; curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, $write_callback); } else { curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true); } // Send request $http_response = curl_exec($curl_handle); $error = curl_error($curl_handle); $errno = curl_errno($curl_handle); $status = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE); $content_type = curl_getinfo($curl_handle, CURLINFO_CONTENT_TYPE); // print_r(curl_getinfo($curl_handle, CURLINFO_HEADER_OUT)); curl_close($curl_handle); $response_headers = $this->parseResponseHeaders($http_response_headers); $response_body = $this->parseHttpResponseBody($http_response, $content_type); $request_id = isset($response_headers[HttpHeaders::BCE_REQUEST_ID]) ? $response_headers[HttpHeaders::BCE_REQUEST_ID] : null; // Error Check if ($error !== '') { // printf("Url = %s\n", $this->getRequestUrl($path, $params)); throw new BceServerError($error, $status, $errno, $request_id); } if ($status >= 100 && $status < 200) { throw new BceClientError('Can not handle 1xx http status code'); } else { if ($status < 200 || $status >= 300) { if (isset($response_body['message'])) { throw new BceServerError($response_body['message'], $status, $response_body['code'], $response_body['requestId']); } throw new BceServerError($http_response, $status); } } // $status >= 200 && $status < 300 means HTTP OK return array('http_headers' => $response_headers, 'body' => $response_body); }
public function testListMultipartUploadsX() { $this->client->createBucket($this->bucket); $time1 = Time::BceTimeNow(); $response = $this->client->initiateMultipartUpload($this->bucket, 'aaa'); $upload_id1 = $response['body']['uploadId']; $time2 = Time::BceTimeNow(); $response = $this->client->initiateMultipartUpload($this->bucket, 'bbb'); $upload_id2 = $response['body']['uploadId']; $response = $this->client->listMultipartUploads($this->bucket); $this->checkProperties($response); $this->assertEquals(1000, $response['body']['maxUploads']); $this->assertEquals('', $response['body']['prefix']); $this->assertEquals('', $response['body']['keyMarker']); $this->assertEquals('false', $response['body']['isTruncated']); $this->assertEquals(2, count($response['body']['uploads'])); $this->assertEquals($upload_id1, $response['body']['uploads'][0]['uploadId']); $this->assertEquals($time1, $response['body']['uploads'][0]['initiated']); $this->assertEquals($upload_id2, $response['body']['uploads'][1]['uploadId']); $this->assertEquals($time2, $response['body']['uploads'][1]['initiated']); $response = $this->client->listMultipartUploads($this->bucket, 1, null, null, ''); $this->checkProperties($response); $this->assertEquals(1, $response['body']['maxUploads']); $this->assertEquals('', $response['body']['prefix']); $this->assertEquals('', $response['body']['keyMarker']); $this->assertEquals('true', $response['body']['isTruncated']); $this->assertEquals(1, count($response['body']['uploads'])); $this->assertEquals($upload_id1, $response['body']['uploads'][0]['uploadId']); $this->assertEquals($time1, $response['body']['uploads'][0]['initiated']); }