Skip to content

Commit

Permalink
Beginnings of formatter middleware.
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Bleigh committed Aug 5, 2010
1 parent f9c9cf3 commit 0fe17a5
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ tmtags
coverage
rdoc
pkg
.rvmrc
.bundle

## PROJECT::SPECIFIC
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ gem 'rack'
gem 'rack-mount'
gem 'rack-jsonp'

gem 'json'
gem 'multi_json'

group :test do
gem 'rspec', '>= 2.0.0.beta.19'
gem 'rack-test'
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ GEM
diff-lcs (1.1.2)
gherkin (2.1.5)
trollop (~> 1.16.2)
json (1.4.3)
json_pure (1.4.3)
multi_json (0.0.4)
rack (1.2.1)
rack-jsonp (1.0.0)
rack-mount (0.6.9)
Expand All @@ -33,6 +35,8 @@ PLATFORMS

DEPENDENCIES
cucumber (>= 0.8.5)
json
multi_json
rack
rack-jsonp
rack-mount
Expand Down
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ begin
gem.email = "michael@intridea.com"
gem.homepage = "http://github.com/intridea/grape"
gem.authors = ["Michael Bleigh"]
gem.add_dependency 'rack'
gem.add_dependency 'multi_json'
gem.add_development_dependency "rspec", ">= 1.2.9"
gem.add_development_dependency "cucumber", ">= 0"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
Expand Down
3 changes: 2 additions & 1 deletion lib/grape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

require 'grape/middleware/base'
require 'grape/middleware/prefixer'
require 'grape/middleware/versioner'
require 'grape/middleware/versioner'
require 'grape/middleware/formatter'
9 changes: 9 additions & 0 deletions lib/grape/middleware/error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'grape/middleware/base'

module Grape
module Middleware
class Error < Base

end
end
end
60 changes: 60 additions & 0 deletions lib/grape/middleware/formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require 'grape/middleware/base'
require 'multi_json'

module Grape
module Middleware
class Formatter < Base
CONTENT_TYPES = {
:xml => 'application/xml',
:json => 'application/json',
:atom => 'application/atom+xml',
:rss => 'application/rss+xml'
}

def default_options
{
:default_format => :json,
:content_types => {}
}
end

def content_types
CONTENT_TYPES.merge(options[:content_types])
end

def before
fmt = format_from_extension || format_from_header || options[:default_format]

if content_types.key?(fmt)
env['api.format'] = fmt
else
env['api.error.status'] = 406
env['api.error.message'] = 'The requested format is not supported.'
end
end

def format_from_extension
parts = request.path.split('.')
hit = parts.last.to_sym

if parts.size <= 1
nil
else
hit
end
end

def format_from_header
# TODO: Implement Accept header parsing.
end

def after
status, headers, bodies = *@app_response
bodies.map! do |body|
MultiJson.encode(body)
end
[status, headers, bodies]
end
end
end
end
5 changes: 5 additions & 0 deletions spec/grape/middleware/error_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'spec_helper'

describe Grape::Middleware::Error do

end
35 changes: 35 additions & 0 deletions spec/grape/middleware/formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'spec_helper'

describe Grape::Middleware::Formatter do
subject{ Grape::Middleware::Formatter.new(app)}
before{ subject.stub!(:dup).and_return(subject) }

let(:app){ lambda{|env| [200, {}, [@body]]} }

context 'serialization' do
it 'should look at the bodies for possibly serializable data' do
@body = {"abc" => "def"}
status, headers, bodies = *subject.call({'PATH_INFO' => '/somewhere'})
bodies.first.should == MultiJson.encode(@body)
end
end

context 'detection' do
it 'should use the extension if one is provided' do
subject.call({'PATH_INFO' => '/info.xml'})
subject.env['api.format'].should == :xml
subject.call({'PATH_INFO' => '/info.json'})
subject.env['api.format'].should == :json
end

it 'should use the default format if none is provided' do
subject.call({'PATH_INFO' => '/info'})
subject.env['api.format'].should == :json
end

it 'should throw an error on an unrecognized format' do
subject.call({'PATH_INFO' => '/info.barklar'})
subject.env['api.error.status'].should == 406
end
end
end
4 changes: 2 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

require 'rubygems'
require 'bundler'
Bundler.setup :test
Bundler.setup :default, :test

require 'rspec'
require 'rack/test'

RSpec.configure do |config|

config.include Rack::Test::Methods
end

0 comments on commit 0fe17a5

Please sign in to comment.