Permalink
Browse files

Don't use duplicate name params for attachments

  • Loading branch information...
1 parent b2be554 commit 0fc30eeb0d9c890661f806260c3bb753aae68ce8 @titanous titanous committed Sep 18, 2012
Showing with 22 additions and 58 deletions.
  1. +0 −1 lib/tentd.rb
  2. +21 −5 lib/tentd/api/router/extract_params.rb
  3. +0 −51 lib/tentd/rack_request.rb
  4. +1 −1 spec/support/json_request.rb
View
1 lib/tentd.rb
@@ -7,7 +7,6 @@ module TentD
autoload :JsonPatch, 'tentd/json_patch'
autoload :TentVersion, 'tentd/tent_version'
autoload :TentType, 'tentd/tent_type'
- autoload :RackRequest, 'tentd/rack_request'
def self.new(options={})
if options[:database] || ENV['DATABASE_URL']
View
26 lib/tentd/api/router/extract_params.rb
@@ -18,7 +18,7 @@ def call(env)
private
def add_request(env)
- env['request'] = RackRequest.new(env)
+ env['request'] = Rack::Request.new(env)
end
def extract_params(env)
@@ -37,17 +37,33 @@ def extract_params(env)
begin
if env['CONTENT_TYPE'] =~ /\bjson\Z/
params['data'] = JSON.parse(env['rack.input'].read)
- elsif env['CONTENT_TYPE'] =~ /\Amultipart/ && params['attachments']
- data_json = params['attachments'].find { |p| p[:type] == MEDIA_TYPE }
- params['attachments'].delete(data_json)
- params['data'] = JSON.parse(data_json[:tempfile].read)
+ elsif env['CONTENT_TYPE'] =~ /\Amultipart/
+ key, data = params.find { |k,p| p[:type] == MEDIA_TYPE }
+ params.delete(key)
+ params['data'] = JSON.parse(data[:tempfile].read)
+ params['attachments'] = get_attachments(params)
end
rescue JSON::ParserError
end
env['params'] = indifferent_params(params)
end
+ def get_attachments(params)
+ params.inject([]) { |a,(key,value)|
+ if attachment?(value)
+ a << value.merge(:name => key)
+ elsif value.kind_of?(Hash)
+ a += value.select { |k,v| attachment?(v) }.map { |k,v| v.merge(:name => key) }
+ end
+ a
+ }
+ end
+
+ def attachment?(v)
+ v.kind_of?(Hash) && v[:tempfile].kind_of?(Tempfile)
+ end
+
# Enable string or symbol key access to the nested params hash.
def indifferent_params(object)
case object
View
51 lib/tentd/rack_request.rb
@@ -1,51 +0,0 @@
-require 'rack/request'
-
-# All this so that we can have duplicate multipart names.
-module TentD
- class RackRequest < Rack::Request
- # Use our custom multipart parser
- def parse_multipart(env)
- RackMultipartParser.new(env).parse
- end
- end
-
- class RackMultipartParser < Rack::Multipart::Parser
- # Rack::Multipart::Parser#parse with the Utils.normalize_params call swapped
- # out for ours.
- def parse
- return nil unless setup_parse
-
- fast_forward_to_first_boundary
-
- loop do
- head, filename, content_type, name, body =
- get_current_head_and_filename_and_content_type_and_name_and_body
-
- if i = @buf.index(rx)
- body << @buf.slice!(0, i)
- @buf.slice!(0, @boundary_size+2)
-
- @content_length = -1 if $1 == "--"
- end
-
- filename, data = get_data(filename, body, content_type, name, head)
-
- # use our custom multipart param parser instead of Rack::Utils
- normalize_params(@params, name, data) unless data.nil?
-
- break if (@buf.empty? && $1 != EOL) || @content_length == -1
- end
-
- @io.rewind
-
- @params.to_params_hash
- end
-
- # Instead of making a params hash using the names, make an array of parts
- # under the key 'attachments'.
- def normalize_params(params, name, v = nil)
- (params['attachments'] ||= []) << v
- params
- end
- end
-end
View
2 spec/support/json_request.rb
@@ -37,7 +37,7 @@ def build_json_part(json)
def build_parts(parts)
parts.map do |k,v|
- v.kind_of?(Array) ? v.map { |part| build_part(k, part) } : build_part(k, v)
+ v.kind_of?(Array) ? v.each_with_index.map { |part,i| build_part("#{k}[#{i}]", part) } : build_part(k, v)
end.join
end

0 comments on commit 0fc30ee

Please sign in to comment.