Handling bad incoming request (keep a check assertion to help during debugging period)
This commit is contained in:
@@ -26,6 +26,7 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
reset
|
reset
|
||||||
do
|
do
|
||||||
|
has_error := False
|
||||||
create method.make_empty
|
create method.make_empty
|
||||||
create uri.make_empty
|
create uri.make_empty
|
||||||
create request_header.make_empty
|
create request_header.make_empty
|
||||||
@@ -48,7 +49,14 @@ feature -- Execution
|
|||||||
end
|
end
|
||||||
|
|
||||||
analyze_request_message (client_socket)
|
analyze_request_message (client_socket)
|
||||||
process_request (Current, client_socket)
|
if has_error then
|
||||||
|
check catch_bad_incoming_connection: False end
|
||||||
|
if is_verbose then
|
||||||
|
log ("ERROR: invalid HTTP incoming request")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
process_request (Current, client_socket)
|
||||||
|
end
|
||||||
reset
|
reset
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -57,6 +65,7 @@ feature -- Request processing
|
|||||||
process_request (a_handler: HTTP_CONNECTION_HANDLER; a_socket: TCP_STREAM_SOCKET)
|
process_request (a_handler: HTTP_CONNECTION_HANDLER; a_socket: TCP_STREAM_SOCKET)
|
||||||
-- Process request ...
|
-- Process request ...
|
||||||
require
|
require
|
||||||
|
no_error: not has_error
|
||||||
a_handler_attached: a_handler /= Void
|
a_handler_attached: a_handler /= Void
|
||||||
a_uri_attached: a_handler.uri /= Void
|
a_uri_attached: a_handler.uri /= Void
|
||||||
a_method_attached: a_handler.method /= Void
|
a_method_attached: a_handler.method /= Void
|
||||||
@@ -74,6 +83,9 @@ feature -- Access
|
|||||||
request_header_map : HASH_TABLE [STRING,STRING]
|
request_header_map : HASH_TABLE [STRING,STRING]
|
||||||
-- Contains key:value of the header
|
-- Contains key:value of the header
|
||||||
|
|
||||||
|
has_error: BOOLEAN
|
||||||
|
-- Error occurred during `analyze_request_message'
|
||||||
|
|
||||||
method: STRING
|
method: STRING
|
||||||
-- http verb
|
-- http verb
|
||||||
|
|
||||||
@@ -85,10 +97,12 @@ feature -- Access
|
|||||||
--| unused for now
|
--| unused for now
|
||||||
|
|
||||||
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
|
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
|
||||||
|
-- Information related to remote client
|
||||||
|
|
||||||
feature -- Parsing
|
feature -- Parsing
|
||||||
|
|
||||||
analyze_request_message (a_socket: TCP_STREAM_SOCKET)
|
analyze_request_message (a_socket: TCP_STREAM_SOCKET)
|
||||||
|
-- Analyze message extracted from `a_socket' as HTTP request
|
||||||
require
|
require
|
||||||
input_readable: a_socket /= Void and then a_socket.is_open_read
|
input_readable: a_socket /= Void and then a_socket.is_open_read
|
||||||
local
|
local
|
||||||
@@ -97,23 +111,31 @@ feature -- Parsing
|
|||||||
line : detachable STRING
|
line : detachable STRING
|
||||||
k, val: STRING
|
k, val: STRING
|
||||||
txt: STRING
|
txt: STRING
|
||||||
|
l_is_verbose: BOOLEAN
|
||||||
do
|
do
|
||||||
create txt.make (64)
|
create txt.make (64)
|
||||||
line := next_line (a_socket)
|
request_header := txt
|
||||||
if line /= Void then
|
|
||||||
analyze_request_line (line)
|
|
||||||
txt.append (line)
|
|
||||||
txt.append_character ('%N')
|
|
||||||
|
|
||||||
request_header := txt
|
if attached next_line (a_socket) as l_request_line and then not l_request_line.is_empty then
|
||||||
|
txt.append (l_request_line)
|
||||||
|
txt.append_character ('%N')
|
||||||
|
analyze_request_line (l_request_line)
|
||||||
|
else
|
||||||
|
has_error := True
|
||||||
|
end
|
||||||
|
|
||||||
|
l_is_verbose := is_verbose
|
||||||
|
|
||||||
|
if not has_error or l_is_verbose then
|
||||||
|
-- if `is_verbose' we can try to print the request, even if it is a bad HTTP request
|
||||||
from
|
from
|
||||||
line := next_line (a_socket)
|
line := next_line (a_socket)
|
||||||
until
|
until
|
||||||
line = Void or end_of_stream
|
line = Void or end_of_stream
|
||||||
loop
|
loop
|
||||||
n := line.count
|
n := line.count
|
||||||
if is_verbose then
|
if l_is_verbose then
|
||||||
print ("%N" + line)
|
log (line)
|
||||||
end
|
end
|
||||||
pos := line.index_of (':',1)
|
pos := line.index_of (':',1)
|
||||||
if pos > 0 then
|
if pos > 0 then
|
||||||
@@ -139,26 +161,26 @@ feature -- Parsing
|
|||||||
end
|
end
|
||||||
|
|
||||||
analyze_request_line (line: STRING)
|
analyze_request_line (line: STRING)
|
||||||
|
-- Analyze `line' as a HTTP request line
|
||||||
require
|
require
|
||||||
line /= Void
|
valid_line: line /= Void and then not line.is_empty
|
||||||
local
|
local
|
||||||
pos, next_pos: INTEGER
|
pos, next_pos: INTEGER
|
||||||
do
|
do
|
||||||
if is_verbose then
|
if is_verbose then
|
||||||
print ("%N## Parse HTTP request line ##")
|
log ("%N## Parse HTTP request line ##")
|
||||||
print ("%N")
|
log (line)
|
||||||
print (line)
|
|
||||||
end
|
end
|
||||||
pos := line.index_of (' ', 1)
|
pos := line.index_of (' ', 1)
|
||||||
method := line.substring (1, pos - 1)
|
method := line.substring (1, pos - 1)
|
||||||
next_pos := line.index_of (' ', pos + 1)
|
next_pos := line.index_of (' ', pos + 1)
|
||||||
uri := line.substring (pos + 1, next_pos - 1)
|
uri := line.substring (pos + 1, next_pos - 1)
|
||||||
version := line.substring (next_pos + 1, line.count)
|
version := line.substring (next_pos + 1, line.count)
|
||||||
ensure
|
has_error := method.is_empty
|
||||||
not_void_method: method /= Void
|
|
||||||
end
|
end
|
||||||
|
|
||||||
next_line (a_socket: TCP_STREAM_SOCKET): detachable STRING
|
next_line (a_socket: TCP_STREAM_SOCKET): detachable STRING
|
||||||
|
-- Next line fetched from `a_socket' is available.
|
||||||
require
|
require
|
||||||
is_readable: a_socket.is_open_read
|
is_readable: a_socket.is_open_read
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ feature -- Output
|
|||||||
-- Log `a_message'
|
-- Log `a_message'
|
||||||
do
|
do
|
||||||
io.put_string (a_message)
|
io.put_string (a_message)
|
||||||
|
io.put_new_line
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Inherited Features
|
feature -- Inherited Features
|
||||||
@@ -50,14 +51,14 @@ feature -- Inherited Features
|
|||||||
create l_listening_socket.make_server_by_port (l_http_port)
|
create l_listening_socket.make_server_by_port (l_http_port)
|
||||||
if not l_listening_socket.is_bound then
|
if not l_listening_socket.is_bound then
|
||||||
if is_verbose then
|
if is_verbose then
|
||||||
log ("Socket could not be bound on port " + l_http_port.out )
|
log ("Socket could not be bound on port " + l_http_port.out)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
l_http_port := l_listening_socket.port
|
l_http_port := l_listening_socket.port
|
||||||
from
|
from
|
||||||
l_listening_socket.listen (max_tcp_clients)
|
l_listening_socket.listen (max_tcp_clients)
|
||||||
if is_verbose then
|
if is_verbose then
|
||||||
log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/%N")
|
log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/")
|
||||||
end
|
end
|
||||||
on_launched (l_http_port)
|
on_launched (l_http_port)
|
||||||
until
|
until
|
||||||
@@ -102,12 +103,15 @@ feature -- Inherited Features
|
|||||||
-- Process incoming connection
|
-- Process incoming connection
|
||||||
do
|
do
|
||||||
if is_verbose then
|
if is_verbose then
|
||||||
log ("Incoming connection...%N")
|
log ("Incoming connection...(socket:" + a_socket.descriptor.out + ")")
|
||||||
end
|
end
|
||||||
--| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection
|
--| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection
|
||||||
--| also handle permanent connection...?
|
--| also handle permanent connection...?
|
||||||
receive_message_and_send_reply (a_socket)
|
receive_message_and_send_reply (a_socket)
|
||||||
a_socket.cleanup
|
a_socket.cleanup
|
||||||
|
if is_verbose then
|
||||||
|
log ("connection completed...")
|
||||||
|
end
|
||||||
ensure
|
ensure
|
||||||
socket_closed: a_socket.is_closed
|
socket_closed: a_socket.is_closed
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ feature -- Initialization
|
|||||||
a_http_handler_valid: a_http_handler /= Void
|
a_http_handler_valid: a_http_handler /= Void
|
||||||
do
|
do
|
||||||
if configuration.is_verbose then
|
if configuration.is_verbose then
|
||||||
print("%N%N%N")
|
log ("%N%N%N")
|
||||||
print ("Starting Web Application Server (port="+ configuration.http_server_port.out +"):%N")
|
log ("Starting Web Application Server (port="+ configuration.http_server_port.out +"):%N")
|
||||||
end
|
end
|
||||||
stop_requested := False
|
stop_requested := False
|
||||||
a_http_handler.execute
|
a_http_handler.execute
|
||||||
@@ -42,6 +42,14 @@ feature -- Access
|
|||||||
stop_requested: BOOLEAN
|
stop_requested: BOOLEAN
|
||||||
-- Stops the server
|
-- Stops the server
|
||||||
|
|
||||||
|
feature -- Output
|
||||||
|
|
||||||
|
log (a_message: READABLE_STRING_8)
|
||||||
|
-- Log `a_message'
|
||||||
|
do
|
||||||
|
io.put_string (a_message)
|
||||||
|
end
|
||||||
|
|
||||||
;note
|
;note
|
||||||
copyright: "2011-2011, Javier Velilla and others"
|
copyright: "2011-2011, Javier Velilla and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
|||||||
Reference in New Issue
Block a user