class Minver::Base

Constants

HTTP_CODES
HTTP_METHODS
HTTP_VERSION

Public Class Methods

new(**options, &block) click to toggle source
# File lib/minver/base.rb, line 60
def initialize(**options, &block)
  @bind = options.fetch(:bind, '::')
  @port = options.fetch(:port, 18167)
  @clients = []
  instance_eval(&block) if block_given?
end

Public Instance Methods

on(method, uri, &block) click to toggle source
# File lib/minver/base.rb, line 71
def on(method, uri, &block)
  triggers[method][normalize_path(uri)] = block
end
pass(return_value) click to toggle source
# File lib/minver/base.rb, line 130
def pass return_value
  @should_pass = true
  @return_value = return_value
end
run(**options) click to toggle source
# File lib/minver/base.rb, line 81
def run(**options)
  $stderr.puts "Listening on #{@bind}:#{@port}." if $DEBUG
  loop do
    result = IO.select([server, *@clients], *([nil, nil, 0] if options[:nonblock]))
    return unless result
    result.first.each do |client|
      # it's possible that "client" here is the server so we extract the client from it.
      @clients << (client = client.accept) if client.respond_to?(:accept)
      if client.eof?
        @clients.delete(client).close
        next
      end
      begin
        request = Request.new(client)
        $stderr.puts request.data.lines.map{|l| "< #{l}"} if $DEBUG
        block = triggers[request.http_method][normalize_path(request.path)]
        response = if block
          begin
            Response.from(instance_exec(request, &block))
          rescue => e
            raise RequestError.new(
              "An error occurred. Check the logs or ask the administrator.",
              500,
              cause: e
            )
          end
        else
          raise RequestError.new("The resource you were looking for does not exist.", 404)
        end
        if @should_pass
          @should_pass = false
          return @return_value
        end
      rescue RequestError => e
        response = Response.from([e.code, e.headers, e.message])
        raise e.cause || e if (500..599).include? e.code
      ensure
        $stderr.puts response.data.lines.map{|l| "> #{l}"} if $DEBUG
        client.write(response.data)
      end
    end
  end
end
server() click to toggle source
# File lib/minver/base.rb, line 67
def server
  @server ||= TCPServer.new @bind, @port
end
stop(return_value=nil) click to toggle source
# File lib/minver/base.rb, line 125
def stop return_value=nil
  pass return_value
  server.close
end

Protected Instance Methods

normalize_path(path) click to toggle source
# File lib/minver/base.rb, line 137
def normalize_path(path)
  path.squeeze("/").chomp "/"
end
triggers() click to toggle source
# File lib/minver/base.rb, line 141
def triggers
  @triggers ||= HTTP_METHODS.inject({}){ |h, m| h.merge(m => {}) }
end