Fixed issue where request was not created on-demand, removed code that is
not 32bit PHP compatible, modified the options for request when method is 'HEAD'. Also updated README.md & CHANGELOG.md
This commit is contained in:
Родитель
9c79381470
Коммит
a71aa6f89f
|
@ -1,4 +1,4 @@
|
|||
2016.09 - version 0.11.0
|
||||
2016.11 - version 0.11.0
|
||||
|
||||
ALL
|
||||
* Fix error string when an error occurs while parsing a connection string and is passed to _createException in `MicrosoftAzure\Storage\Common\Internal\ConnectionStringParser`.
|
||||
|
|
|
@ -25,7 +25,14 @@ This project provides a set of PHP client libraries that make it easy to access
|
|||
|
||||
* PHP 5.5 or above
|
||||
* See [composer.json](composer.json) for dependencies
|
||||
* Required extension for PHP:
|
||||
php_fileinfo.dll
|
||||
php_mbstring.dll
|
||||
php_openssl.dll
|
||||
php_xsl.dll
|
||||
|
||||
* Recommanded extension for PHP:
|
||||
php_curl.dll
|
||||
|
||||
## Download Source Code
|
||||
|
||||
|
|
|
@ -1310,7 +1310,6 @@ class BlobRestProxy extends ServiceRestProxy implements IBlob
|
|||
$headers = array();
|
||||
$postParams = array();
|
||||
$queryParams = array();
|
||||
$bodySize = null;
|
||||
$path = $this->_createPath($container, $blob);
|
||||
$statusCode = Resources::STATUS_CREATED;
|
||||
|
||||
|
@ -1628,9 +1627,6 @@ class BlobRestProxy extends ServiceRestProxy implements IBlob
|
|||
);
|
||||
};
|
||||
|
||||
//generate the decider.
|
||||
$decider = Utilities::generateIsSeekableStreamEndDecider($contentStream);
|
||||
|
||||
//add number of concurrency if specified int options.
|
||||
$clientOptions = $options->getNumberOfConcurrency() == null?
|
||||
array() : array($options->getNumberOfConcurrency);
|
||||
|
@ -1641,7 +1637,7 @@ class BlobRestProxy extends ServiceRestProxy implements IBlob
|
|||
$this->sendConcurrent(
|
||||
array(),
|
||||
$generator,
|
||||
$decider,
|
||||
Resources::STATUS_CREATED,
|
||||
$clientOptions
|
||||
);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ use GuzzleHttp\Psr7;
|
|||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use GuzzleHttp\Pool;
|
||||
use GuzzleHttp\Promise\EachPromise;
|
||||
|
||||
/**
|
||||
* Base class for all services rest proxies.
|
||||
|
@ -161,7 +161,8 @@ class ServiceRestProxy extends RestProxy
|
|||
$this->_options['http'],
|
||||
array(
|
||||
"defaults" => array(
|
||||
"allow_redirects" => true, "exceptions" => true,
|
||||
"allow_redirects" => true,
|
||||
"exceptions" => true,
|
||||
"decode_content" => true,
|
||||
),
|
||||
'cookies' => true,
|
||||
|
@ -185,8 +186,8 @@ class ServiceRestProxy extends RestProxy
|
|||
* using the generator.
|
||||
* @param callable $generator the generator function to
|
||||
* generate request upon fullfilment
|
||||
* @param callable $decider decide if the generator
|
||||
* continues to append.
|
||||
* @param int $expectedStatusCode The expected status code for each
|
||||
* of the request.
|
||||
* @param array $clientOptions an array of additional options
|
||||
* for the client.
|
||||
*
|
||||
|
@ -195,7 +196,7 @@ class ServiceRestProxy extends RestProxy
|
|||
protected function sendConcurrent(
|
||||
$requests,
|
||||
$generator,
|
||||
$decider,
|
||||
$expectedStatusCode,
|
||||
$clientOptions = []
|
||||
) {
|
||||
//set the number of concurrency to default value if not defined
|
||||
|
@ -208,41 +209,41 @@ class ServiceRestProxy extends RestProxy
|
|||
//create the client
|
||||
$client = $this->createClient($clientOptions);
|
||||
|
||||
//generate the first batch if requests are empty.
|
||||
if (empty($requests) && is_callable($generator)) {
|
||||
$requests = array();
|
||||
for ($index = 0;
|
||||
$index < $numberOfConcurrency && !$decider();
|
||||
++$index) {
|
||||
$requests[] = $generator();
|
||||
}
|
||||
}
|
||||
|
||||
$requestsIterator = new \ArrayIterator($requests);
|
||||
|
||||
$pool = new Pool($client, $requestsIterator, [
|
||||
'concurrency' => $numberOfConcurrency,
|
||||
'fulfilled' => function (
|
||||
$response,
|
||||
$index
|
||||
) use (
|
||||
$requestsIterator,
|
||||
$generator,
|
||||
$decider
|
||||
) {
|
||||
//append new request using the generator.
|
||||
if (is_callable($generator) && !$decider()) {
|
||||
$requestsIterator->append($generator());
|
||||
$promises = \call_user_func(
|
||||
function () use ($requests, $generator, $client) {
|
||||
$sendAsync = function ($request) use ($client) {
|
||||
$options = $request->getMethod() == 'HEAD'?
|
||||
array('decode_content' => false) : array();
|
||||
return $client->sendAsync($request, $options);
|
||||
};
|
||||
foreach ($requests as $request) {
|
||||
yield $sendAsync($request);
|
||||
}
|
||||
while (is_callable($generator) && ($request = $generator())) {
|
||||
yield $sendAsync($request);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$eachPromise = new EachPromise($promises, [
|
||||
'concurrency' => $numberOfConcurrency,
|
||||
'fulfilled' => function ($response, $index) use ($expectedStatusCode) {
|
||||
//the promise is fulfilled, evaluate the response
|
||||
self::throwIfError(
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase(),
|
||||
$response->getBody(),
|
||||
$expectedStatusCode
|
||||
);
|
||||
},
|
||||
'rejected' => function ($reason, $index) {
|
||||
//Still rejected even if the retry logic has been applied.
|
||||
//Throwing exception.
|
||||
throw $reason;
|
||||
},
|
||||
}
|
||||
]);
|
||||
|
||||
return $pool->promise()->wait();
|
||||
|
||||
return $eachPromise->promise()->wait();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -338,7 +339,9 @@ class ServiceRestProxy extends RestProxy
|
|||
$client = $this->createClient($clientOptions);
|
||||
|
||||
try {
|
||||
$response = $client->send($request);
|
||||
$options = $request->getMethod() == 'HEAD'?
|
||||
array('decode_content' => false) : array();
|
||||
$response = $client->send($request, $options);
|
||||
self::throwIfError(
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase(),
|
||||
|
|
|
@ -778,33 +778,4 @@ class Utilities
|
|||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a decider that returns false if a given stream is not ended.
|
||||
*
|
||||
* @param StreamInterface $contentStream The stream to be decided on.
|
||||
*
|
||||
* @return callable A callable that returns true
|
||||
* if the stream reaches its end.
|
||||
*/
|
||||
public static function generateIsSeekableStreamEndDecider($contentStream)
|
||||
{
|
||||
return function () use ($contentStream) {
|
||||
$isEnd = false;
|
||||
if ($contentStream->eof()) {
|
||||
$isEnd = true;
|
||||
} else {
|
||||
//if the content stream is read to exactly the end of file
|
||||
//the content stream will still not return true for eof()
|
||||
//Have to read another byte, then see if it is null.
|
||||
$str = $contentStream->read(1);
|
||||
if ($str != '') {
|
||||
$contentStream->seek(-1, SEEK_CUR);
|
||||
} else {
|
||||
$isEnd = true;
|
||||
}
|
||||
}
|
||||
return $isEnd;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -769,52 +769,4 @@ class UtilitiesTest extends \PHPUnit_Framework_TestCase
|
|||
// Delete file after assertion.
|
||||
unlink($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers MicrosoftAzure\Storage\Common\Internal\Utilities::generateIsSeekableStreamEndDecider
|
||||
*/
|
||||
public function testGenerateIsSeekableStreamEndDecider()
|
||||
{
|
||||
//prepare a file
|
||||
$cwd = getcwd();
|
||||
$uuid = uniqid('test-file-', true);
|
||||
$path = $cwd.DIRECTORY_SEPARATOR.$uuid.'.txt';
|
||||
$resource = fopen($path, 'w+');
|
||||
$count = 2;
|
||||
for ($index = 0; $index < $count; ++$index) {
|
||||
fwrite($resource, openssl_random_pseudo_bytes(4194304));
|
||||
}
|
||||
rewind($resource);
|
||||
$stream = Psr7\stream_for($resource);
|
||||
$decider = Utilities::generateIsSeekableStreamEndDecider($stream);
|
||||
$result_0 = $decider();
|
||||
$stream->read(4194304 * $count - 1);
|
||||
$result_1 = $decider();
|
||||
$stream->read(1);
|
||||
$result_2 = $decider();
|
||||
|
||||
//prepare a string
|
||||
$count = 2;
|
||||
$testStr = openssl_random_pseudo_bytes(4194304 * $count);
|
||||
$stream = Psr7\stream_for($testStr);
|
||||
$decider = Utilities::generateIsSeekableStreamEndDecider($stream);
|
||||
$result_3 = $decider();
|
||||
$stream->read(4194304 * $count - 1);
|
||||
$result_4 = $decider();
|
||||
$stream->read(1);
|
||||
$result_5 = $decider();
|
||||
|
||||
$this->assertFalse($result_0);
|
||||
$this->assertFalse($result_1);
|
||||
$this->assertFalse($result_3);
|
||||
$this->assertFalse($result_4);
|
||||
$this->assertTrue($result_2);
|
||||
$this->assertTrue($result_5);
|
||||
|
||||
if (is_resource($resource)) {
|
||||
fclose($resource);
|
||||
}
|
||||
// Delete file after assertion.
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче