multipart-post 0.1 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.