Class: Minver::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/minver/base.rb

Constant Summary collapse

HTTP_VERSION =
"1.1"
HTTP_METHODS =
%w(GET POST PATCH PUT DELETE HEAD)
HTTP_CODES =
{
  100 => "Continue",
  101 => "Switching Protocols",
  103 => "Checkpoint",
  200 => "OK",
  201 => "Created",
  202 => "Accepted",
  203 => "Non-Authoritative Information",
  204 => "No Content",
  205 => "Reset Content",
  206 => "Partial Content",
  300 => "Multiple Choices",
  301 => "Moved Permanently",
  302 => "Found",
  303 => "See Other",
  304 => "Not Modified",
  306 => "Switch Proxy",
  307 => "Temporary Redirect",
  308 => "Resume Incomplete",
  400 => "Bad Request",
  401 => "Unauthorized",
  402 => "Payment Required",
  403 => "Forbidden",
  404 => "Not Found",
  405 => "Method Not Allowed",
  406 => "Not Acceptable",
  407 => "Proxy Authentication Required",
  408 => "Request Timeout",
  409 => "Conflict",
  410 => "Gone",
  411 => "Length Required",
  412 => "Precondition Failed",
  413 => "Request Entity Too Large",
  414 => "Request-URI Too Long",
  415 => "Unsupported Media Type",
  416 => "Requested Range Not Satisfiable",
  417 => "Expectation Failed",
  422 => "Unprocessable Entity",
  423 => "Locked",
  424 => "Failed Dependency",
  500 => "Internal Server Error",
  501 => "Not Implemented",
  502 => "Bad Gateway",
  503 => "Service Unavailable",
  504 => "Gateway Timeout",
  505 => "HTTP Version Not Supported",
  511 => "Network Authentication Required"
}

Instance Method Summary collapse

Constructor Details

#initialize(**options, &block) ⇒ Base

Returns a new instance of Base.



60
61
62
63
64
65
# 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

Instance Method Details

#on(method, uri, &block) ⇒ Object



71
72
73
# File 'lib/minver/base.rb', line 71

def on(method, uri, &block)
  triggers[method][normalize_path(uri)] = block
end

#pass(return_value) ⇒ Object



130
131
132
133
# File 'lib/minver/base.rb', line 130

def pass return_value
  @should_pass = true
  @return_value = return_value
end

#run(**options) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 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

#serverObject



67
68
69
# File 'lib/minver/base.rb', line 67

def server
  @server ||= TCPServer.new @bind, @port
end

#stop(return_value = nil) ⇒ Object



125
126
127
128
# File 'lib/minver/base.rb', line 125

def stop return_value=nil
  pass return_value
  server.close
end