summaryrefslogtreecommitdiff
path: root/spec/ruby/library/net-http/http/fixtures/http_server.rb
diff options
context:
space:
mode:
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.rb123
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