Class: Yarn::AbstractHandler
- Inherits:
-
Object
- Object
- Yarn::AbstractHandler
- Defined in:
- lib/yarn/abstract_handler.rb
Overview
Base class for the handler classes. Built using the Template Method design pattern.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#parser ⇒ Object
Returns the value of attribute parser.
-
#request ⇒ Object
Returns the value of attribute request.
-
#response ⇒ Object
Returns the value of attribute response.
-
#session ⇒ Object
Returns the value of attribute session.
Instance Method Summary collapse
-
#client_address ⇒ Object
Proxy for the clients address.
-
#extract_path ⇒ Object
Extracts the path from the parsed request.
-
#initialize ⇒ AbstractHandler
constructor
A new instance of AbstractHandler.
-
#parse_request ⇒ Object
Invokes the parser upon the request.
-
#post_body ⇒ Object
Proxy to getting the request body.
-
#prepare_response ⇒ Object
Only implemented in the actual handler classes.
-
#read_request ⇒ Object
Reads the request from the socket.
-
#request_path ⇒ Object
Proxy for getting the request path.
-
#return_response ⇒ Object
returns the reqponse by writing it to the socket.
-
#run(session) ⇒ Object
The template method which drives the handlers.
-
#set_common_headers ⇒ Object
Sets common headers like server name and date.
Methods included from ErrorPage
#serve_404_page, #serve_500_page
Methods included from Logging
#debug, #log, #output, #timestamp
Constructor Details
#initialize ⇒ AbstractHandler
Returns a new instance of AbstractHandler.
21 22 23 24 |
# File 'lib/yarn/abstract_handler.rb', line 21 def initialize @parser = Parser.new @response = Response.new end |
Instance Attribute Details
#parser ⇒ Object
Returns the value of attribute parser.
19 20 21 |
# File 'lib/yarn/abstract_handler.rb', line 19 def parser @parser end |
#request ⇒ Object
Returns the value of attribute request.
19 20 21 |
# File 'lib/yarn/abstract_handler.rb', line 19 def request @request end |
#response ⇒ Object
Returns the value of attribute response.
19 20 21 |
# File 'lib/yarn/abstract_handler.rb', line 19 def response @response end |
#session ⇒ Object
Returns the value of attribute session.
19 20 21 |
# File 'lib/yarn/abstract_handler.rb', line 19 def session @session end |
Instance Method Details
#client_address ⇒ Object
Proxy for the clients address.
131 132 133 134 135 136 137 |
# File 'lib/yarn/abstract_handler.rb', line 131 def client_address begin @session.peeraddr(:numeric)[2] if @session rescue Errno::ENOTCONN return "" end end |
#extract_path ⇒ Object
Extracts the path from the parsed request
112 113 114 115 116 117 118 |
# File 'lib/yarn/abstract_handler.rb', line 112 def extract_path path = @request[:uri][:path].to_s if path[0] == "/" && path != "/" path = path[1..-1] end path.gsub(/%20/, " ").strip end |
#parse_request ⇒ Object
Invokes the parser upon the request
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/yarn/abstract_handler.rb', line 49 def parse_request raw_request = read_request raise EmptyRequestError if raw_request.empty? begin @request = @parser.run raw_request rescue Parslet::ParseFailed => e @response.status = 400 debug "Parse failed: #{@request}" end end |
#post_body ⇒ Object
Proxy to getting the request body.
121 122 123 |
# File 'lib/yarn/abstract_handler.rb', line 121 def post_body @request ? @request[:body].to_s : "" end |
#prepare_response ⇒ Object
Only implemented in the actual handler classes.
62 63 |
# File 'lib/yarn/abstract_handler.rb', line 62 def prepare_response end |
#read_request ⇒ Object
Reads the request from the socket. If a Content-Length header is given, that means there is an accompanying request body. The body is read according to the set Content-Length.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/yarn/abstract_handler.rb', line 83 def read_request input = [] while (line = @session.gets) do length = line.gsub(/\D/,"") if line =~ /Content-Length/ if line == "\r\n" input << line input << @session.read(length.to_i) if length break else input << line end end debug "Done reading request" input.join end |
#request_path ⇒ Object
Proxy for getting the request path.
126 127 128 |
# File 'lib/yarn/abstract_handler.rb', line 126 def request_path @request[:uri][:path] if @request end |
#return_response ⇒ Object
returns the reqponse by writing it to the socket.
66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/yarn/abstract_handler.rb', line 66 def return_response begin @session.puts "HTTP/1.1 #{@response.status} #{STATUS_CODES[@response.status]}" @session.puts @response.headers.map { |k,v| "#{k}: #{v}" } @session.puts "" @response.body.each do |line| @session.puts line end rescue Exception => exception log "An error occured returning the response to the client" end end |
#run(session) ⇒ Object
The template method which drives the handlers. Starts by setting common headers and parses the request, prepares the response, returns it to the client, and closes the connection.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/yarn/abstract_handler.rb', line 30 def run(session) set_common_headers @session = session begin parse_request debug "Request parsed, path: #{request_path}" prepare_response debug "Response prepared: #{@response.status}" return_response log "#{STATUS_CODES[@response.status]} #{client_address} #{request_path}" rescue EmptyRequestError log "Empty request from #{client_address}" ensure @session.close debug "Connection closed" end end |
#set_common_headers ⇒ Object
Sets common headers like server name and date.
101 102 103 104 105 106 107 108 109 |
# File 'lib/yarn/abstract_handler.rb', line 101 def set_common_headers @response.headers[:Server] = "Yarn webserver v#{VERSION}" # HTTP date format: Fri, 31 Dec 1999 23:59:59 GMT time ||= DateTime.now.new_offset(0) @response.headers[:Date] = time.strftime("%a, %d %b %Y %H:%M:%S GMT") # Close connection header ( until support for persistent connections ) @response.headers[:Connection] = "Close" end |