/usr/lib/ruby/vendor_ruby/capybara/server.rb is in ruby-capybara 2.10.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # frozen_string_literal: true
require 'uri'
require 'net/http'
require 'rack'
module Capybara
class Server
class Middleware
class Counter
attr_reader :value
def initialize
@value = 0
@mutex = Mutex.new
end
def increment
@mutex.synchronize { @value += 1 }
end
def decrement
@mutex.synchronize { @value -= 1 }
end
end
attr_accessor :error
def initialize(app)
@app = app
@counter = Counter.new
end
def pending_requests?
@counter.value > 0
end
def call(env)
if env["PATH_INFO"] == "/__identify__"
[200, {}, [@app.object_id.to_s]]
else
@counter.increment
begin
@app.call(env)
rescue *Capybara.server_errors => e
@error = e unless @error
raise e
ensure
@counter.decrement
end
end
end
end
class << self
def ports
@ports ||= {}
end
end
attr_reader :app, :port, :host
def initialize(app, port=Capybara.server_port, host=Capybara.server_host)
@app = app
@server_thread = nil # suppress warnings
@host, @port = host, port
@port ||= Capybara::Server.ports[port_key]
@port ||= find_available_port(host)
end
def reset_error!
middleware.error = nil
end
def error
middleware.error
end
def responsive?
return false if @server_thread && @server_thread.join(0)
res = Net::HTTP.start(host, port) { |http| http.get('/__identify__') }
if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
return res.body == app.object_id.to_s
end
rescue SystemCallError
return false
end
def wait_for_pending_requests
Timeout.timeout(60) { sleep(0.01) while pending_requests? }
rescue Timeout::Error
raise "Requests did not finish in 60 seconds"
end
def boot
unless responsive?
Capybara::Server.ports[port_key] = port
@server_thread = Thread.new do
Capybara.server.call(middleware, port, host)
end
Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }
end
rescue Timeout::Error
raise "Rack application timed out during boot"
else
self
end
private
def middleware
@middleware ||= Middleware.new(app)
end
def port_key
Capybara.reuse_server ? app.object_id : middleware.object_id
end
def pending_requests?
middleware.pending_requests?
end
def find_available_port(host)
server = TCPServer.new(host, 0)
server.addr[1]
ensure
server.close if server
end
end
end
|