apis 0.4.1 → 0.5.0.pre1

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/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