135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # Copyright 2015 Google Inc.
 | |
| #
 | |
| # 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.
 | |
| 
 | |
| 
 | |
| module Google
 | |
|   module Apis
 | |
|     module Core
 | |
|       # Part of a multipart request for holding JSON data
 | |
|       #
 | |
|       # @private
 | |
|       class JsonPart
 | |
| 
 | |
|         # @param [String] value
 | |
|         #   JSON content
 | |
|         # @param [Hash] header
 | |
|         #   Additional headers
 | |
|         def initialize(value, header = {})
 | |
|           @value = value
 | |
|           @header = header
 | |
|         end
 | |
| 
 | |
|         def to_io(boundary)
 | |
|           part = ''
 | |
|           part << "--#{boundary}\r\n"
 | |
|           part << "Content-Type: application/json\r\n"
 | |
|           @header.each do |(k, v)|
 | |
|             part << "#{k}: #{v}\r\n"
 | |
|           end
 | |
|           part << "\r\n"
 | |
|           part << "#{@value}\r\n"
 | |
|           StringIO.new(part)
 | |
|         end
 | |
| 
 | |
|       end
 | |
| 
 | |
|       # Part of a multipart request for holding arbitrary content.
 | |
|       #
 | |
|       # @private
 | |
|       class FilePart
 | |
|         # @param [IO] io
 | |
|         #   IO stream
 | |
|         # @param [Hash] header
 | |
|         #   Additional headers
 | |
|         def initialize(io, header = {})
 | |
|           @io = io
 | |
|           @header = header
 | |
|           @length = io.respond_to?(:size) ? io.size : nil
 | |
|         end
 | |
| 
 | |
|         def to_io(boundary)
 | |
|           head = ''
 | |
|           head << "--#{boundary}\r\n"
 | |
|           @header.each do |(k, v)|
 | |
|             head << "#{k}: #{v}\r\n"
 | |
|           end
 | |
|           head << "Content-Length: #{@length}\r\n" unless @length.nil?
 | |
|           head << "Content-Transfer-Encoding: binary\r\n"
 | |
|           head << "\r\n"
 | |
|           Google::Apis::Core::CompositeIO.new(StringIO.new(head), @io, StringIO.new("\r\n"))
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       # Helper for building multipart requests
 | |
|       class Multipart
 | |
|         MULTIPART_RELATED = 'multipart/related'
 | |
| 
 | |
|         # @return [String]
 | |
|         #  Content type header
 | |
|         attr_reader :content_type
 | |
| 
 | |
|         # @param [String] content_type
 | |
|         #  Content type for the multipart request
 | |
|         # @param [String] boundary
 | |
|         #  Part delimiter
 | |
| 
 | |
|         def initialize(content_type: MULTIPART_RELATED, boundary: nil)
 | |
|           @parts = []
 | |
|           @boundary = boundary || Digest::SHA1.hexdigest(SecureRandom.random_bytes(8))
 | |
|           @content_type = "#{content_type}; boundary=#{@boundary}"
 | |
|         end
 | |
| 
 | |
|         # Append JSON data part
 | |
|         #
 | |
|         # @param [String] body
 | |
|         #   JSON text
 | |
|         # @param [String] content_id
 | |
|         #   Optional unique ID of this part
 | |
|         # @return [self]
 | |
|         def add_json(body, content_id: nil)
 | |
|           header = {}
 | |
|           header['Content-ID'] = content_id unless content_id.nil?
 | |
|           @parts << Google::Apis::Core::JsonPart.new(body, header).to_io(@boundary)
 | |
|           self
 | |
|         end
 | |
| 
 | |
|         # Append arbitrary data as a part
 | |
|         #
 | |
|         # @param [IO] upload_io
 | |
|         #   IO stream
 | |
|         # @param [String] content_id
 | |
|         #   Optional unique ID of this part
 | |
|         # @return [self]
 | |
|         def add_upload(upload_io, content_type: nil, content_id: nil)
 | |
|           header = {
 | |
|               'Content-Type' => content_type || 'application/octet-stream'
 | |
|           }
 | |
|           header['Content-Id'] = content_id unless content_id.nil?
 | |
|           @parts << Google::Apis::Core::FilePart.new(upload_io,
 | |
|                                                      header).to_io(@boundary)
 | |
|           self
 | |
|         end
 | |
| 
 | |
|         # Assemble the multipart requests
 | |
|         #
 | |
|         # @return [IO]
 | |
|         #  IO stream
 | |
|         def assemble
 | |
|           @parts <<  StringIO.new("--#{@boundary}--\r\n\r\n")
 | |
|           Google::Apis::Core::CompositeIO.new(*@parts)
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end |