1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/connection.rb

160 lines
4.1 KiB
Ruby
Raw Normal View History

require 'rubygems'
require 'openssl'
require 'socket'
require 'uri'
require "fog/errors"
require "fog/response"
2009-08-07 03:28:53 -04:00
unless Fog.mocking?
2009-08-07 03:28:53 -04:00
module Fog
class Connection
unless const_defined?(:CHUNK_SIZE)
CHUNK_SIZE = 1048576 # 1 megabyte
end
2009-08-07 03:28:53 -04:00
def initialize(url)
@uri = URI.parse(url)
@connection = TCPSocket.open(@uri.host, @uri.port)
if @uri.scheme == 'https'
@ssl_context = OpenSSL::SSL::SSLContext.new
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
@connection = OpenSSL::SSL::SSLSocket.new(@connection, @ssl_context)
@connection.sync_close = true
@connection.connect
end
end
2009-08-07 03:28:53 -04:00
def request(params)
params[:path] ||= ''
unless params[:path][0] == '/'
params[:path] = '/' + params[:path].to_s
end
if params[:query] && !params[:query].empty?
params[:path] << "?#{params[:query]}"
end
request = "#{params[:method]} #{params[:path]} HTTP/1.1\r\n"
params[:headers] ||= {}
params[:headers]['Host'] = params[:host]
2009-09-09 23:44:28 -04:00
if params[:body] && !params[:headers]['Content-Length']
2009-08-07 03:28:53 -04:00
params[:headers]['Content-Length'] = params[:body].length
end
for key, value in params[:headers]
request << "#{key}: #{value}\r\n"
end
2009-09-09 23:44:28 -04:00
request << "\r\n"
2009-08-07 03:28:53 -04:00
@connection.write(request)
2009-09-09 23:44:28 -04:00
if params[:body]
if params[:body].is_a?(String)
body = StringIO.new(params[:body])
else
body = params[:body]
end
while chunk = body.read(CHUNK_SIZE)
2009-09-09 23:44:28 -04:00
@connection.write(chunk)
end
end
2009-08-07 03:28:53 -04:00
response = Fog::Response.new
response.request = params
response.status = @connection.readline[9..11].to_i
2009-08-19 22:10:59 -04:00
if params[:expects] && params[:expects] != response.status
error = true
end
2009-08-07 03:28:53 -04:00
while true
data = @connection.readline.chomp!
if data == ""
break
end
header = data.split(': ')
response.headers[capitalize(header[0])] = header[1]
end
2009-08-19 22:10:59 -04:00
if error || params[:parser]
if error
parser = Fog::Errors::Parser.new
elsif params[:parser]
parser = params[:parser]
end
body = Nokogiri::XML::SAX::PushParser.new(parser)
2009-09-09 23:44:28 -04:00
elsif params[:block]
body = nil
2009-08-07 03:28:53 -04:00
else
body = ''
end
unless params[:method] == 'HEAD'
if response.headers['Content-Length']
if error || !params[:block]
body << @connection.read(response.headers['Content-Length'].to_i)
2009-09-09 23:44:28 -04:00
else
remaining = response.headers['Content-Length'].to_i
while remaining > 0
params[:block].call(@connection.read([CHUNK_SIZE, remaining].min))
remaining -= CHUNK_SIZE;
end
2009-09-09 23:44:28 -04:00
end
2009-08-07 03:28:53 -04:00
elsif response.headers['Transfer-Encoding'] == 'chunked'
while true
# 2 == "/r/n".length
chunk_size = @connection.readline.chomp!.to_i(16) + 2
2009-09-09 23:44:28 -04:00
chunk = @connection.read(chunk_size)[0...-2]
if error || !params[:block]
2009-09-09 23:44:28 -04:00
body << chunk
else
params[:block].call(chunk)
end
2009-08-07 03:28:53 -04:00
if chunk_size == 2
break
end
end
end
end
2009-08-19 22:10:59 -04:00
if parser
2009-08-07 03:28:53 -04:00
body.finish
2009-08-19 22:10:59 -04:00
response.body = parser.response
2009-08-07 03:28:53 -04:00
else
response.body = body
end
2009-08-19 22:10:59 -04:00
if error
raise(Fog::Errors.status_error(params[:expects], response.status, response))
2009-08-07 03:28:53 -04:00
else
response
end
end
2009-08-07 03:28:53 -04:00
private
def capitalize(header)
words = header.split('-')
header = ''
for word in words
header << word[0..0].upcase << word[1..-1] << '-'
end
header.chop!
end
2009-08-07 03:28:53 -04:00
end
2009-08-07 03:28:53 -04:00
end
else
2009-08-07 03:28:53 -04:00
module Fog
class Connection
2009-08-07 03:28:53 -04:00
def initialize(url)
end
2009-08-07 03:28:53 -04:00
def request(params)
end
end
end
2009-08-07 03:28:53 -04:00
end