caseyamcl/wosclient

一个便携式PHP客户端库,用于访问DDN(WOS)Web对象标量API中的数据

v1.0 2016-06-09 20:05 UTC

This package is auto-updated.

Last update: 2024-09-12 06:14:14 UTC


README

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

这个库是一个便携式HTTP客户端,用于访问DDN Web Object Scalar存储系统的HTTP API。

与官方DDN PHP客户端不同,此库通过HTTP与WOS设备通信,不需要安装任何PHP C扩展。

安装

此库需要PHP v5.5或更高版本。它已在PHP7上进行了测试。如果您想运行测试,您必须运行v5.6或更高版本。

我还建议安装ext-curl PHP扩展。

通过Composer

$ composer require caseyamcl/wosclient guzzlehttp/guzzle

注意:默认情况下,此库使用Guzzle v6.0。但是,如果您不想使用Guzzle 6,您可以通过自己实现WosClientInterface来创建自己的实现(详情见下文)。

用法

此库使用PSR-4自动加载。如果您不使用Composer或其他PSR-4自动加载器,您需要手动包含src/目录中的所有文件(但我强烈建议这样做;使用自动加载器!)。

如果您知道您的WOS API的URL以及您的WOS策略名称或ID,您可以通过调用WosClient::build()构造函数来创建一个WosClient实例。传入您的WOS API的URL以及您的WOS策略名称或ID

use WosClient\WosClient;

$wosClient = WosClient::build('http://mywos.example.org/', 'my-policy-id');

WosClient包含几个公共方法,用于与对象存储API交互

// Get an object by its Object ID (OID)
$wosObject = $wosClient->getObject('abcdef-ghijkl-mnopqr-12345');

// Get a range of data for a large object (get bytes 50000-100000)
$partialWosObject = $wosClient->getObject('abcdef-ghijkl-mnopqr-12345', '50000-100000'); 

// Get metadata for an Object ID (OID)
$wosMetadata = $wosClient->getMetadata('abcdef-ghijkl-mnopqr-12345');

// Put an object
$wosObjectId = $wosClient->putObject('some-serializable-or-streamable-data', ['some' => 'metadata']);

// Reserve an Object ID, without putting any data in it yet
$wosObjectId = $wosClient->reserveObject();

// Put an object having reserved its ID ahead of time with reserveObject()
$wosObjectId = $wosClient->putObject('some-serializable-or-streamable-data', [], $reservedObjectId);

// Delete an object
$wosClient->deleteObject('abcdef-ghijkl-mnopqr-12345');

所有这些方法都可选地接受一个包含Guzzle HTTP请求选项的数组作为最后一个方法参数。如果您以这种方式传递任何选项,它们将覆盖所有默认和计算出的请求选项。如果您以这种方式传递HTTP头,它们将与默认头合并(见Guzzle文档)。

使用响应

WosClient::getObject()方法返回一个WosClient\WosObject实例

// Get the object
$wosObject = $wosClient->getObject('abcdef-ghijkl-mnopqr-12345');

// Get the data from the response as a string
$wosObject->getData()->__toString();

// or, as a shortcut..
$wosObject->__toString();

// Get the Object ID
$wosObject->getId();

WosClient::getMetadata()WosObject::getMetadata()方法返回一个WosClient\WosObjectMetadata实例

// Get the meta-data (instance of WosObjectMetadata; see below)
$metadata = $wosObject->getMetadata();

// Get access to the HTTP response
$wosObject->getHttpResponse();

// Get the metadata from the object
$wosObject = $wosClient->getObject('abcdef-ghijkl-mnopqr-12345');
$metadata = $wosObject->getMetadata();

// ..or just get the metadata for the object from the WOS server without
// getting the content
$metadata = $wosClient->getMetadata('abcdef-ghijkl-mnopqr-12345');

// Get the object ID
$objectId = $metadata->getObjectId();

// Get the object size in bytes - This returns NULL if not known
$numBytes = $metadata->getObjectSize();

// Access custom metadata (having been added with `WosObject::putMetadata()`
$foo = $metadata->get('foo');

// Conditionally get metadat if it exists
if  ($metadata->has('bar')) {
    $bar = $metadata->get('bar');
}

// Metadata implements \Countable, \ArrayAccess, and \Traversable
$foo = $metadata['foo'];
$bar = $metadata['bar'];
$num = count($metadata);

for ($metadata as $key => $val) {
    echo "$key: $val";
}

WosClient::putObject()WosClient::reserveObject()方法返回一个WosClient\WosObjectId实例

// Put an object with auto-generated ID
$wosObjectId = $wosClient->putObject('some object data');

// Reserve an object ID
$wosObjectId = $wosClient->reserveObject();

// Get the ID as a string
$idString = $wosObjectId->getId();

// ..or cast as string..
$idString = (string) $wosObjectId;

流式传输大对象

WOS支持最大5太字节的对象!

如果您从WOS服务器检索的对象非常大,一次性将其全部读入内存不是一个好主意。

幸运的是,默认情况下,此库将从WOS服务器流数据,而不是将其下载到内存中。该库使用PSR-7 StreamableInterface来完成此操作。

要流式传输大文件,只需在文件中进行查找,而不是将其转换为字符串

$veryLargeWosObject = $wosClient->getObject('abcdef-ghijkl-mnopqr-12345');
$dataStream = $veryLargeWosObject->getData();

// Read the data stream 1024 bytes at a time, and 
// echo the data out..  You could do anything with the chunked data if
// you wish...
while ( ! $dataStream->eof()) {
    echo $dataStream->read(1024);
}

另一种从您的WOS服务器流式传输数据的方法是指定WosClient::getObject()$range参数,以一次检索大对象的片段

$metadata  = $wosClient->getMetadata('abcdef-ghijkl-mnopqr-12345');
$chunkSize = 1024; // read this many bytes at a time

for ($i = 0; $i < $metadata->getLength(); $i+= $chunkSize) {

    $from = $i;
    $to   = $i + $chunkSize;

    // WosClient::getObject second parameter accepts range in the format '####-####' (e.g. '1024-2048')
    echo $wosClient->getObject('abcdef-ghijkl-mnopqr-12345', $from . '- . $to)->__toString();
}

处理错误

此库将所有应用层运行时错误转换为WosClient\Exception\WosException实例。有三个子类

  • WosClient\Exception\WosServerException - 当 WOS 服务器拒绝请求或遇到错误并返回带有除成功(0)之外的其他 x-ddn-status 标头的响应时,会抛出此异常。异常代码将对应于 WOS DDN 状态代码,而消息将是服务器返回的代码的详细描述。
  • WosClient\Exception\InvalidResponseException - 当服务器返回的 HTTP 响应缺少预期存在的 HTTP 标头时,会抛出此异常。例如,当 getObject() 服务器响应不包括 x-ddn-oid 标头时。
  • WosClient\Exception\InvalidParameterException - 当提供的头值不是 WOS 所需的预期格式时,会抛出此异常。例如,如果 Range 头不是 ###-### 格式。它在将请求发送到服务器之前抛出。

示例

use WosClient\Exception\WosServerException;

try {
   $wosClient->getObject('does-not-exist');
} catch (WosServerException $e) {

    // WOS User-friendly message, e.g., 'Object cannot be located'
    echo $e->getMessage();
    
    // WOS Code, e.g., 207
    echo $e->getCode();
    
    // WOS Error Name (machine-friendly, uses CamelCase), e.g., 'ObjNotFound'
    echo $e->getErrorName();
}

请注意,只有当服务器返回带有 x-ddn-status 标头的响应,并且该标头值不为零时,才会抛出 WosServerException

它不会在发生任何其他 HTTP 传输错误(如网络超时或 WOS 服务器内部错误)时抛出。您可以通过捕获 Guzzle 异常来分别捕获这些类型的 HTTP 错误。

use WosClient\Exception\WosServerException;
use WosClient\Exception\WosRequestException;
use GuzzleHttp\Exception\GuzzleException;

try {
   $wosClient->getObject('does-not-exist');
}
catch (WosServerException $e) {

    // WOS Exception thrown by the WOS Client
    echo 'WOS Error: ' . $e->getMessage();
    
}
catch (WosRequestException $e) {

    // Some other application exception occurred, such as
    // the WOS server returned a response that is missing an
    // expected header (this really should never happen)
    echo 'Something strange happened: ' . $e->getMessage();
}
catch (GuzzleException $e) {

   // HTTP Exception thrown by Guzzle
   echo 'HTTP Error: ' . $e->getMessage();
}

Guzzle 库包含多个不同类型的异常类,以便您在异常处理中更加具体。

使用自定义 Guzzle 6 客户端实例进行实例化

您可能希望使用自己的 Guzzle 6 客户端实例向 WOS 服务器发送请求。您可能希望这样做的一些原因包括

  • 您已设置自己的请求/响应中间件,或
  • 您希望使用自定义 HTTP 请求默认值(例如 connect_timeout),或
  • 您希望在请求/响应周期中访问 HTTP Response 对象。

要使用自定义 Guzzle 客户端实例,只需使用 WosClient\WosClient 类的主构造函数,而不是 build() 构造函数。

base_uri 参数必须在您的 Guzzle 客户端类中设置,否则库将在对象构造期间抛出 \RuntimeException。此值必须是您的 WOS 节点之一的 URL。

您还可以设置 x-ddn-policy 标头,这样您就不必在每次请求中指定它。

use WosClient\WosClient;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;

// Setup custom Guzzle client
$guzzleClient = new GuzzleClient([
    'base_uri'        => 'http://mywos.example.org/',
    'connect_timeout' => 60,
    'handler'         => HandlerStack::create(new CurlHandler()),
    'headers'         => [
        'x-ddn-policy' => 'my-policy'
    ],
    /** ..other guzzle options here.. */
]);

// Instantiate a new WOS Client
$wosClient = new WosClient($guzzleClient);

创建不同的 WOS 客户端实现

您可能希望为该库中包含的接口编写自己的实现。在这种情况下,唯一的依赖项是您必须包含 "psr/http-message": "~1.0" 包。

如果您的实现使用的是符合 PSR-7 的 HTTP 库,则您只需要实现 WosClient\WosClientInterface。您可以使用所有其他类的内置实现。

然而,如果您的实现不实现 PSR-7,则您需要实现以下接口

  • WosClient\WosClientInterface
  • WosObjectInterface
  • WosObjectIdInterface
  • WosObjectMetadataInterface
  • Psr\Http\Message\StreamInterface(提示:Guzzle Streams 做得相当不错)

每个接口文件都包含有关其方法应如何行为的相当不错的文档。

请注意,您应在特定情况下仅抛出异常

  • WosClient\Exception\WosServerException - 如果 WOS 服务器发出错误代码(请参阅 WOS API 文档),则抛出此异常。
  • WosClient\Exception\InvalidParameterException - 如果您在发送请求到服务器之前在客户端验证参数或 HTTP 头,则抛出此异常。
  • WosClient\Exception\InvalidResponseException - 如果服务器生成客户端无法处理的响应,则抛出此异常。例如,服务器不包括预期存在的 HTTP 头。

变更日志

有关最近更改的更多信息,请参阅变更日志

测试

要运行测试,请确保您已经安装了 composer.json 文件中的 require-dev 部分的所有依赖项。

运行单元测试

$ composer test

此库还包括一个简单的控制台工具,用于测试客户端与您的 WOS 设备。测试套件将两个微小的对象写入 WOS,然后删除它们。

$ composer livetest http://your-wos.example.org your-policy-id

运行 PHP CodeSniffer 检测风格错误

$ composer sniff

贡献

有关详细信息,请参阅 CONTRIBUTING

安全性

如果您发现任何与安全相关的问题,请通过电子邮件 caseyamcl@gmail.com 联系,而不是使用问题跟踪器。

致谢

许可证

MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件