1
0
Fork 0
mirror of https://github.com/rest-client/rest-client.git synced 2022-11-09 13:49:40 -05:00

Add much more documentation around streaming.

Write docs on both methods of streaming responses, and add docs around
streaming request payloads.
This commit is contained in:
Andy Brody 2017-05-22 02:34:38 -04:00
parent e0e48fc4db
commit 8c3375b299
2 changed files with 87 additions and 14 deletions

View file

@ -446,33 +446,103 @@ You can:
See `RestClient::Request`'s documentation for more information.
### Streaming
### Streaming request payload
RestClient will try to stream any file-like payload rather than reading it into
memory. This happens through `RestClient::Payload::Streamed`, which is
automatically called internally by `RestClient::Payload.generate` on anything
with a `read` method.
```ruby
>> r = RestClient.put('http://httpbin.org/put', File.open('/tmp/foo.txt', 'r'),
content_type: 'text/plain')
=> <RestClient::Response 200 "{\n \"args\":...">
```
In Multipart requests, RestClient will also stream file handles passed as Hash
(or __new in 2.1__ ParamsArray).
```ruby
>> r = RestClient.put('http://httpbin.org/put',
{file_a: File.open('a.txt', 'r'),
file_b: File.open('b.txt', 'r')})
=> <RestClient::Response 200 "{\n \"args\":...">
# received by server as two file uploads with multipart/form-data
>> JSON.parse(r)['files'].keys
=> ['file_a', 'file_b']
```
### Streaming responses
Normally, when you use `RestClient.get` or the lower level
`RestClient::Request.execute method: :get` to retrieve data, the entire
response is buffered in memory and returned as the response to the call.
However, if you are retrieving a large amount of data, for example a Docker
image, an iso or any other large file, you may want to stream the response
image, an iso, or any other large file, you may want to stream the response
directly to disk rather than loading it in memory. If you have a very large
file, it may become *impossible* to load it into memory.
If you want to stream the data from the `GET` to a file as it comes, rather
than entirely in memory, you must pass `RestClient::Request.execute` a
parameter `block_response` to which you pass a `block` that streams the
request. That block, in turn, will receive the response and the ability to
stream directly to file as each chunk comes across.
There are two main ways to do this:
#### `raw_response`, saves into Tempfile
If you pass `raw_response: true` to `RestClient::Request.execute`, it will save
the response body to a temporary file (using `Tempfile`) and return a
`RestClient::RawResponse` object rather than a `RestClient::Response`.
Note that the tempfile created by `Tempfile.new` will be in `Dir.tmpdir`
(usually `/tmp/`), which you can override to store temporary files in a
different location. This file will be unlinked when it is dereferenced.
If logging is enabled, this will also print download progress.
__New in 2.1:__ Customize the interval with `:stream_log_percent` (defaults to
10 for printing a message every 10% complete).
For example:
```ruby
>> raw = RestClient::Request.execute(
method: :get,
url: 'http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso',
raw_response: true)
=> <RestClient::RawResponse @code=200, @file=#<Tempfile:/tmp/rest-client.20170522-5346-1pptjm1>, @request=<RestClient::Request @method="get", @url="http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso">>
>> raw.file.size
=> 1554186240
>> raw.file.path
=> "/tmp/rest-client.20170522-5346-1pptjm1"
raw.file.path
=> "/tmp/rest-client.20170522-5346-1pptjm1"
>> require 'digest/sha1'
>> Digest::SHA1.file(raw.file.path).hexdigest
=> "4375b73e3a1aa305a36320ffd7484682922262b3"
```
#### `block_response`, receives raw Net::HTTPResponse
If you want to stream the data from the response to a file as it comes, rather
than entirely in memory, you can also pass `RestClient::Request.execute` a
parameter `:block_response` to which you pass a block/proc. This block receives
the raw unmodified Net::HTTPResponse object from Net::HTTP, which you can use
to stream directly to a file as each chunk is received.
Note that this bypasses all the usual HTTP status code handling, so you will
want to do you own checking for HTTP 20x response codes, redirects, etc.
The following is an example:
````ruby
File.open('/some/output/file', 'w') {|f|
block = proc { |response|
response.read_body do |chunk|
f.write chunk
end
}
RestClient::Request.new(method: :get, url: 'http://somedomain.com/some/really/big/file.img', block_response: block).execute
block = proc { |response|
response.read_body do |chunk|
f.write chunk
end
}
RestClient::Request.execute(method: :get,
url: 'http://example.com/some/really/big/file.img',
block_response: block)
}
````

View file

@ -121,6 +121,9 @@ module RestClient
end
end
# TODO (breaks compatibility): ought to use mime_for() to autodetect the
# Content-Type for stream objects that have a filename.
alias :length :size
end