Sha256: 90f4d41e466b74a7e35a283304f1faa752b99c336b7a79072faaddfe78de9cba
Contents?: true
Size: 1.79 KB
Versions: 11
Compression:
Stored size: 1.79 KB
Contents
# frozen_string_literal: true module GoodJob class HttpServer SOCKET_READ_TIMEOUT = 5 # in seconds def initialize(app, options = {}) @app = app @port = options[:port] @logger = options[:logger] @running = Concurrent::AtomicBoolean.new(false) end def run @running.make_true start_server handle_connections if @running.true? rescue StandardError => e @logger.error "Server encountered an error: #{e}" ensure stop end def stop @running.make_false @server&.close end def running? @running.true? end private def start_server @server = TCPServer.new('0.0.0.0', @port) rescue StandardError => e @logger.error "Failed to start server: #{e}" @running.make_false end def handle_connections while @running.true? begin ready_sockets, = IO.select([@server], nil, nil, SOCKET_READ_TIMEOUT) next unless ready_sockets client = @server.accept_nonblock request = client.gets if request status, headers, body = @app.call(parse_request(request)) respond(client, status, headers, body) end client.close rescue IO::WaitReadable, Errno::EINTR, Errno::EPIPE retry end end end def parse_request(request) method, full_path = request.split path, query = full_path.split('?') { 'REQUEST_METHOD' => method, 'PATH_INFO' => path, 'QUERY_STRING' => query || '' } end def respond(client, status, headers, body) client.write "HTTP/1.1 #{status}\r\n" headers.each { |key, value| client.write "#{key}: #{value}\r\n" } client.write "\r\n" body.each { |part| client.write part.to_s } end end end
Version data entries
11 entries across 11 versions & 1 rubygems