zephyr 1.0.0

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+
2
+ source "http://rubygems.org"
3
+ gem "typhoeus", ">= 0.2.4"
4
+
5
+
6
+ group :development do
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.6.4"
9
+ end
10
+
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.4)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ mime-types (1.16)
10
+ rake (0.9.2)
11
+ typhoeus (0.2.4)
12
+ mime-types
13
+ mime-types
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ bundler (~> 1.0.0)
20
+ jeweler (~> 1.6.4)
21
+ typhoeus (>= 0.2.4)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Matt Knopp
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ ## Simple HTTP client using Typheous, derived from the Riak client
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "zephyr"
18
+ gem.homepage = "http://github.com/mhat/zephyr"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Simple HTTP client using Typheous, derived from the Riak client}
21
+ gem.description = %Q{Simple HTTP client using Typheous, derived from the Riak client}
22
+ gem.email = "matt.knopp@gmail.com"
23
+ gem.authors = ["Matt Knopp"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ ##require 'rcov/rcovtask'
36
+ ##Rcov::RcovTask.new do |test|
37
+ ## test.libs << 'test'
38
+ ## test.pattern = 'test/**/test_*.rb'
39
+ ## test.verbose = true
40
+ ## test.rcov_opts << '--exclude "gems/*"'
41
+ ##end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "zephyr #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/lib/zephyr.rb ADDED
@@ -0,0 +1,350 @@
1
+ # Stolen with a fair bit of modification from the riak-client gem, which is
2
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # Splits headers into < 8KB chunks
17
+ # @private
18
+ module Net::HTTPHeader
19
+ def each_capitalized
20
+ # 1.9 check
21
+ respond_to?(:enum_for) and (block_given? or return enum_for(__method__))
22
+ @header.each do |k,v|
23
+ base_length = "#{k}: \r\n".length
24
+ values = v.map { |i| i.to_s.split(', ') }.flatten
25
+ while !values.empty?
26
+ current_line = ""
27
+ while values.first && current_line.length + base_length + values.first.length + 2 < 8192
28
+ val = values.shift.strip
29
+ current_line += current_line.empty? ? val : ", #{val}"
30
+ end
31
+ yield capitalize(k), current_line
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ # A simple front-end for doing HTTP requests quickly and simply.
38
+ class Zephyr
39
+ def initialize(root_uri = '')
40
+ @root_uri = URI.parse(root_uri.to_s).freeze
41
+ end
42
+
43
+ def default_headers
44
+ {
45
+ 'Accept' => 'application/json;q=0.7, */*;q=0.5',
46
+ 'User-Agent' => 'lib-http.rb',
47
+ }
48
+ end
49
+
50
+ # Performs a HEAD request to the specified resource.
51
+ #
52
+ # A request to /users/#{@user.id}/things?q=woof with an Accept header of
53
+ # "text/plain" which is expecting a 200 OK within 50ms
54
+ #
55
+ # http.head(200, 50, ["users", @user.id, "things", {"q" => "woof"}], "Accept" => "text/plain")
56
+ #
57
+ # This returns a hash with three keys:
58
+ # :status The numeric HTTP status code
59
+ # :body The body of the response entity, if any
60
+ # :headers A hash of header values
61
+ def head(expected_statuses, timeout, path_components, headers={})
62
+ headers = default_headers.merge(headers)
63
+ verify_path!(path_components)
64
+ perform(:head, path_components, headers, expected_statuses, timeout)
65
+ end
66
+
67
+ Workfeed::Timer.time_method self, :head, 'http_head'
68
+
69
+ # Performs a GET request to the specified resource.
70
+ #
71
+ # A request to /users/#{@user.id}/things?q=woof with an Accept header of
72
+ # "text/plain" which is expecting a 200 OK within 50ms
73
+ #
74
+ # http.get(200, 50 ["users", @user.id, "things", {"q" => "woof"}], "Accept" => "text/plain")
75
+ #
76
+ # This returns a hash with three keys:
77
+ # :status The numeric HTTP status code
78
+ # :body The body of the response entity, if any
79
+ # :headers A hash of header values
80
+ def get(expected_statuses, timeout, path_components, headers={})
81
+ headers = default_headers.merge(headers)
82
+ verify_path!(path_components)
83
+ perform(:get, path_components, headers, expected_statuses, timeout)
84
+ end
85
+
86
+ Workfeed::Timer.time_method self, :get, 'http_get'
87
+
88
+ # The same thing as #get, but decodes the response entity as JSON (if it's
89
+ # application/json) and adds it under the :json key in the returned hash.
90
+ def get_json(expected_statuses, timeout, path_components, headers={}, yajl_opts={})
91
+ response = get(expected_statuses, timeout, path_components, headers)
92
+
93
+ content_type = response[:headers]['content-type']
94
+ content_type = content_type.first if content_type.respond_to?(:first)
95
+
96
+ if content_type.to_s.strip.match /^application\/json/
97
+ response[:json] = Yajl::Parser.parse(response[:body], yajl_opts)
98
+ end
99
+
100
+ response
101
+ end
102
+
103
+ # Performs a PUT request to the specified resource.
104
+ #
105
+ # A request to /users/#{@user.id}/things?q=woof with an Content-Type header of
106
+ # "text/plain" and a request entity of "yay" which is expecting a 204 No
107
+ # Content within 1000ms
108
+ #
109
+ # http.put(204, 1000, ["users", @user.id, "things", {"q" => "woof"}], "yay", "Content-Type" => "text/plain")
110
+ #
111
+ # This returns a hash with three keys:
112
+ # :status The numeric HTTP status code
113
+ # :body The body of the response entity, if any
114
+ # :headers A hash of header values
115
+ def put(expected_statuses, timeout, path_components, entity, headers={})
116
+ headers = default_headers.merge(headers)
117
+ verify_path_and_entity!(path_components, entity)
118
+ perform(:put, path_components, headers, expected_statuses, timeout, entity)
119
+ end
120
+
121
+ Workfeed::Timer.time_method self, :put, 'http_put'
122
+
123
+ # The same thing as #put, but encodes the entity as JSON and specifies
124
+ # "application/json" as the request entity content type.
125
+ def put_json(expected_statuses, timeout, path_components, entity, headers={})
126
+ put(expected_statuses, timeout, path_components, Yajl::Encoder.encode(entity), headers.merge("Content-Type" => "application/json"))
127
+ end
128
+
129
+ # Performs a POST request to the specified resource.
130
+ #
131
+ # A request to /users/#{@user.id}/things?q=woof with an Content-Type header of
132
+ # "text/plain" and a request entity of "yay" which is expecting a 201 Created
133
+ # within 500ms
134
+ #
135
+ # http.post(201, 500, ["users", @user.id, "things", {"q" => "woof"}], "yay", "Content-Type" => "text/plain")
136
+ #
137
+ # This returns a hash with three keys:
138
+ # :status The numeric HTTP status code
139
+ # :body The body of the response entity, if any
140
+ # :headers A hash of header values
141
+ def post(expected_statuses, timeout, path_components, entity, headers={})
142
+ headers = default_headers.merge(headers)
143
+ verify_path_and_entity!(path_components, entity)
144
+ perform(:post, path_components, headers, expected_statuses, timeout, entity)
145
+ end
146
+
147
+ Workfeed::Timer.time_method self, :post, 'http_post'
148
+
149
+ # The same thing as #post, but encodes the entity as JSON and specifies
150
+ # "application/json" as the request entity content type.
151
+ def post_json(expected_statuses, timeout, path_components, entity, headers={})
152
+ post(
153
+ expected_statuses,
154
+ timeout,
155
+ path_components,
156
+ Yajl::Encoder.encode(entity),
157
+ headers.merge("Content-Type" => "application/json")
158
+ )
159
+ end
160
+
161
+ # Performs a DELETE request to the specified resource.
162
+ #
163
+ # A request to /users/#{@user.id}/things?q=woof which is expecting a 204 No
164
+ # Content within 666ms
165
+ #
166
+ # http.put(200, 666, ["users", @user.id, "things", {"q" => "woof"}])
167
+ #
168
+ # This returns a hash with three keys:
169
+ # :status The numeric HTTP status code
170
+ # :body The body of the response entity, if any
171
+ # :headers A hash of header values
172
+ def delete(expected_statuses, timeout, path_components, headers={})
173
+ headers = default_headers.merge(headers)
174
+ verify_path!(path_components)
175
+ perform(:delete, path_components, headers, expected_statuses, timeout)
176
+ end
177
+
178
+ Workfeed::Timer.time_method self, :delete, 'http_delete'
179
+
180
+ # Creates a URI object, combining the root_uri passed on initialization
181
+ # with the given parts.
182
+ #
183
+ # Example:
184
+ #
185
+ # http = Zephyr.new 'http://host/'
186
+ # http.uri(['hi', 'bob', {:foo => 'bar'}]) => http://host/hi/bob?foo=bar
187
+ #
188
+ def uri(given_parts = [])
189
+ @root_uri.dup.tap do |uri|
190
+ parts = given_parts.dup.unshift(uri.path) # URI#merge is broken.
191
+ uri.query = build_query_string(parts.pop) if parts.last.is_a? Hash
192
+ uri.path = ('/%s/' % parts.join('/')).gsub(/\/+/, '/')
193
+ end
194
+ end
195
+
196
+ # Comes handy in IRB
197
+ #
198
+ def inspect
199
+ '#<%s:0x%s root_uri=%s>' % [ self.class.to_s, object_id.to_s(16), uri.to_s ]
200
+ end
201
+
202
+ def cleanup!
203
+ Typheous::Hydra.hydra.cleanup
204
+ end
205
+
206
+ # Assembles a query string from a Hash, escaping values and keys. If a
207
+ # value is an Array, the query parameter simply appears twice.
208
+ #
209
+ # Stolen from Rack (with minor changes for sorting).
210
+ #
211
+ def build_query_string(params)
212
+ params.map do |k, v|
213
+ if v.kind_of? Array
214
+ build_query_string(v.map { |x| [k, x] })
215
+ else
216
+ "#{percent_encode(k)}=#{percent_encode(v)}"
217
+ end
218
+ end.sort.join '&'
219
+ end
220
+
221
+ def percent_encode(value)
222
+ typhoeus_easy.send(:easy_escape, value.to_s, value.to_s.bytesize)
223
+ end
224
+
225
+ private
226
+
227
+ # NOTE: This is here only because it provides a binding to
228
+ # Curb's 'easy_escape' function, which does what we want.
229
+ # Don't use it to perform requests. Ever.
230
+ #
231
+ def typhoeus_easy
232
+ @_typhoeus_easy ||= Typhoeus::Easy.new.freeze
233
+ end
234
+
235
+ def verify_path_and_entity!(path_components, entity)
236
+ begin
237
+ verify_path!(path_components)
238
+ rescue ArgumentError
239
+ raise ArgumentError, "You must supply both a resource path and a body."
240
+ end
241
+
242
+ raise ArgumentError, "Request body must be a string or IO." unless String === entity || IO === entity
243
+ end
244
+
245
+ def verify_path!(path_components)
246
+ path_components = Array(path_components).flatten
247
+ raise ArgumentError, "Resource path too short" unless path_components.length > 0
248
+ end
249
+
250
+ def valid_response?(expected, actual)
251
+ Array(expected).map { |code| code.to_i }.include?(actual.to_i)
252
+ end
253
+
254
+ def return_body?(method, code)
255
+ method != :head && !valid_response?([204,205,304], code)
256
+ end
257
+
258
+ def perform(method, path_components, headers, expect, timeout, data=nil)
259
+ params = {}
260
+ params[:headers] = headers
261
+ params[:timeout] = timeout
262
+ params[:follow_location] = false
263
+
264
+ # if you want debugging
265
+ # params[:verbose] = true
266
+
267
+ # have a vague feeling this isn't going to work as expected
268
+ if method == :post || method == :put
269
+ data = data.read if data.respond_to?(:read)
270
+ params[:body] = data
271
+ end
272
+
273
+ # request has class methods for :delete, :get, :head, :put, and :post
274
+ response = Typhoeus::Request.send(method, uri(path_components).to_s, params)
275
+
276
+ if defined?(Rails)
277
+ Rails.logger.info "lib/http.rb: #{method.to_s.upcase} #{uri(path_components).to_s}"
278
+ end
279
+
280
+ # be consistent with what came before
281
+ response_headers = Headers.new.tap do |h|
282
+ response.headers.split(/\n/).each do |header_line|
283
+ h.parse(header_line)
284
+ end
285
+ end
286
+
287
+ if valid_response?(expect, response.code)
288
+ result = { :headers => response_headers.to_hash, :status => response.code }
289
+ if return_body?(method, response.code)
290
+ result[:body] = response.body
291
+ end
292
+ result
293
+ else
294
+ response_body = response.timed_out? || response.code == 0 ? "Exceeded #{timeout}ms" : response.body
295
+ raise FailedRequest.new(method, expect, response.code, response_headers.to_hash, response_body, response.timed_out?)
296
+ end
297
+ end
298
+
299
+ def create_request_headers(hash)
300
+ h = Headers.new
301
+ hash.each {|k,v| h.add_field(k,v) }
302
+ [].tap do |arr|
303
+ h.each_capitalized do |k,v|
304
+ arr << "#{k}: #{v}"
305
+ end
306
+ end
307
+ end
308
+ end
309
+ Http = YammerHttp
310
+
311
+ # Represents headers from an HTTP request or response.
312
+ # Used internally by HTTP backends for processing headers.
313
+ class Headers
314
+ include Net::HTTPHeader
315
+
316
+ def initialize
317
+ initialize_http_header({})
318
+ end
319
+
320
+ # Parse a single header line into its key and value
321
+ # @param [String] chunk a single header line
322
+ def self.parse(chunk)
323
+ line = chunk.strip
324
+ # thanks Net::HTTPResponse
325
+ return [nil,nil] if chunk =~ /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in
326
+ m = /\A([^:]+):\s*/.match(line)
327
+ [m[1], m.post_match] rescue [nil, nil]
328
+ end
329
+
330
+ # Parses a header line and adds it to the header collection
331
+ # @param [String] chunk a single header line
332
+ def parse(chunk)
333
+ key, value = self.class.parse(chunk)
334
+ add_field(key, value) if key && value
335
+ end
336
+ end
337
+
338
+ class FailedRequest < StandardError
339
+ attr_reader :method
340
+ attr_reader :expected
341
+ attr_reader :code
342
+ attr_reader :headers
343
+ attr_reader :body
344
+ attr_reader :timed_out
345
+
346
+ def initialize(method, expected_code, received_code, headers, body, timed_out)
347
+ @method, @expected, @code, @headers, @body, @timed_out = method, expected_code, received_code, headers, body, timed_out
348
+ super "Expected #{@expected.inspect} from the server but received #{@code}. #{@body}"
349
+ end
350
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'zephyr'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestZephyr < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
data/zephyr.gemspec ADDED
@@ -0,0 +1,56 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{zephyr}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matt Knopp"]
12
+ s.date = %q{2011-09-30}
13
+ s.description = %q{Simple HTTP client using Typheous, derived from the Riak client}
14
+ s.email = %q{matt.knopp@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/zephyr.rb",
28
+ "test/helper.rb",
29
+ "test/test_zephyr.rb",
30
+ "zephyr.gemspec"
31
+ ]
32
+ s.homepage = %q{http://github.com/mhat/zephyr}
33
+ s.licenses = ["MIT"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.5.2}
36
+ s.summary = %q{Simple HTTP client using Typheous, derived from the Riak client}
37
+
38
+ if s.respond_to? :specification_version then
39
+ s.specification_version = 3
40
+
41
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
+ s.add_runtime_dependency(%q<typhoeus>, [">= 0.2.4"])
43
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
44
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
45
+ else
46
+ s.add_dependency(%q<typhoeus>, [">= 0.2.4"])
47
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
48
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<typhoeus>, [">= 0.2.4"])
52
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
54
+ end
55
+ end
56
+
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zephyr
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Matt Knopp
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-30 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: typhoeus
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 31
29
+ segments:
30
+ - 0
31
+ - 2
32
+ - 4
33
+ version: 0.2.4
34
+ prerelease: false
35
+ type: :runtime
36
+ requirement: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 0
49
+ version: 1.0.0
50
+ prerelease: false
51
+ type: :development
52
+ requirement: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: jeweler
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 7
61
+ segments:
62
+ - 1
63
+ - 6
64
+ - 4
65
+ version: 1.6.4
66
+ prerelease: false
67
+ type: :development
68
+ requirement: *id003
69
+ description: Simple HTTP client using Typheous, derived from the Riak client
70
+ email: matt.knopp@gmail.com
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files:
76
+ - LICENSE.txt
77
+ - README.md
78
+ files:
79
+ - .document
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - VERSION
86
+ - lib/zephyr.rb
87
+ - test/helper.rb
88
+ - test/test_zephyr.rb
89
+ - zephyr.gemspec
90
+ has_rdoc: true
91
+ homepage: http://github.com/mhat/zephyr
92
+ licenses:
93
+ - MIT
94
+ post_install_message:
95
+ rdoc_options: []
96
+
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project:
120
+ rubygems_version: 1.5.2
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Simple HTTP client using Typheous, derived from the Riak client
124
+ test_files: []
125
+