module Wpxf::Net::HttpServer
Provides basic, single threaded HTTP server functionality.
Public Class Methods
Initialize a new instance of {HttpServer}.
# File lib/wpxf/net/http_server.rb, line 11 def initialize super register_options([ StringOption.new( name: 'http_server_bind_address', desc: 'Address to bind the HTTP server to', default: '0.0.0.0', required: true ), PortOption.new( name: 'http_server_bind_port', desc: 'Port for the HTTP server to listen on', default: 80, required: true ) ]) @http_server_kill_switch = false end
Public Instance Methods
@return [String] the address the HTTP server is bound to.
# File lib/wpxf/net/http_server.rb, line 33 def http_server_bind_address normalized_option_value('http_server_bind_address') end
@return [Integer] the port the HTTP server is listening on.
# File lib/wpxf/net/http_server.rb, line 38 def http_server_bind_port normalized_option_value('http_server_bind_port') end
@return [Thread] thread that the server runs on when in non-blocking mode.
# File lib/wpxf/net/http_server.rb, line 98 def http_server_thread @http_server_thread end
@return [String] the AJAX download helper script.
# File lib/wpxf/net/http_server.rb, line 54 def js_ajax_download File.read(File.join(Wpxf.data_directory, 'js', 'ajax_download.js')) end
@return [String] the AJAX post helper script.
# File lib/wpxf/net/http_server.rb, line 59 def js_ajax_post File.read(File.join(Wpxf.data_directory, 'js', 'ajax_post.js')) end
@return [String] the JS post helper script.
# File lib/wpxf/net/http_server.rb, line 64 def js_post File.read(File.join(Wpxf.data_directory, 'js', 'post.js')) end
Invoked when a HTTP request is made to the server. @param path [String] the path requested. @param params [Hash] the query string parameters. @param headers [Hash] the HTTP headers. @return [String, Hash] if a string is returned, it will be used as the response body
to send to the client. If a hash is returned, it should contain the keys: * +:body+ - the body text of the response. * +:type+ - the MIME type of the response. * +:headers+ - an array of header strings.
# File lib/wpxf/net/http_server.rb, line 51 def on_http_request(path, params, headers) end
Start the HTTP server. @param non_block [Boolean] run the server in non-blocking mode.
# File lib/wpxf/net/http_server.rb, line 70 def start_http_server(non_block = false) @tcp_server = TCPServer.new(http_server_bind_address, http_server_bind_port) emit_info "Started HTTP server on #{http_server_bind_address}:"\ "#{http_server_bind_port}" if non_block @http_server_thread = Thread.new do _http_server_loop end else _http_server_loop end end
Stop the HTTP server after it has finished processing the current request.
# File lib/wpxf/net/http_server.rb, line 85 def stop_http_server return false if @is_stopping @is_stopping = true emit_info 'Stopping HTTP server...', true @http_server_kill_switch = true @http_server_thread&.exit @tcp_server.close if !@tcp_server.nil? && !@tcp_server.closed? emit_info 'HTTP server stopped' @is_stopping = false end
Private Instance Methods
# File lib/wpxf/net/http_server.rb, line 159 def _handle_incoming_http_request(socket) request = socket.gets return unless request emit_info "Incoming HTTP request: #{request}", true headers = '' while (line = socket.gets) != "\r\n" headers += line emit_info line, true end headers = Hash[headers.each_line.map { |l| l.chomp.split(': ', 2) }] path = request.gsub(/^[A-Za-z]+\s(.+?)\s.*$/, '\1').chomp params = {} if path.include?('?') params = CGI.parse(path.split('?')[-1]) params.each do |k, v| params[k] = v.join(' ') end path = path.split('?')[0] end # Dispatch parsed data to the callback in the module. on_http_request(path, params, headers) end
# File lib/wpxf/net/http_server.rb, line 135 def _http_server_loop begin loop do socket = @tcp_server.accept begin response = _handle_incoming_http_request(socket) _send_response(response, socket) if response socket.close rescue Errno::EPIPE emit_warning 'A socket was closed by the requester', true end break if @http_server_kill_switch end rescue SignalException emit_warning 'Caught kill signal', true rescue StandardError => e emit_error "Socket error: #{e}" end stop_http_server end
# File lib/wpxf/net/http_server.rb, line 104 def _send_headers(socket, body, content_type, custom_headers) headers = [] headers.push 'HTTP/1.1 200 OK' headers.push "Content-Type: #{content_type}" headers.push "Content-Length: #{body.bytesize}" headers += custom_headers unless custom_headers.nil? headers.push 'Connection: close' headers.each do |header| socket.print "#{header}\r\n" end end
# File lib/wpxf/net/http_server.rb, line 117 def _send_response(response, socket) content_type = 'text/plain' body = '' custom_headers = nil if response.is_a? String body = response else body = response[:body] content_type = response[:type] custom_headers = response[:headers] end _send_headers(socket, body, content_type, custom_headers) socket.print "\r\n" socket.print body end