rack-raw-upload 1.0.11 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,9 +1,10 @@
1
1
  source :rubygems
2
2
 
3
- gem 'json'
3
+ gem 'multi_json'
4
4
 
5
5
  group :development, :test do
6
6
  gem 'rake'
7
7
  gem 'rack-test'
8
8
  gem 'shoulda'
9
+ gem 'rr'
9
10
  end
@@ -1,12 +1,12 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- json (1.4.6)
5
- json (1.4.6-java)
4
+ multi_json (1.3.2)
6
5
  rack (1.2.1)
7
6
  rack-test (0.5.6)
8
7
  rack (>= 1.0)
9
8
  rake (0.8.7)
9
+ rr (1.0.4)
10
10
  shoulda (2.11.3)
11
11
 
12
12
  PLATFORMS
@@ -14,7 +14,8 @@ PLATFORMS
14
14
  ruby
15
15
 
16
16
  DEPENDENCIES
17
- json
17
+ multi_json
18
18
  rack-test
19
19
  rake
20
+ rr
20
21
  shoulda
data/README.md CHANGED
@@ -1,17 +1,23 @@
1
+ # WARNING: you may not need this
2
+
3
+ If you want to use this because you are performing HTML5 file uploads, you may be doing it [the "old way"](http://blog.new-bamboo.co.uk/2010/7/30/html5-powered-ajax-file-uploads).
4
+
5
+ There is a "new", [better way of doing this](http://blog.new-bamboo.co.uk/2012/01/10/ridiculously-simple-ajax-uploads-with-formdata). It may be a better solution for your problems.
6
+
7
+ However, if this is not the case, please read on. I hope you find this middleware useful.
8
+
1
9
  # Rack Raw Upload middleware
2
10
 
3
11
  Rack::RawUpload converts raw uploads into normal multipart requests, like those in a form. Rack applications can then read these as normal (using `params` for example), rather than from `env['rack.input']` or similar.
4
12
 
5
- Rack::RawUpload processes a request this way when the mimetype **is not** one of the following:
6
-
7
13
  ## Assumptions
8
14
 
9
15
  Rack::RawUpload performs this conversion when all these conditions are met:
10
16
 
11
17
  1. The request method is POST or PUT
12
18
  2. The mimetype is one of
13
- * application/x-www-form-urlencoded
14
- * multipart/form-data
19
+ * `application/x-www-form-urlencoded`
20
+ * `multipart/form-data`
15
21
  3. The Content-Length is greater than 0
16
22
 
17
23
  ## Configuration
@@ -53,7 +59,10 @@ The upload is made into a request argument called `file`. In several popular fra
53
59
  Raw uploads, due to their own nature, can't provide additional arguments in the request. This limitation can be worked around using headers.
54
60
 
55
61
  * `X-File-Name`: specify the name of the uploaded file.
56
- * `X-Query-Params`: JSON-formatted hash containing additional arguments. On Rails or Sinatra, you can read these as `params[:name_of_argument]`
62
+ * `X-File-Upload`: explicitly tells whether to perform the conversion or not. Possible values are 'true' (string), 'false' (string) or 'smart'. Default is 'smart', unless the middleware is initialized with `:explicit => true`, in which case default is 'false'.
63
+ * `X-Params`: query string with additional arguments. On Rails or Sinatra, you can read these as `params[:name_of_argument]`.
64
+ * `X-JSON-Params`: same thing, but in the form of a JSON string.
65
+ * `X-Query-Params`: **deprecated**. Equivalent to `X-JSON-Params`. Will be removed in future versions.
57
66
 
58
67
 
59
68
  ## Additional info
@@ -1,9 +1,10 @@
1
1
  require 'tmpdir' # Needed in 1.8.7 to access Dir::tmpdir
2
+ require 'multi_json'
2
3
 
3
4
  module Rack
4
5
  class RawUpload
5
6
 
6
- VERSION = '1.0.11'
7
+ VERSION = '1.1.1'
7
8
 
8
9
  def initialize(app, opts = {})
9
10
  @app = app
@@ -43,6 +44,7 @@ module Rack
43
44
  tempfile << chunk
44
45
  end
45
46
  end
47
+ env['rack.input'].rewind
46
48
 
47
49
  tempfile.flush
48
50
  tempfile.rewind
@@ -57,11 +59,15 @@ module Rack
57
59
  env['rack.request.query_hash'] ||= {}
58
60
  env['rack.request.form_hash']['file'] = fake_file
59
61
  env['rack.request.query_hash']['file'] = fake_file
60
- if query_params = env['HTTP_X_QUERY_PARAMS']
61
- require 'json'
62
- params = JSON.parse(query_params)
63
- env['rack.request.form_hash'].merge!(params)
64
- env['rack.request.query_hash'].merge!(params)
62
+ if env['HTTP_X_QUERY_PARAMS']
63
+ env['rack.errors'].puts("Warning! The header X-Query-Params is deprecated. Please use X-JSON-Params instead.")
64
+ inject_json_params!(env, env['HTTP_X_QUERY_PARAMS'])
65
+ end
66
+ if env['HTTP_X_JSON_PARAMS']
67
+ inject_json_params!(env, env['HTTP_X_JSON_PARAMS'])
68
+ end
69
+ if env['HTTP_X_PARAMS']
70
+ inject_query_params!(env, env['HTTP_X_PARAMS'])
65
71
  end
66
72
  @app.call(env)
67
73
  end
@@ -101,6 +107,18 @@ module Rack
101
107
  def random_string
102
108
  (0...8).map{65.+(rand(25)).chr}.join
103
109
  end
110
+
111
+ def inject_json_params!(env, params)
112
+ hsh = MultiJson.load(params)
113
+ env['rack.request.form_hash'].merge!(hsh)
114
+ env['rack.request.query_hash'].merge!(hsh)
115
+ end
116
+
117
+ def inject_query_params!(env, params)
118
+ hsh = Rack::Utils.parse_query(params)
119
+ env['rack.request.form_hash'].merge!(hsh)
120
+ env['rack.request.query_hash'].merge!(hsh)
121
+ end
104
122
  end
105
123
 
106
124
 
@@ -0,0 +1,4 @@
1
+ APP_ROOT = File.dirname(File.expand_path(__FILE__))
2
+
3
+ require 'rubygems'
4
+ require 'simple_app'
@@ -0,0 +1,44 @@
1
+ require 'pp'
2
+ require 'sinatra/base'
3
+ require 'multi_json'
4
+
5
+ class SimpleApp < Sinatra::Base
6
+
7
+ set :root, APP_ROOT
8
+ set :static, true
9
+ set :public_folder, Proc.new{ File.join(root, 'public') }
10
+ set :upload_dir, Proc.new{ File.join(public_folder, 'uploads') }
11
+
12
+ configure do
13
+ FileUtils.mkdir_p(settings.upload_dir)
14
+ end
15
+
16
+ get '/' do
17
+ erb :index
18
+ end
19
+
20
+ post '/' do
21
+ content_type :json
22
+ dump = Rack::Utils.escape_html(PP.pp(params, ''))
23
+ download_url = file_url(store_file(params[:file]))
24
+ MultiJson.dump({
25
+ :dump => dump,
26
+ :download_url => download_url,
27
+ })
28
+ end
29
+
30
+
31
+ private
32
+
33
+ def store_file(file_param)
34
+ dirpath = Dir.mktmpdir(nil, settings.upload_dir)
35
+ filepath = File.join(dirpath, file_param[:filename])
36
+ FileUtils.mv(file_param[:tempfile], filepath)
37
+ filepath
38
+ end
39
+
40
+ def file_url(path)
41
+ path.gsub(Regexp.new('^' + settings.public_folder), '').tap{|x| pp x}
42
+ end
43
+
44
+ end
@@ -2,11 +2,13 @@ require 'rubygems'
2
2
  require 'rack/test'
3
3
  require 'shoulda'
4
4
  require 'rack-raw-upload'
5
- require 'json'
5
+ require 'multi_json'
6
6
  require 'digest'
7
+ require 'rr'
7
8
 
8
9
  class RawUploadTest < Test::Unit::TestCase
9
10
  include Rack::Test::Methods
11
+ include RR::Adapters::TestUnit
10
12
 
11
13
  def app
12
14
  opts = @middleware_opts
@@ -79,9 +81,7 @@ class RawUploadTest < Test::Unit::TestCase
79
81
  should "not work when there is no input" do
80
82
  upload('rack.input' => '')
81
83
  assert_successful_non_upload
82
- end
83
84
 
84
- should "not work when there is no input" do
85
85
  upload('rack.input' => StringIO.new(''))
86
86
  assert_successful_non_upload
87
87
  end
@@ -120,6 +120,11 @@ class RawUploadTest < Test::Unit::TestCase
120
120
  assert_successful_non_upload
121
121
  end
122
122
 
123
+ should "leave rack.input in a state readable by other middlewares" do
124
+ upload
125
+ assert !last_request.env['rack.input'].eof?, "rack.input should be rewind'd"
126
+ end
127
+
123
128
  context "when garbage collection runs (Ruby 1.9)" do
124
129
  context "and the file is received as a Tempfile" do
125
130
  should "ensure that the uploaded file remains" do
@@ -196,9 +201,9 @@ class RawUploadTest < Test::Unit::TestCase
196
201
  end
197
202
  end
198
203
 
199
- context "with query parameters" do
204
+ context "with JSON parameters" do
200
205
  setup do
201
- upload('HTTP_X_QUERY_PARAMS' => JSON.generate({
206
+ upload('HTTP_X_JSON_PARAMS' => MultiJson.dump({
202
207
  :argument => 'value1',
203
208
  'argument with spaces' => 'value 2'
204
209
  }))
@@ -210,6 +215,43 @@ class RawUploadTest < Test::Unit::TestCase
210
215
  end
211
216
  end
212
217
 
218
+ context "with query parameters" do
219
+ setup do
220
+ upload('HTTP_X_PARAMS' => "arg=val1&ar+g=val2")
221
+ end
222
+
223
+ should "convert these into arguments" do
224
+ assert_equal last_request.POST['arg'], 'val1'
225
+ assert_equal last_request.POST['ar g'], 'val2'
226
+ end
227
+ end
228
+
229
+ context "with query parameters, deprecated style" do
230
+ setup do
231
+ json_params = MultiJson.dump({
232
+ :argument => 'value1',
233
+ 'argument with spaces' => 'value 2'
234
+ })
235
+ @mock_error_stream = obj = Object.new
236
+ stub(obj).puts
237
+ stub(obj).flush
238
+
239
+ upload({
240
+ 'HTTP_X_QUERY_PARAMS' => json_params,
241
+ 'rack.errors' => @mock_error_stream
242
+ })
243
+ end
244
+
245
+ should "convert these into arguments" do
246
+ assert_equal last_request.POST['argument'], 'value1'
247
+ assert_equal last_request.POST['argument with spaces'], 'value 2'
248
+ end
249
+
250
+ should "give a deprecation warning" do
251
+ assert_received(@mock_error_stream) {|subject| subject.puts(is_a(String)) }
252
+ end
253
+ end
254
+
213
255
  context "with filename" do
214
256
  setup do
215
257
  upload('HTTP_X_FILE_NAME' => @filename)
metadata CHANGED
@@ -1,78 +1,72 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-raw-upload
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
5
4
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 11
10
- version: 1.0.11
5
+ version: 1.1.1
11
6
  platform: ruby
12
7
  authors:
13
- - Pablo Brasero
8
+ - Pablo Brasero
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-11-23 00:00:00 Z
13
+ date: 2013-01-06 00:00:00 Z
19
14
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: json
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
32
- type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: rake
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
46
- type: :development
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: rack-test
50
- prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
60
- type: :development
61
- version_requirements: *id003
62
- - !ruby/object:Gem::Dependency
63
- name: shoulda
64
- prerelease: false
65
- requirement: &id004 !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
74
- type: :development
75
- version_requirements: *id004
15
+ - !ruby/object:Gem::Dependency
16
+ name: multi_json
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rake
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: rack-test
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: shoulda
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rr
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
76
70
  description: Middleware that converts files uploaded with mimetype application/octet-stream into normal form input, so Rack applications can read these as normal, rather than as raw input.
77
71
  email: pablobm@gmail.com
78
72
  executables: []
@@ -80,71 +74,66 @@ executables: []
80
74
  extensions: []
81
75
 
82
76
  extra_rdoc_files:
83
- - LICENSE
84
- - README.md
77
+ - LICENSE
78
+ - README.md
85
79
  files:
86
- - lib/rack/raw_upload.rb
87
- - lib/rack-raw-upload.rb
88
- - test/apps/undefined_conversion_error/app/controllers/application_controller.rb
89
- - test/apps/undefined_conversion_error/app/controllers/test_controller.rb
90
- - test/apps/undefined_conversion_error/app/helpers/application_helper.rb
91
- - test/apps/undefined_conversion_error/config/application.rb
92
- - test/apps/undefined_conversion_error/config/boot.rb
93
- - test/apps/undefined_conversion_error/config/environment.rb
94
- - test/apps/undefined_conversion_error/config/environments/development.rb
95
- - test/apps/undefined_conversion_error/config/environments/production.rb
96
- - test/apps/undefined_conversion_error/config/environments/test.rb
97
- - test/apps/undefined_conversion_error/config/initializers/backtrace_silencers.rb
98
- - test/apps/undefined_conversion_error/config/initializers/inflections.rb
99
- - test/apps/undefined_conversion_error/config/initializers/mime_types.rb
100
- - test/apps/undefined_conversion_error/config/initializers/secret_token.rb
101
- - test/apps/undefined_conversion_error/config/initializers/session_store.rb
102
- - test/apps/undefined_conversion_error/config/initializers/wrap_parameters.rb
103
- - test/apps/undefined_conversion_error/config/routes.rb
104
- - test/apps/undefined_conversion_error/db/seeds.rb
105
- - test/apps/undefined_conversion_error/test/performance/browsing_test.rb
106
- - test/apps/undefined_conversion_error/test/test_helper.rb
107
- - test/raw_upload_test.rb
108
- - LICENSE
109
- - README.md
110
- - Gemfile
111
- - Gemfile.lock
80
+ - lib/rack-raw-upload.rb
81
+ - lib/rack/raw_upload.rb
82
+ - test/raw_upload_test.rb
83
+ - test/apps/example/app.rb
84
+ - test/apps/example/lib/simple_app.rb
85
+ - test/apps/undefined_conversion_error/app/controllers/application_controller.rb
86
+ - test/apps/undefined_conversion_error/app/controllers/test_controller.rb
87
+ - test/apps/undefined_conversion_error/app/helpers/application_helper.rb
88
+ - test/apps/undefined_conversion_error/config/application.rb
89
+ - test/apps/undefined_conversion_error/config/boot.rb
90
+ - test/apps/undefined_conversion_error/config/environment.rb
91
+ - test/apps/undefined_conversion_error/config/routes.rb
92
+ - test/apps/undefined_conversion_error/config/environments/development.rb
93
+ - test/apps/undefined_conversion_error/config/environments/production.rb
94
+ - test/apps/undefined_conversion_error/config/environments/test.rb
95
+ - test/apps/undefined_conversion_error/config/initializers/backtrace_silencers.rb
96
+ - test/apps/undefined_conversion_error/config/initializers/inflections.rb
97
+ - test/apps/undefined_conversion_error/config/initializers/mime_types.rb
98
+ - test/apps/undefined_conversion_error/config/initializers/secret_token.rb
99
+ - test/apps/undefined_conversion_error/config/initializers/session_store.rb
100
+ - test/apps/undefined_conversion_error/config/initializers/wrap_parameters.rb
101
+ - test/apps/undefined_conversion_error/db/seeds.rb
102
+ - test/apps/undefined_conversion_error/test/test_helper.rb
103
+ - test/apps/undefined_conversion_error/test/performance/browsing_test.rb
104
+ - LICENSE
105
+ - README.md
106
+ - Gemfile
107
+ - Gemfile.lock
112
108
  homepage: https://github.com/newbamboo/rack-raw-upload
113
109
  licenses: []
114
110
 
115
111
  post_install_message:
116
112
  rdoc_options:
117
- - --charset=UTF-8
118
- - --main
119
- - README.rdoc
113
+ - --charset=UTF-8
114
+ - --main
115
+ - README.rdoc
120
116
  require_paths:
121
- - lib
117
+ - lib
122
118
  required_ruby_version: !ruby/object:Gem::Requirement
123
119
  none: false
124
120
  requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- hash: 3
128
- segments:
129
- - 0
130
- version: "0"
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: "0"
131
124
  required_rubygems_version: !ruby/object:Gem::Requirement
132
125
  none: false
133
126
  requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- hash: 3
137
- segments:
138
- - 0
139
- version: "0"
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: "0"
140
130
  requirements: []
141
131
 
142
132
  rubyforge_project:
143
- rubygems_version: 1.8.10
133
+ rubygems_version: 1.8.15
144
134
  signing_key:
145
135
  specification_version: 3
146
136
  summary: Rack Raw Upload middleware
147
137
  test_files:
148
- - test/apps/undefined_conversion_error/app/controllers/test_controller.rb
149
- - test/apps/undefined_conversion_error/test/test_helper.rb
150
- has_rdoc:
138
+ - test/apps/undefined_conversion_error/app/controllers/test_controller.rb
139
+ - test/apps/undefined_conversion_error/test/test_helper.rb