apis 0.4.1 → 0.5.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,43 +1,42 @@
1
1
  ## Usage
2
2
 
3
- connection = Apis::Connecton.new(:url => 'http://api.example.com') do
4
- request do
5
- use Apis::Request::JSON # |
6
- use Apis::Request::OAuth2 # |
7
- use Apis::Request::Logger # \/
8
- end
9
- adapter :net_http # -->
10
- response do
11
- use Apis::Response::JSON # |
12
- use Apis::Response::Logger # \/
13
- end
14
- end
3
+ connection = Apis::Connecton.new(:url => 'http://api.example.com') do
4
+ use Apis::Request::JSON
5
+ use Apis::Request::OAuth2
6
+ use Apis::Request::Logger
7
+ adapter Apis::Adapter::NetHTTP
8
+ end
15
9
 
16
- connection.get('/hello')
17
-
18
- connection.request.replace Apis::Request::OAuth2, Apis::Request::OAuth
19
-
20
- connection.post('/post_with_oauth_10') do |request|
21
- request.params = {:q => 'm'}
22
- end
10
+ connection.get('/hello')
11
+
12
+ ## Specification
23
13
 
24
- ## Request Middleware
14
+ ### Middleware
25
15
 
26
- ### Example
16
+ Middleware is object that responds to `call`, accepts `env` hash and returns array
17
+ with three elements in order: `status`, `headers`, `body`.
27
18
 
28
- class Request::Middleware
29
- def call(env)
30
- env[:params][:token] = 'abcdef'
31
- end
32
- end
19
+ Middleware should accept `application` it decorates as first parameter to initializer.
33
20
 
34
- ### Description
21
+ Example middleware:
35
22
 
36
- Basically, request middleware is an object that responds to `#call`.
37
- It will be initialized with args passed if any.
23
+ class Middleware
24
+ def initialize(app)
25
+ @app = app
26
+ end
27
+
28
+ def call(env)
29
+ # do something with request
30
+ response = @app.call(env) # it's decorator, you are responsible to forward message to decorated app
31
+ # do something with response
32
+ response
33
+ end
34
+ end
38
35
 
39
36
  ### Environment
40
37
 
41
- * `:method` - HTTP method name
42
- * `:body` body of request sent to server
43
- * `:headers` headers hash
38
+ * `:method` - uppercased request method, should be one of: `:GET`, `:POST`, `:PUT`, `:DELETE`
39
+ * `:uri` - parsed URi, instance of `Addressable::URI`
40
+ * `:params` - params to be sent, instance of `Hash`
41
+ * `:body` - body to be sent. If set than `:params` are not used
42
+ * `:headers` - headers to be sent, instance of `Hash`
data/Rakefile CHANGED
@@ -1,4 +1,7 @@
1
1
  require 'bundler'
2
2
  require 'rspec/core/rake_task'
3
+
3
4
  Bundler::GemHelper.install_tasks
4
- RSpec::Core::RakeTask.new
5
+ RSpec::Core::RakeTask.new do |rspec|
6
+ rspec.pattern = ENV['SPEC'] || 'spec/**/*_spec.rb'
7
+ end
data/apis.gemspec CHANGED
@@ -6,17 +6,17 @@ Gem::Specification.new do |s|
6
6
  s.name = "apis"
7
7
  s.version = Apis::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
+ s.required_ruby_version = '>= 1.9'
9
10
  s.authors = ["Marjan Krekoten' (Мар'ян Крекотень)"]
10
- s.email = ["m@hmarynka.com"]
11
- s.homepage = "http://hmarynka.com/labs/apis"
11
+ s.email = ["krekoten@gmail.com"]
12
+ s.homepage = "https://github.com/krekoten/apis"
12
13
  s.summary = %q{Working bee of API wrapper}
13
14
  s.description = %q{Rack-like HTTP client library inspired by Faraday done my way}
14
15
 
15
- s.rubyforge_project = "apis"
16
+ s.rubyforge_project = "[none]"
16
17
 
17
18
  s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.test_files = `git ls-files -- spec/*`.split("\n")
20
20
  s.require_paths = ["lib"]
21
21
 
22
22
  s.add_development_dependency 'rspec', '>= 2.5'
@@ -2,19 +2,26 @@ require 'net/http'
2
2
 
3
3
  module Apis
4
4
  module Adapter
5
- class NetHTTP < Abstract
6
- def connection
7
- Net::HTTP.start(uri.host, uri.port)
8
- end
5
+ class NetHTTP
6
+ def call(env)
7
+ env[:url].path = '/' if env[:url].path.empty?
8
+ http = Net::HTTP.new(env[:url].host, env[:url].port)
9
+ query = Addressable::URI.new
10
+ query.query_values = env[:params]
11
+ response = case env[:method]
12
+ when :GET
13
+ http.get([env[:url].path, query.query].compact.join('?'), env[:headers])
14
+ when :HEAD
15
+ http.head([env[:url].path, query.query].compact.join('?'), env[:headers])
16
+ when :POST
17
+ http.post(env[:url].path, query.query, env[:headers])
18
+ when :PUT
19
+ http.put(env[:url].path, query.query, env[:headers])
20
+ when :DELETE
21
+ http.delete([env[:url].path, query.query].compact.join('?'), env[:headers])
22
+ end
9
23
 
10
- def run(method, path, params = {}, headers = {})
11
- _module = Net::HTTP.const_get(method.to_s.capitalize)
12
- request = _module.new(path)
13
- response = connection.request(
14
- request,
15
- params.empty? ? nil : Addressable::URI.new.tap { |uri| uri.query_values = params }.query
16
- )
17
- [response.code.to_i] + response
24
+ [response.code.to_i, response, response.body]
18
25
  end
19
26
  end
20
27
  end
@@ -4,16 +4,7 @@ module Apis
4
4
  module Adapter
5
5
  class RackTest < Abstract
6
6
  include Rack::Test::Methods
7
-
8
7
  attr_accessor :app
9
-
10
- attr_reader :last_path, :last_params, :last_headers
11
-
12
- def run(method, path, params = {}, headers = {})
13
- @last_path, @last_params, @last_headers = path, params, headers
14
- send(method, path, params, headers)
15
- [last_response.status, last_response.headers, last_response.body]
16
- end
17
8
  end
18
9
  end
19
10
  end
data/lib/apis/builder.rb CHANGED
@@ -1,76 +1,32 @@
1
1
  module Apis
2
2
  class Builder
3
- attr_accessor :lookup_context
4
- def initialize(options = {}, &block)
5
- options.each do |key, value|
6
- send("#{key}=", value) if respond_to?("#{key}=")
7
- end
8
- @stack = []
9
- @mapping = {}
10
- block_eval(&block) if block
11
- end
12
-
13
- def use(middleware)
14
- insert(middleware)
3
+ def initialize(&block)
4
+ @handlers = []
5
+ @adapter = nil
6
+ instance_eval(&block) if block
15
7
  end
16
8
 
17
- def replace(old, middleware)
18
- if index = index(old)
19
- insert(middleware, index)
20
- remove(old)
9
+ def use(middleware, *args)
10
+ block = block_given? ? Proc.new : nil
11
+ @handlers << -> parent do
12
+ middleware.new(parent, *args, &block)
21
13
  end
22
14
  end
23
15
 
24
- def insert(middleware, index = nil)
25
- middleware = lookup_middleware(middleware)
26
- raise Apis::DuplicateMiddleware, "#{middleware} already in stack" if include?(middleware)
27
- index ||= @stack.length
28
- @stack[index] = lambda do |parent|
29
- middleware.new(parent)
16
+ def adapter(middleware = nil, *args)
17
+ if middleware
18
+ block = block_given? ? Proc.new : nil
19
+ @adapter = nil
20
+ end
21
+ @adapter ||= -> do
22
+ (middleware || Apis::Adapter::NetHTTP).new(*args, &block)
30
23
  end
31
- @mapping[middleware] = index
32
- end
33
-
34
- def remove(middleware)
35
- middleware = lookup_middleware(middleware)
36
- @stack.delete_at(@mapping.delete(middleware))
37
- end
38
-
39
- def index(middleware)
40
- middleware = lookup_middleware(middleware)
41
- @mapping[middleware]
42
- end
43
-
44
- def length
45
- @stack.length
46
- end
47
-
48
- def include?(middleware)
49
- !!index(middleware)
50
- end
51
-
52
- def to_a
53
- @mapping.to_a.sort { |a, b| a.last <=> b.last}.map { |e| e.first }
54
24
  end
55
- alias to_ary to_s
56
25
 
57
26
  def to_app
58
- unless @stack.empty?
59
- inner_app = @stack.last.call(nil)
60
- @stack.reverse[1..-1].inject(inner_app) { |parent, lazy| lazy.call(parent) }
61
- else
62
- []
27
+ @handlers.reverse.inject(adapter.call) do |parent, handler|
28
+ handler.call(parent)
63
29
  end
64
30
  end
65
-
66
- def block_eval(&block)
67
- instance_eval(&block)
68
- end
69
-
70
- def lookup_middleware(middleware)
71
- @lookup_context && !(Class === middleware) ?
72
- @lookup_context.lookup(middleware) :
73
- middleware
74
- end
75
31
  end
76
32
  end
@@ -1,96 +1,52 @@
1
- require 'addressable/uri'
1
+ require 'fiber'
2
2
 
3
3
  module Apis
4
- class Connection
5
- def initialize(options = {})
6
- @scope = Apis::ConnectionScope.new
7
- @scope.headers, @scope.params = {}, {}
8
-
9
- if String === options
10
- self.uri = options
11
- else
12
- options.each do |key, value|
13
- send("#{key}=", value) if respond_to?("#{key}=")
14
- end
15
- end
16
-
17
- if block_given?
18
- block = Proc.new
19
- instance_eval(&block)
20
- end
21
- adapter(Apis::Adapter.default) unless @adapter
4
+ class Request
5
+ attr_accessor :params, :headers
6
+ def initialize
7
+ @params, @headers = {}, {}
22
8
  end
9
+ end
23
10
 
24
- def uri
25
- @scope.uri
11
+ class Connection
12
+ attr_reader :uri
13
+ def initialize(options)
14
+ options.each do |key, value|
15
+ send("#{key}=", value) if respond_to?("#{key}=")
16
+ end
17
+ @builder = Builder.new(&(block_given? ? Proc.new : nil))
26
18
  end
27
19
 
28
20
  def uri=(value)
29
- @scope.uri = Addressable::URI.parse(value)
30
- end
31
-
32
- def headers
33
- @scope.headers
21
+ @uri = Addressable::URI.parse(value)
34
22
  end
35
23
 
36
- def headers=(value)
37
- @scope.headers.merge!(value)
38
- end
24
+ def head(*args, &block) make_request(:HEAD, *args, &block) end
39
25
 
40
- def params
41
- @scope.params
42
- end
26
+ def get(*args, &block) make_request(:GET, *args, &block) end
43
27
 
44
- def params=(value)
45
- @scope.params.merge!(value)
46
- end
28
+ def post(*args, &block) make_request(:POST, *args, &block) end
47
29
 
48
- def request
49
- block = block_given? ? Proc.new : nil
50
- @request ||= Apis::Builder.new(:lookup_context => Apis::Middleware::Request, &block)
51
- @request
52
- end
30
+ def put(*args, &block) make_request(:PUT, *args, &block) end
53
31
 
54
- def response
55
- block = block_given? ? Proc.new : nil
56
- @response ||= Apis::Builder.new(:lookup_context => Apis::Middleware::Response, &block)
57
- @response
58
- end
32
+ def delete(*args, &block) make_request(:DELETE, *args, &block) end
59
33
 
60
- def adapter(value = nil)
61
- if Symbol === value
62
- value = Apis::Adapter.lookup(value)
34
+ def make_request(method, uri = nil, params = {}, headers = {}, &block)
35
+ if block
36
+ request = Apis::Request.new
37
+ yield request
38
+ params.merge!(request.params)
39
+ headers.merge!(request.headers)
63
40
  end
64
41
 
65
- @adapter = value.new(:uri => uri) if value
66
- @adapter
67
- end
68
-
69
- [:get, :head, :post, :put, :delete].each do |method|
70
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
71
- def #{method}(path = nil, params = {}, headers = {})
72
- run_request(#{method.inspect}, path, params, headers, &(block_given? ? Proc.new : nil))
73
- end
74
- RUBY
75
- end
76
-
77
- def run_request(method, path = nil, params = {}, headers = {}, &block)
78
- #block = block_given? ? Proc.new : nil
79
- # TODO: refactor this, it's ugly
80
- @scope.scoped do
81
- self.params = params if params
82
- self.headers = headers if headers
83
- block.call(self) if block
84
- path ||= uri.path.empty? ? '/' : uri.path
85
- self.request.to_app.call(
86
- :method => method,
87
- :params => self.params,
88
- :headers => self.headers
89
- ) unless self.request.to_a.empty?
90
- res = Apis::Response.new(*adapter.run(method, path, self.params, self.headers))
91
- self.response.to_app.call(res) unless self.response.to_a.empty?
92
- res
93
- end
42
+ Fiber.new do
43
+ @builder.to_app.call(
44
+ :method => method,
45
+ :uri => uri ? self.uri.join(uri) : self.uri,
46
+ :params => params,
47
+ :headers => headers
48
+ )
49
+ end.resume
94
50
  end
95
51
  end
96
52
  end
@@ -4,23 +4,19 @@ module Apis
4
4
  module Middleware
5
5
  module Response
6
6
  class Json
7
- attr_accessor :app
8
- def initialize(app = nil)
7
+ APPLICATION_JSON = 'application/json'
8
+ def initialize(app)
9
9
  @app = app
10
10
  end
11
11
 
12
12
  def call(env)
13
- env.body = case env.body
14
- when ''
15
- nil
16
- when 'true'
17
- true
18
- when 'false'
19
- false
13
+ env[:headers]['Accept'] = APPLICATION_JSON
14
+ status, headers, body = @app.call(env)
15
+ if headers['Content-Type'] && headers['Content-Type'].include?(APPLICATION_JSON)
16
+ [status, headers, MultiJson.decode(body)]
20
17
  else
21
- ::MultiJson.decode(env.body)
18
+ [status, headers, body]
22
19
  end
23
- @app.call(env) if @app
24
20
  end
25
21
  end
26
22
  end
data/lib/apis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Apis
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0.pre1"
3
3
  end
data/lib/apis.rb CHANGED
@@ -1,55 +1,21 @@
1
1
  $: << lib_dir unless $:.include?(lib_dir = File.expand_path('..', __FILE__))
2
2
 
3
+ require 'addressable/uri'
4
+
3
5
  module Apis
4
6
  class DuplicateMiddleware < StandardError; end
5
7
  autoload :Connection, 'apis/connection'
6
- autoload :ConnectionScope, 'apis/connection_scope'
7
8
  autoload :Builder, 'apis/builder'
8
- autoload :Response, 'apis/response'
9
-
10
- module Registerable
11
- def register(symbol, klass)
12
- @lookup_table ||= {}
13
- @lookup_table[symbol] = klass
14
- end
15
-
16
- def lookup(symbol)
17
- @lookup_table ||= {}
18
- self.const_get(@lookup_table[symbol])
19
- end
20
- end
21
9
 
22
10
  module Adapter
23
11
  autoload :Abstract, 'apis/adapter/abstract'
24
12
  autoload :NetHTTP, 'apis/adapter/net_http'
25
13
  autoload :RackTest, 'apis/adapter/rack_test'
26
-
27
- extend Registerable
28
-
29
- class << self
30
- # Default connection adapter
31
- # You can change it by assignin new value
32
- def default
33
- @default ||= :net_http
34
- end
35
- attr_writer :default
36
- end
37
-
38
- register :net_http, :NetHTTP
39
- register :rack_test, :RackTest
40
14
  end
41
15
 
42
16
  module Middleware
43
- module Request
44
- extend Registerable
45
- end
46
-
47
17
  module Response
48
- autoload :Json, 'apis/middleware/response/json'
49
-
50
- extend Registerable
51
-
52
- register :json, :Json
18
+ autoload :Json, 'apis/middleware/response/json'
53
19
  end
54
20
  end
55
21
  end
@@ -9,37 +9,48 @@ describe Apis::Adapter::NetHTTP do
9
9
  stop_server
10
10
  end
11
11
 
12
- [:get, :post, :put, :delete, :head].each do |method|
13
- context method.to_s.upcase do
12
+ [:HEAD, :GET, :POST, :PUT, :DELETE].each do |method|
13
+ context method do
14
+ it "returns status" do
15
+ adapter = Apis::Adapter::NetHTTP.new
16
+ status, headers, body = adapter.call(
17
+ :method => method,
18
+ :url => Addressable::URI.parse(server_host),
19
+ :headers => {}
20
+ )
21
+ status.should == 200
22
+ end
23
+
14
24
  it "returns body" do
15
- adapter = Apis::Adapter::NetHTTP.new(:uri => Addressable::URI.parse(server_host))
16
- status, headers, body = adapter.run(method, '/')
17
- body.should == method.to_s.upcase
18
- end unless method == :head
25
+ adapter = Apis::Adapter::NetHTTP.new
26
+ status, headers, body = adapter.call(
27
+ :method => method,
28
+ :url => Addressable::URI.parse(server_host),
29
+ :headers => {}
30
+ )
31
+ body.should == method.to_s
32
+ end unless method == :HEAD
19
33
 
20
34
  it "returns headers" do
21
- adapter = Apis::Adapter::NetHTTP.new(:uri => Addressable::URI.parse(server_host))
22
- status, headers, body = adapter.run(method, '/')
23
- headers['X-Requested-With-Method'].should == method.to_s.upcase
24
- end
25
-
26
- it "returns status" do
27
- adapter = Apis::Adapter::NetHTTP.new(:uri => Addressable::URI.parse(server_host))
28
- status, headers, body = adapter.run(method, '/')
29
- status.should == 200
35
+ adapter = Apis::Adapter::NetHTTP.new
36
+ status, headers, body = adapter.call(
37
+ :method => method,
38
+ :url => Addressable::URI.parse(server_host),
39
+ :headers => {}
40
+ )
41
+ headers['X-Requested-With-Method'].should == method.to_s
30
42
  end
31
43
 
32
44
  it "sends params" do
33
- adapter = Apis::Adapter::NetHTTP.new(:uri => Addressable::URI.parse(server_host))
34
- status, headers, body = adapter.run(method, "/#{method}", {:param => 'value'})
35
- headers['X-Sent-Params'].should == '{"param"=>"value"}'
45
+ adapter = Apis::Adapter::NetHTTP.new
46
+ status, headers, body = adapter.call(
47
+ :method => method,
48
+ :url => Addressable::URI.parse(server_host).join(method.to_s.downcase),
49
+ :headers => {},
50
+ :params => {:test => 'params'}
51
+ )
52
+ headers['X-Sent-Params'].should == %|{"test"=>"params"}|
36
53
  end
37
54
  end
38
55
  end
39
-
40
- it 'registered under :net_http' do
41
- Apis::Connection.new do
42
- adapter :net_http
43
- end.adapter.should be_instance_of(Apis::Adapter::NetHTTP)
44
- end
45
56
  end
@@ -14,44 +14,4 @@ class RackApp
14
14
  end
15
15
 
16
16
  describe Apis::Adapter::RackTest do
17
- [:get, :post, :put, :delete, :head].each do |method|
18
- context method.to_s.upcase do
19
- let(:adapter) { Apis::Adapter::RackTest.new(:app => RackApp.new) }
20
- it "returns body" do
21
- status, headers, body = adapter.run(method, '/')
22
- body.should == method.to_s.upcase
23
- end unless method == :head
24
-
25
- it "returns headers" do
26
- status, headers, body = adapter.run(method, '/')
27
- headers['X-Request-Method'].should == method.to_s.upcase
28
- end
29
-
30
- it "returns status" do
31
- status, headers, body = adapter.run(method, '/')
32
- status.should == 200
33
- end
34
-
35
- it 'saves passed path' do
36
- adapter.run(method, "/#{method}")
37
- adapter.last_path.should == "/#{method}"
38
- end
39
-
40
- it 'saves passed params' do
41
- adapter.run(method, '/', {:test => 'param'})
42
- adapter.last_params.should == {:test => 'param'}
43
- end
44
-
45
- it 'saves passed headers' do
46
- adapter.run(method, '/', {}, {'Content-Type' => 'text'})
47
- adapter.last_headers.should == {'Content-Type' => 'text'}
48
- end
49
- end
50
- end
51
-
52
- it 'registered under :rack_test' do
53
- Apis::Connection.new do
54
- adapter :rack_test
55
- end.adapter.should be_instance_of(Apis::Adapter::RackTest)
56
- end
57
17
  end
@@ -1,100 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Apis::Builder do
4
- it 'adds middleware to stack' do
5
- builder = Apis::Builder.new
6
- builder.use Middleware
7
- builder.length.should == 1
8
- end
9
-
10
- it 'raises error when duplicate middleware added' do
11
- builder = Apis::Builder.new
12
- builder.use Middleware
13
- expect { builder.use Middleware }.to raise_error(Apis::DuplicateMiddleware, 'Middleware already in stack')
14
- end
15
-
16
- it 'shows if middleware in stack' do
17
- builder = Apis::Builder.new
18
- builder.use Middleware
19
- builder.include?(Middleware).should == true
20
- end
21
-
22
- it 'replaces middleware with another' do
23
- builder = Apis::Builder.new
24
- builder.use Middleware
25
- builder.use RESTMiddleware
26
- builder.replace Middleware, NewMiddleware
27
- builder.include?(Middleware).should == false
28
- builder.include?(NewMiddleware).should == true
29
- builder.to_a.should == [NewMiddleware, RESTMiddleware]
30
- end
31
-
32
- it 'removes middleware from stack' do
33
- builder = Apis::Builder.new
34
- builder.use Middleware
35
- builder.include?(Middleware).should == true
36
- builder.remove(Middleware)
37
- builder.include?(Middleware).should == false
38
- end
39
-
40
- it 'returns stacked middlewares in order' do
41
- builder = Apis::Builder.new
42
- builder.use Middleware
43
- builder.use NewMiddleware
44
- builder.use RESTMiddleware
45
- app = builder.to_app
46
- app.should be_instance_of(Middleware)
47
- app.app.should be_instance_of(NewMiddleware)
48
- app.app.app.should be_instance_of(RESTMiddleware)
49
- end
50
-
51
- it 'evals block' do
52
- builder = Apis::Builder.new
53
- builder.block_eval do |builder|
54
- use Middleware
4
+ it 'builds appilcation stack' do
5
+ app = Apis::Builder.new do
55
6
  use NewMiddleware
56
7
  use RESTMiddleware
57
- end
58
-
59
- app = builder.to_app
60
- app.should be_instance_of(Middleware)
61
- app.app.should be_instance_of(NewMiddleware)
62
- app.app.app.should be_instance_of(RESTMiddleware)
8
+ adapter FakeAdapter
9
+ end.to_app
10
+ app.should be_instance_of(NewMiddleware)
11
+ app.app.should be_instance_of(RESTMiddleware)
12
+ app.app.app.should be_instance_of(FakeAdapter)
63
13
  end
64
14
 
65
- it 'evals block passed to constructor' do
66
- builder = Apis::Builder.new do
67
- use Middleware
15
+ it 'uses default adapter if none specified' do
16
+ app = Apis::Builder.new do
68
17
  use NewMiddleware
69
18
  use RESTMiddleware
70
- end
71
-
72
- app = builder.to_app
73
- app.should be_instance_of(Middleware)
74
- app.app.should be_instance_of(NewMiddleware)
75
- app.app.app.should be_instance_of(RESTMiddleware)
76
- end
77
-
78
- it 'inserts middleware only once' do
79
- builder = Apis::Builder.new do
80
- use Middleware
81
- end
82
-
83
- app = builder.to_app
84
- app.should be_instance_of(Middleware)
85
- app.app.should be_nil
86
- end
87
-
88
- it 'lookups middleware by shortcut if lookup object givven' do
89
- Lookup = Module.new do
90
- extend Apis::Registerable
91
- end
92
- Lookup.register(:middleware, :Middleware)
93
- builder = Apis::Builder.new(:lookup_context => Lookup) do
94
- use :middleware
95
- end
96
-
97
- app = builder.to_app
98
- app.should be_instance_of(Middleware)
19
+ end.to_app
20
+ app.should be_instance_of(NewMiddleware)
21
+ app.app.should be_instance_of(RESTMiddleware)
22
+ app.app.app.should be_instance_of(Apis::Adapter::NetHTTP)
99
23
  end
100
24
  end
@@ -1,230 +1,52 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Apis::Connection do
4
- context 'configuration' do
5
- context 'options' do
6
- it 'sets url' do
7
- Apis::Connection.new(:uri => 'http://api.example.org').uri.should == Addressable::URI.parse('http://api.example.org')
8
- end
9
-
10
- it 'sets url if it is only parameter' do
11
- Apis::Connection.new('http://api.example.org').uri.should == Addressable::URI.parse('http://api.example.org')
12
- end
13
-
14
- it 'sets headers' do
15
- Apis::Connection.new(
16
- :headers => {
17
- 'Content-Type' => 'text',
18
- 'User-Agent' => 'apis'
19
- }
20
- ).headers.should == {
21
- 'Content-Type' => 'text',
22
- 'User-Agent' => 'apis'
23
- }
24
- end
25
-
26
- it 'sets params' do
27
- Apis::Connection.new(
28
- :params => {:q => 'apis', :hl => 'uk'}
29
- ).params.should == {:q => 'apis', :hl => 'uk'}
30
- end
4
+ let(:connection) do
5
+ Apis::Connection.new(:uri => 'http://api.example.com/') do
6
+ use EnvCheck
31
7
  end
8
+ end
32
9
 
33
- context 'methods' do
34
- let(:connection) { Apis::Connection.new }
35
- it 'sets url' do
36
- connection.uri = 'http://api.example.org'
37
- connection.uri.should == Addressable::URI.parse('http://api.example.org')
38
- end
39
-
40
- it 'sets headers' do
41
- connection.headers = {
42
- 'Content-Type' => 'text',
43
- 'User-Agent' => 'apis'
44
- }
45
- connection.headers.should == {
46
- 'Content-Type' => 'text',
47
- 'User-Agent' => 'apis'
48
- }
49
- end
50
-
51
- it 'sets params' do
52
- connection.params = {:q => 'apis', :hl => 'uk'}
53
- connection.params.should == {:q => 'apis', :hl => 'uk'}
54
- end
55
-
56
- it 'updates headers' do
57
- connection.headers = {'Content-Type' => 'text'}
58
- connection.headers = {'User-Agent' => 'apis'}
59
- connection.headers.should == {
60
- 'Content-Type' => 'text',
61
- 'User-Agent' => 'apis'
62
- }
63
- end
64
-
65
- it 'updates params' do
66
- connection.params = {:q => 'apis'}
67
- connection.params = {:hl => 'uk'}
68
- connection.params.should == {:q => 'apis', :hl => 'uk'}
10
+ context "on request" do
11
+ [:head, :get, :post, :put, :delete].each do |method|
12
+ it "sets env[:method] to :#{method.to_s.upcase} on #{method}" do
13
+ connection.send(method)
14
+ EnvCheck.env[:method].should == method.to_s.upcase.to_sym
69
15
  end
70
16
  end
71
17
 
72
- context 'stack building' do
73
- it 'constructs request stack' do
74
- connection = Apis::Connection.new do
75
- request do
76
- use Middleware
77
- use NewMiddleware
78
- use RESTMiddleware
79
- end
80
- end
81
-
82
- connection.request.to_a.should == [Middleware, NewMiddleware, RESTMiddleware]
83
- end
84
-
85
- it 'constructs response stack' do
86
- connection = Apis::Connection.new do
87
- response do
88
- use Middleware
89
- use NewMiddleware
90
- use RESTMiddleware
91
- end
92
- end
93
-
94
- connection.response.to_a.should == [Middleware, NewMiddleware, RESTMiddleware]
95
- end
96
-
97
- it 'sets adapter' do
98
- connection = Apis::Connection.new do
99
- adapter FakeAdapter
100
- end
101
- connection.adapter.should be_instance_of(FakeAdapter)
102
- end
103
-
104
- it 'finds adapter using symbol shortcut' do
105
- Apis::Adapter.register(:fake, :FakeAdapter)
106
- connection = Apis::Connection.new do
107
- adapter :fake
108
- end
109
- connection.adapter.should be_instance_of(FakeAdapter)
110
- end
111
-
112
- it 'uses default adapter if none specified' do
113
- connection = Apis::Connection.new
114
- connection.adapter nil
115
- connection.adapter.should be_instance_of(Apis::Adapter::NetHTTP)
116
- end
18
+ it "sets env[:uri] to Addressable::URI object initialized with URL" do
19
+ connection.get
20
+ EnvCheck.env[:uri].should == Addressable::URI.parse('http://api.example.com/')
117
21
  end
118
- end
119
22
 
120
- context 'performing request' do
121
- before do
122
- @connection = Apis::Connection.new(:uri => server_host) do
123
- adapter FakeAdapter
124
- end
23
+ it "merges uri passed to connection with uri passed to request" do
24
+ connection.get('users/1')
25
+ EnvCheck.env[:uri].should == Addressable::URI.parse('http://api.example.com/users/1')
125
26
  end
126
27
 
127
- [:get, :head, :post, :put, :delete].each do |method|
128
- context method.to_s.upcase do
129
- it 'passes method to adapter' do
130
- @connection.send(method)
131
- @connection.adapter.last_method.should == method
132
- end
133
-
134
- it 'passes path to adapter' do
135
- @connection.send(method, "/#{method}")
136
- @connection.adapter.last_path.should == "/#{method}"
137
- end
138
-
139
- it 'passes query params to adapter' do
140
- @connection.send(method, "/#{method}", {:q => 'text'})
141
- @connection.adapter.last_params.should == {:q => 'text'}
142
- end
143
-
144
- it 'passes params specified in block' do
145
- @connection.send(method, "/#{method}") do |request|
146
- request.params = {:test => 'params'}
147
- end
148
- @connection.adapter.last_params.should == {:test => 'params'}
149
- end
150
-
151
- it 'doesn\'t not overwrite params of connection' do
152
- @connection.params = {:q => 'test'}
153
- @connection.send(method, "/#{method}") do |request|
154
- request.params = {:test => 'params'}
155
- end
156
- @connection.adapter.last_params.should == {:q => 'test', :test => 'params'}
157
- @connection.params.should == {:q => 'test'}
158
- end
159
-
160
- it 'merges connection params with method params' do
161
- @connection.params = {:test => 'param'}
162
- @connection.send(method, "/#{method}", {:q => 'text'})
163
- @connection.adapter.last_params.should == {:q => 'text', :test => 'param'}
164
- end
165
-
166
- it 'passes headers to adapter' do
167
- @connection.send(method, "/#{method}", {}, {'Content-Type' => 'text'})
168
- @connection.adapter.last_headers.should == {'Content-Type' => 'text'}
169
- end
170
-
171
- it 'merges connection headers with method headers' do
172
- @connection.headers = {'User-Agent' => 'apis'}
173
- @connection.send(method, "/#{method}", {}, {'Content-Type' => 'text'})
174
- @connection.adapter.last_headers.should == {'Content-Type' => 'text', 'User-Agent' => 'apis'}
175
- end
176
-
177
- it 'doesn\'t overwrite headers of connection' do
178
- @connection.headers = {:q => 'test'}
179
- @connection.send(method, "/#{method}") do |request|
180
- request.headers = {:test => 'params'}
181
- end
182
- @connection.adapter.last_headers.should == {:q => 'test', :test => 'params'}
183
- @connection.headers.should == {:q => 'test'}
184
- end
185
- end
28
+ it "sets env[:params] to params hash passed to request" do
29
+ connection.get(nil, :param => 'test')
30
+ EnvCheck.env[:params].should == {:param => 'test'}
186
31
  end
187
- end
188
32
 
189
- context 'request with middleware' do
190
- context 'request middleware' do
191
- before do
192
- Apis::Middleware::Request.register(:middleware, :Middleware)
193
- @connection = Apis::Connection.new(:uri => server_host) do
194
- request do
195
- use :middleware
196
- end
197
- adapter FakeAdapter
198
- end
199
- end
200
-
201
- it 'calls midleware' do
202
- @connection.get
203
- @connection.adapter.last_headers.should == {'Middleware' => 'true'}
204
- end
205
-
206
- it "doesn't overwrite headers of connection" do
207
- @connection.get
208
- @connection.adapter.last_headers.should == {'Middleware' => 'true'}
209
- @connection.headers.should == {}
33
+ it "sets env[:params] to params passed in block" do
34
+ connection.get do |request|
35
+ request.params[:param] = 'test'
210
36
  end
37
+ EnvCheck.env[:params].should == {:param => 'test'}
211
38
  end
212
39
 
213
- context 'response midleware' do
214
- before do
215
- Apis::Middleware::Response.register(:res, :Response)
216
- @connection = Apis::Connection.new(:uri => server_host) do
217
- adapter FakeAdapter
218
- response do
219
- use :res
220
- end
221
- end
222
- end
40
+ it "sets env[:headers] to headers hash passed to request" do
41
+ connection.get(nil, {}, {'Content-Type' => 'text/xml'})
42
+ EnvCheck.env[:headers].should == {'Content-Type' => 'text/xml'}
43
+ end
223
44
 
224
- it 'calls midleware' do
225
- response = @connection.get
226
- response.body.should == 'altered'
45
+ it "sets env[:headers] to headers passed in block" do
46
+ connection.get do |request|
47
+ request.headers['Content-Type'] = 'text/xml'
227
48
  end
49
+ EnvCheck.env[:headers].should == {'Content-Type' => 'text/xml'}
228
50
  end
229
51
  end
230
52
  end
@@ -1,19 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Apis::Middleware::Response::Json do
4
- it 'replaces body with parsed data' do
5
- MultiJson.engine = :yajl
6
- json = Apis::Middleware::Response::Json.new
7
- request = Apis::Response.new(200, {}, %|{"name":"Marjan Krekoten'","age": 23}|)
8
- json.call(request)
9
- request.body.should == {"name" => "Marjan Krekoten'", "age" => 23}
4
+ it "calls decorated application" do
5
+ middleware = double('middleware')
6
+ middleware.should_receive(:call).and_return([200, {}, ''])
7
+ Apis::Middleware::Response::Json.new(middleware).call({:headers => {}})
10
8
  end
11
9
 
12
- it 'registered under :json' do
13
- Apis::Connection.new do
14
- response do
15
- use :json
16
- end
17
- end.response.to_a.should include(Apis::Middleware::Response::Json)
10
+ it "adds accept header" do
11
+ middleware = -> env do
12
+ env[:headers]['Accept'].should == 'application/json'
13
+ [200, {'Content-Type' => 'application/json'}, %|{"user":{"name":"User","age":25}}|]
14
+ end
15
+ Apis::Middleware::Response::Json.new(middleware).call({:headers => {}})
18
16
  end
19
- end
17
+
18
+ it 'parses body when content-type matches' do
19
+ middleware = -> env do
20
+ [200, {'Content-Type' => 'application/json'}, %|{"user":{"name":"User","age":25}}|]
21
+ end
22
+ status, headers, body = Apis::Middleware::Response::Json.new(middleware).call(:headers => {})
23
+ status.should == 200
24
+ headers.should == {'Content-Type' => 'application/json'}
25
+ body.should == {'user' => {'name' => 'User', 'age' => 25}}
26
+ end
27
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,17 @@
1
1
  require File.expand_path('../../lib/apis', __FILE__)
2
2
 
3
+ class EnvCheck
4
+ class << self
5
+ attr_accessor :env
6
+ def call(env)
7
+ @env = env
8
+ end
9
+ def new(*args)
10
+ self
11
+ end
12
+ end
13
+ end
14
+
3
15
  class BaseMiddleware
4
16
  attr_accessor :app
5
17
  def initialize(app)
@@ -28,6 +40,9 @@ class FakeAdapter < Apis::Adapter::Abstract
28
40
  @last_method, @last_path, @last_params, @last_headers = method, path, params, headers
29
41
  [200, {}, 'body']
30
42
  end
43
+
44
+ def call(env)
45
+ end
31
46
  end
32
47
 
33
48
  module DirHelper
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apis
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.4.1
4
+ prerelease: 6
5
+ version: 0.5.0.pre1
6
6
  platform: ruby
7
7
  authors:
8
8
  - "Marjan Krekoten' (\xD0\x9C\xD0\xB0\xD1\x80'\xD1\x8F\xD0\xBD \xD0\x9A\xD1\x80\xD0\xB5\xD0\xBA\xD0\xBE\xD1\x82\xD0\xB5\xD0\xBD\xD1\x8C)"
@@ -10,8 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-07 00:00:00 +03:00
14
- default_executable:
13
+ date: 2011-04-11 00:00:00 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: rspec
@@ -92,7 +91,7 @@ dependencies:
92
91
  version_requirements: *id007
93
92
  description: Rack-like HTTP client library inspired by Faraday done my way
94
93
  email:
95
- - m@hmarynka.com
94
+ - krekoten@gmail.com
96
95
  executables: []
97
96
 
98
97
  extensions: []
@@ -112,13 +111,10 @@ files:
112
111
  - lib/apis/adapter/rack_test.rb
113
112
  - lib/apis/builder.rb
114
113
  - lib/apis/connection.rb
115
- - lib/apis/connection_scope.rb
116
114
  - lib/apis/middleware/response/json.rb
117
- - lib/apis/response.rb
118
115
  - lib/apis/version.rb
119
116
  - spec/apis/adapter/net_http_spec.rb
120
117
  - spec/apis/adapter/rack_test_spec.rb
121
- - spec/apis/adapter_spec.rb
122
118
  - spec/apis/builder_spec.rb
123
119
  - spec/apis/connection_spec.rb
124
120
  - spec/apis/middleware/response/json_spec.rb
@@ -126,8 +122,7 @@ files:
126
122
  - spec/quality_spec.rb
127
123
  - spec/spec_helper.rb
128
124
  - spec/test_app.ru
129
- has_rdoc: true
130
- homepage: http://hmarynka.com/labs/apis
125
+ homepage: https://github.com/krekoten/apis
131
126
  licenses: []
132
127
 
133
128
  post_install_message:
@@ -140,24 +135,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
135
  requirements:
141
136
  - - ">="
142
137
  - !ruby/object:Gem::Version
143
- version: "0"
138
+ version: "1.9"
144
139
  required_rubygems_version: !ruby/object:Gem::Requirement
145
140
  none: false
146
141
  requirements:
147
- - - ">="
142
+ - - ">"
148
143
  - !ruby/object:Gem::Version
149
- version: "0"
144
+ version: 1.3.1
150
145
  requirements: []
151
146
 
152
- rubyforge_project: apis
153
- rubygems_version: 1.6.2
147
+ rubyforge_project: "[none]"
148
+ rubygems_version: 1.7.2
154
149
  signing_key:
155
150
  specification_version: 3
156
151
  summary: Working bee of API wrapper
157
152
  test_files:
158
153
  - spec/apis/adapter/net_http_spec.rb
159
154
  - spec/apis/adapter/rack_test_spec.rb
160
- - spec/apis/adapter_spec.rb
161
155
  - spec/apis/builder_spec.rb
162
156
  - spec/apis/connection_spec.rb
163
157
  - spec/apis/middleware/response/json_spec.rb
@@ -1,27 +0,0 @@
1
- module Apis
2
- class ConnectionScope
3
- def initialize
4
- @data = {}
5
- end
6
-
7
- def method_missing(method, value = nil)
8
- if method =~ /\=$/ && value
9
- @data[method.to_s.gsub(/\=/, '').to_sym] = value
10
- else
11
- @data[method]
12
- end
13
- end
14
-
15
- def scoped
16
- backup = {}
17
- @data.each do |key, value|
18
- backup[key] = value.dup
19
- end
20
- yield
21
- ensure
22
- backup.each do |key, value|
23
- @data[key] = value
24
- end
25
- end
26
- end
27
- end
data/lib/apis/response.rb DELETED
@@ -1,25 +0,0 @@
1
- module Apis
2
- class Response
3
- attr_accessor :status, :headers, :body
4
- def initialize(status, headers, body)
5
- @status, @headers, @body = status, headers, body
6
- end
7
-
8
- def to_env
9
- {:status => status, :headers => headers, :body => body}
10
- end
11
-
12
- def to_a
13
- [status, headers, body]
14
- end
15
- alias to_ary to_a
16
-
17
- def [](key)
18
- respond_to?(key) ? send(key) : nil
19
- end
20
-
21
- def []=(key, value)
22
- send("#{key}=", value) if respond_to?("#{key}=")
23
- end
24
- end
25
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Apis::Adapter do
4
- it 'registers adapters shortnames' do
5
- Apis::Adapter.register(:fake, :FakeAdapter)
6
- Apis::Adapter.lookup(:fake).should == FakeAdapter
7
- end
8
-
9
- specify ':net_http is set as default adapter' do
10
- Apis::Adapter.default.should == :net_http
11
- end
12
- end