Sha256: 62a31208f87846c905063521df2c7a7d24db15787c0fe4e0f0fb67b28bdb0a86

Contents?: true

Size: 1.76 KB

Versions: 2

Compression:

Stored size: 1.76 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(exception: false)
          request = client.gets

          status, headers, body = @app.call(parse_request(request))
          respond(client, status, headers, body)

          client.close
        rescue IO::WaitReadable, Errno::EINTR
          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

2 entries across 2 versions & 1 rubygems

Version Path
good_job-3.17.2 lib/good_job/http_server.rb
good_job-3.17.1 lib/good_job/http_server.rb