add Fetcher for http requests

This commit is contained in:
Benjamin Neff 2015-07-12 14:59:05 +02:00
parent 09904b54d0
commit 0204b3d9ff
9 changed files with 169 additions and 4 deletions

View file

@ -42,6 +42,7 @@ group :test do
gem "fixture_builder", "~> 0.4.1"
gem "factory_girl_rails", "~> 4.5.0"
gem "rspec-collection_matchers", "~> 1.1.2"
gem "webmock", "~> 1.21.0"
end
group :development, :test do

View file

@ -2,7 +2,10 @@ PATH
remote: .
specs:
diaspora_federation (0.0.3)
faraday (~> 0.9.0)
faraday_middleware (~> 0.9.0)
nokogiri (~> 1.6, >= 1.6.6)
typhoeus (~> 0.7.0)
diaspora_federation-rails (0.0.3)
diaspora_federation (= 0.0.3)
rails (~> 4.2)
@ -45,6 +48,7 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.3.8)
arel (6.0.0)
ast (2.0.0)
astrolabe (1.3.0)
@ -56,14 +60,22 @@ GEM
simplecov (>= 0.7.1, < 1.0.0)
coderay (1.1.0)
columnize (0.9.0)
crack (0.4.2)
safe_yaml (~> 1.0.0)
diff-lcs (1.2.5)
docile (1.1.5)
erubis (2.7.0)
ethon (0.7.4)
ffi (>= 1.3.0)
factory_girl (4.5.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.5.0)
factory_girl (~> 4.5.0)
railties (>= 3.0.0)
faraday (0.9.1)
multipart-post (>= 1.2, < 3)
faraday_middleware (0.9.2)
faraday (>= 0.7.4, < 0.10)
ffi (1.9.10)
fixture_builder (0.4.1)
activerecord (>= 2)
@ -111,6 +123,7 @@ GEM
mini_portile (0.6.2)
minitest (5.7.0)
multi_json (1.11.1)
multipart-post (2.0.0)
nenv (0.2.0)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
@ -193,6 +206,7 @@ GEM
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-progressbar (1.7.5)
safe_yaml (1.0.4)
shellany (0.0.1)
simplecov (0.10.0)
docile (~> 1.1.0)
@ -218,10 +232,15 @@ GEM
systemu (2.6.5)
thor (0.19.1)
thread_safe (0.3.5)
typhoeus (0.7.2)
ethon (>= 0.7.4)
tzinfo (1.2.2)
thread_safe (~> 0.1)
uuid (2.3.8)
macaddr (~> 1.0)
webmock (1.21.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
yard (0.8.7.6)
PLATFORMS
@ -250,6 +269,7 @@ DEPENDENCIES
spring-watcher-listen
sqlite3 (~> 1.3.10)
uuid (~> 2.3.8)
webmock (~> 1.21.0)
yard
BUNDLED WITH

View file

@ -21,4 +21,7 @@ Gem::Specification.new do |s|
s.required_ruby_version = "~> 2.0"
s.add_dependency "nokogiri", "~> 1.6", ">= 1.6.6"
s.add_dependency "faraday", "~> 0.9.0"
s.add_dependency "faraday_middleware", "~> 0.9.0"
s.add_dependency "typhoeus", "~> 0.7.0"
end

View file

@ -4,6 +4,8 @@ require "diaspora_federation/callbacks"
require "diaspora_federation/properties_dsl"
require "diaspora_federation/entity"
require "diaspora_federation/fetcher"
require "diaspora_federation/discovery"
# diaspora* federation library
@ -30,6 +32,12 @@ module DiasporaFederation
# config.server_uri = AppConfig.pod_uri
attr_accessor :server_uri
# Set the bundle of certificate authorities (CA) certificates
#
# @example
# config.certificate_authorities = AppConfig.environment.certificate_authorities.get
attr_accessor :certificate_authorities
# configure the federation library
#
# @example
@ -63,10 +71,17 @@ module DiasporaFederation
# called from after_initialize
# @raise [ConfigurationError] if the configuration is incomplete or invalid
def validate_config
configuration_error "Missing server_uri" unless @server_uri.respond_to? :host
configuration_error "server_uri: Missing or invalid" unless @server_uri.respond_to? :host
configuration_error "certificate_authorities: Not configured" if @certificate_authorities.nil?
unless File.file? @certificate_authorities
configuration_error "certificate_authorities: File not found: #{@certificate_authorities}"
end
unless @callbacks.definition_complete?
configuration_error "Missing handlers for #{@callbacks.missing_handlers.join(', ')}"
end
logger.info "successfully configured the federation library"
end

View file

@ -0,0 +1,42 @@
require "faraday"
require "faraday_middleware/response/follow_redirects"
require "typhoeus/adapters/faraday"
module DiasporaFederation
# A wrapper for {https://github.com/lostisland/faraday Faraday} used for
# fetching
#
# @see Discovery::Discovery
class Fetcher
# Perform a GET request
#
# @param [String] uri the URI
# @return [Faraday::Response] the response
def self.get(uri)
connection.get(uri)
end
# gets the Faraday connection
#
# @return [Faraday::Connection] the response
def self.connection
create_default_connection unless @connection
@connection.dup
end
def self.create_default_connection
options = {
request: {timeout: 30},
ssl: {ca_file: DiasporaFederation.certificate_authorities}
}
@connection = Faraday::Connection.new(options) do |builder|
builder.use FaradayMiddleware::FollowRedirects, limit: 4
builder.adapter :typhoeus
end
@connection.headers["User-Agent"] = "DiasporaFederation/#{DiasporaFederation::VERSION}"
end
private_class_method :create_default_connection
end
end

View file

@ -0,0 +1,56 @@
module DiasporaFederation
describe Fetcher do
describe ".get" do
it "gets the url" do
stub_request(:get, "http://www.example.com")
.to_return(body: "foobar", status: 200)
response = Fetcher.get("http://www.example.com")
expect(response.body).to eq("foobar")
end
it "follows redirects" do
stub_request(:get, "http://www.example.com")
.to_return(status: 302, headers: {"Location" => "http://www.example.com/redirected"})
stub_request(:get, "http://www.example.com/redirected")
.to_return(body: "foobar", status: 200)
response = Fetcher.get("http://www.example.com")
expect(response.body).to eq("foobar")
end
it "follows redirects 4 times" do
stub_request(:get, "http://www.example.com")
.to_return(status: 302, headers: {"Location" => "http://www.example.com"}).times(4)
.to_return(status: 200)
Fetcher.get("http://www.example.com")
end
it "follows redirects not more than 4 times" do
stub_request(:get, "http://www.example.com")
.to_return(status: 302, headers: {"Location" => "http://www.example.com"})
expect { Fetcher.get("http://www.example.com") }.to raise_error FaradayMiddleware::RedirectLimitReached
end
it "uses the gem name as User-Agent" do
stub_request(:get, "http://www.example.com")
.with(headers: {"User-Agent" => "DiasporaFederation/#{DiasporaFederation::VERSION}"})
Fetcher.get("http://www.example.com")
end
end
describe ".connection" do
it "returns a new connection every time" do
expect(Fetcher.connection).to be_a Faraday::Connection
end
it "returns a new connection every time" do
connection1 = Fetcher.connection
expect(Fetcher.connection).to_not be(connection1)
end
end
end
end

View file

@ -6,14 +6,31 @@ module DiasporaFederation
DiasporaFederation.validate_config
end
it "should fails if the server_uri is missing" do
it "should fail if the server_uri is missing" do
temp = DiasporaFederation.server_uri
DiasporaFederation.server_uri = nil
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError, "Missing server_uri"
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError,
"server_uri: Missing or invalid"
DiasporaFederation.server_uri = temp
end
it "should validate the config" do
it "should fail if the certificate_authorities is missing" do
temp = DiasporaFederation.certificate_authorities
DiasporaFederation.certificate_authorities = nil
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError,
"certificate_authorities: Not configured"
DiasporaFederation.certificate_authorities = temp
end
it "should fail if the certificate_authorities is missing" do
temp = DiasporaFederation.certificate_authorities
DiasporaFederation.certificate_authorities = "/unknown"
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError,
"certificate_authorities: File not found: /unknown"
DiasporaFederation.certificate_authorities = temp
end
it "should validate the callbacks" do
expect(DiasporaFederation.callbacks).to receive(:definition_complete?).and_return(false)
expect { DiasporaFederation.validate_config }.to raise_error ConfigurationError, "Missing handlers for "
end

View file

@ -18,6 +18,7 @@ ENV["RAILS_ENV"] ||= "test"
require File.join(File.dirname(__FILE__), "..", "test", "dummy", "config", "environment")
require "rspec/rails"
require "webmock/rspec"
# load factory girl factories
require "factories"

View file

@ -1,10 +1,20 @@
require "diaspora_federation/discovery"
if File.file?("/etc/ssl/certs/ca-certificates.crt")
# For Debian, Ubuntu, Archlinux, Gentoo
ca_file = "/etc/ssl/certs/ca-certificates.crt"
else
# For CentOS, Fedora
ca_file = "/etc/pki/tls/certs/ca-bundle.crt"
end
# configure the federation engine
DiasporaFederation.configure do |config|
# the pod url
config.server_uri = URI("http://localhost:3000/")
config.certificate_authorities = ca_file
config.define_callbacks do
on :person_webfinger_fetch do |handle|
person = Person.find_by(diaspora_handle: handle)