Skip to content

Commit c9d6211

Browse files
committed
Merge pull request #13 from tjdett/trailing-slashes
Fixing incorrect redirection handling
2 parents 98c430e + 1a87b29 commit c9d6211

File tree

4 files changed

+149
-75
lines changed

4 files changed

+149
-75
lines changed

lib/oai/client.rb

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,17 @@ def initialize(base_url, options={})
8282
@debug = options.fetch(:debug, false)
8383
@parser = options.fetch(:parser, 'rexml')
8484

85-
@follow_redirects = options.fetch(:redirects, true)
86-
@http_client = options.fetch(:http, Faraday.new(@base))
87-
88-
if !options.key?(:http) and @follow_redirects
89-
90-
count = @folow_redirects if @folow_redirects.is_a? Fixnum
91-
count ||= 5
92-
93-
require 'faraday_middleware'
94-
@http_client.use FaradayMiddleware::FollowRedirects, :limit => count
85+
@http_client = options.fetch(:http) do
86+
Faraday.new(:url => @base) do |builder|
87+
follow_redirects = options.fetch(:redirects, true)
88+
if follow_redirects
89+
count = follow_redirects.is_a?(Fixnum) ? follow_redirects : 5
90+
91+
require 'faraday_middleware'
92+
builder.response :follow_redirects, :limit => count
93+
end
94+
builder.adapter :net_http
95+
end
9596
end
9697

9798
# load appropriate parser

test/client/helpers/provider.rb

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,58 @@ class ComplexProvider < OAI::Provider::Base
88
source_model ComplexModel.new(100)
99
end
1010

11-
class ProviderServer < WEBrick::HTTPServlet::AbstractServlet
12-
@@server = nil
13-
14-
def initialize(server)
15-
super(server)
11+
class ProviderServer
12+
13+
attr_reader :consumed, :server
14+
15+
def initialize(port, mount_point)
16+
@consumed = []
1617
@provider = ComplexProvider.new
18+
@server = WEBrick::HTTPServer.new(
19+
:BindAddress => '127.0.0.1',
20+
:Logger => WEBrick::Log.new('/dev/null'),
21+
:AccessLog => [],
22+
:Port => port)
23+
@server.mount_proc(mount_point, server_proc)
1724
end
18-
19-
def do_GET(req, res)
20-
begin
21-
res.body = @provider.process_request(req.query)
22-
res.status = 200
23-
res['Content-Type'] = 'text/xml'
24-
rescue => err
25-
puts err
26-
puts err.backtrace.join("\n")
27-
res.body = err.backtrace.join("\n")
28-
res.status = 500
29-
end
25+
26+
def port
27+
@server.config[:Port]
3028
end
31-
32-
def self.start(port)
33-
unless @@server
34-
@@server = WEBrick::HTTPServer.new(
35-
:BindAddress => '127.0.0.1',
36-
:Logger => WEBrick::Log.new('/dev/null'),
37-
:AccessLog => [],
38-
:Port => port)
39-
@@server.mount("/oai", ProviderServer)
4029

41-
trap("INT") { @@server.shutdown }
42-
@@thread = Thread.new { @@server.start }
43-
puts "Starting Webrick/Provider on port[#{port}]"
44-
end
30+
def start
31+
@thread = Thread.new { @server.start }
4532
end
46-
47-
def self.stop
48-
puts "Stopping Webrick/Provider"
49-
if @@thread
50-
@@thread.exit
51-
end
33+
34+
def stop
35+
@thread.exit if @thread
5236
end
53-
54-
def self.wrap(port = 3333)
37+
38+
def self.wrap(port = 3333, mount_point='/oai')
39+
server = self.new(port, mount_point)
5540
begin
56-
start(port)
41+
server.start
42+
yield(server)
43+
ensure
44+
server.stop
45+
end
46+
end
5747

58-
# Wait for startup
59-
sleep 2
60-
61-
yield
48+
protected
6249

63-
ensure
64-
stop
50+
def server_proc
51+
Proc.new do |req, res|
52+
begin
53+
res.body = @provider.process_request(req.query)
54+
res.status = 200
55+
res['Content-Type'] = 'text/xml'
56+
rescue => err
57+
puts err
58+
puts err.backtrace.join("\n")
59+
res.body = err.backtrace.join("\n")
60+
res.status = 500
61+
end
6562
end
6663
end
67-
68-
end
64+
65+
end

test/client/helpers/test_wrapper.rb

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
1-
module Test::Unit
2-
class AutoRunner
3-
alias_method :real_run, :run
4-
5-
def run
6-
ProviderServer.wrap { real_run }
7-
end
8-
9-
end
10-
11-
end
12-
13-
unless $provider_server_already_started
14-
$provider_server_already_started = true
15-
ProviderServer.start(3333)
16-
sleep 2
1+
unless $provider_server
2+
$provider_server = ProviderServer.new(3333, '/oai')
3+
$provider_server.start
4+
sleep 0.2
175
end
186

test/client/tc_http_client.rb

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
require 'test_helper'
2+
require 'webrick'
23

34
class HttpClientTest < Test::Unit::TestCase
45

56
def test_pluggable_http_client
67
oai_response = <<-eos
78
<Identify>
89
<repositoryName>Mock OAI Provider</repositoryName>
9-
<baseURL>http://nowhere.example.com</baseURL>
10+
<baseURL>http://nowhere.example.com</baseURL>
1011
</Identify>
1112
eos
1213

@@ -20,7 +21,94 @@ def test_pluggable_http_client
2021

2122
assert_kind_of OAI::IdentifyResponse, response
2223
assert_equal 'Mock OAI Provider [http://nowhere.example.com]', response.to_s
23-
24+
25+
end
26+
27+
def test_http_client_handles_trailing_slash_redirects
28+
# First, test that this works when mocking out Faraday client
29+
oai_response = <<-eos
30+
<Identify>
31+
<repositoryName>Mock OAI Provider</repositoryName>
32+
<baseURL>http://nowhere.example.com</baseURL>
33+
</Identify>
34+
eos
35+
36+
stubs = TrailingSlashAwareStubs.new do |stub|
37+
stub.get('/oai/?verb=Identify') { [200, {}, oai_response] }
38+
stub.get('/oai?verb=Identify') {
39+
[301, {
40+
'Location' => 'http://localhost:3334/oai/?verb=Identify'
41+
}, '']
42+
}
43+
end
44+
45+
faraday_stub = Faraday.new do |builder|
46+
require 'faraday_middleware'
47+
builder.use FaradayMiddleware::FollowRedirects
48+
builder.adapter :test, stubs
49+
end
50+
51+
client = OAI::Client.new 'http://localhost:3334/oai', :http => faraday_stub
52+
response = client.identify
53+
54+
assert_kind_of OAI::IdentifyResponse, response
55+
assert_equal 'Mock OAI Provider [http://nowhere.example.com]', response.to_s
56+
assert_equal 2, stubs.consumed[:get].length
57+
assert_equal stubs.consumed[:get].first.path, '/oai'
58+
assert_equal stubs.consumed[:get].last.path, '/oai/'
59+
60+
# Now try it with a real server and default Faraday client
61+
TrailingSlashProviderServer.wrap(3334) do |server|
62+
client = OAI::Client.new "http://localhost:#{server.port}/oai"
63+
response = client.identify
64+
65+
assert_kind_of OAI::IdentifyResponse, response
66+
assert_equal 'Complex Provider [http://localhost]', response.to_s
67+
assert_equal 2, server.consumed.length
68+
assert_equal server.consumed.first.path, '/oai'
69+
assert_equal server.consumed.last.path, '/oai/'
70+
end
71+
end
72+
73+
private
74+
75+
class TrailingSlashProviderServer < ProviderServer
76+
def server_proc
77+
Proc.new do |req, res|
78+
@consumed << req
79+
case req.path
80+
when "/oai/"
81+
begin
82+
res.body = @provider.process_request(req.query)
83+
res.status = 200
84+
res['Content-Type'] = 'text/xml'
85+
rescue => err
86+
puts err
87+
puts err.backtrace.join("\n")
88+
res.body = err.backtrace.join("\n")
89+
res.status = 500
90+
end
91+
else
92+
res.body = ''
93+
res.status = 301
94+
res['Location'] = "http://localhost:#{port}/oai/?#{req.query_string}"
95+
end
96+
res
97+
end
98+
end
99+
end
100+
101+
class TrailingSlashAwareStubs < Faraday::Adapter::Test::Stubs
102+
attr_reader :consumed
103+
104+
# ensure leading, but not trailing slash
105+
def normalize_path(path)
106+
path = '/' + path if path.index('/') != 0
107+
#path = path.sub('?', '/?')
108+
#path = path + '/' unless $&
109+
path.gsub('//', '/')
110+
end
111+
24112
end
25113
end
26114

0 commit comments

Comments
 (0)