tap-http 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/History CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.3.2 / 2009-02-23
2
+
3
+ Bug fix in handling of multipart/form data.
4
+
5
+ * parse_rack_request now parses overloaded params
6
+
1
7
  == 0.3.1 / 2009-02-19
2
8
 
3
9
  Improved handling of multipart/form data.
@@ -41,7 +41,7 @@ class CaptureController < Tap::Controller
41
41
  # Echos back redirected HTTP requests formatted as YAML.
42
42
  def echo
43
43
  response['Content-Type'] = "text/plain"
44
- YAML.dump(config)
44
+ YAML.dump(parse_request)
45
45
  end
46
46
 
47
47
  protected
@@ -49,6 +49,17 @@ class CaptureController < Tap::Controller
49
49
  # helper to parse the request into a request hash for
50
50
  # use by a Tap::Http::Submit task
51
51
  def parse_request(keep_content=true) # :nodoc:
52
+
53
+ # perform the actions of Rack::Request::POST, but capturing
54
+ # overloaded parameter names
55
+ env = request.env
56
+ env["rack.request.form_input"] = env["rack.input"]
57
+ unless env["rack.request.form_hash"] = Tap::Http::Utils.parse_multipart(env)
58
+ env["rack.request.form_vars"] = env["rack.input"].read
59
+ env["rack.request.form_hash"] = Rack::Utils.parse_query(env["rack.request.form_vars"])
60
+ env["rack.input"].rewind if env["rack.input"].respond_to?(:rewind)
61
+ end
62
+
52
63
  config = {}
53
64
  parse_rack_request(request, keep_content).each_pair do |key, value|
54
65
  config[key.to_s] = value
@@ -1,6 +1,7 @@
1
1
  autoload(:WEBrick, 'webrick')
2
2
  autoload(:Zlib, 'zlib')
3
3
  autoload(:StringIO, 'stringio')
4
+ require 'rack'
4
5
 
5
6
  module Tap
6
7
  module Http
@@ -137,10 +138,11 @@ module Tap
137
138
  request.params.each_pair do |key, value|
138
139
  params[key] = each_member(value) do |obj|
139
140
  if obj.kind_of?(Hash)
140
- file = {'Content-Type' => value[:type], 'Filename' => value[:filename]}
141
- file['Content'] = value[:tempfile].read if keep_content
141
+ file = {'Content-Type' => obj[:type], 'Filename' => obj[:filename]}
142
+ file['Content'] = obj[:tempfile].read if keep_content
142
143
  file
143
- else value
144
+ else
145
+ obj
144
146
  end
145
147
  end
146
148
  end
@@ -207,6 +209,99 @@ module Tap
207
209
  def inflate(str)
208
210
  Zlib::GzipReader.new( StringIO.new( str ) ).read
209
211
  end
212
+
213
+ EOL = Rack::Utils::Multipart::EOL
214
+ # Lifted from Rack::Utils::Multipart, and modified to collect
215
+ # overloaded params and params with names suffixed by '[]' as
216
+ # arrays.
217
+ def parse_multipart(env)
218
+ unless env['CONTENT_TYPE'] =~
219
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
220
+ nil
221
+ else
222
+ boundary = "--#{$1}"
223
+
224
+ params = {}
225
+ buf = ""
226
+ content_length = env['CONTENT_LENGTH'].to_i
227
+ input = env['rack.input']
228
+
229
+ boundary_size = boundary.size + EOL.size
230
+ bufsize = 16384
231
+
232
+ content_length -= boundary_size
233
+
234
+ status = input.read(boundary_size)
235
+ raise EOFError, "bad content body" unless status == boundary + EOL
236
+
237
+ rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/
238
+
239
+ loop {
240
+ head = nil
241
+ body = ''
242
+ filename = content_type = name = nil
243
+
244
+ until head && buf =~ rx
245
+ if !head && i = buf.index("\r\n\r\n")
246
+ head = buf.slice!(0, i+2) # First \r\n
247
+ buf.slice!(0, 2) # Second \r\n
248
+
249
+ filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
250
+ content_type = head[/Content-Type: (.*)\r\n/ni, 1]
251
+ name = head[/Content-Disposition:.* name="?([^\";]*)"?/ni, 1]
252
+
253
+ if filename
254
+ body = Tempfile.new("RackMultipart")
255
+ body.binmode if body.respond_to?(:binmode)
256
+ end
257
+
258
+ next
259
+ end
260
+
261
+ # Save the read body part.
262
+ if head && (boundary_size+4 < buf.size)
263
+ body << buf.slice!(0, buf.size - (boundary_size+4))
264
+ end
265
+
266
+ c = input.read(bufsize < content_length ? bufsize : content_length)
267
+ raise EOFError, "bad content body" if c.nil? || c.empty?
268
+ buf << c
269
+ content_length -= c.size
270
+ end
271
+
272
+ # Save the rest.
273
+ if i = buf.index(rx)
274
+ body << buf.slice!(0, i)
275
+ buf.slice!(0, boundary_size+2)
276
+
277
+ content_length = -1 if $1 == "--"
278
+ end
279
+
280
+ if filename
281
+ body.rewind
282
+ data = {:filename => filename, :type => content_type,
283
+ :name => name, :tempfile => body, :head => head}
284
+ else
285
+ data = body
286
+ end
287
+
288
+ if name
289
+ case current = params[name]
290
+ when nil
291
+ params[name] = (name =~ /\[\]\z/ ? [data] : data)
292
+ when Array
293
+ params[name] << data
294
+ else
295
+ params[name] = [current, data]
296
+ end
297
+ end
298
+
299
+ break if buf.empty? || content_length == -1
300
+ }
301
+
302
+ params
303
+ end
304
+ end
210
305
  end
211
306
  end
212
307
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tap-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Chiang
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-19 00:00:00 -07:00
12
+ date: 2009-02-23 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.12.0
23
+ version: 0.12.2
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rack