multipart-post 0.1 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
1
  lib/composite_io.rb
2
+ lib/multipartable.rb
3
+ lib/parts.rb
2
4
  lib/net/http/post/multipart.rb
3
5
  Manifest.txt
4
6
  Rakefile
data/README.txt CHANGED
@@ -33,14 +33,13 @@ None
33
33
 
34
34
  == INSTALL:
35
35
 
36
- rake package
37
- gem install pkg/multipart-form*.gem
36
+ gem install multipart-post
38
37
 
39
38
  == LICENSE:
40
39
 
41
40
  (The MIT License)
42
41
 
43
- Copyright (c) 2007-2008 Nick Sieger <nick@nicksieger.com>
42
+ Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
44
43
 
45
44
  Permission is hereby granted, free of charge, to any person obtaining
46
45
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -2,7 +2,9 @@ begin
2
2
  require 'rubygems'
3
3
  require 'hoe'
4
4
 
5
- hoe = Hoe.new("multipart-post", '0.1') do |p|
5
+ require 'lib/multipart_post'
6
+
7
+ hoe = Hoe.new("multipart-post", MultipartPost::VERSION) do |p|
6
8
  p.rubyforge_name = "caldersphere"
7
9
  p.author = "Nick Sieger"
8
10
  p.url = "http://github.com/nicksieger/multipart-post"
@@ -0,0 +1,13 @@
1
+ require 'parts'
2
+ module Multipartable
3
+ DEFAULT_BOUNDARY = "-----------RubyMultipartPost"
4
+ def initialize(path, params, headers={}, boundary = DEFAULT_BOUNDARY)
5
+ super(path, headers)
6
+ parts = params.map {|k,v| Parts::Part.new(boundary, k, v)}
7
+ parts << Parts::EpiloguePart.new(boundary)
8
+ ios = parts.map{|p| p.to_io }
9
+ self.set_content_type("multipart/form-data", { "boundary" => boundary })
10
+ self.content_length = parts.inject(0) {|sum,i| sum + i.length }
11
+ self.body_stream = CompositeReadIO.new(*ios)
12
+ end
13
+ end
@@ -8,95 +8,20 @@ require 'net/http'
8
8
  require 'stringio'
9
9
  require 'cgi'
10
10
  require 'composite_io'
11
+ require 'multipartable'
12
+ require 'parts'
11
13
 
12
14
  module Net #:nodoc:
13
15
  class HTTP #:nodoc:
14
- class Post #:nodoc:
15
- module Part #:nodoc:
16
- def self.new(boundary, name, value)
17
- if value.respond_to? :content_type
18
- FilePart.new(boundary, name, value)
19
- else
20
- ParamPart.new(boundary, name, value)
21
- end
22
- end
23
-
24
- def length
25
- @part.length
26
- end
27
-
28
- def to_io
29
- @io
30
- end
31
- end
32
-
33
- # Represents a part to be filled with a string name/value pair.
34
- class ParamPart
35
- include Part
36
- def initialize(boundary, name, value)
37
- @part = build_part(boundary, name, value)
38
- @io = StringIO.new(@part)
39
- end
40
-
41
- def build_part(boundary, name, value)
42
- part = ''
43
- part << "--#{boundary}\r\n"
44
- part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n"
45
- part << "\r\n"
46
- part << "#{value}\r\n"
47
- end
16
+ class Put
17
+ class Multipart < Put
18
+ include Multipartable
48
19
  end
49
-
50
- # Represents a part to be filled from file IO.
51
- class FilePart
52
- include Part
53
- attr_reader :length
54
- def initialize(boundary, name, io)
55
- @head = build_head(boundary, name, io.original_filename, io.content_type)
56
- file_length = if io.respond_to? :length
57
- io.length
58
- else
59
- File.size(io.local_path)
60
- end
61
- @length = @head.length + file_length
62
- @io = CompositeReadIO.new(StringIO.new(@head), io, StringIO.new("\r\n"))
63
- end
64
-
65
- def build_head(boundary, name, filename, type)
66
- part = ''
67
- part << "--#{boundary}\r\n"
68
- part << "Content-Disposition: form-data; name=\"#{name.to_s}\"; filename=\"#{filename}\"\r\n"
69
- part << "Content-Type: #{type}\r\n"
70
- part << "Content-Transfer-Encoding: binary\r\n"
71
- part << "\r\n"
72
- end
73
- end
74
-
75
- # Represents the epilogue or closing boundary.
76
- class EpiloguePart
77
- include Part
78
- def initialize(boundary)
79
- @part = "--#{boundary}--\r\n"
80
- @io = StringIO.new(@part)
81
- end
82
- end
83
-
84
- DEFAULT_BOUNDARY = "-----------RubyMultipartPost"
85
-
86
- # Extension to the Net::HTTP::Post class that builds a post body
87
- # consisting of a multipart mime stream based on the parameters given.
88
- # See README.txt for synopsis and details.
20
+ end
21
+ class Post #:nodoc:
89
22
  class Multipart < Post
90
- def initialize(path, params, boundary = DEFAULT_BOUNDARY)
91
- super(path)
92
- parts = params.map {|k,v| Part.new(boundary, k, v)}
93
- parts << EpiloguePart.new(boundary)
94
- ios = parts.map{|p| p.to_io }
95
- self.set_content_type("multipart/form-data", { "boundary" => boundary })
96
- self.content_length = parts.inject(0) {|sum,i| sum + i.length }
97
- self.body_stream = CompositeReadIO.new(*ios)
98
- end
23
+ include Multipartable
99
24
  end
100
25
  end
101
26
  end
102
- end
27
+ end
@@ -0,0 +1,66 @@
1
+ module Parts
2
+ module Part #:nodoc:
3
+ def self.new(boundary, name, value)
4
+ if value.respond_to? :content_type
5
+ FilePart.new(boundary, name, value)
6
+ else
7
+ ParamPart.new(boundary, name, value)
8
+ end
9
+ end
10
+
11
+ def length
12
+ @part.length
13
+ end
14
+
15
+ def to_io
16
+ @io
17
+ end
18
+ end
19
+
20
+ class ParamPart
21
+ include Part
22
+ def initialize(boundary, name, value)
23
+ @part = build_part(boundary, name, value)
24
+ @io = StringIO.new(@part)
25
+ end
26
+
27
+ def build_part(boundary, name, value)
28
+ part = ''
29
+ part << "--#{boundary}\r\n"
30
+ part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n"
31
+ part << "\r\n"
32
+ part << "#{value}\r\n"
33
+ end
34
+ end
35
+
36
+ # Represents a part to be filled from file IO.
37
+ class FilePart
38
+ include Part
39
+ attr_reader :length
40
+ def initialize(boundary, name, io)
41
+ file_length = io.respond_to?(:length) ? io.length : File.size(io.local_path)
42
+ @head = build_head(boundary, name, io.original_filename, io.content_type, file_length)
43
+ @length = @head.length + file_length
44
+ @io = CompositeReadIO.new(StringIO.new(@head), io, StringIO.new("\r\n"))
45
+ end
46
+
47
+ def build_head(boundary, name, filename, type, content_len)
48
+ part = ''
49
+ part << "--#{boundary}\r\n"
50
+ part << "Content-Disposition: form-data; name=\"#{name.to_s}\"; filename=\"#{filename}\"\r\n"
51
+ part << "Content-Length: #{content_len}\r\n"
52
+ part << "Content-Type: #{type}\r\n"
53
+ part << "Content-Transfer-Encoding: binary\r\n"
54
+ part << "\r\n"
55
+ end
56
+ end
57
+
58
+ # Represents the epilogue or closing boundary.
59
+ class EpiloguePart
60
+ include Part
61
+ def initialize(boundary)
62
+ @part = "--#{boundary}--\r\n"
63
+ @io = StringIO.new(@part)
64
+ end
65
+ end
66
+ end
@@ -26,6 +26,12 @@ class Net::HTTP::Post::MultiPartTest < Test::Unit::TestCase
26
26
  UploadIO.convert! @io, "text/plain", TEMP_FILE, TEMP_FILE
27
27
  assert_results Net::HTTP::Post::Multipart.new("/foo/bar", :foo => 'bar', :file => @io)
28
28
  end
29
+ def test_form_multipart_body_put
30
+ File.open(TEMP_FILE, "w") {|f| f << "1234567890"}
31
+ @io = File.open(TEMP_FILE)
32
+ UploadIO.convert! @io, "text/plain", TEMP_FILE, TEMP_FILE
33
+ assert_results Net::HTTP::Put::Multipart.new("/foo/bar", :foo => 'bar', :file => @io)
34
+ end
29
35
 
30
36
  def test_form_multipart_body_with_stringio
31
37
  @io = StringIO.new("1234567890")
@@ -36,9 +42,9 @@ class Net::HTTP::Post::MultiPartTest < Test::Unit::TestCase
36
42
  def assert_results(post)
37
43
  assert post.content_length && post.content_length > 0
38
44
  assert post.body_stream
39
- assert_equal "multipart/form-data; boundary=#{Net::HTTP::Post::DEFAULT_BOUNDARY}", post['content-type']
45
+ assert_equal "multipart/form-data; boundary=#{Multipartable::DEFAULT_BOUNDARY}", post['content-type']
40
46
  body = post.body_stream.read
41
- boundary_regex = Regexp.quote Net::HTTP::Post::DEFAULT_BOUNDARY
47
+ boundary_regex = Regexp.quote Multipartable::DEFAULT_BOUNDARY
42
48
  assert body =~ /1234567890/
43
49
  # ensure there is at least one boundary
44
50
  assert body =~ /^--#{boundary_regex}\r\n/
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multipart-post
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.1"
4
+ version: "1.0"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sieger
@@ -9,18 +9,18 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-13 00:00:00 -05:00
12
+ date: 2009-02-12 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: hoe
17
- type: :runtime
17
+ type: :development
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.5.3
23
+ version: 1.8.2
24
24
  version:
25
25
  description: "Use with Net::HTTP to do multipart form posts. IO values that have #content_type, #original_filename, and #local_path will be posted as a binary file."
26
26
  email: nick@nicksieger.com
@@ -33,6 +33,8 @@ extra_rdoc_files:
33
33
  - README.txt
34
34
  files:
35
35
  - lib/composite_io.rb
36
+ - lib/multipartable.rb
37
+ - lib/parts.rb
36
38
  - lib/net/http/post/multipart.rb
37
39
  - Manifest.txt
38
40
  - Rakefile
@@ -62,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
64
  requirements: []
63
65
 
64
66
  rubyforge_project: caldersphere
65
- rubygems_version: 1.2.0
67
+ rubygems_version: 1.3.1
66
68
  signing_key:
67
69
  specification_version: 2
68
70
  summary: Creates a multipart form post accessory for Net::HTTP.