module Midori::Server
Logic to EventMachine TCP Server
, running inside Midori::Connection
Attributes
api[RW]
@!attribute request
@return [Midori::Request] raw request
@!attribute api
@return [Class] inherited from Midori::API
@!attribute websocket
@return [Midori::WebSocket] defined websocket instance
@!attribute eventsource
@return [Midori::EventSource] defined eventsource instance
eventsource[RW]
@!attribute request
@return [Midori::Request] raw request
@!attribute api
@return [Class] inherited from Midori::API
@!attribute websocket
@return [Midori::WebSocket] defined websocket instance
@!attribute eventsource
@return [Midori::EventSource] defined eventsource instance
request[RW]
@!attribute request
@return [Midori::Request] raw request
@!attribute api
@return [Class] inherited from Midori::API
@!attribute websocket
@return [Midori::WebSocket] defined websocket instance
@!attribute eventsource
@return [Midori::EventSource] defined eventsource instance
websocket[RW]
@!attribute request
@return [Midori::Request] raw request
@!attribute api
@return [Class] inherited from Midori::API
@!attribute websocket
@return [Midori::WebSocket] defined websocket instance
@!attribute eventsource
@return [Midori::EventSource] defined eventsource instance
Public Instance Methods
call_event(event, args = [])
click to toggle source
To call a websocket event if it exist @param [Symbol] event event name @param [Array] args arg list
# File lib/midori/server.rb, line 113 def call_event(event, args = []) -> { @websocket.instance_exec(*args, &@websocket.events[event]) }.call unless @websocket.events[event].nil? end
receive_data(socket)
click to toggle source
Logic of receiving data @param [Scoket] the socket able to read
# File lib/midori/server.rb, line 32 def receive_data(socket) begin @request.ip, @request.port = @peer_addr if @request.parsed? && !(@request.body_parsed?) data = socket.read @request.body.bytesize - @request.header['Content-Length'] else data = socket.readline end if @request.websocket? websocket_request(StringIO.new(data)) else @request.parse(data) receive_new_request if @request.parsed? && @request.body_parsed? end rescue EOFError, Errno::ENOTCONN => _e close_connection # Ignore client's disconnection rescue => e # :nocov: # Leave for corner cases close_connection @logger.warn "#{@request.ip} - - #{e.class} #{e.backtrace.join("\n")}".yellow # :nocov: end end
receive_new_request()
click to toggle source
Logic of receiving new request
# File lib/midori/server.rb, line 60 def receive_new_request begin start_time = Time.now @response = @api.receive(request, self) now_time = Time.now @logger.info "#{@request.ip} - - \"#{@request.method} #{@request.path} HTTP/#{@request.protocol}\" #{@response.status} #{sprintf("%.6f", now_time.to_f - start_time.to_f)}".green call_event(:open) if @request.websocket? rescue Midori::Exception::NotFound => e @response = Midori::Sandbox.capture(e) rescue => e @response = Midori::Sandbox.capture(e) @logger.error e.inspect.red @logger.warn e.backtrace.join("\n").yellow end unless @request.websocket? || @request.eventsource? send_data @response proceed_keep_alive end end
server_initialize(api, logger)
click to toggle source
Define server behaviour @param [Class] api inherited from Midori::API
@param [Logger] logger global logger
# File lib/midori/server.rb, line 17 def server_initialize(api, logger) @api = api @logger = logger @request = Midori::Request.new @websocket = Midori::WebSocket.new(self) @eventsource = Midori::EventSource.new(self) # Add keep-alive parameters @keep_alive_timer = nil @keep_alive_count = 1 end
websocket_request(data)
click to toggle source
Logic of receiving WebSocket
request @param [StringIO] data raw data
# File lib/midori/server.rb, line 83 def websocket_request(data) @websocket.decode(data) case @websocket.opcode when 0x1, 0x2 call_event(:message, [@websocket.msg]) when 0x9 @websocket.pong(@websocket.msg) call_event(:ping) when 0xA call_event(:pong) end rescue Midori::Exception::FrameEnd => _e call_event(:close) send_data "\b" # Opcode 0x8 close_connection_after_writing rescue Midori::Exception::PingPongSizeTooLarge => e @logger.warn e.inspect.yellow call_event(:error) # Too large ping request send_data "\b" # Opcode 0x8 close_connection_after_writing rescue => e call_event(:error) @logger.error e.inspect.red @logger.warn e.backtrace.join("\n").yellow close_connection_after_writing end
Private Instance Methods
proceed_keep_alive()
click to toggle source
# File lib/midori/server.rb, line 117 def proceed_keep_alive # Detect if it should close connection if !Midori::Configure.keep_alive || (@keep_alive_count >= Midori::Configure.keep_alive_requests) close_connection_after_writing return end # Add timeout for keep-alive @keep_alive_count += 1 Fiber.schedule do sleep Midori::Configure.keep_alive_timeout close_connection end # Reset request @request.reset! end