• Модуль: clouds
  • Путь к файлу: ~/bitrix/modules/clouds/classes/general/storage_service_google.php
  • Класс: CCloudStorageService_GoogleStorage
  • Вызов: CCloudStorageService_GoogleStorage::SendRequest
function SendRequest($access_key, $secret_key, $verb, $bucket, $file_name='/', $params='', $content='', $additional_headers=array())
{
	global $APPLICATION;
	$this->status = 0;

	if(isset($additional_headers["Content-Type"]))
	{
		$ContentType = $additional_headers["Content-Type"];
		unset($additional_headers["Content-Type"]);
	}
	else
	{
		$ContentType = $content? 'text/plain': '';
	}

	if(!array_key_exists("x-goog-api-version", $additional_headers))
		$additional_headers["x-goog-api-version"] = "1";

	$RequestMethod = $verb;
	$RequestURI = $file_name;
	$RequestDATE = gmdate('D, d M Y H:i:s', time()).' GMT';

	//Prepare Signature
	$CanonicalizedAmzHeaders = "";
	ksort($additional_headers);
	foreach($additional_headers as $key => $value)
		if(preg_match("/^x-goog-/", $key))
			$CanonicalizedAmzHeaders .= $key.":".$value."n";

	$CanonicalizedResource = "/".$bucket.$RequestURI;

	$StringToSign = "$RequestMethodnn$ContentTypen$RequestDATEn$CanonicalizedAmzHeaders$CanonicalizedResource";
	//$utf = $APPLICATION->ConvertCharset($StringToSign, LANG_CHARSET, "UTF-8");

	$Signature = base64_encode($this->hmacsha1($StringToSign, $secret_key));
	$Authorization = "GOOG1 ".$access_key.":".$Signature;

	$request = new BitrixMainWebHttpClient(array(
		"redirect" => false,
		"streamTimeout" => $this->streamTimeout,
	));
	if (isset($additional_headers["option-file-result"]))
	{
		$request->setOutputStream($additional_headers["option-file-result"]);
	}

	$request->setHeader("Date", $RequestDATE);
	$request->setHeader("Authorization", $Authorization);
	foreach($additional_headers as $key => $value)
		if(!preg_match("/^option-/", $key))
			$request->setHeader($key, $value);

	if(
		$this->new_end_point
		&& preg_match('#^(http|https)://'.preg_quote($bucket, '#').'(.+)/#', $this->new_end_point, $match))
	{
		$host = $match[2];
	}
	else
	{
		$host = $bucket.".commondatastorage.googleapis.com";
	}

	$was_end_point = $this->new_end_point;
	$this->new_end_point = '';

	$this->status = 0;
	$this->host = $host;
	$this->verb = $RequestMethod;
	$this->url =  "http://".$host.$RequestURI.$params;
	$this->headers = array();
	$this->errno = 0;
	$this->errstr = '';
	$this->result = '';

	$logRequest = false;
	if (defined("BX_CLOUDS_TRACE") && $verb !== "GET" && $verb !== "HEAD")
	{
		$stime = microtime(1);
		$logRequest = array(
			"request_id" => md5((string)mt_rand()),
			"portal" => $_SERVER["HTTP_HOST"],
			"verb" => $this->verb,
			"url" => $this->url,
		);
		AddMessage2Log(json_encode($logRequest), 'clouds', 20);
	}

	$request->setHeader("Content-type", $ContentType);
	$request->query($this->verb, $this->url, $content);

	$this->status = $request->getStatus();
	foreach($request->getHeaders() as $key => $value)
	{
		$this->headers[$key] = is_array($value) ? $value[0] : $value;
	}
	$this->errstr = implode("n", $request->getError());
	$this->errno = $this->errstr? 255: 0;
	$this->result = $request->getResult();

	if ($logRequest)
	{
		$logRequest["status"] = $this->status;
		$logRequest["time"] = round(microtime(true) - $stime, 6);
		$logRequest["headers"] = $this->headers;
		AddMessage2Log(json_encode($logRequest), 'clouds', 0);
	}

	if($this->status == 200)
	{
		if(isset($additional_headers["option-raw-result"]))
		{
			return $this->result;
		}
		elseif($this->result)
		{
			$obXML = new CDataXML;
			$text = preg_replace("/<"."\?XML.*?\?".">/i", "", $this->result);
			if($obXML->LoadString($text))
			{
				$arXML = $obXML->GetArray();
				if(is_array($arXML))
				{
					return $arXML;
				}
			}
			//XML parse error
			$APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_PARSE_ERROR', array('#errno#'=>1)));
			return false;
		}
		else
		{
			//Empty success result
			return array();
		}
	}
	elseif(
		$this->status == 307  //Temporary redirect
		&& isset($this->headers["Location"])
		&& !$was_end_point //No recurse yet
	)
	{
		$this->new_end_point = $this->headers["Location"];
		return $this->SendRequest(
			$access_key,
			$secret_key,
			$verb,
			$bucket,
			$file_name,
			$params,
			$content,
			$additional_headers
		);
	}
	elseif($this->status > 0)
	{
		if($this->result)
		{
			$obXML = new CDataXML;
			if($obXML->LoadString($this->result))
			{
				$arXML = $obXML->GetArray();
				if(is_array($arXML) && is_string($arXML["Error"]["#"]["Message"][0]["#"]))
				{
					$APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_ERROR', array('#errmsg#'=>trim($arXML["Error"]["#"]["Message"][0]["#"], '.'))));
					return false;
				}
			}
		}
		$APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_PARSE_ERROR', array('#errno#'=>2)));
		return false;
	}
	else
	{
		$APPLICATION->ThrowException(GetMessage('CLO_STORAGE_GOOGLE_XML_PARSE_ERROR', array('#errno#'=>3)));
		return false;
	}
}