Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Improve middleware handling on API#setup

  • Loading branch information...
commit 3b3c7acdde17ad29ae799e18bda61372c7e8b5d1 1 parent 85e40ba
@remiprev authored
Showing with 61 additions and 36 deletions.
  1. +27 −30 README.md
  2. +11 −4 lib/her/api.rb
  3. +23 −2 spec/api_spec.rb
View
57 README.md
@@ -54,39 +54,40 @@ User.find(1)
# PUT https://api.example.com/users/1 with the data and return+update the User object
```
-## Parsing data
+## Middlware
+
+Since Her relies on [Faraday](https://github.com/technoweenie/faraday) to send HTTP requests, you can add additional middleware to handle requests and responses.
+
+### Authentication
+
+Her doesn’t support any kind of authentication. However, it’s very easy to implement one with a request middleware. Using the `add_middleware` key, we add it to the default list of middleware.
+
+```ruby
+class MyAuthentication < Faraday::Middleware
+ def call(env)
+ env[:request_headers]["X-API-Token"] = "bb2b2dd75413d32c1ac421d39e95b978d1819ff611f68fc2fdd5c8b9c7331192"
+ @all.call(env)
+ end
+end
+
+Her::API.setup :base_uri => "https://api.example.com", :add_middleware => [MyAuthentication]
+```
+
+Now, each HTTP request made by Her will have the `X-API-Token` header.
+
+### Parsing data
By default, Her handles JSON data. It expects the data to be formatted in a certain structure. The default is this:
```javascript
// The response of GET /users/1
-{
- "data" : {
- "id" : 1,
- "name" : "Tobias Fünke"
- }
-}
+{ "data" : { "id" : 1, "name" : "Tobias Fünke" } }
// The response of GET /users
-{
- "data" : [
- {
- "id" : 1,
- "name" : "Tobias Fünke"
- },
- {
- "id" : 2,
- "name" : "Lindsay Fünke"
- }
- ],
- "metadata" : {
- "page" : 1,
- "per_page" : 10
- }
-}
+{ "data" : [{ "id" : 1, "name" : "Tobias Fünke" }] }
```
-However, you can define your own parsing method, using a Faraday response middleware. The middleware is expected to return a hash with three keys: `data`, `errors` and `metadata`. The following code enables parsing JSON data and treating this data as first-level properties:
+However, you can define your own parsing method, using a response middleware. The middleware is expected to set `env[:body]` to a hash with three keys: `data`, `errors` and `metadata`. The following code enables parsing JSON data and treating the result as first-level properties. Using the `parse_middleware` key, we then replace the default parser.
```ruby
class MyCustomParser < Faraday::Response::Middleware
@@ -94,15 +95,11 @@ class MyCustomParser < Faraday::Response::Middleware
json = JSON.parse(env[:body], :symbolize_names => true)
errors = json.delete(:errors) || []
metadata = json.delete(:metadata) || []
- env[:body] = {
- :data => json,
- :errors => errors,
- :metadata => metadata,
- }
+ env[:body] = { :data => json, :errors => errors, :metadata => metadata }
end
end
-Her::API.setup :base_uri => "https://api.example.com", :middleware => [MyCustomParser] + Her::API.default_middleware
+Her::API.setup :base_uri => "https://api.example.com", :parse_middleware => MyCustomParser
# User.find(1) will now expect "https://api.example.com/users/1" to return something like '{ "id": 1, "name": "Tobias Fünke" }'
```
View
15 lib/her/api.rb
@@ -22,12 +22,12 @@ def self.default_api(attrs={}) # {{{
# @private
def self.default_middleware # {{{
- [Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
+ [Her::Middleware::DefaultParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
end # }}}
# Setup the API connection
#
- # @example
+ # @example A custom parse middleware
# module MyAPI
# class ParseResponse
# def on_complete(env)
@@ -40,10 +40,17 @@ def self.default_middleware # {{{
# end
# end
# end
- # Her::API.setup :base_url => "https://api.example.com", :middleware => [MyAPI::ParseResponse, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
+ # Her::API.setup :base_url => "https://api.example.com", :parse_middleware => MyAPI::ParseResponse
def setup(attrs={}) # {{{
@base_uri = attrs[:base_uri]
- middleware = @middleware = attrs[:middleware] || [Her::Middleware::DefaultParseJSON] + Her::API.default_middleware
+ @middleware = Her::API.default_middleware
+
+ @middleware = [attrs[:middleware]] if attrs[:middleware]
+ @middleware = [attrs[:add_middleware]] + @middleware if attrs[:add_middleware]
+ @middleware = [attrs[:parse_middleware]] + @middleware.reject { |item| item == Her::Middleware::DefaultParseJSON } if attrs[:parse_middleware]
+
+ @middleware.flatten!
+ middleware = @middleware
@connection = Faraday.new(:url => @base_uri) do |builder|
middleware.each { |m| builder.use(m) }
end
View
25 spec/api_spec.rb
@@ -17,7 +17,20 @@
@api.base_uri.should == "https://api.example.com"
end # }}}
- it "sets middleware" do # {{{
+ it "sets additional middleware" do # {{{
+ class Foo < Faraday::Response::Middleware; end;
+ class Bar < Faraday::Response::Middleware; end;
+
+ @api = Her::API.new
+ @api.setup :base_uri => "https://api.example.com", :add_middleware => [Foo, Bar]
+ @api.middleware.should == [Foo, Bar, Her::Middleware::DefaultParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
+
+ @api = Her::API.new
+ @api.setup :base_uri => "https://api.example.com", :add_middleware => Foo
+ @api.middleware.should == [Foo, Her::Middleware::DefaultParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
+ end # }}}
+
+ it "overrides middleware" do # {{{
class Foo < Faraday::Response::Middleware; end;
class Bar < Faraday::Response::Middleware; end;
@@ -25,6 +38,14 @@ class Bar < Faraday::Response::Middleware; end;
@api.setup :base_uri => "https://api.example.com", :middleware => [Foo, Bar]
@api.middleware.should == [Foo, Bar]
end # }}}
+
+ it "sets a parse middleware" do # {{{
+ class Foo < Faraday::Response::Middleware; end;
+
+ @api = Her::API.new
+ @api.setup :base_uri => "https://api.example.com", :parse_middleware => Foo
+ @api.middleware.should == [Foo, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
+ end # }}}
end
describe "#request" do
@@ -73,7 +94,7 @@ def on_complete(env)
end
@api = Her::API.new
- @api.setup :base_uri => "https://api.example.com", :middleware => [CustomParser] + Her::API.default_middleware
+ @api.setup :base_uri => "https://api.example.com", :parse_middleware => CustomParser
@api.request(:_method => :get, :_path => "users/1") do |parsed_data|
parsed_data[:data].should == { :id => 1, :name => "George Michael Bluth" }
parsed_data[:errors].should == []
Please sign in to comment.
Something went wrong with that request. Please try again.