Skip to content

Commit 14fa34b

Browse files
author
Michael Bleigh
committed
Add .use to allow for custom middleware.
1 parent c0a7255 commit 14fa34b

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

lib/grape/api.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,24 @@ def namespace(space = nil, &block)
177177
def scope(name = nil, &block)
178178
nest(block)
179179
end
180-
180+
181+
# Apply a custom middleware to the API. Applies
182+
# to the current namespace and any children, but
183+
# not parents.
184+
#
185+
# @param middleware_class [Class] The class of the middleware you'd like to inject.
186+
def use(middleware_class, *args)
187+
settings_stack.last[:middleware] ||= []
188+
settings_stack.last[:middleware] << [middleware_class, *args]
189+
end
190+
191+
# Retrieve an array of the middleware classes
192+
# and arguments that are currently applied to the
193+
# application.
194+
def middleware
195+
settings_stack.inject([]){|a,s| a += s[:middleware] if s[:middleware]; a}
196+
end
197+
181198
protected
182199

183200
# Execute first the provided block, then each of the
@@ -202,7 +219,8 @@ def build_endpoint(&block)
202219
b.use Grape::Middleware::Prefixer, :prefix => prefix if prefix
203220
b.use Grape::Middleware::Versioner, :versions => (version if version.is_a?(Array)) if version
204221
b.use Grape::Middleware::Formatter, :default_format => default_format || :json
205-
222+
middleware.each{|m| b.use *m }
223+
206224
endpoint = Grape::Endpoint.generate(&block)
207225
endpoint.send :include, helpers
208226
b.run endpoint

spec/grape/api_spec.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,67 @@ def app; subject end
227227
end
228228
end
229229

230+
context 'custom middleware' do
231+
class PhonyMiddleware
232+
def initialize(app, *args)
233+
@args = args
234+
@app = app
235+
end
236+
237+
def call(env)
238+
env['phony.args'] ||= []
239+
env['phony.args'] << @args
240+
@app.call(env)
241+
end
242+
end
243+
244+
describe '.middleware' do
245+
it 'should include middleware arguments from settings' do
246+
subject.stub!(:settings_stack).and_return [{:middleware => [[PhonyMiddleware, 'abc', 123]]}]
247+
subject.middleware.should == [[PhonyMiddleware, 'abc', 123]]
248+
end
249+
250+
it 'should include all middleware from stacked settings' do
251+
subject.stub!(:settings_stack).and_return [
252+
{:middleware => [[PhonyMiddleware, 123],[PhonyMiddleware, 'abc']]},
253+
{:middleware => [[PhonyMiddleware, 'foo']]}
254+
]
255+
256+
subject.middleware.should == [
257+
[PhonyMiddleware, 123],
258+
[PhonyMiddleware, 'abc'],
259+
[PhonyMiddleware, 'foo']
260+
]
261+
end
262+
end
263+
264+
describe '.use' do
265+
it 'should add middleware' do
266+
subject.use PhonyMiddleware, 123
267+
subject.middleware.should == [[PhonyMiddleware, 123]]
268+
end
269+
270+
it 'should not show up outside the namespace' do
271+
subject.use PhonyMiddleware, 123
272+
subject.namespace :awesome do
273+
use PhonyMiddleware, 'abc'
274+
middleware.should == [[PhonyMiddleware, 123],[PhonyMiddleware, 'abc']]
275+
end
276+
277+
subject.middleware.should == [[PhonyMiddleware, 123]]
278+
end
279+
280+
it 'should actually call the middleware' do
281+
subject.use PhonyMiddleware, 'hello'
282+
subject.get '/' do
283+
env['phony.args'].first.first
284+
end
285+
286+
get '/'
287+
last_response.body.should == 'hello'
288+
end
289+
end
290+
end
230291
describe '.basic' do
231292
it 'should protect any resources on the same scope' do
232293
subject.http_basic do |u,p|

0 commit comments

Comments
 (0)