class Rack::RawUpload

Constants

VERSION

Public Class Methods

new(app, opts = {}) click to toggle source
# File lib/rack/raw_upload.rb, line 9
def initialize(app, opts = {})
  @app = app
  @paths = opts[:paths]
  @explicit = opts[:explicit]
  @tmpdir = opts[:tmpdir] || Dir::tmpdir
  @paths = [@paths] if @paths.kind_of?(String)
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/raw_upload.rb, line 17
def call(env)
  kick_in?(env) ? convert_and_pass_on(env) : @app.call(env)
end
upload_path?(request_path) click to toggle source
# File lib/rack/raw_upload.rb, line 21
def upload_path?(request_path)
  return true if @paths.nil?

  @paths.any? do |candidate|
    literal_path_match?(request_path, candidate) || wildcard_path_match?(request_path, candidate)
  end
end

Private Instance Methods

content_type_of_raw_file?(content_type) click to toggle source
# File lib/rack/raw_upload.rb, line 98
def content_type_of_raw_file?(content_type)
  case content_type
  when %r{^application/x-www-form-urlencoded}, %r{^multipart/form-data}
    false
  else
    true
  end
end
convert_and_pass_on(env) click to toggle source
# File lib/rack/raw_upload.rb, line 32
def convert_and_pass_on(env)
  if env['rack.input'].kind_of?(Tempfile)
    env['rack.input'].extend(EqlFix)
    tempfile = env['rack.input']
  else
    tempfile = Tempfile.new('raw-upload.', @tmpdir)

    # Can't get to produce a test case for this :-(
    env['rack.input'].each do |chunk|
      if chunk.respond_to?(:force_encoding)
        tempfile << chunk.force_encoding('UTF-8')
      else
        tempfile << chunk
      end
    end
    env['rack.input'].rewind

    tempfile.flush
    tempfile.rewind
  end
  fake_file = {
    :filename => env['HTTP_X_FILE_NAME'],
    :type => env['CONTENT_TYPE'],
    :tempfile => tempfile,
  }
  env['rack.request.form_input'] = env['rack.input']
  env['rack.request.form_hash'] ||= {}
  env['rack.request.query_hash'] ||= {}
  env['rack.request.form_hash']['file'] = fake_file
  env['rack.request.query_hash']['file'] = fake_file
  if env['HTTP_X_QUERY_PARAMS']
    env['rack.errors'].puts("Warning! The header X-Query-Params is deprecated. Please use X-JSON-Params instead.")
    inject_json_params!(env, env['HTTP_X_QUERY_PARAMS'])
  end
  if env['HTTP_X_JSON_PARAMS']
    inject_json_params!(env, env['HTTP_X_JSON_PARAMS'])
  end
  if env['HTTP_X_PARAMS']
    inject_query_params!(env, env['HTTP_X_PARAMS'])
  end
  @app.call(env)
end
inject_json_params!(env, params) click to toggle source
# File lib/rack/raw_upload.rb, line 111
def inject_json_params!(env, params)
  hsh = MultiJson.load(params)
  env['rack.request.form_hash'].merge!(hsh)
  env['rack.request.query_hash'].merge!(hsh)
end
inject_query_params!(env, params) click to toggle source
# File lib/rack/raw_upload.rb, line 117
def inject_query_params!(env, params)
  hsh = Rack::Utils.parse_query(params)
  env['rack.request.form_hash'].merge!(hsh)
  env['rack.request.query_hash'].merge!(hsh)
end
kick_in?(env) click to toggle source
# File lib/rack/raw_upload.rb, line 75
def kick_in?(env)
  env['HTTP_X_FILE_UPLOAD'] == 'true' ||
    ! @explicit && env['HTTP_X_FILE_UPLOAD'] != 'false' && raw_file_upload?(env) ||
    env.has_key?('HTTP_X_FILE_UPLOAD') && env['HTTP_X_FILE_UPLOAD'] != 'false' && raw_file_upload?(env)
end
literal_path_match?(request_path, candidate) click to toggle source
# File lib/rack/raw_upload.rb, line 88
def literal_path_match?(request_path, candidate)
  candidate == request_path
end
random_string() click to toggle source
# File lib/rack/raw_upload.rb, line 107
def random_string
  (0...8).map{65.+(rand(25)).chr}.join
end
raw_file_upload?(env) click to toggle source
# File lib/rack/raw_upload.rb, line 81
def raw_file_upload?(env)
  upload_path?(env['PATH_INFO']) &&
    %Q{POST PUT}.include?(env['REQUEST_METHOD']) &&
    content_type_of_raw_file?(env['CONTENT_TYPE']) &&
    env['CONTENT_LENGTH'].to_i > 0
end
wildcard_path_match?(request_path, candidate) click to toggle source
# File lib/rack/raw_upload.rb, line 92
def wildcard_path_match?(request_path, candidate)
  return false unless candidate.include?('*')
  regexp = '^' + candidate.gsub('.', '\.').gsub('*', '[^/]*') + '$'
  !! (Regexp.new(regexp) =~ request_path)
end