multiparty 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011 by David Verhasselt (david@crowdway.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ multiparty
2
+ ==========
3
+
4
+ Easily generate a multipart/form-data header and body.
5
+
6
+ Usage
7
+ -----
8
+
9
+ You can add multiple values, corresponding to multiple <input> statements:
10
+
11
+ ```ruby
12
+ @multiparty = Multiparty.new
13
+ @multiparty[:name] = "David Verhasselt"
14
+ @multiparty[:state] = "awesome"
15
+ @multiparty[:avatar] = {:filename => "avatar.jpg", :content => "...jpegdata..."}
16
+
17
+ # Retrieve the header and body like this:
18
+ @multiparty.header
19
+ # Content-Type: multipart/form-data; boundary=multiparty-boundary-1342
20
+ @multiparty.body
21
+ # --multiparty-boundary-1342
22
+ # Content-Disposition: form-data; name="name"
23
+ #
24
+ # David Verhasselt
25
+ # --multiparty-boundary-1342
26
+ # Content-Disposition: form-data; name="state"
27
+ #
28
+ # awesome
29
+ # --multiparty-boundary-1342
30
+ # Content-Disposition: form-data; name="avatar"; filename="avatar.jpg"
31
+ # Content-Type: application/octet-stream
32
+ # Content-Transfer-Encoding: binary
33
+ #
34
+ # ...jpegdata...
35
+ # --multiparty-boundary-1342--
36
+ ```
37
+
38
+ You can also add files:
39
+
40
+ ```ruby
41
+ @multiparty[:your_avatar] => File.open("foo.txt")
42
+ ```
43
+
44
+ You can specify an optional content-type. If you don't, Multiparty will try and detect the correct MIME-type based on the filename.
45
+
46
+ ```ruby
47
+ @multiparty[:your_avatar] => {:filename => "foo.jpg", :content_type => "text/plain", :content => File.read("foo.txt")}
48
+ # -> Content-Type: text/plain
49
+ @multiparty[:your_avatar] => {:filename => "foo.jpg", content => "not really jpeg")}
50
+ # -> Content-Type: image/jpeg
51
+ @multiparty[:your_avatar] => File.open("foo.jpg")
52
+ # -> Content-Type: image/jpeg
53
+ ```
54
+
55
+ Files and Tempfiles are interchangable in Multiparty:
56
+
57
+ ```ruby
58
+ tempfile = Tempfile.new("foo")
59
+ tempfile.write("Hello World!")
60
+ tempfile.rewind
61
+
62
+ @multiparty[:message] => tempfile
63
+ # is the same as
64
+ @multiparty[:message] => File.open(tempfile.path)
65
+ ```
66
+
67
+ Installation
68
+ ------------
69
+
70
+ $ gem install multiparty
71
+
72
+ Testing
73
+ -------
74
+
75
+ $ bundle install
76
+ $ rake spec
77
+
78
+ Todo
79
+ ----
80
+
81
+ * Nested multiparts ("multipart/mixed") not yet supported
82
+
83
+ Author
84
+ ------
85
+
86
+ [David Verhasselt](http://davidverhasselt.com) - david@crowdway.com
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ task :default => :spec
2
+ task :test => :spec
3
+
4
+ desc "Run specs"
5
+ task :spec do
6
+ exec "rspec spec/multiparty_spec.rb"
7
+ end
data/lib/multiparty.rb ADDED
@@ -0,0 +1,74 @@
1
+ require "mime/types"
2
+
3
+ class Multiparty
4
+ attr_accessor :boundary
5
+ attr_accessor :parts
6
+
7
+ # Multiparty.new("my-boundary")
8
+ # Multiparty.new(:boundary => "my-boundary")
9
+ def initialize(options = {})
10
+ case options
11
+ when Hash
12
+ @boundary = options[:boundary]
13
+ @content_type = options[:content_type]
14
+ when String
15
+ @boundary = options
16
+ end
17
+
18
+ @parts = {}
19
+ @content_type ||= "multipart/form-data"
20
+ @boundary ||= "multiparty-boundary-#{rand(1000000000)}"
21
+
22
+ yield self if block_given?
23
+ end
24
+
25
+ def header
26
+ "Content-Type: #{@content_type}; boundary=#{@boundary}\r\n"
27
+ end
28
+
29
+ def body
30
+ result = "--#{@boundary}\r\n"
31
+ result << parts.map do |name, value|
32
+ parse_part(name, value)
33
+ end.join("\r\n")
34
+
35
+ result << "--"
36
+ end
37
+
38
+ def parse_part(name, value)
39
+ content_disposition = "form-data"
40
+ case value
41
+ when Hash
42
+ content_disposition = value[:content_disposition] if value[:content_disposition]
43
+ content_type = value[:content_type]
44
+ filename = value[:filename]
45
+ encoding = value[:encoding]
46
+ body_part = value[:content]
47
+ when File, Tempfile
48
+ content_type = "application/octet-stream"
49
+ filename = File.split(value.path).last
50
+ body_part = value.read
51
+ else
52
+ body_part = value
53
+ end
54
+
55
+ if filename
56
+ content_type ||= MIME::Types.of(filename).first.to_s || "application/octet-stream"
57
+ encoding ||= "binary"
58
+ end
59
+
60
+ head_part = "Content-Disposition: #{content_disposition}; name=\"#{name}\""
61
+ head_part << "; filename=\"#{filename}\"" if filename
62
+ head_part << "\r\n"
63
+ head_part << "Content-Type: #{content_type}\r\n" if content_type
64
+ head_part << "Content-Transfer-Encoding: #{encoding}\r\n" if encoding
65
+
66
+ "#{head_part}\r\n#{body_part}\r\n--#{@boundary}"
67
+ end
68
+
69
+ def add_part(index, value)
70
+ parts[index] = value
71
+ end
72
+ alias_method :[]=, :add_part
73
+
74
+ end
@@ -0,0 +1,80 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "multiparty" do
4
+ it "should initialize" do
5
+ Multiparty.new.should_not be_nil
6
+ end
7
+
8
+ it "should accept a string as the boundary in #initialize" do
9
+ multiparty = Multiparty.new("my-boundary")
10
+ multiparty.boundary.should == "my-boundary"
11
+ end
12
+
13
+ it "should accept an option has in #initialize" do
14
+ multiparty = Multiparty.new :boundary => "my-boundary"
15
+ multiparty.boundary.should == "my-boundary"
16
+ end
17
+
18
+ it "should execute a block in #initialize" do
19
+ blocktest = false
20
+ Multiparty.new do
21
+ blocktest = true
22
+ end
23
+
24
+ blocktest.should be true
25
+ end
26
+
27
+ describe "instance" do
28
+ before(:each) do
29
+ @multiparty = Multiparty.new("my-boundary")
30
+ end
31
+
32
+ it "should return a correct header" do
33
+ @multiparty.header.should == "Content-Type: multipart/form-data; boundary=my-boundary\r\n"
34
+ end
35
+
36
+ it "should be able to set-index a key-value pair" do
37
+ @multiparty[:key] = :value
38
+ @multiparty[:key] = {:filename => "hello.jpg", :content => ""}
39
+ end
40
+
41
+ it "should return a correctly formed multipart response" do
42
+ @multiparty.boundary = "AaB03x"
43
+ @multiparty['submit-name'] = "Larry"
44
+ @multiparty['files'] = {:filename => "file1.txt", :content_type => "text/plain", :content => "... contents of file1.txt ..."}
45
+
46
+ @multiparty.body.gsub("\r\n", "\n").should == '--AaB03x
47
+ Content-Disposition: form-data; name="submit-name"
48
+
49
+ Larry
50
+ --AaB03x
51
+ Content-Disposition: form-data; name="files"; filename="file1.txt"
52
+ Content-Type: text/plain
53
+ Content-Transfer-Encoding: binary
54
+
55
+ ... contents of file1.txt ...
56
+ --AaB03x--'
57
+ end
58
+
59
+ it "should accept a File" do
60
+ begin
61
+ @tempfile = Tempfile.new("foo.txt")
62
+ @tempfile.write("Hi world!")
63
+ @tempfile.rewind
64
+ name = File.split(@tempfile.path).last
65
+
66
+ @multiparty[:bar] = @tempfile
67
+ @multiparty.body.gsub("\r\n", "\n").should == '--my-boundary
68
+ Content-Disposition: form-data; name="bar"; filename="' + name + '"
69
+ Content-Type: application/octet-stream
70
+ Content-Transfer-Encoding: binary
71
+
72
+ Hi world!
73
+ --my-boundary--'
74
+ ensure
75
+ @tempfile.close
76
+ @tempfile.unlink
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test)
4
+ Bundler.require(:default, :test)
5
+
6
+ require 'rspec'
7
+ require 'tempfile'
8
+
9
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
10
+ require "multiparty"
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multiparty
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - David Verhasselt
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-09-18 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: mime-types
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: |
34
+ Easily generate a multipart/form-data header and body.
35
+
36
+ email: david@crowdway.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - README.md
45
+ - Rakefile
46
+ - LICENSE
47
+ - lib/multiparty.rb
48
+ - spec/spec_helper.rb
49
+ - spec/multiparty_spec.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/dv/multiparty
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options: []
56
+
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.7
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Easily generate a multipart/form-data header and body.
82
+ test_files: []
83
+