footrest 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
data/footrest.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'footrest/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ["Nathan Mills"]
8
+ gem.email = ["nathanm@instructure.com"]
9
+ gem.description = %q{Ruby interface for restful APIs}
10
+ gem.summary = %q{REST APIs}
11
+
12
+ gem.files = %w[Rakefile footrest.gemspec]
13
+ gem.files += Dir.glob("lib/**/*.rb")
14
+ gem.files += Dir.glob("spec/**/*")
15
+ gem.test_files = Dir.glob("spec/**/*")
16
+ gem.name = "footrest"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = Footrest::VERSION
19
+
20
+ gem.add_development_dependency "rake"
21
+ gem.add_development_dependency "bundler", ">= 1.0.0"
22
+ gem.add_development_dependency "rspec", "~> 2.6"
23
+ gem.add_development_dependency "webmock"
24
+ gem.add_development_dependency "debugger"
25
+ gem.add_development_dependency "pry"
26
+
27
+ gem.add_dependency "faraday", "~> 0.8.8"
28
+ gem.add_dependency "faraday_middleware", "~> 0.9.0"
29
+ gem.add_dependency "activesupport", ">= 3.0.0"
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class Response::RaiseFootrestHttpError < Response::Middleware
5
+ ERROR_MAP = {
6
+ 400 => Footrest::HttpError::BadRequest,
7
+ 401 => Footrest::HttpError::Unauthorized,
8
+ 403 => Footrest::HttpError::Forbidden,
9
+ 404 => Footrest::HttpError::NotFound,
10
+ 405 => Footrest::HttpError::MethodNotAllowed,
11
+ 500 => Footrest::HttpError::InternalServerError,
12
+ 501 => Footrest::HttpError::NotImplemented,
13
+ 502 => Footrest::HttpError::BadGateway,
14
+ 503 => Footrest::HttpError::ServiceUnavailable
15
+ }
16
+
17
+ def on_complete(response)
18
+ key = response[:status].to_i
19
+ raise ERROR_MAP[key].new(response) if ERROR_MAP.has_key? key
20
+ end
21
+ end
22
+ end
data/lib/footrest.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'footrest/http_error'
2
+ require 'footrest/configuration'
3
+ require 'footrest/client'
4
+
5
+ module Footrest
6
+ end
@@ -0,0 +1,16 @@
1
+ require 'footrest/connection'
2
+ require 'footrest/request'
3
+
4
+ module Footrest
5
+ class Client
6
+ attr_reader :options
7
+
8
+ include Footrest::Connection
9
+ include Footrest::Request
10
+
11
+ def initialize(options={}, &block)
12
+ @options = Footrest.config.merge(options)
13
+ @faraday_option_block = block
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ require 'faraday'
2
+ require 'active_support/configurable'
3
+
4
+ module Footrest
5
+ include ActiveSupport::Configurable
6
+ config_accessor :token
7
+ config_accessor :domain
8
+ config_accessor :path_prefix
9
+
10
+ def configure
11
+ yield self
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'faraday/response/raise_footrest_http_error'
4
+
5
+ module Footrest
6
+ module Connection
7
+
8
+ def connection
9
+ @options ||= {}
10
+ @connection ||= Faraday.new(url: @options[:domain]) do |faraday|
11
+ faraday.request :multipart
12
+ faraday.request :url_encoded
13
+ faraday.response :logger if @options[:logging]
14
+ faraday.adapter Faraday.default_adapter
15
+ faraday.use FaradayMiddleware::FollowRedirects
16
+ faraday.use FaradayMiddleware::ParseJson, :content_type => /\bjson$/
17
+ faraday.use Faraday::Response::RaiseFootrestHttpError
18
+ faraday.headers[:accept] = "application/json"
19
+ faraday.headers[:authorization] = "Bearer #{@options[:token]}"
20
+ faraday.headers[:user_agent] = "Footrest"
21
+ @faraday_option_block.call(faraday) if @faraday_option_block
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Footrest
2
+ module HttpError
3
+ class ErrorBase < StandardError
4
+
5
+ attr_reader :status, :body, :method, :response
6
+
7
+ def initialize(response=nil)
8
+ @response = response
9
+ @status = @response[:status]
10
+ @body = @response[:body]
11
+ @method = @response[:method]
12
+
13
+ super("HTTP ERROR: #{@status}")
14
+ end
15
+ end
16
+
17
+ %w(
18
+ BadRequest Unauthorized Forbidden
19
+ NotFound MethodNotAllowed InternalServerError
20
+ NotImplemented BadGateway ServiceUnavailable
21
+ ).each do |error|
22
+ const_set error.to_sym, Class.new(ErrorBase)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ module Footrest
2
+ module Request
3
+
4
+ def delete(path, options={})
5
+ request_with_params_in_url(:delete, path, options)
6
+ end
7
+
8
+ def get(path, options={})
9
+ request_with_params_in_url(:get, path, options)
10
+ end
11
+
12
+ def post(path, options={})
13
+ request_with_params_in_body(:post, path, options)
14
+ end
15
+
16
+ def put(path, options={})
17
+ request_with_params_in_body(:put, path, options)
18
+ end
19
+
20
+ def request_with_params_in_url(method, path, options)
21
+ request(method, options) do |r|
22
+ r.url(File.join(path_prefix, path), options)
23
+ end
24
+ end
25
+
26
+ def request_with_params_in_body(method, path, options)
27
+ request(method, options) do |r|
28
+ r.path = File.join(path_prefix, path)
29
+ r.body = options unless options.empty?
30
+ end
31
+ end
32
+
33
+ # Generic request
34
+ def request(method, options, &block)
35
+ connection.send(method, &block).body
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Footrest
2
+ VERSION = '0.1' unless defined?(Footrest::VERSION)
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'helper'
2
+
3
+ describe Footrest::Client do
4
+
5
+ it "sets the domain" do
6
+ client = Footrest::Client.new(domain:"http://domain.com")
7
+ expect(client.options[:domain]).to eq("http://domain.com")
8
+
9
+ end
10
+
11
+ it "sets the authtoken" do
12
+ client = Footrest::Client.new(token:"test_token")
13
+ expect(client.options[:token]).to eq("test_token")
14
+ end
15
+
16
+ end
@@ -0,0 +1,99 @@
1
+ require 'helper'
2
+
3
+ describe Footrest::HttpError do
4
+ before do
5
+ @client = Footrest::Client.new(domain: "http://domain.com", token: "test_token")
6
+ end
7
+
8
+ it "raises a bad request error" do
9
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 400)
10
+
11
+ begin
12
+ @client.get "/api/v1/not_found"
13
+ rescue Footrest::HttpError::BadRequest => e
14
+ expect(e.status).to eq(400)
15
+ end
16
+ end
17
+
18
+ it "raises a unauthorized error" do
19
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 401)
20
+
21
+ begin
22
+ @client.get "/api/v1/not_found"
23
+ rescue Footrest::HttpError::Unauthorized => e
24
+ expect(e.status).to eq(401)
25
+ end
26
+ end
27
+
28
+ it "raises a forbidden error" do
29
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 403)
30
+
31
+ begin
32
+ @client.get "/api/v1/not_found"
33
+ rescue Footrest::HttpError::Forbidden => e
34
+ expect(e.status).to eq(403)
35
+ end
36
+ end
37
+
38
+
39
+ it "raises a not found error" do
40
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 404)
41
+
42
+ begin
43
+ @client.get "/api/v1/not_found"
44
+ rescue Footrest::HttpError::NotFound => e
45
+ expect(e.status).to eq(404)
46
+ end
47
+ end
48
+
49
+ it "raises a method not found allowed" do
50
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 405)
51
+
52
+ begin
53
+ @client.get "/api/v1/not_found"
54
+ rescue Footrest::HttpError::MethodNotAllowed => e
55
+ expect(e.status).to eq(405)
56
+ end
57
+ end
58
+
59
+ it "raises a internal server error" do
60
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 500)
61
+
62
+ begin
63
+ @client.get "/api/v1/not_found"
64
+ rescue Footrest::HttpError::InternalServerError => e
65
+ expect(e.status).to eq(500)
66
+ end
67
+ end
68
+
69
+ it "raises a not implemented error" do
70
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 501)
71
+
72
+ begin
73
+ @client.get "/api/v1/not_found"
74
+ rescue Footrest::HttpError::NotImplemented => e
75
+ expect(e.status).to eq(501)
76
+ end
77
+ end
78
+
79
+ it "raises a bad gateway error" do
80
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 502)
81
+
82
+ begin
83
+ @client.get "/api/v1/not_found"
84
+ rescue Footrest::HttpError::BadGateway => e
85
+ expect(e.status).to eq(502)
86
+ end
87
+ end
88
+
89
+ it "raises a Server Unavailible error" do
90
+ stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 503)
91
+
92
+ begin
93
+ @client.get "/api/v1/not_found"
94
+ rescue Footrest::HttpError::ServiceUnavailable => e
95
+ expect(e.status).to eq(503)
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,38 @@
1
+ require 'helper'
2
+ require 'ostruct'
3
+
4
+ class RequestHarness
5
+ include Footrest::Connection
6
+ include Footrest::Request
7
+ end
8
+
9
+ describe Footrest::Request do
10
+
11
+ let(:request) { RequestHarness.new }
12
+
13
+ it "gets" do
14
+ stub_request(:get, "http://domain.test/page?p=1").
15
+ to_return(:status => 200, :body => "", :headers => {})
16
+ request.get('http://domain.test/page', :p => 1)
17
+ end
18
+
19
+ it "deletes" do
20
+ stub_request(:get, "http://domain.test/page?auth=xyz").
21
+ to_return(:status => 200, :body => "", :headers => {})
22
+ request.get('http://domain.test/page', :auth => 'xyz')
23
+ end
24
+
25
+ it "posts" do
26
+ stub_request(:post, "http://domain.test/new_page").
27
+ with(:body => {"password"=>"xyz", "username"=>"abc"}).
28
+ to_return(:status => 200, :body => "", :headers => {})
29
+ request.post('http://domain.test/new_page', :username => 'abc', :password => 'xyz')
30
+ end
31
+
32
+ it "puts" do
33
+ stub_request(:put, "http://domain.test/update_page").
34
+ with(:body => {"password"=>"zzz", "username"=>"aaa"}).
35
+ to_return(:status => 200, :body => "", :headers => {})
36
+ request.put('http://domain.test/update_page', :username => 'aaa', :password => 'zzz')
37
+ end
38
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,43 @@
1
+
2
+ require 'footrest'
3
+ require 'rspec'
4
+ require 'webmock/rspec'
5
+ require 'json'
6
+
7
+ WebMock.disable_net_connect!
8
+
9
+ RSpec.configure do |config|
10
+ config.expect_with :rspec do |c|
11
+ c.syntax = :expect
12
+ end
13
+ end
14
+
15
+ def fixture(file)
16
+ File.new(File.join(File.expand_path("../fixtures", __FILE__), file))
17
+ end
18
+
19
+ def stub_get(client, url)
20
+ stub_request(:get, "#{client.domain}#{url}")
21
+ end
22
+
23
+ def stub_post(client, url)
24
+ stub_request(:post, "#{client.domain}#{url}")
25
+ end
26
+
27
+ def stub_put(client, url)
28
+ stub_request(:put, "#{client.domain}#{url}")
29
+ end
30
+
31
+ def stub_delete(client, url)
32
+ stub_request(:delete, "#{client.domain}#{url}")
33
+ end
34
+
35
+ def json_response(file)
36
+ {
37
+ :body => fixture(file),
38
+ :headers => {
39
+ :content_type => 'application/json; charset=utf-8'
40
+ }
41
+ }
42
+ end
43
+
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: footrest
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nathan Mills
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.6'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.6'
62
+ - !ruby/object:Gem::Dependency
63
+ name: webmock
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: debugger
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: pry
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: faraday
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.8.8
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 0.8.8
126
+ - !ruby/object:Gem::Dependency
127
+ name: faraday_middleware
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: 0.9.0
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: 0.9.0
142
+ - !ruby/object:Gem::Dependency
143
+ name: activesupport
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: 3.0.0
150
+ type: :runtime
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: 3.0.0
158
+ description: Ruby interface for restful APIs
159
+ email:
160
+ - nathanm@instructure.com
161
+ executables: []
162
+ extensions: []
163
+ extra_rdoc_files: []
164
+ files:
165
+ - Rakefile
166
+ - footrest.gemspec
167
+ - lib/faraday/response/raise_footrest_http_error.rb
168
+ - lib/footrest/client.rb
169
+ - lib/footrest/configuration.rb
170
+ - lib/footrest/connection.rb
171
+ - lib/footrest/http_error.rb
172
+ - lib/footrest/request.rb
173
+ - lib/footrest/version.rb
174
+ - lib/footrest.rb
175
+ - spec/footrest/client_spec.rb
176
+ - spec/footrest/http_error_spec.rb
177
+ - spec/footrest/request_spec.rb
178
+ - spec/helper.rb
179
+ homepage:
180
+ licenses: []
181
+ post_install_message:
182
+ rdoc_options: []
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ! '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ! '>='
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 1.8.23
200
+ signing_key:
201
+ specification_version: 3
202
+ summary: REST APIs
203
+ test_files:
204
+ - spec/footrest/client_spec.rb
205
+ - spec/footrest/http_error_spec.rb
206
+ - spec/footrest/request_spec.rb
207
+ - spec/helper.rb
208
+ has_rdoc: