Skip to content

Commit

Permalink
Merge pull request #1280 from lfidnl/support_rack_sendfile
Browse files Browse the repository at this point in the history
Support Rack::Sendfile middleware
  • Loading branch information
dblock committed Feb 29, 2016
2 parents 267ca05 + 0c827c1 commit d78422d
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* [#1252](https://github.com/ruby-grape/grape/pull/1252): Allow default to be a subset or equal to allowed values without raising IncompatibleOptionValues - [@jeradphelps](https://github.com/jeradphelps).
* [#1255](https://github.com/ruby-grape/grape/pull/1255): Allow param type definition in `route_param` - [@namusyaka](https://github.com/namusyaka).
* [#1257](https://github.com/ruby-grape/grape/pull/1257): Allow Proc, Symbol or String in `rescue_from with: ...` - [@namusyaka](https://github.com/namusyaka).
* [#1280](https://github.com/ruby-grape/grape/pull/1280): Support `Rack::Sendfile` middleware - [@lfidnl](https://github.com/lfidnl).
* [#1285](https://github.com/ruby-grape/grape/pull/1285): Add a warning for errors appearing in `after` callbacks - [@gregormelhorn](https://github.com/gregormelhorn).
* [#1295](https://github.com/ruby-grape/grape/pull/1295): Add custom validation messages for parameter exceptions - [@railsmith](https://github.com/railsmith).
* Your contribution here.
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2442,6 +2442,30 @@ class API < Grape::API
end
```
If you want to take advantage of `Rack::Sendfile`, which intercepts responses whose body is
being served from a file and replaces it with a server specific X-Sendfile header, specify `to_path`
method in your file streamer class which returns path of served file:
```ruby
class FileStreamer
# ...
def to_path
@file_path
end
# ...
end
```
Note: don't forget turn on `Rack::Sendfile` middleware in your API:

```ruby
class API < Grape::API
use Rack::Sendfile
end
```

## Authentication

### Basic and Digest Auth
Expand Down
1 change: 1 addition & 0 deletions lib/grape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ module Util
autoload :InheritableSetting
autoload :StrictHashConfiguration
autoload :FileResponse
autoload :SendfileResponse
end

module DSL
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/middleware/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def build_formatted_response(status, headers, bodies)
headers = ensure_content_type(headers)

if bodies.is_a?(Grape::Util::FileResponse)
Rack::Response.new([], status, headers) do |resp|
Grape::Util::SendfileResponse.new([], status, headers) do |resp|
resp.body = bodies.file
end
else
Expand Down
19 changes: 19 additions & 0 deletions lib/grape/util/sendfile_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Grape
module Util
# Response should respond to to_path method
# for using Rack::SendFile middleware
class SendfileResponse < Rack::Response
def respond_to?(method_name, include_all = false)
if method_name == :to_path
@body.respond_to?(:to_path, include_all)
else
super
end
end

def to_path
@body.to_path
end
end
end
end
44 changes: 44 additions & 0 deletions spec/grape/integration/rack_sendfile_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'spec_helper'

describe Rack::Sendfile do
subject do
send_file = file_streamer
app = Class.new(Grape::API) do
use Rack::Sendfile
format :json
get do
file send_file
end
end

options = {
method: 'GET',
'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
'HTTP_X_ACCEL_MAPPING' => '/accel/mapping/=/replaced/'
}
env = Rack::MockRequest.env_for('/', options)
app.call(env)
end

context do
let(:file_streamer) do
double(:file_streamer, to_path: '/accel/mapping/some/path')
end

it 'contains Sendfile headers' do
headers = subject[1]
expect(headers).to include('X-Accel-Redirect')
end
end

context do
let(:file_streamer) do
double(:file_streamer)
end

it 'not contains Sendfile headers' do
headers = subject[1]
expect(headers).to_not include('X-Accel-Redirect')
end
end
end
10 changes: 10 additions & 0 deletions spec/grape/middleware/formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,14 @@ def to_xml
end
end
end

context 'send file' do
let(:app) { ->(_env) { [200, {}, @body] } }

it 'returns Grape::Uril::SendFileReponse' do
@body = Grape::Util::FileResponse.new('file')
env = { 'PATH_INFO' => '/somewhere', 'HTTP_ACCEPT' => 'application/json' }
expect(subject.call(env)).to be_a(Grape::Util::SendfileResponse)
end
end
end

0 comments on commit d78422d

Please sign in to comment.