~ballot/wordpress/openstack-objectstorage

« back to all changes in this revision

Viewing changes to vendor/guzzlehttp/guzzle/docs/streams.rst

  • Committer: Benjamin Allot
  • Date: 2020-07-02 16:31:38 UTC
  • Revision ID: benjamin.allot@canonical.com-20200702163138-qyk6njanak5uw2pg
Revert to revno 3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=======
 
2
Streams
 
3
=======
 
4
 
 
5
Guzzle uses stream objects to represent request and response message bodies.
 
6
These stream objects allow you to work with various types of data all using a
 
7
common interface.
 
8
 
 
9
HTTP messages consist of a start-line, headers, and a body. The body of an HTTP
 
10
message can be very small or extremely large. Attempting to represent the body
 
11
of a message as a string can easily consume more memory than intended because
 
12
the body must be stored completely in memory. Attempting to store the body of a
 
13
request or response in memory would preclude the use of that implementation from
 
14
being able to work with large message bodies. The StreamInterface is used in
 
15
order to hide the implementation details of where a stream of data is read from
 
16
or written to.
 
17
 
 
18
Guzzle's StreamInterface exposes several methods that enable streams to be read
 
19
from, written to, and traversed effectively.
 
20
 
 
21
Streams expose their capabilities using three methods: ``isReadable()``,
 
22
``isWritable()``, and ``isSeekable()``. These methods can be used by stream
 
23
collaborators to determine if a stream is capable of their requirements.
 
24
 
 
25
Each stream instance has various capabilities: they can be read-only,
 
26
write-only, read-write, allow arbitrary random access (seeking forwards or
 
27
backwards to any location), or only allow sequential access (for example in the
 
28
case of a socket or pipe).
 
29
 
 
30
Creating Streams
 
31
================
 
32
 
 
33
The best way to create a stream is using the static factory method,
 
34
``GuzzleHttp\Stream\Stream::factory()``. This factory accepts strings,
 
35
resources returned from ``fopen()``, an object that implements
 
36
``__toString()``, and an object that implements
 
37
``GuzzleHttp\Stream\StreamInterface``.
 
38
 
 
39
.. code-block:: php
 
40
 
 
41
    use GuzzleHttp\Stream\Stream;
 
42
 
 
43
    $stream = Stream::factory('string data');
 
44
    echo $stream;
 
45
    // string data
 
46
    echo $stream->read(3);
 
47
    // str
 
48
    echo $stream->getContents();
 
49
    // ing data
 
50
    var_export($stream->eof());
 
51
    // true
 
52
    var_export($stream->tell());
 
53
    // 11
 
54
 
 
55
Metadata Streams
 
56
================
 
57
 
 
58
Guzzle streams that implement ``GuzzleHttp\Stream\MetadataStreamInterface``
 
59
expose stream metadata through the ``getMetadata()`` method. This method
 
60
provides the data you would retrieve when calling PHP's
 
61
`stream_get_meta_data() function <http://php.net/manual/en/function.stream-get-meta-data.php>`_.
 
62
 
 
63
.. code-block:: php
 
64
 
 
65
    use GuzzleHttp\Stream\Stream;
 
66
 
 
67
    $resource = fopen('/path/to/file', 'r');
 
68
    $stream = Stream::factory($resource);
 
69
    echo $stream->getMetadata('uri');
 
70
    // /path/to/file
 
71
    var_export($stream->isReadable());
 
72
    // true
 
73
    var_export($stream->isWritable());
 
74
    // false
 
75
    var_export($stream->isSeekable());
 
76
    // true
 
77
 
 
78
.. note::
 
79
 
 
80
    Streams created using ``GuzzleHttp\Stream\Stream::factory()`` all implement
 
81
    ``GuzzleHttp\Stream\MetadataStreamInterface``.
 
82
 
 
83
Stream Decorators
 
84
=================
 
85
 
 
86
With the small and focused interface, add custom functionality to streams is
 
87
very simple with stream decorators. Guzzle provides several built-in decorators
 
88
that provide additional stream functionality.
 
89
 
 
90
CachingStream
 
91
-------------
 
92
 
 
93
The CachingStream is used to allow seeking over previously read bytes on
 
94
non-seekable streams. This can be useful when transferring a non-seekable
 
95
entity body fails due to needing to rewind the stream (for example, resulting
 
96
from a redirect). Data that is read from the remote stream will be buffered in
 
97
a PHP temp stream so that previously read bytes are cached first in memory,
 
98
then on disk.
 
99
 
 
100
.. code-block:: php
 
101
 
 
102
    use GuzzleHttp\Stream\Stream;
 
103
    use GuzzleHttp\Stream\CachingStream;
 
104
 
 
105
    $original = Stream::factory(fopen('http://www.google.com', 'r'));
 
106
    $stream = new CachingStream($original);
 
107
 
 
108
    $stream->read(1024);
 
109
    echo $stream->tell();
 
110
    // 1024
 
111
 
 
112
    $stream->seek(0);
 
113
    echo $stream->tell();
 
114
    // 0
 
115
 
 
116
LimitStream
 
117
-----------
 
118
 
 
119
LimitStream can be used to read a subset or slice of an existing stream object.
 
120
This can be useful for breaking a large file into smaller pieces to be sent in
 
121
chunks (e.g. Amazon S3's multipart upload API).
 
122
 
 
123
.. code-block:: php
 
124
 
 
125
    use GuzzleHttp\Stream\Stream;
 
126
    use GuzzleHttp\Stream\LimitStream;
 
127
 
 
128
    $original = Stream::factory(fopen('/tmp/test.txt', 'r+'));
 
129
    echo $original->getSize();
 
130
    // >>> 1048576
 
131
 
 
132
    // Limit the size of the body to 1024 bytes and start reading from byte 2048
 
133
    $stream = new LimitStream($original, 1024, 2048);
 
134
    echo $stream->getSize();
 
135
    // >>> 1024
 
136
    echo $stream->tell();
 
137
    // >>> 0
 
138
 
 
139
NoSeekStream
 
140
------------
 
141
 
 
142
NoSeekStream wraps a stream and does not allow seeking.
 
143
 
 
144
.. code-block:: php
 
145
 
 
146
    use GuzzleHttp\Stream\Stream;
 
147
    use GuzzleHttp\Stream\LimitStream;
 
148
 
 
149
    $original = Stream::factory('foo');
 
150
    $noSeek = new NoSeekStream($original);
 
151
 
 
152
    echo $noSeek->read(3);
 
153
    // foo
 
154
    var_export($noSeek->isSeekable());
 
155
    // false
 
156
    $noSeek->seek(0);
 
157
    var_export($noSeek->read(3));
 
158
    // NULL
 
159
 
 
160
Creating Custom Decorators
 
161
--------------------------
 
162
 
 
163
Creating a stream decorator is very easy thanks to the
 
164
``GuzzleHttp\Stream\StreamDecoratorTrait``. This trait provides methods that
 
165
implement ``GuzzleHttp\Stream\StreamInterface`` by proxying to an underlying
 
166
stream. Just ``use`` the ``StreamDecoratorTrait`` and implement your custom
 
167
methods.
 
168
 
 
169
For example, let's say we wanted to call a specific function each time the last
 
170
byte is read from a stream. This could be implemented by overriding the
 
171
``read()`` method.
 
172
 
 
173
.. code-block:: php
 
174
 
 
175
    use GuzzleHttp\Stream\StreamDecoratorTrait;
 
176
 
 
177
    class EofCallbackStream implements StreamInterface, MetadataStreamInterface
 
178
    {
 
179
        use StreamDecoratorTrait;
 
180
 
 
181
        private $callback;
 
182
 
 
183
        public function __construct(StreamInterface $stream, callable $callback)
 
184
        {
 
185
            $this->stream = $stream;
 
186
            $this->callback = $callback;
 
187
        }
 
188
 
 
189
        public function read($length)
 
190
        {
 
191
            $result = $this->stream->read($length);
 
192
 
 
193
            // Invoke the callback when EOF is hit.
 
194
            if ($this->eof()) {
 
195
                call_user_func($this->callback);
 
196
            }
 
197
 
 
198
            return $result;
 
199
        }
 
200
    }
 
201
 
 
202
This decorator could be added to any existing stream and used like so:
 
203
 
 
204
.. code-block:: php
 
205
 
 
206
    use GuzzleHttp\Stream\Stream;
 
207
 
 
208
    $original = Stream::factory('foo');
 
209
    $eofStream = new EofCallbackStream($original, function () {
 
210
        echo 'EOF!';
 
211
    });
 
212
 
 
213
    $eofStream->read(2);
 
214
    $eofStream->read(1);
 
215
    // echoes "EOF!"
 
216
    $eofStream->seek(0);
 
217
    $eofStream->read(3);
 
218
    // echoes "EOF!"