hugs 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2-p0@hugs
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "yajl-ruby", "~> 0.7.8"
4
+ gem "net-http-persistent", "~> 1.4.1"
5
+
6
+ group :development do
7
+ gem "rake"
8
+ gem "jeweler", "~> 1.5.1"
9
+ gem "minitest", "~> 2.0.0"
10
+ gem "mocha", "~> 0.9.10"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.1)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ minitest (2.0.0)
10
+ mocha (0.9.10)
11
+ rake
12
+ net-http-persistent (1.4.1)
13
+ rake (0.8.7)
14
+ yajl-ruby (0.7.8)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ jeweler (~> 1.5.1)
21
+ minitest (~> 2.0.0)
22
+ mocha (~> 0.9.10)
23
+ net-http-persistent (~> 1.4.1)
24
+ rake
25
+ yajl-ruby (~> 0.7.8)
data/LICENSE ADDED
@@ -0,0 +1,4 @@
1
+ "THE BEER-WARE LICENSE" (Revision 42):
2
+ <john@dewey.ws> wrote this file. As long as you retain this notice you
3
+ can do whatever you want with this stuff. If we meet some day, and you think
4
+ this stuff is worth it, you can buy me a beer in return John-B Dewey Jr.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Hugs
2
+
3
+ Hugs net-http-persistent with convenient get, delete, post, and put methods.
4
+
5
+ Opted to write this gem for two reasons:
6
+
7
+ * [Ganeti's API](http://docs.ganeti.org/ganeti/2.2/html/rapi.html), required
8
+ the sending of a message body with the HTTP Get request, which
9
+ [rest-client](https://github.com/archiloque/rest-client) does not do.
10
+ * Wanted a [fast](http://blog.segment7.net/articles/2010/05/07/net-http-is-not-slow),
11
+ thread-safe, and persistent client.
12
+
13
+ ## Assumptions
14
+
15
+ * The webservice returns JSON.
16
+ * You want to objectify the returned JSON.
17
+ * The message body is JSON.
18
+ * The webservice requires basic auth (will remove this requirement shortly).
19
+
20
+ ## Usage
21
+
22
+ ### Bundler
23
+
24
+ gem "hugs"
25
+
26
+ ### Examples
27
+
28
+ See the 'Examples' section in the [wiki](http://github.com/retr0h/rubineti/wiki/).
29
+
30
+ ### TODO
31
+
32
+ * Remove HTTP Auth requirement, as mentioned in the 'Assumptions' section.
33
+ * Move @request instance method in #response_for to local. It was set to an instance
34
+ for ease of testing but it bothers me.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require "rubygems"
2
+ require "rake"
3
+
4
+ begin
5
+ require "jeweler"
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "hugs"
8
+ gem.summary = %Q{Hugs net-http-persistent with convenient get, delete, post, and put methods.}
9
+ gem.email = "john@dewey.ws"
10
+ gem.homepage = "http://github.com/retr0h/hugs"
11
+ gem.authors = ["retr0h"]
12
+ end
13
+ Jeweler::GemcutterTasks.new
14
+ rescue LoadError
15
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
16
+ end
17
+
18
+ require "rake/testtask"
19
+ Rake::TestTask.new(:test) do |test|
20
+ test.libs << "lib" << "test"
21
+ test.pattern = "test/**/test_*.rb"
22
+ test.verbose = true
23
+ end
24
+
25
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/lib/hugs.rb ADDED
@@ -0,0 +1,93 @@
1
+ require "net/http/persistent"
2
+ require "yajl"
3
+
4
+ class Hugs
5
+ Headers = {
6
+ :json => "application/json"
7
+ }.freeze
8
+
9
+ ##
10
+ # Required options:
11
+ # +user+: A String containing the username for use in HTTP Basic auth.
12
+ # +password+: A String containing the password for use in HTTP Basic auth.
13
+ # +host+: A String with the host to connect.
14
+ # Optional:
15
+ # +port+: An Integer containing the port to connect.
16
+ # +scheme+: A String containing the HTTP scheme.
17
+
18
+ def initialize options
19
+ @user = options[:user]
20
+ @password = options[:password]
21
+ @host = options[:host]
22
+ @port = options[:port] || 80
23
+ @scheme = options[:scheme] || "https"
24
+ end
25
+
26
+ ##
27
+ # Perform an HTTP get, delete, post, or put.
28
+ # +path+: A String with the path to the HTTP resource.
29
+ # +params+: A Hash with the following keys:
30
+ # - +:query+: Query String in the format "foo=bar"
31
+ # - +:body+: A sub Hash to be JSON encoded, and posted in
32
+ # the message body.
33
+
34
+ %w(get delete post put).each do |verb|
35
+ define_method verb do |*args|
36
+ path = args[0]
37
+ params = args[1] || {}
38
+ clazz = eval "Net::HTTP::#{verb.capitalize}"
39
+
40
+ parse response_for(clazz, path, params)
41
+ end
42
+ end
43
+
44
+ ##
45
+ # :method: get
46
+
47
+ ##
48
+ # :method: delete
49
+
50
+ ##
51
+ # :method: post
52
+
53
+ ##
54
+ # :method: put
55
+
56
+ private
57
+ ##
58
+ # Worker method to be called by #get, #delete, #post, #put.
59
+ # Method arguments have been documented in the callers.
60
+
61
+ def response_for request, path, params
62
+ query = params[:query] && params.delete(:query)
63
+ body = params[:body] && params.delete(:body)
64
+
65
+ @http ||= Net::HTTP::Persistent.new
66
+ @url ||= URI.parse "#{@scheme}://#{@host}:#{@port}"
67
+
68
+ @request = request.new [path, query].compact.join "?"
69
+ @request.body = encode(body) if body
70
+ common_headers @request
71
+
72
+ @http.request(@url, @request).body
73
+ end
74
+
75
+ def common_headers request
76
+ request.basic_auth @user, @password
77
+ case request.class.to_s
78
+ when Net::HTTP::Get.to_s, Net::HTTP::Delete.to_s
79
+ request.add_field "accept", Headers[:json]
80
+ when Net::HTTP::Post.to_s, Net::HTTP::Put.to_s
81
+ request.add_field "accept", Headers[:json]
82
+ request.add_field "content-type", Headers[:json]
83
+ end
84
+ end
85
+
86
+ def parse data
87
+ ::Yajl::Parser.parse data
88
+ end
89
+
90
+ def encode hash
91
+ ::Yajl::Encoder.encode hash
92
+ end
93
+ end
data/test/support.rb ADDED
@@ -0,0 +1,13 @@
1
+ Bundler.setup :default, :test
2
+
3
+ require "minitest/spec"
4
+ require "mocha"
5
+
6
+ #Dir[File.join "./lib", "**", "*.rb"].each { |f| require f }
7
+
8
+ require "./lib/hugs"
9
+
10
+ class MiniTest::Unit::TestCase
11
+ end
12
+
13
+ MiniTest::Unit.autorun
data/test/test_hugs.rb ADDED
@@ -0,0 +1,91 @@
1
+ require "support"
2
+ require "base64"
3
+ require "hugs"
4
+
5
+ describe Hugs do
6
+ before do
7
+ @user = "user",
8
+ @password = "credentials"
9
+ @valid_options = {
10
+ :user => @user,
11
+ :password => @password,
12
+ :host => "example.com",
13
+ :port => 80,
14
+ :scheme => "https",
15
+ }
16
+
17
+ @instance = Hugs.new @valid_options
18
+ end
19
+
20
+ describe "#response_for" do
21
+ before do
22
+ @http = mock(:request => mock(:body => :body))
23
+ @request = Net::HTTP::Get
24
+
25
+ Net::HTTP::Persistent.stubs :new => @http
26
+ end
27
+
28
+ it "generates a path" do
29
+ @instance.send :response_for, @request, "/", {}
30
+
31
+ @instance.instance_variable_get(:@request).path.must_equal "/"
32
+ end
33
+
34
+ it "generates a path when a valid :query exists" do
35
+ @instance.send :response_for, @request, "/", :query => "foo=bar"
36
+
37
+ @instance.instance_variable_get(:@request).path.must_equal "/?foo=bar"
38
+ end
39
+
40
+ it "generates a path when a nil :query exists" do
41
+ @instance.send :response_for, @request, "/", :query => nil
42
+
43
+ @instance.instance_variable_get(:@request).path.must_equal "/"
44
+ end
45
+
46
+ it "sets the body as JSON when a valid :body exists" do
47
+ @instance.send :response_for, @request, "/", :body => {:foo => :bar}
48
+
49
+ @instance.instance_variable_get(:@request).body.must_equal '{"foo":"bar"}'
50
+ end
51
+
52
+ it "doesn't set the body when an invalid :body exists" do
53
+ @instance.send :response_for, @request, "/", :body => nil
54
+
55
+ @instance.instance_variable_get(:@request).body.must_be_nil
56
+ end
57
+
58
+ describe "headers" do
59
+ Json_Headers_Matcher = %r{#{"application/json"}}
60
+
61
+ it "has authentication" do
62
+ @instance.send :response_for, @request, "/", {}
63
+
64
+ @instance.instance_variable_get(:@request).get_fields("authorization").join.
65
+ must_match %r{Basic #{Base64.encode64("#{@user}:#{@password}").delete("\r\n")}}
66
+ end
67
+
68
+ [Net::HTTP::Post, Net::HTTP::Put].each do |clazz|
69
+ it "has content-type and accept for '#{clazz}'" do
70
+ @instance.send :response_for, clazz, "/", {}
71
+
72
+ @instance.instance_variable_get(:@request).get_fields("content-type").join.
73
+ must_match Json_Headers_Matcher
74
+ @instance.instance_variable_get(:@request).get_fields("accept").join.
75
+ must_match Json_Headers_Matcher
76
+ end
77
+ end
78
+
79
+ [Net::HTTP::Get, Net::HTTP::Delete].each do |clazz|
80
+ it "has accept for '#{clazz}'" do
81
+ @instance.send :response_for, clazz, "/", {}
82
+
83
+ @instance.instance_variable_get(:@request).get_fields("accept").join.
84
+ must_match Json_Headers_Matcher
85
+ @instance.instance_variable_get(:@request).get_fields("content-type").
86
+ must_be_nil
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hugs
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - retr0h
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-11 00:00:00 -08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: yajl-ruby
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 7
30
+ - 8
31
+ version: 0.7.8
32
+ type: :runtime
33
+ prerelease: false
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: net-http-persistent
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 4
45
+ - 1
46
+ version: 1.4.1
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rake
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: jeweler
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 1
72
+ - 5
73
+ - 1
74
+ version: 1.5.1
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ name: minitest
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 2
87
+ - 0
88
+ - 0
89
+ version: 2.0.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: mocha
95
+ requirement: &id006 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ - 9
103
+ - 10
104
+ version: 0.9.10
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: *id006
108
+ description:
109
+ email: john@dewey.ws
110
+ executables: []
111
+
112
+ extensions: []
113
+
114
+ extra_rdoc_files:
115
+ - LICENSE
116
+ - README.md
117
+ files:
118
+ - .bundle/config
119
+ - .rvmrc
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE
123
+ - README.md
124
+ - Rakefile
125
+ - VERSION
126
+ - lib/hugs.rb
127
+ - test/support.rb
128
+ - test/test_hugs.rb
129
+ has_rdoc: true
130
+ homepage: http://github.com/retr0h/hugs
131
+ licenses: []
132
+
133
+ post_install_message:
134
+ rdoc_options: []
135
+
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ segments:
144
+ - 0
145
+ version: "0"
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ segments:
152
+ - 0
153
+ version: "0"
154
+ requirements: []
155
+
156
+ rubyforge_project:
157
+ rubygems_version: 1.3.7
158
+ signing_key:
159
+ specification_version: 3
160
+ summary: Hugs net-http-persistent with convenient get, delete, post, and put methods.
161
+ test_files:
162
+ - test/support.rb
163
+ - test/test_hugs.rb