Skip to content

Commit

Permalink
Added media_type methods in Rack::Response
Browse files Browse the repository at this point in the history
  • Loading branch information
AMekss committed Jun 12, 2015
1 parent df941b3 commit a193c57
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 14 deletions.
38 changes: 38 additions & 0 deletions lib/rack/media_type.rb
@@ -0,0 +1,38 @@
module Rack
# Rack::MediaType parse media type and parameters out of content_type string

class MediaType
SPLIT_PATTERN = %r{\s*[;,]\s*}

class << self
# The media type (type/subtype) portion of the CONTENT_TYPE header
# without any media type parameters. e.g., when CONTENT_TYPE is
# "text/plain;charset=utf-8", the media-type is "text/plain".
#
# For more information on the use of media types in HTTP, see:
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
def type(content_type)
return nil unless content_type
content_type.split(SPLIT_PATTERN, 2).first.downcase
end

# The media type parameters provided in CONTENT_TYPE as a Hash, or
# an empty Hash if no CONTENT_TYPE or media-type parameters were
# provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
# this method responds with the following Hash:
# { 'charset' => 'utf-8' }
def params(content_type)
return {} if content_type.nil?
Hash[*content_type.split(SPLIT_PATTERN)[1..-1].
collect { |s| s.split('=', 2) }.
map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten]
end

private

def strip_doublequotes(str)
(str[0] == ?" && str[-1] == ?") ? str[1..-2] : str
end
end
end
end
17 changes: 3 additions & 14 deletions lib/rack/request.rb
@@ -1,4 +1,5 @@
require 'rack/utils'
require 'rack/media_type'

module Rack
# Rack::Request provides a convenient interface to a Rack
Expand Down Expand Up @@ -46,7 +47,7 @@ def logger; @env['rack.logger'] end
# For more information on the use of media types in HTTP, see:
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
def media_type
content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
@media_type ||= MediaType.type(content_type)
end

# The media type parameters provided in CONTENT_TYPE as a Hash, or
Expand All @@ -55,10 +56,7 @@ def media_type
# this method responds with the following Hash:
# { 'charset' => 'utf-8' }
def media_type_params
return {} if content_type.nil?
Hash[*content_type.split(/\s*[;,]\s*/)[1..-1].
collect { |s| s.split('=', 2) }.
map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten]
@media_type_params ||= MediaType.params(content_type)
end

# The character set of the request body if a "charset" media type
Expand Down Expand Up @@ -384,14 +382,5 @@ def parse_http_accept_header(header)
[attribute, quality]
end
end

private
def strip_doublequotes(s)
if s[0] == ?" && s[-1] == ?"
s[1..-2]
else
s
end
end
end
end
9 changes: 9 additions & 0 deletions lib/rack/response.rb
@@ -1,6 +1,7 @@
require 'rack/request'
require 'rack/utils'
require 'rack/body_proxy'
require 'rack/media_type'
require 'time'

module Rack
Expand Down Expand Up @@ -150,6 +151,14 @@ def content_type
headers[CONTENT_TYPE]
end

def media_type
@media_type ||= MediaType.type(content_type)
end

def media_type_params
@media_type_params ||= MediaType.params(content_type)
end

def content_length
cl = headers[CONTENT_LENGTH]
cl ? cl.to_i : cl
Expand Down
41 changes: 41 additions & 0 deletions test/spec_media_type.rb
@@ -0,0 +1,41 @@
require 'rack/media_type'

describe Rack::MediaType do
before { @empty_hash = {} }

describe 'when content_type nil' do
before { @content_type = nil }

it '#type is nil' do
Rack::MediaType.type(@content_type).should.be.nil
end

it '#params is empty' do
Rack::MediaType.params(@content_type).should.equal @empty_hash
end
end

describe 'when content_type contains only media_type' do
before { @content_type = 'application/text' }

it '#type is application/text' do
Rack::MediaType.type(@content_type).should.equal 'application/text'
end

it '#params is empty' do
Rack::MediaType.params(@content_type).should.equal @empty_hash
end
end

describe 'when content_type contains media_type and params' do
before { @content_type = 'application/text;CHARSET="utf-8"' }

it '#type is application/text' do
Rack::MediaType.type(@content_type).should.equal 'application/text'
end

it '#params has key "charset" with value "utf-8"' do
Rack::MediaType.params(@content_type)['charset'].should.equal 'utf-8'
end
end
end

0 comments on commit a193c57

Please sign in to comment.