summaryrefslogtreecommitdiff
path: root/chef/lib/chef/cookbook_site_streaming_uploader.rb
diff options
context:
space:
mode:
authorDaniel DeLeo <dan@opscode.com>2010-07-22 17:17:38 -0700
committerDaniel DeLeo <dan@opscode.com>2010-07-22 17:17:38 -0700
commitc95c31a36e62b216f1afeec27b3cec927bcd1aa3 (patch)
treeaab5a981f29d6489481144507301f1df5b097e55 /chef/lib/chef/cookbook_site_streaming_uploader.rb
parent0100df72eb2a66c9d07de46a04fcacfd4c7d9c14 (diff)
downloadchef-c95c31a36e62b216f1afeec27b3cec927bcd1aa3.tar.gz
purge whitespace and add license header
Diffstat (limited to 'chef/lib/chef/cookbook_site_streaming_uploader.rb')
-rw-r--r--chef/lib/chef/cookbook_site_streaming_uploader.rb79
1 files changed, 48 insertions, 31 deletions
diff --git a/chef/lib/chef/cookbook_site_streaming_uploader.rb b/chef/lib/chef/cookbook_site_streaming_uploader.rb
index 4a6e751f77..932661785e 100644
--- a/chef/lib/chef/cookbook_site_streaming_uploader.rb
+++ b/chef/lib/chef/cookbook_site_streaming_uploader.rb
@@ -1,29 +1,48 @@
+#
+# Author:: Stanislav Vitvitskiy
+# Author:: Nuo Yan (nuo@opscode.com)
+# Author:: Christopher Walters (<cw@opscode.com>)
+# Copyright:: Copyright (c) 2009, 2010 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
require 'net/http'
require 'mixlib/authentication/signedheaderauth'
require 'openssl'
-# inspired by/cargo-culted from http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
-# TODO: confirm that code is public domain
+# inspired by from http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
class Chef
class CookbookSiteStreamingUploader
DefaultHeaders = { 'accept' => 'application/json', 'x-chef-version' => ::Chef::VERSION }
-
+
class << self
def post(to_url, user_id, secret_key_filename, params = {}, headers = {})
make_request(:post, to_url, user_id, secret_key_filename, params, headers)
end
-
+
def put(to_url, user_id, secret_key_filename, params = {}, headers = {})
make_request(:put, to_url, user_id, secret_key_filename, params, headers)
end
-
+
def make_request(http_verb, to_url, user_id, secret_key_filename, params = {}, headers = {})
boundary = '----RubyMultipartClient' + rand(1000000).to_s + 'ZZZZZ'
parts = []
content_file = nil
-
+
timestamp = Time.now.utc.iso8601
secret_key = OpenSSL::PKey::RSA.new(File.read(secret_key_filename))
@@ -46,31 +65,31 @@ class Chef
end
parts << StringPart.new("--" + boundary + "--\r\n")
end
-
+
body_stream = MultipartStream.new(parts)
-
+
timestamp = Time.now.utc.iso8601
-
+
url = URI.parse(to_url)
-
+
Chef::Log.logger.debug("Signing: method: #{http_verb}, path: #{url.path}, file: #{content_file}, User-id: #{user_id}, Timestamp: #{timestamp}")
-
+
# We use the body for signing the request if the file parameter
- # wasn't a valid file or wasn't included. Extract the body (with
+ # wasn't a valid file or wasn't included. Extract the body (with
# multi-part delimiters intact) to sign the request.
# TODO: tim: 2009-12-28: It'd be nice to remove this special case, and
# always hash the entire request body. In the file case it would just be
# expanded multipart text - the entire body of the POST.
content_body = parts.inject("") { |result,part| result + part.read(0, part.size) }
content_file.rewind if content_file # we consumed the file for the above operation, so rewind it.
-
+
signing_options = {
:http_method=>http_verb,
:path=>url.path,
:user_id=>user_id,
:timestamp=>timestamp}
(content_file && signing_options[:file] = content_file) || (signing_options[:body] = (content_body || ""))
-
+
headers.merge!(Mixlib::Authentication::SignedHeaderAuth.signing_object(signing_options).sign(secret_key))
content_file.rewind if content_file
@@ -83,11 +102,11 @@ class Chef
Net::HTTP::Put.new(url.path, headers)
when :post
Net::HTTP::Post.new(url.path, headers)
- end
+ end
req.content_length = body_stream.size
req.content_type = 'multipart/form-data; boundary=' + boundary unless parts.empty?
req.body_stream = body_stream
-
+
http = Net::HTTP.new(url.host, url.port)
if url.scheme == "https"
http.use_ssl = true
@@ -100,30 +119,30 @@ class Chef
# TODO: stop the following madness!
class << res
alias :to_s :body
-
+
# BUGBUG this makes the response compatible with what respsonse_steps expects to test headers (response.headers[] -> response[])
def headers
self
end
-
+
def status
code.to_i
end
end
res
end
-
+
end
class StreamPart
def initialize(stream, size)
@stream, @size = stream, size
end
-
+
def size
@size
end
-
+
# read the specified amount from the stream
def read(offset, how_much)
@stream.read(how_much)
@@ -134,7 +153,7 @@ class Chef
def initialize(str)
@str = str
end
-
+
def size
@str.length
end
@@ -151,26 +170,26 @@ class Chef
@part_no = 0
@part_offset = 0
end
-
+
def size
@parts.inject(0) {|size, part| size + part.size}
end
-
+
def read(how_much)
return nil if @part_no >= @parts.size
how_much_current_part = @parts[@part_no].size - @part_offset
-
+
how_much_current_part = if how_much_current_part > how_much
how_much
else
how_much_current_part
end
-
+
how_much_next_part = how_much - how_much_current_part
current_part = @parts[@part_no].read(@part_offset, how_much_current_part)
-
+
# recurse into the next part if the current one was not large enough
if how_much_next_part > 0
@part_no += 1
@@ -187,8 +206,6 @@ class Chef
end
end
end
-
- end
-
-end \ No newline at end of file
+ end
+end