diff options
Diffstat (limited to 'spec/ruby/library/net-http/http/fixtures/http_server.rb')
-rw-r--r-- | spec/ruby/library/net-http/http/fixtures/http_server.rb | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/spec/ruby/library/net-http/http/fixtures/http_server.rb b/spec/ruby/library/net-http/http/fixtures/http_server.rb new file mode 100644 index 0000000000..c1cedbfa76 --- /dev/null +++ b/spec/ruby/library/net-http/http/fixtures/http_server.rb @@ -0,0 +1,123 @@ +require 'socket' + +module NetHTTPSpecs + class NullWriter + def <<(s) end + def puts(*args) end + def print(*args) end + def printf(*args) end + end + + class SmallHTTPServer + def initialize(bind_address) + @server = TCPServer.new(bind_address, 0) + @thread = Thread.new { + Thread.current.abort_on_exception = true + listen + } + end + + def ip + @server.addr[3] + end + + def port + @server.addr[1] + end + + def listen + until @server.closed? + client = @server.accept + handle_client(client) + end + end + + def handle_client(client) + begin + until client.closed? + request = client.gets("\r\n\r\n") + break unless request + if request == "CLOSE" + @server.close + break + end + handle_request(client, request) + end + ensure + client.close + end + end + + def parse_request(request) + request, *headers = request.chomp.lines.map { |line| line.chomp } + request_method, request_uri, _http_version = request.split + headers = headers.map { |line| line.split(': ', 2) }.to_h + [request_method, request_uri, headers] + end + + def handle_request(client, request) + request_method, request_uri, headers = parse_request(request) + + if headers.include? 'Content-Length' + request_body_size = Integer(headers['Content-Length']) + request_body = client.read(request_body_size) + end + + case request_uri + when '/' + raise request_method unless request_method == 'GET' + reply(client, "This is the index page.", request_method) + when '/request' + reply(client, "Request type: #{request_method}", request_method) + when '/request/body' + reply(client, request_body, request_method) + when '/request/header' + reply(client, headers.inspect, request_method) + when '/request/basic_auth' + reply(client, "username: \npassword: ", request_method) + else + raise request_uri + end + end + + def reply(client, body, request_method) + client.print "HTTP/1.1 200 OK\r\n" + if request_method == 'HEAD' + client.close + else + client.print "Content-Type: text/plain\r\n" + client.print "Content-Length: #{body.bytesize}\r\n" + client.print "\r\n" + client.print body + end + end + + def close + TCPSocket.open(ip, port) do |socket| + socket.write "CLOSE" + end + @thread.join + end + end + + @server = nil + + class << self + def port + raise "server not started" unless @server + @server.port + end + + def start_server + bind_address = platform_is(:windows) ? "localhost" : "127.0.0.1" + @server = SmallHTTPServer.new(bind_address) + end + + def stop_server + if @server + @server.close + @server = nil + end + end + end +end |