Module: S33r::Networking

Defined in:
lib/s33r/networking.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#chunk_sizeObject

Default chunk size for connections.



13
14
15
# File 'lib/s33r/networking.rb', line 13

def chunk_size
  @chunk_size
end

#clientObject

Net::HTTP instance.



7
8
9
# File 'lib/s33r/networking.rb', line 7

def client
  @client
end

#dump_requestsObject

Should requests be dumped?



16
17
18
# File 'lib/s33r/networking.rb', line 16

def dump_requests
  @dump_requests
end

#last_responseObject (readonly)

The last response received by the client.



19
20
21
# File 'lib/s33r/networking.rb', line 19

def last_response
  @last_response
end

#persistentObject

Are HTTP connections persistent?



10
11
12
# File 'lib/s33r/networking.rb', line 10

def persistent
  @persistent
end

Instance Method Details

#do_delete(options = {}, headers = {}) ⇒ Object

Perform a delete request.



177
178
179
# File 'lib/s33r/networking.rb', line 177

def do_delete(options={}, headers={})
  do_request('DELETE', options, headers)
end

#do_get(options = {}, headers = {}) ⇒ Object

Perform a get request.



167
168
169
# File 'lib/s33r/networking.rb', line 167

def do_get(options={}, headers={})
  do_request('GET', options, nil, headers)
end

#do_head(options = {}, headers = {}) ⇒ Object

Perform a head request.



182
183
184
# File 'lib/s33r/networking.rb', line 182

def do_head(options={}, headers={})
  do_request('HEAD', options, headers)
end

#do_put(data, options = {}, headers = {}) ⇒ Object

Perform a put request.



172
173
174
# File 'lib/s33r/networking.rb', line 172

def do_put(data, options={}, headers={})
  do_request('PUT', options, data, headers)
end

#do_request(method, url_options = {}, data = nil, headers = {}) ⇒ Object

Send a request over the wire.

This method streams data if it responds to the stat method (as file handles do).

Keys for headers should be strings (e.g. ‘Content-Type’).

url_options is a standard set of options acceptable to s3_url; if any options aren’t set, they are set using the request_defaults method (options passed in here override defaults).

You can also pass :authenticated => false if you want to visit a public URL here; otherwise, an Authorization header is generated and sent. If the client doesn’t have an access key or secret access key specified, however, trying to create an access key will result in an error being raised.

Returns a Net::HTTPResponse instance.

Raises:

  • (MethodNotAllowed)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/s33r/networking.rb', line 48

def do_request(method, url_options={}, data=nil, headers={})
  # Use the default settings only if not specified in url_options.
  url_options = request_defaults.merge(url_options)
  
  # Get the URL.
  url = s3_url(url_options)
  uri = URI(url)
  
  # Bar any except the allowed methods.
  raise MethodNotAllowed, "The #{method} HTTP method is not supported" unless METHOD_VERBS.include?(method)
  
  # Get a requester.
  path = uri.path
  path += "?" + uri.query if uri.query
  req = eval("HTTP::" + method[0,1].upcase + method[1..-1].downcase + ".new('#{path}')")
  
  req.chunk_size = chunk_size || DEFAULT_CHUNK_SIZE

  # Add the S3 headers which are always required.
  headers.merge!(default_headers(headers))

  # Headers for canned ACL
  headers.merge! canned_acl_header(url_options[:canned_acl]) if 'PUT' == method

  # Generate the S3 authorization header if the client has 
  # the appropriate instance variable getters.
  unless (false == url_options[:authenticated])
    subdomain = nil
    subdomain = url_options[:bucket] if url_options[:subdomain]

    headers['Authorization'] = generate_auth_header_value(method, path, headers,
    url_options[:access], url_options[:secret], subdomain)
  end

  # Insert the headers into the request object.
  headers.each do |key, value|
    req[key] = value
  end

  # Add data to the request as a stream.
  if req.request_body_permitted?
    # For streaming files; NB Content-Length will be set by Net::HTTP
    # for character-based data: this section of is only used
    # when reading directly from a file.
    if data.respond_to?(:stat)
      length = data.stat.size
    # Strings can be streamed too.
    elsif data.is_a?(String)
      length = data.length
      data = StringIO.new(data)
    else
      length = 0
    end
    
    # Data can be streamed if it responds to the read method.
    if data.respond_to?(:read)
      req.body_stream = data
      req['Content-Length'] = length.to_s
      data = nil
    end
  else
    data = nil
  end
  
  puts req.dump(uri.host) if @dump_requests
  
  # Set up the request.
  ### <snip> start shameless stealing from Marcel Molina
  request_runner = Proc.new do
    response = @client.request(req, data)
    
    # Add some nice messages to the response (like the S3 error 
    # message if it occurred).
    response.conveniencify(method)
    @last_response = response
    
    return response
  end

  # Get a client instance.
  init_client(uri)

  # Run the request.
  if persistent
    @client.start unless @client.started?
    response = request_runner.call
  else
    response = @client.start(&request_runner)
  end

  response
  ### </snip> end shameless stealing from Marcel Molina
end

#init_client(url) ⇒ Object

Setup an HTTP client instance.

Note that when you send your first request, the client is set up using whichever parameters for host and port you passed the first time. If you change the host or port, the client will be regenerated.

url is a URI instance generated from a full URL, including a host name and scheme.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/s33r/networking.rb', line 150

def init_client(url)
  host = url.host || HOST
  port = url.port
  if @client.nil? or @client.port != port or @client.address != host
    @client = HTTP.new(host, port)
    @client.use_ssl = false
    
    # Check whether client needs to use SSL.
    if port == PORT
      # turn off SSL certificate verification
      @client.verify_mode = OpenSSL::SSL::VERIFY_NONE
      @client.use_ssl = true
    end
  end
end

#request_defaultsObject

Get default options to use on every response.



22
23
24
# File 'lib/s33r/networking.rb', line 22

def request_defaults
  @request_defaults || {}
end

#request_defaults=(options = {}) ⇒ Object

Set the defaults.



27
28
29
# File 'lib/s33r/networking.rb', line 27

def request_defaults=(options={})
  @request_defaults = options
end