This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
require 'rack'
|
||||
require 'rack/handler/webrick'
|
||||
require 'net/http'
|
||||
|
||||
# The code for this is inspired by Capybara's server:
|
||||
# http://github.com/jnicklas/capybara/blob/0.3.9/lib/capybara/server.rb
|
||||
class LocalhostServer
|
||||
READY_MESSAGE = "Server ready"
|
||||
|
||||
class Identify
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env["PATH_INFO"] == "/__identify__"
|
||||
[200, {}, [LocalhostServer::READY_MESSAGE]]
|
||||
else
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :port
|
||||
|
||||
def initialize(rack_app, port = nil)
|
||||
@port = port || find_available_port
|
||||
@rack_app = rack_app
|
||||
concurrently { boot }
|
||||
wait_until(10, "Boot failed.") { booted? }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_available_port
|
||||
server = TCPServer.new('127.0.0.1', 0)
|
||||
server.addr[1]
|
||||
ensure
|
||||
server.close if server
|
||||
end
|
||||
|
||||
def boot
|
||||
# Use WEBrick since it's part of the ruby standard library and is available on all ruby interpreters.
|
||||
options = { :Port => port }
|
||||
options.merge!(:AccessLog => [], :Logger => WEBrick::BasicLog.new(StringIO.new)) unless ENV['VERBOSE_SERVER']
|
||||
Rack::Handler::WEBrick.run(Identify.new(@rack_app), options)
|
||||
end
|
||||
|
||||
def booted?
|
||||
res = ::Net::HTTP.get_response("localhost", '/__identify__', port)
|
||||
if res.is_a?(::Net::HTTPSuccess) or res.is_a?(::Net::HTTPRedirection)
|
||||
return res.body == READY_MESSAGE
|
||||
end
|
||||
rescue Errno::ECONNREFUSED, Errno::EBADF
|
||||
return false
|
||||
end
|
||||
|
||||
def concurrently
|
||||
if should_use_subprocess?
|
||||
pid = Process.fork do
|
||||
trap(:INT) { ::Rack::Handler::WEBrick.shutdown }
|
||||
yield
|
||||
exit # manually exit; otherwise this sub-process will re-run the specs that haven't run yet.
|
||||
end
|
||||
|
||||
at_exit do
|
||||
Process.kill('INT', pid)
|
||||
begin
|
||||
Process.wait(pid)
|
||||
rescue Errno::ECHILD
|
||||
# ignore this error...I think it means the child process has already exited.
|
||||
end
|
||||
end
|
||||
else
|
||||
Thread.new { yield }
|
||||
end
|
||||
end
|
||||
|
||||
def should_use_subprocess?
|
||||
# !ENV['THREADED']
|
||||
false
|
||||
end
|
||||
|
||||
def wait_until(timeout, error_message, &block)
|
||||
start_time = Time.now
|
||||
|
||||
while true
|
||||
return if yield
|
||||
raise TimeoutError.new(error_message) if (Time.now - start_time) > timeout
|
||||
sleep(0.05)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class MemoryCache
|
||||
attr_reader :memory
|
||||
|
||||
def initialize
|
||||
@memory = {}
|
||||
end
|
||||
|
||||
def get(request)
|
||||
memory[request]
|
||||
end
|
||||
|
||||
def set(request, response)
|
||||
memory[request] = response
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env ruby
|
||||
require 'json'
|
||||
require 'zlib'
|
||||
require 'sinatra/base'
|
||||
require 'rack/typhoeus'
|
||||
|
||||
TESTSERVER = Sinatra.new do
|
||||
set :logging, false
|
||||
use Rack::Typhoeus::Middleware::ParamsDecoder
|
||||
|
||||
fail_count = 0
|
||||
|
||||
post '/file' do
|
||||
{
|
||||
'content-type' => params[:file][:type],
|
||||
'filename' => params[:file][:filename],
|
||||
'content' => params[:file][:tempfile].read,
|
||||
'request-content-type' => request.env['CONTENT_TYPE']
|
||||
}.to_json
|
||||
end
|
||||
|
||||
get '/multiple-headers' do
|
||||
[200, { 'Set-Cookie' => %w[ foo bar ], 'Content-Type' => 'text/plain' }, ['']]
|
||||
end
|
||||
|
||||
get '/cookies-test' do
|
||||
[200, { 'Set-Cookie' => %w(foo=bar bar=foo), 'Content-Type' => 'text/plain' }, ['']]
|
||||
end
|
||||
|
||||
get '/cookies-test2' do
|
||||
[200, { 'Set-Cookie' => %w(foo2=bar bar2=foo), 'Content-Type' => 'text/plain' }, ['']]
|
||||
end
|
||||
|
||||
get '/fail/:number' do
|
||||
if fail_count >= params[:number].to_i
|
||||
"ok"
|
||||
else
|
||||
fail_count += 1
|
||||
error 500, "oh noes!"
|
||||
end
|
||||
end
|
||||
|
||||
get '/fail_forever' do
|
||||
error 500, "oh noes!"
|
||||
end
|
||||
|
||||
get '/redirect' do
|
||||
redirect '/'
|
||||
end
|
||||
|
||||
get '/bad_redirect' do
|
||||
redirect '/bad_redirect'
|
||||
end
|
||||
|
||||
get '/auth_basic/:username/:password' do
|
||||
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
||||
# Check that we've got a basic auth, and that it's credentials match the ones
|
||||
# provided in the request
|
||||
if @auth.provided? && @auth.basic? && @auth.credentials == [ params[:username], params[:password] ]
|
||||
# auth is valid - confirm it
|
||||
true
|
||||
else
|
||||
# invalid auth - request the authentication
|
||||
response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth")
|
||||
throw(:halt, [401, "Not authorized\n"])
|
||||
end
|
||||
end
|
||||
|
||||
get '/auth_ntlm' do
|
||||
# we're just checking for the existence if NTLM auth header here. It's validation
|
||||
# is too troublesome and really doesn't bother is much, it's up to libcurl to make
|
||||
# it valid
|
||||
response['WWW-Authenticate'] = 'NTLM'
|
||||
is_ntlm_auth = /^NTLM/ =~ request.env['HTTP_AUTHORIZATION']
|
||||
true if is_ntlm_auth
|
||||
throw(:halt, [401, "Not authorized\n"]) if !is_ntlm_auth
|
||||
end
|
||||
|
||||
get '/gzipped' do
|
||||
req_env = request.env.to_json
|
||||
z = Zlib::Deflate.new
|
||||
gzipped_env = z.deflate(req_env, Zlib::FINISH)
|
||||
z.close
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
gzipped_env
|
||||
end
|
||||
|
||||
get '/**' do
|
||||
sleep params["delay"].to_i if params.has_key?("delay")
|
||||
request.env.merge!(:body => request.body.read).to_json
|
||||
end
|
||||
|
||||
head '/**' do
|
||||
sleep params["delay"].to_i if params.has_key?("delay")
|
||||
end
|
||||
|
||||
put '/**' do
|
||||
request.env.merge!(:body => request.body.read).to_json
|
||||
end
|
||||
|
||||
post '/**' do
|
||||
request.env.merge!(:body => request.body.read).to_json
|
||||
end
|
||||
|
||||
delete '/**' do
|
||||
request.env.merge!(:body => request.body.read).to_json
|
||||
end
|
||||
|
||||
patch '/**' do
|
||||
request.env.merge!(:body => request.body.read).to_json
|
||||
end
|
||||
|
||||
options '/**' do
|
||||
request.env.merge!(:body => request.body.read).to_json
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user