class Toycol::Server
Constants
- BACKLOG
- CHUNK_SIZE
Public Class Methods
new(app, **options)
click to toggle source
# File lib/toycol/server.rb, line 14 def initialize(app, **options) @app = app @path = options[:Path] @port = options[:Port] @env = default_env @returned_status = nil @returned_headers = nil @returned_body = nil end
run(app, **options)
click to toggle source
# File lib/toycol/server.rb, line 9 def run(app, **options) new(app, **options).run end
Public Instance Methods
run()
click to toggle source
# File lib/toycol/server.rb, line 24 def run verify_file_path! server = UNIXServer.new @path server.listen BACKLOG loop do trap(:INT) { exit } socket = server.accept request_message = [] request_message << socket.readpartial(CHUNK_SIZE) until socket.eof? request_message = request_message.join assign_parsed_attributes!(request_message) @returned_status, @returned_headers, @returned_body = @app.call(@env) socket.puts response_message socket.close_write socket.close end end
Private Instance Methods
assign_parsed_attributes!(request_message)
click to toggle source
# File lib/toycol/server.rb, line 104 def assign_parsed_attributes!(request_message) request_line, *request_headers, request_body = request_message.split("\r\n").reject(&:empty?) request_method, request_path, = request_line.split request_path, query_string = request_path.split("?") @env[REQUEST_METHOD] = request_method @env[PATH_INFO] = request_path @env[QUERY_STRING] = query_string || "" @env[CONTENT_LENGTH] request_headers.each do |request_header| k, v = request_header.split(":").map(&:strip) @env[k.tr("-", "_").upcase.to_s] = v end @env[RACK_INPUT] = stringio(request_body) end
default_env()
click to toggle source
# File lib/toycol/server.rb, line 49 def default_env { PATH_INFO => "", QUERY_STRING => "", REQUEST_METHOD => "", SERVER_NAME => "toycol_server", SERVER_PORT => @port.to_s, CONTENT_LENGTH => "0", RACK_VERSION => Rack::VERSION, RACK_INPUT => stringio(""), RACK_ERRORS => $stderr, RACK_MULTITHREAD => false, RACK_MULTIPROCESS => false, RACK_RUN_ONCE => false, RACK_URL_SCHEME => "http" } end
response_body()
click to toggle source
# File lib/toycol/server.rb, line 81 def response_body res = [] @returned_body.each { |body| res << body } res.join end
response_headers()
click to toggle source
# File lib/toycol/server.rb, line 75 def response_headers @returned_headers["Content-Length"] = response_body.size unless @returned_headers["Content-Length"] @returned_headers.map { |k, v| "#{k}: #{v}" }.join("\r\n") + "\r\n" end
response_message()
click to toggle source
# File lib/toycol/server.rb, line 67 def response_message "#{response_status_code}#{response_headers}\r\n#{response_body}" end
response_status_code()
click to toggle source
# File lib/toycol/server.rb, line 71 def response_status_code "HTTP/1.1 #{@returned_status} #{DEFAULT_HTTP_STATUS_CODES[@returned_status.to_i] || "CUSTOM"}\r\n" end
stringio(body = "")
click to toggle source
# File lib/toycol/server.rb, line 87 def stringio(body = "") StringIO.new(body).set_encoding("ASCII-8BIT") end
verify_file_path!()
click to toggle source
# File lib/toycol/server.rb, line 91 def verify_file_path! return unless File.exist? @path begin bound_file = UNIXSocket.new @path rescue SystemCallError, IOError File.unlink @path else bound_file.close raise "[Toycol] Address already in use: #{@path}" end end