189 lines
5.5 KiB
PHP
189 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace Yeepay\Yop\Sdk\Utils\Http;
|
|
|
|
use GuzzleHttp\Psr7\Uri;
|
|
use Yeepay\Yop\Sdk\Http\Headers;
|
|
use Yeepay\Yop\Sdk\Http\HttpMethod;
|
|
use Yeepay\Yop\Sdk\Internal\Request;
|
|
|
|
class HttpUtils
|
|
{
|
|
|
|
private static $defaultPorts;
|
|
|
|
private static $PERCENT_ENCODED_STRINGS;
|
|
|
|
public static function __init()
|
|
{
|
|
self::$defaultPorts = ["http" => 80, "https" => 443];
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS = [];
|
|
for ($i = 0; $i < 256; ++$i) {
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[$i] = sprintf("%%%02X", $i);
|
|
}
|
|
foreach (range('a', 'z') as $ch) {
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord($ch)] = $ch;
|
|
}
|
|
|
|
foreach (range('A', 'Z') as $ch) {
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord($ch)] = $ch;
|
|
}
|
|
|
|
foreach (range('0', '9') as $ch) {
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord($ch)] = $ch;
|
|
}
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord('-')] = '-';
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord('.')] = '.';
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord('_')] = '_';
|
|
HttpUtils::$PERCENT_ENCODED_STRINGS[ord('~')] = '~';
|
|
}
|
|
|
|
public static function generateHostHeader(Uri $uri)
|
|
{
|
|
$host = $uri->getHost();
|
|
if (self::isUsingNonDefaultPort($uri)) {
|
|
$host .= ':'.$uri->getPort();
|
|
}
|
|
|
|
return $host;
|
|
}
|
|
|
|
public static function isUsingNonDefaultPort(Uri $uri)
|
|
{
|
|
$schema = strtolower($uri->getScheme());
|
|
$port = $uri->getPort();
|
|
if (empty($port) && $port < 0) {
|
|
return false;
|
|
}
|
|
|
|
return $port != self::$defaultPorts[$schema];
|
|
}
|
|
|
|
/**
|
|
* Normalize a string for use in url path. The algorithm is:
|
|
* <p>
|
|
* <ol>
|
|
* <li>Normalize the string</li>
|
|
* <li>replace all "%2F" with "/"</li>
|
|
* <li>replace all "//" with "/%2F"</li>
|
|
* </ol>
|
|
* <p>
|
|
* Bos object key can contain arbitrary characters, which may result double
|
|
* slash in the url path. Apache Http client will replace "//" in the path
|
|
* with a single '/', which makes the object key incorrect. Thus we replace
|
|
* "//" with "/%2F" here.
|
|
* @param $path string the path string to normalize.
|
|
* @return string the normalized path string.
|
|
* @see #normalize(string)
|
|
*/
|
|
public static function urlEncodeExceptSlash($path)
|
|
{
|
|
return str_replace("%2F", "/", self::urlEncode($path));
|
|
}
|
|
|
|
/**
|
|
* Normalize a string for use in BCE web service APIs. The normalization
|
|
* algorithm is:
|
|
* <p>
|
|
* <ol>
|
|
* <li>Convert the string into a UTF-8 byte array.</li>
|
|
* <li>Encode all octets into percent-encoding, except all URI unreserved
|
|
* characters per the RFC 3986.</li>
|
|
* </ol>
|
|
* <p>
|
|
* All letters used in the percent-encoding are in uppercase.
|
|
* @param $value string the string to normalize.
|
|
* @return string the normalized string.
|
|
*/
|
|
public static function urlEncode($value)
|
|
{
|
|
$result = '';
|
|
for ($i = 0; $i < strlen($value); ++$i) {
|
|
$result .= self::$PERCENT_ENCODED_STRINGS[ord($value[$i])];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @param $parameters array
|
|
* @param $forSignature bool
|
|
* @return string
|
|
*/
|
|
public static function getCanonicalQueryString(array $parameters, $forSignature)
|
|
{
|
|
if (count($parameters) == 0) {
|
|
return '';
|
|
}
|
|
|
|
$parameterStrings = [];
|
|
foreach ($parameters as $name => $values) {
|
|
if ($forSignature
|
|
&& strcasecmp(Headers::AUTHORIZATION, $name) == 0) {
|
|
continue;
|
|
}
|
|
if (!isset($name)) {
|
|
throw new \InvalidArgumentException(
|
|
"parameter key should not be null"
|
|
);
|
|
}
|
|
if (empty($values)) {
|
|
if ($forSignature) {
|
|
$parameterStrings[] = self::urlEncode($name).'=';
|
|
} else {
|
|
$parameterStrings[] = self::urlEncode($name);
|
|
}
|
|
} else {
|
|
foreach ($values as $value) {
|
|
$parameterStrings[] = self::urlEncode($name)
|
|
.'='.self::urlEncode($value);
|
|
}
|
|
}
|
|
|
|
}
|
|
if ($forSignature) {
|
|
sort($parameterStrings);
|
|
}
|
|
|
|
return implode('&', $parameterStrings);
|
|
}
|
|
|
|
/**
|
|
* @param array $parameters
|
|
* @return array
|
|
*/
|
|
public static function encodedParameters(array $parameters)
|
|
{
|
|
if (empty($parameters)) {
|
|
return [];
|
|
}
|
|
$encodedParameters = [];
|
|
foreach ($parameters as $name => $values) {
|
|
if (empty($values)) {
|
|
$encodedParameters[$name] = '';
|
|
} elseif (count($values) == 1) {
|
|
$encodedParameters[$name] = self::urlEncode($values[0]);
|
|
} else {
|
|
$targetValues = [];
|
|
foreach ($values as $value) {
|
|
$targetValues[] = self::urlEncode($value);
|
|
}
|
|
$encodedParameters[$name] = $targetValues;
|
|
}
|
|
}
|
|
|
|
return $encodedParameters;
|
|
}
|
|
|
|
public static function usePayloadForQueryParameters(Request $request)
|
|
{
|
|
$requestIsPOST = HttpMethod::POST == $request->getHttpMethod();
|
|
$requestHasNoPayload = empty($request->getContent());
|
|
|
|
return $requestIsPOST && $requestHasNoPayload;
|
|
}
|
|
|
|
}
|
|
|
|
HttpUtils::__init();
|