remote-controller 0.1.2 → 0.1.3

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/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ remote_controller
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p0
@@ -1,12 +1,22 @@
1
1
  require 'net/http'
2
2
 
3
3
  class RemoteController::Base
4
+ DefaultMultipartBoundary = "-----------1a5ef2de8917334afe03269e42657dea596c90fb"
5
+
4
6
  include RemoteController::CGIHelpers
5
7
 
6
8
  class RemoteControllerError < StandardError #:nodoc:
7
9
  end
8
10
 
9
- def initialize(url)
11
+ def initialize(url, options = {})
12
+ @options = {
13
+ verbose: false,
14
+ log_factory: RemoteController::DefaultLogFactory
15
+ }.merge options
16
+
17
+ logger_factory = @options[:verbose] ? @options[:log_factory] : RemoteController::EmptyLoggerFactory
18
+ @log = logger_factory.create_logger('remote-controller')
19
+
10
20
  @url = url
11
21
  @error_handlers = []
12
22
  end
@@ -50,9 +60,8 @@ class RemoteController::Base
50
60
 
51
61
  uri = URI.parse(@url)
52
62
  action_path = "#{uri.path}/#{action_name}"
53
-
63
+ @log.info('Preparing request...')
54
64
  request = nil
55
-
56
65
  case method
57
66
  when :get
58
67
  request = Net::HTTP::Get.new("#{action_path}?#{to_param(parameters)}")
@@ -60,18 +69,22 @@ class RemoteController::Base
60
69
  request = Net::HTTP::Post.new(action_path)
61
70
  request.body = to_param(parameters)
62
71
  when :multipart
63
- request = Net::HTTP::Post::Multipart.new(action_path, parameters)
72
+ request = Net::HTTP::Post::Multipart.new(action_path, parameters, {}, DefaultMultipartBoundary)
64
73
  else
65
74
  raise RemoteControllerError.new("Unsupported method")
66
75
  end
67
76
  initialize_request(request)
77
+ @log.info("Sending request. Method: #{method}, uri: #{action_path}.")
68
78
  response = Net::HTTP.start(uri.host, uri.port) {|http|
69
79
  http.request(request)
70
80
  }
81
+ @log.info("Response received: #{response.code} #{response.message}")
71
82
  process_headers(response)
72
83
  begin
84
+ @log.info('Evaluating response')
73
85
  response.value #Will raise error in case response is not 2xx
74
86
  rescue
87
+ @log.info("Response returned error: #{$!}")
75
88
  @error_handlers.each { |e| e.call($!) }
76
89
  raise $!
77
90
  end
@@ -1,3 +1,3 @@
1
1
  module RemoteController
2
- VERSION = "0.1.2".freeze
2
+ VERSION = "0.1.3".freeze
3
3
  end
@@ -1,11 +1,34 @@
1
1
  module RemoteController
2
- require 'remote_controller/multipart'
2
+ class DefaultLogFactory
3
+ def self.create_logger(name)
4
+ require 'logger' unless defined? Logger
5
+ log = Logger.new(STDOUT)
6
+ log.formatter = proc do |severity, datetime, progname, msg|
7
+ "#{datetime.strftime('%Y-%m-%d %H:%M:%S,%L')} [#{severity}] (#{name}) - #{msg}\n"
8
+ end
9
+ log
10
+ end
11
+ end
12
+
13
+ class EmptyLoggerFactory
14
+ def self.fatal(*args); end
15
+ def self.error(*args); end
16
+ def self.warn(*args); end
17
+ def self.info(*args); end
18
+ def self.debug(*args); end
19
+
20
+ def self.create_logger(*args)
21
+ self
22
+ end
23
+ end
24
+
25
+ require 'net/http/post/multipart'
3
26
  autoload :CookiesContainer, 'remote_controller/cookies_container'
4
27
  autoload :CGIHelpers, 'remote_controller/cgi_helpers'
5
28
  autoload :Base, 'remote_controller/base'
6
29
  autoload :VERSION, 'remote_controller/version'
7
30
 
8
31
  def self.file_part(file_path, content_type)
9
- RemoteController::Multipart::UploadIO.new(file_path, content_type)
32
+ UploadIO.new(file_path, content_type)
10
33
  end
11
34
  end
@@ -9,10 +9,13 @@ Gem::Specification.new do |s|
9
9
  s.homepage = 'http://github.com/evgeny-myasishchev/remote-controller'
10
10
  s.summary = %q{Helps to invoke actions of remote controllers.}
11
11
  s.description = %q{Library to simplify remote controller actions invocation.}
12
+
13
+ s.rubyforge_project = 'remote-controller'
14
+ s.required_ruby_version = '>= 1.9.3'
15
+
16
+ s.add_dependency 'multipart-post', '>= 1.2.0'
12
17
 
13
- s.rubyforge_project = 'remote-controller'
14
-
15
- s.add_development_dependency 'http-testing', '>= 0.1.3'
18
+ s.add_development_dependency 'http-testing', '>= 0.1.5'
16
19
  s.add_development_dependency 'rake'
17
20
  s.add_development_dependency 'rdoc'
18
21
 
@@ -1,31 +1,3 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
1
  require File.dirname(__FILE__) + '/test_helper'
30
2
 
31
3
  class RemoteControllerCookiesContainerTest < Test::Unit::TestCase
@@ -68,7 +68,7 @@ class RemoteControllerTest < Test::Unit::TestCase
68
68
  def test_invoke_args_multipart
69
69
  @context.start do |request, response|
70
70
  assert_equal "POST", request.request_method
71
- assert_equal ["multipart/form-data; boundary=#{Net::HTTP::Post::Multipart::DEFAULT_BOUNDARY}"], request.header["content-type"]
71
+ assert_equal ["multipart/form-data; boundary=#{RemoteController::Base::DefaultMultipartBoundary}"], request.header["content-type"]
72
72
  end
73
73
  @controller.args_post(:multipart, {:arg1 => "value1", :arg2 => "value2"})
74
74
  @context.wait
metadata CHANGED
@@ -1,77 +1,90 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: remote-controller
3
- version: !ruby/object:Gem::Version
4
- hash: 31
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 2
10
- version: 0.1.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Evgeny Myasishchev
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-01-03 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: http-testing
12
+ date: 2013-04-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: multipart-post
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.2.0
22
+ type: :runtime
22
23
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: http-testing
32
+ requirement: !ruby/object:Gem::Requirement
24
33
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 29
29
- segments:
30
- - 0
31
- - 1
32
- - 3
33
- version: 0.1.3
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.5
34
38
  type: :development
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: rake
38
39
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.5
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
40
49
  none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
48
54
  type: :development
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: rdoc
52
55
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rdoc
64
+ requirement: !ruby/object:Gem::Requirement
54
65
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
62
70
  type: :development
63
- version_requirements: *id003
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
64
78
  description: Library to simplify remote controller actions invocation.
65
- email:
79
+ email:
66
80
  - evgeny.myasishchev@gmail.com
67
81
  executables: []
68
-
69
82
  extensions: []
70
-
71
83
  extra_rdoc_files: []
72
-
73
- files:
84
+ files:
74
85
  - .gitignore
86
+ - .ruby-gemset
87
+ - .ruby-version
75
88
  - Gemfile
76
89
  - MIT-LICENSE
77
90
  - README.rdoc
@@ -81,58 +94,38 @@ files:
81
94
  - lib/remote_controller/base.rb
82
95
  - lib/remote_controller/cgi_helpers.rb
83
96
  - lib/remote_controller/cookies_container.rb
84
- - lib/remote_controller/multipart.rb
85
- - lib/remote_controller/multipart/composite_io.rb
86
- - lib/remote_controller/multipart/multipartable.rb
87
- - lib/remote_controller/multipart/parts.rb
88
- - lib/remote_controller/multipart/parts/epilogue_part.rb
89
- - lib/remote_controller/multipart/parts/file_part.rb
90
- - lib/remote_controller/multipart/parts/param_part.rb
91
- - lib/remote_controller/multipart/parts/part.rb
92
97
  - lib/remote_controller/version.rb
93
98
  - lib/samples/sample1.rb
94
99
  - lib/samples/sample1.txt
95
100
  - remote-controller.gemspec
96
101
  - test/remote_controller_action_args_test.rb
97
- - test/remote_controller_composite_io_test.rb
98
102
  - test/remote_controller_cookies_container_test.rb
99
103
  - test/remote_controller_error_handling_test.rb
100
104
  - test/remote_controller_test.rb
101
- - test/remote_controller_test_multipart_test.rb
102
105
  - test/test_helper.rb
103
106
  - tmp/.gitkeep
104
107
  homepage: http://github.com/evgeny-myasishchev/remote-controller
105
108
  licenses: []
106
-
107
109
  post_install_message:
108
110
  rdoc_options: []
109
-
110
- require_paths:
111
+ require_paths:
111
112
  - lib
112
- required_ruby_version: !ruby/object:Gem::Requirement
113
+ required_ruby_version: !ruby/object:Gem::Requirement
113
114
  none: false
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- hash: 3
118
- segments:
119
- - 0
120
- version: "0"
121
- required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: 1.9.3
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
120
  none: false
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- hash: 3
127
- segments:
128
- - 0
129
- version: "0"
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
130
125
  requirements: []
131
-
132
126
  rubyforge_project: remote-controller
133
- rubygems_version: 1.8.10
127
+ rubygems_version: 1.8.25
134
128
  signing_key:
135
129
  specification_version: 3
136
130
  summary: Helps to invoke actions of remote controllers.
137
131
  test_files: []
138
-
@@ -1,111 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- # Concatenate together multiple IO objects into a single, composite IO object
30
- # for purposes of reading as a single stream.
31
- #
32
- # Usage:
33
- #
34
- # crio = CompositeReadIO.new(StringIO.new('one'), StringIO.new('two'), StringIO.new('three'))
35
- # puts crio.read # => "onetwothree"
36
- #
37
- class RemoteController::Multipart::CompositeReadIO
38
- # Create a new composite-read IO from the arguments, all of which should
39
- # respond to #read in a manner consistent with IO.
40
- def initialize(*ios)
41
- @ios = ios.flatten
42
- end
43
-
44
- # Read from the IO object, overlapping across underlying streams as necessary.
45
- def read(amount = nil, buf = nil)
46
- buffer = buf || ''
47
- done = if amount; nil; else ''; end
48
- partial_amount = amount
49
-
50
- loop do
51
- result = done
52
-
53
- while !@ios.empty? && (result = @ios.first.read(partial_amount)) == done
54
- @ios.shift
55
- end
56
-
57
- buffer << result if result
58
- partial_amount -= result.length if partial_amount && result != done
59
-
60
- break if partial_amount && partial_amount <= 0
61
- break if result == done
62
- end
63
-
64
- if buffer.length > 0
65
- buffer
66
- else
67
- done
68
- end
69
- end
70
- end
71
-
72
- # Convenience methods for dealing with files and IO that are to be uploaded.
73
- module RemoteController::Multipart::UploadIO
74
- # Create an upload IO suitable for including in the params hash of a
75
- # Net::HTTP::Post::Multipart.
76
- #
77
- # Can take two forms. The first accepts a filename and content type, and
78
- # opens the file for reading (to be closed by finalizer). The second accepts
79
- # an already-open IO, but also requires a third argument, the filename from
80
- # which it was opened.
81
- #
82
- # UploadIO.new("file.txt", "text/plain")
83
- # UploadIO.new(file_io, "text/plain", "file.txt")
84
- def self.new(filename_or_io, content_type, filename = nil)
85
- io = filename_or_io
86
- unless io.respond_to? :read
87
- io = File.open(filename_or_io)
88
- filename = filename_or_io
89
- end
90
- convert!(io, content_type, File.basename(filename), filename)
91
- io
92
- end
93
-
94
- # Enhance an existing IO for including in the params hash of a
95
- # Net::HTTP::Post::Multipart by adding #content_type, #original_filename,
96
- # and #local_path methods to the object's singleton class.
97
- def self.convert!(io, content_type, original_filename, local_path)
98
- io.instance_eval(<<-EOS, __FILE__, __LINE__)
99
- def content_type
100
- "#{content_type}"
101
- end
102
- def original_filename
103
- "#{original_filename}"
104
- end
105
- def local_path
106
- "#{local_path}"
107
- end
108
- EOS
109
- io
110
- end
111
- end
@@ -1,40 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- module RemoteController::Multipart::Multipartable
30
- DEFAULT_BOUNDARY = "-----------1a5ef2de8917334afe03269e42657dea596c90fb"
31
- def initialize(path, params, headers={}, boundary = DEFAULT_BOUNDARY)
32
- super(path, headers)
33
- parts = params.map {|k,v| RemoteController::Multipart::Parts::Part.new(boundary, k, v)}
34
- parts << RemoteController::Multipart::Parts::EpiloguePart.new(boundary)
35
- ios = parts.map{|p| p.to_io }
36
- self.set_content_type("multipart/form-data", { "boundary" => boundary })
37
- self.content_length = parts.inject(0) {|sum,i| sum + i.length }
38
- self.body_stream = RemoteController::Multipart::CompositeReadIO.new(*ios)
39
- end
40
- end
@@ -1,36 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- # Represents the epilogue or closing boundary.
30
- class RemoteController::Multipart::Parts::EpiloguePart
31
- include RemoteController::Multipart::Parts::Part
32
- def initialize(boundary)
33
- @part = "--#{boundary}--\r\n"
34
- @io = StringIO.new(@part)
35
- end
36
- end
@@ -1,49 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- # Represents a part to be filled from file IO.
30
- class RemoteController::Multipart::Parts::FilePart
31
- include RemoteController::Multipart::Parts::Part
32
- attr_reader :length
33
- def initialize(boundary, name, io)
34
- file_length = io.respond_to?(:length) ? io.length : File.size(io.path)
35
- @head = build_head(boundary, name, io.original_filename, io.content_type, file_length)
36
- @length = @head.length + file_length
37
- @io = RemoteController::Multipart::CompositeReadIO.new(StringIO.new(@head), io, StringIO.new("\r\n"))
38
- end
39
-
40
- def build_head(boundary, name, filename, type, content_len)
41
- part = ''
42
- part << "--#{boundary}\r\n"
43
- part << "Content-Disposition: form-data; name=\"#{name.to_s}\"; filename=\"#{filename}\"\r\n"
44
- part << "Content-Length: #{content_len}\r\n"
45
- part << "Content-Type: #{type}\r\n"
46
- part << "Content-Transfer-Encoding: binary\r\n"
47
- part << "\r\n"
48
- end
49
- end
@@ -1,43 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- class RemoteController::Multipart::Parts::ParamPart
30
- include RemoteController::Multipart::Parts::Part
31
- def initialize(boundary, name, value)
32
- @part = build_part(boundary, name, value)
33
- @io = StringIO.new(@part)
34
- end
35
-
36
- def build_part(boundary, name, value)
37
- part = ''
38
- part << "--#{boundary}\r\n"
39
- part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n"
40
- part << "\r\n"
41
- part << "#{value}\r\n"
42
- end
43
- end
@@ -1,45 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- module RemoteController::Multipart::Parts::Part
30
- def self.new(boundary, name, value)
31
- if value.respond_to? :content_type
32
- RemoteController::Multipart::Parts::FilePart.new(boundary, name, value)
33
- else
34
- RemoteController::Multipart::Parts::ParamPart.new(boundary, name, value)
35
- end
36
- end
37
-
38
- def length
39
- @part.length
40
- end
41
-
42
- def to_io
43
- @io
44
- end
45
- end
@@ -1,6 +0,0 @@
1
- module RemoteController::Multipart::Parts end
2
-
3
- require 'remote_controller/multipart/parts/part'
4
- require 'remote_controller/multipart/parts/param_part'
5
- require 'remote_controller/multipart/parts/file_part'
6
- require 'remote_controller/multipart/parts/epilogue_part'
@@ -1,63 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
-
30
- #Example:
31
- # url = URI.parse('http://www.example.com/upload')
32
- # File.open("./image.jpg") do |jpg|
33
- # req = Net::HTTP::Post::Multipart.new url.path,
34
- # "file" => UploadIO.new(jpg, "image/jpeg", "image.jpg")
35
- # res = Net::HTTP.start(url.host, url.port) do |http|
36
- # http.request(req)
37
- # end
38
- # end
39
-
40
-
41
- require 'net/http'
42
- require 'stringio'
43
-
44
- module RemoteController::Multipart end
45
-
46
- require 'remote_controller/multipart/parts'
47
- require 'remote_controller/multipart/composite_io'
48
- require 'remote_controller/multipart/multipartable'
49
-
50
- module Net #:nodoc:
51
- class HTTP #:nodoc:
52
- class Put
53
- class Multipart < Put
54
- include RemoteController::Multipart::Multipartable
55
- end
56
- end
57
- class Post #:nodoc:
58
- class Multipart < Post
59
- include RemoteController::Multipart::Multipartable
60
- end
61
- end
62
- end
63
- end
@@ -1,76 +0,0 @@
1
- #++
2
- # (The MIT License)
3
- #
4
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining
7
- # a copy of this software and associated documentation files (the
8
- # 'Software'), to deal in the Software without restriction, including
9
- # without limitation the rights to use, copy, modify, merge, publish,
10
- # distribute, sublicense, and/or sell copies of the Software, and to
11
- # permit persons to whom the Software is furnished to do so, subject to
12
- # the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be
15
- # included in all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
-
25
- require File.dirname(__FILE__) + '/test_helper'
26
- require 'stringio'
27
-
28
- class RemoteControllerCompositeReadIOTest < Test::Unit::TestCase
29
-
30
- include RemoteController::Multipart
31
-
32
- def setup
33
- @io = CompositeReadIO.new(CompositeReadIO.new(StringIO.new('the '), StringIO.new('quick ')),
34
- StringIO.new('brown '), StringIO.new('fox'))
35
- end
36
-
37
- def test_full_read_from_several_ios
38
- assert_equal 'the quick brown fox', @io.read
39
- end
40
-
41
- def test_partial_read
42
- assert_equal 'the quick', @io.read(9)
43
- end
44
-
45
- def test_partial_read_to_boundary
46
- assert_equal 'the quick ', @io.read(10)
47
- end
48
-
49
- def test_read_with_size_larger_than_available
50
- assert_equal 'the quick brown fox', @io.read(32)
51
- end
52
-
53
- def test_read_into_buffer
54
- buf = ''
55
- @io.read(nil, buf)
56
- assert_equal 'the quick brown fox', buf
57
- end
58
-
59
- def test_multiple_reads
60
- assert_equal 'the ', @io.read(4)
61
- assert_equal 'quic', @io.read(4)
62
- assert_equal 'k br', @io.read(4)
63
- assert_equal 'own ', @io.read(4)
64
- assert_equal 'fox', @io.read(4)
65
- end
66
-
67
- def test_read_after_end
68
- @io.read
69
- assert_equal "", @io.read
70
- end
71
-
72
- def test_read_after_end_with_amount
73
- @io.read(32)
74
- assert_equal nil, @io.read(32)
75
- end
76
- end
@@ -1,91 +0,0 @@
1
- #--
2
- # (c) Copyright 2007-2008 Nick Sieger.
3
- # See the file README.txt included with the distribution for
4
- # software license details.
5
- #++
6
- # (The MIT License)
7
- #
8
- # Copyright (c) 2007-2009 Nick Sieger <nick@nicksieger.com>
9
- #
10
- # Permission is hereby granted, free of charge, to any person obtaining
11
- # a copy of this software and associated documentation files (the
12
- # 'Software'), to deal in the Software without restriction, including
13
- # without limitation the rights to use, copy, modify, merge, publish,
14
- # distribute, sublicense, and/or sell copies of the Software, and to
15
- # permit persons to whom the Software is furnished to do so, subject to
16
- # the following conditions:
17
- #
18
- # The above copyright notice and this permission notice shall be
19
- # included in all copies or substantial portions of the Software.
20
- #
21
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
22
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
-
29
- require File.dirname(__FILE__) + '/test_helper'
30
-
31
- class RemoteControllerMultiPartTest < Test::Unit::TestCase
32
-
33
- include RemoteController::Multipart
34
-
35
- TEMP_FILE = "temp.txt"
36
-
37
- HTTPPost = Struct.new("HTTPPost", :content_length, :body_stream, :content_type)
38
- HTTPPost.module_eval do
39
- def set_content_type(type, params = {})
40
- self.content_type = type + params.map{|k,v|"; #{k}=#{v}"}.join('')
41
- end
42
- end
43
-
44
- def setup
45
- @another_temp_file = "#{File.dirname(__FILE__)}/../tmp/temp_file.txt"
46
- end
47
-
48
- def teardown
49
- File.delete(TEMP_FILE) rescue nil
50
- File.delete(@another_temp_file) rescue nil
51
- end
52
-
53
- def test_form_multipart_body
54
- File.open(TEMP_FILE, "w") {|f| f << "1234567890"}
55
- @io = File.open(TEMP_FILE)
56
- UploadIO.convert! @io, "text/plain", TEMP_FILE, TEMP_FILE
57
- assert_results Net::HTTP::Post::Multipart.new("/foo/bar", :foo => 'bar', :file => @io)
58
- end
59
- def test_form_multipart_body_no_text_plain
60
- File.open(@another_temp_file, "w") {|f| f << "1234567890"}
61
- @io = File.open(@another_temp_file)
62
- UploadIO.convert! @io, "application/octet-stream", File.basename(@another_temp_file), File.basename(@another_temp_file)
63
- file_part = RemoteController::Multipart::Parts::FilePart.new("--bound", "name", @io)
64
- end
65
- def test_form_multipart_body_put
66
- File.open(TEMP_FILE, "w") {|f| f << "1234567890"}
67
- @io = File.open(TEMP_FILE)
68
- UploadIO.convert! @io, "text/plain", TEMP_FILE, TEMP_FILE
69
- assert_results Net::HTTP::Put::Multipart.new("/foo/bar", :foo => 'bar', :file => @io)
70
- end
71
-
72
- def test_form_multipart_body_with_stringio
73
- @io = StringIO.new("1234567890")
74
- UploadIO.convert! @io, "text/plain", TEMP_FILE, TEMP_FILE
75
- assert_results Net::HTTP::Post::Multipart.new("/foo/bar", :foo => 'bar', :file => @io)
76
- end
77
-
78
- def assert_results(post)
79
- assert post.content_length && post.content_length > 0
80
- assert post.body_stream
81
- assert_equal "multipart/form-data; boundary=#{Multipartable::DEFAULT_BOUNDARY}", post['content-type']
82
- body = post.body_stream.read
83
- boundary_regex = Regexp.quote Multipartable::DEFAULT_BOUNDARY
84
- assert body =~ /1234567890/
85
- # ensure there is at least one boundary
86
- assert body =~ /^--#{boundary_regex}\r\n/
87
- # ensure there is an epilogue
88
- assert body =~ /^--#{boundary_regex}--\r\n/
89
- assert body =~ /text\/plain/
90
- end
91
- end