ruby-multipart-post 0.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.
data/Manifest ADDED
@@ -0,0 +1,12 @@
1
+ README
2
+ README.rdoc
3
+ Rakefile
4
+ lib/file_upload_io.rb
5
+ lib/multi_part_post.rb
6
+ lib/parts.rb
7
+ lib/ruby-multipart-post.rb
8
+ lib/stream.rb
9
+ test/file_upload_io_test.rb
10
+ test/files/file_0.txt
11
+ test/parts_test.rb
12
+ Manifest
data/README ADDED
@@ -0,0 +1 @@
1
+ Copyright (c) 2010 (Amit Kumar), released under the MIT license
data/README.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = ruby-multipart-post
2
+
3
+ * http://github.com/toamitkumar/ruby-multipart-post
4
+
5
+ == DESCRIPTION
6
+
7
+ Multipart form post thru Ruby script, headers content-type and content-length properly set
8
+
9
+ == REQUIREMENTS
10
+
11
+ None
12
+
13
+ == INSTALL
14
+
15
+ gem install ruby-multipart-post
16
+
17
+ == LICENSE:
18
+
19
+ (The MIT License)
20
+
21
+ Copyright (c) 2010-2011 Amit Kumar <toamitkumar@gmail.com>
22
+
23
+ Permission is hereby granted, free of charge, to any person obtaining
24
+ a copy of this software and associated documentation files (the
25
+ 'Software'), to deal in the Software without restriction, including
26
+ without limitation the rights to use, copy, modify, merge, publish,
27
+ distribute, sublicense, and/or sell copies of the Software, and to
28
+ permit persons to whom the Software is furnished to do so, subject to
29
+ the following conditions:
30
+
31
+ The above copyright notice and this permission notice shall be
32
+ included in all copies or substantial portions of the Software.
33
+
34
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
35
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
37
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
38
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
39
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('ruby-multipart-post', '0.1.0') do |p|
6
+ p.description = "Multipart form post thru Ruby script, headers content-type and content-length properly set"
7
+ p.url = "http://github.com/toamitkumar/ruby-multipart-post"
8
+ p.author = "Amit Kumar"
9
+ p.email = "toamitkumar@gmail.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,20 @@
1
+ module FileUploadIO
2
+ def self.new(file_path, content_type)
3
+ raise ArgumentError, "File content type required" unless content_type
4
+ file_io = File.open(file_path, "rb")
5
+ file_io.instance_eval(<<-EOS, __FILE__, __LINE__)
6
+ def content_type
7
+ "#{content_type}"
8
+ end
9
+
10
+ def file_name
11
+ "#{File.basename(file_path)}"
12
+ end
13
+
14
+ def file_size
15
+ "#{File.size(file_path)}"
16
+ end
17
+ EOS
18
+ file_io
19
+ end
20
+ end
@@ -0,0 +1,50 @@
1
+ require 'net/http'
2
+ require "parts"
3
+ require "stream"
4
+
5
+ module MultiPart
6
+ class Post
7
+ def initialize(post_params, request_headers={})
8
+ @parts, @streams = [], []
9
+ construct_post_params(post_params)
10
+ @request_headers = request_headers
11
+ end
12
+
13
+ def construct_post_params(post_params)
14
+ post_params.each_pair do |key, val|
15
+ if(val.respond_to?(:content_type)) #construct file part
16
+ @parts << Parts::StringParam.new( "--" + multi_part_boundary + "\r\n" + \
17
+ "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val.file_name}\"\r\n" + \
18
+ "Content-Type: #{val.content_type}\r\n\r\n"
19
+ )
20
+ @streams << val
21
+ @parts << Parts::StreamParam.new(val, val.file_size)
22
+ else #construct string part param
23
+ @parts << Parts::StringParam.new("--#{multi_part_boundary}\r\n" + "Content-Disposition: form-data; name=\"#{key}\"\r\n" + "\r\n" + "#{val}\r\n")
24
+ end
25
+ end
26
+ @parts << Parts::StringParam.new( "\r\n--" + multi_part_boundary + "--\r\n" )
27
+ end
28
+
29
+ def multi_part_boundary
30
+ @boundary ||= '----RubyMultiPart' + rand(1000000).to_s + 'ZZZZZ'
31
+ end
32
+
33
+ def submit(to_url, query_string=nil)
34
+ post_stream = Stream::MultiPart.new(@parts)
35
+ url = URI.parse( to_url )
36
+ post_url_with_query_string = "#{url.path}?#{query_string}"
37
+ req = Net::HTTP::Post.new(post_url_with_query_string, @request_headers)
38
+ req.content_length = post_stream.size
39
+ req.content_type = 'multipart/form-data; boundary=' + multi_part_boundary
40
+ req.body_stream = post_stream
41
+ res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
42
+
43
+ #close all the open hooks to the file on file-system
44
+ @streams.each do |local_stream|
45
+ local_stream.close();
46
+ end
47
+ res
48
+ end
49
+ end
50
+ end
data/lib/parts.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Parts
2
+ class StreamParam
3
+ def initialize(stream, size)
4
+ @stream, @size = stream, size
5
+ end
6
+
7
+ def size
8
+ @size
9
+ end
10
+
11
+ def read(offset, how_much)
12
+ @stream.read(how_much)
13
+ end
14
+ end
15
+
16
+ class StringParam
17
+ def initialize (str)
18
+ @str = str
19
+ end
20
+
21
+ def size
22
+ @str.length
23
+ end
24
+
25
+ def read (offset, how_much)
26
+ @str[offset, how_much]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,2 @@
1
+ require 'multi_part_post'
2
+ require 'file_upload_io'
data/lib/stream.rb ADDED
@@ -0,0 +1,46 @@
1
+ module Stream
2
+ class MultiPart
3
+ def initialize(parts)
4
+ @parts = parts
5
+ @part_no = 0
6
+ @part_offset = 0
7
+ end
8
+
9
+ def size
10
+ total = 0
11
+ @parts.each do |part|
12
+ total += part.size
13
+ end
14
+ total
15
+ end
16
+
17
+ def read (how_much)
18
+ return nil if @part_no >= @parts.size
19
+
20
+ how_much_current_part = @parts[@part_no].size - @part_offset
21
+
22
+ how_much_current_part = if how_much_current_part > how_much
23
+ how_much
24
+ else
25
+ how_much_current_part
26
+ end
27
+
28
+ how_much_next_part = how_much - how_much_current_part
29
+ current_part = @parts[@part_no].read(@part_offset, how_much_current_part )
30
+
31
+ if how_much_next_part > 0
32
+ @part_no += 1
33
+ @part_offset = 0
34
+ next_part = read( how_much_next_part )
35
+ current_part + if next_part
36
+ next_part
37
+ else
38
+ ''
39
+ end
40
+ else
41
+ @part_offset += how_much_current_part
42
+ current_part
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ruby-multipart-post}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Amit Kumar"]
9
+ s.date = %q{2010-02-11}
10
+ s.description = %q{Multipart form post thru Ruby script, headers content-type and content-length properly set}
11
+ s.email = %q{toamitkumar@gmail.com}
12
+ s.extra_rdoc_files = ["README", "README.rdoc", "lib/file_upload_io.rb", "lib/multi_part_post.rb", "lib/parts.rb", "lib/ruby-multipart-post.rb", "lib/stream.rb"]
13
+ s.files = ["README", "README.rdoc", "Rakefile", "lib/file_upload_io.rb", "lib/multi_part_post.rb", "lib/parts.rb", "lib/ruby-multipart-post.rb", "lib/stream.rb", "test/file_upload_io_test.rb", "test/files/file_0.txt", "test/parts_test.rb", "Manifest", "ruby-multipart-post.gemspec"]
14
+ s.homepage = %q{http://github.com/toamitkumar/ruby-multipart-post}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ruby-multipart-post", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{ruby-multipart-post}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{Multipart form post thru Ruby script, headers content-type and content-length properly set}
20
+ s.test_files = ["test/file_upload_io_test.rb", "test/parts_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ require "test/unit"
2
+ require File.expand_path(File.dirname(__FILE__)) + "/../lib/file_upload_io"
3
+
4
+ class FileUploadIOTest < Test::Unit::TestCase
5
+ def setup
6
+ @file_io = FileUploadIO.new("files/file_0.txt", "text/plain")
7
+ end
8
+
9
+ def teardown
10
+ @file_io.close
11
+ end
12
+
13
+ def test_should_raise_when_content_type_not_specified
14
+ assert_raises ArgumentError do
15
+ FileUploadIO.new("files/file_0.txt")
16
+ end
17
+ end
18
+
19
+ def test_should_have_content_type
20
+ assert_equal("text/plain", @file_io.content_type)
21
+ end
22
+
23
+ def test_should_have_file_name
24
+ assert_equal("file_0.txt", @file_io.file_name)
25
+ end
26
+
27
+ def test_should_have_file_size
28
+ assert_equal("41", @file_io.file_size)
29
+ end
30
+ end
@@ -0,0 +1,8 @@
1
+ Text
2
+ here
3
+ to
4
+ be
5
+ tested
6
+ for
7
+ File
8
+ IO
@@ -0,0 +1,29 @@
1
+ require "test/unit"
2
+ require File.expand_path(File.dirname(__FILE__)) + "/../lib/parts"
3
+
4
+ class PartsTest < Test::Unit::TestCase
5
+ def setup
6
+ @string_part = Parts::StringParam.new("Test String")
7
+ @file_part = Parts::StreamParam.new(File.new("files/file_0.txt"), 41)
8
+ end
9
+
10
+ def teardown
11
+ # Do nothing
12
+ end
13
+
14
+ def test_string_part_should_have_size
15
+ assert_equal(11, @string_part.size)
16
+ end
17
+
18
+ def test_should_read_string_part_by_offset
19
+ assert_equal("St", @string_part.read(5, 2))
20
+ end
21
+
22
+ def test_file_part_should_have_size
23
+ assert_equal(41, @file_part.size)
24
+ end
25
+
26
+ def test_should_read_file_part
27
+ assert_equal("Text\nhere\n", @file_part.read(5, 10))
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-multipart-post
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Amit Kumar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-11 00:00:00 -02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Multipart form post thru Ruby script, headers content-type and content-length properly set
17
+ email: toamitkumar@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - README.rdoc
25
+ - lib/file_upload_io.rb
26
+ - lib/multi_part_post.rb
27
+ - lib/parts.rb
28
+ - lib/ruby-multipart-post.rb
29
+ - lib/stream.rb
30
+ files:
31
+ - README
32
+ - README.rdoc
33
+ - Rakefile
34
+ - lib/file_upload_io.rb
35
+ - lib/multi_part_post.rb
36
+ - lib/parts.rb
37
+ - lib/ruby-multipart-post.rb
38
+ - lib/stream.rb
39
+ - test/file_upload_io_test.rb
40
+ - test/files/file_0.txt
41
+ - test/parts_test.rb
42
+ - Manifest
43
+ - ruby-multipart-post.gemspec
44
+ has_rdoc: true
45
+ homepage: http://github.com/toamitkumar/ruby-multipart-post
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --line-numbers
51
+ - --inline-source
52
+ - --title
53
+ - Ruby-multipart-post
54
+ - --main
55
+ - README.rdoc
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "1.2"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project: ruby-multipart-post
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Multipart form post thru Ruby script, headers content-type and content-length properly set
77
+ test_files:
78
+ - test/file_upload_io_test.rb
79
+ - test/parts_test.rb