abstracted the HTTP_HANDLER
to let the user integrate at the level of its choice (either very early so handle itself the header handling, or later to reuse existing code)
This commit is contained in:
@@ -19,14 +19,14 @@ feature {NONE} -- Initialization
|
|||||||
local
|
local
|
||||||
l_server : HTTP_SERVER
|
l_server : HTTP_SERVER
|
||||||
l_cfg: HTTP_SERVER_CONFIGURATION
|
l_cfg: HTTP_SERVER_CONFIGURATION
|
||||||
l_http_handler : HTTP_CONNECTION_HANDLER
|
l_http_handler : HTTP_HANDLER
|
||||||
do
|
do
|
||||||
create l_cfg.make
|
create l_cfg.make
|
||||||
l_cfg.http_server_port := 9_000
|
l_cfg.http_server_port := 9_000
|
||||||
l_cfg.document_root := default_document_root
|
l_cfg.document_root := default_document_root
|
||||||
|
|
||||||
create l_server.make (l_cfg)
|
create l_server.make (l_cfg)
|
||||||
create l_http_handler.make (l_server, "HTTP_HANDLER")
|
create {APPLICATION_CONNECTION_HANDLER} l_http_handler.make (l_server, "HTTP_HANDLER")
|
||||||
l_server.setup (l_http_handler)
|
l_server.setup (l_http_handler)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
57
application_handler.e
Normal file
57
application_handler.e
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {HTTP_CONNECTION_HANDLER}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION_CONNECTION_HANDLER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
HTTP_CONNECTION_HANDLER
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature -- Request processing
|
||||||
|
|
||||||
|
process_request (a_uri: STRING; a_method: STRING; a_headers_map: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
|
||||||
|
-- Process request ...
|
||||||
|
do
|
||||||
|
if a_method.is_equal (Get) then
|
||||||
|
execute_get_request (a_uri, a_headers_map, a_headers_text, a_input, a_output)
|
||||||
|
elseif a_method.is_equal (Post) then
|
||||||
|
execute_post_request (a_uri, a_headers_map, a_headers_text, a_input, a_output)
|
||||||
|
elseif a_method.is_equal (Put) then
|
||||||
|
elseif a_method.is_equal (Options) then
|
||||||
|
elseif a_method.is_equal (Head) then
|
||||||
|
elseif a_method.is_equal (Delete) then
|
||||||
|
elseif a_method.is_equal (Trace) then
|
||||||
|
elseif a_method.is_equal (Connect) then
|
||||||
|
else
|
||||||
|
debug
|
||||||
|
print ("Method [" + a_method + "] not supported")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
execute_get_request (a_uri: STRING; a_headers_map: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
|
||||||
|
local
|
||||||
|
l_http_request : HTTP_REQUEST_HANDLER
|
||||||
|
do
|
||||||
|
create {GET_REQUEST_HANDLER} l_http_request.make (a_input, a_output)
|
||||||
|
l_http_request.set_uri (a_uri)
|
||||||
|
l_http_request.process
|
||||||
|
end
|
||||||
|
|
||||||
|
execute_post_request (a_uri: STRING; a_headers_map: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
|
||||||
|
local
|
||||||
|
l_http_request : HTTP_REQUEST_HANDLER
|
||||||
|
do
|
||||||
|
check not_yet_implemented: False end
|
||||||
|
create {POST_REQUEST_HANDLER} l_http_request.make (a_input, a_output)
|
||||||
|
l_http_request.set_uri (a_uri)
|
||||||
|
l_http_request.process
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
nino: system execution failed.
|
|
||||||
Following is the set of recorded exceptions:
|
|
||||||
|
|
||||||
******************************** Thread exception *****************************
|
|
||||||
In thread Child thread 0x88 (thread id)
|
|
||||||
*******************************************************************************
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Class / Object Routine Nature of exception Effect
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
TCP_STREAM_SOCKET send @1 socket_exists:
|
|
||||||
<00000000024B1A48> (From SOCKET) Precondition violated. Fail
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
GET_REQUEST_HANDLER send_message @4
|
|
||||||
<00000000024B4428> Routine failure. Fail
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
GET_REQUEST_HANDLER execute @2
|
|
||||||
<00000000024B4428> Routine failure. Fail
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
GET_REQUEST_HANDLER thr_main @4
|
|
||||||
<00000000024B4428> (From THREAD) Routine failure. Rescue
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
APPLICATION root's creation
|
|
||||||
<00000000024B05A8> Routine failure. Exit
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
nino: system execution failed.
|
|
||||||
Following is the set of recorded exceptions:
|
|
||||||
|
|
||||||
******************************** Thread exception *****************************
|
|
||||||
In thread Child thread 0x88 (thread id)
|
|
||||||
*******************************************************************************
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Class / Object Routine Nature of exception Effect
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
TCP_STREAM_SOCKET put_string @1 extendible:
|
|
||||||
<0000000002621A48> (From SOCKET) Precondition violated. Fail
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
GET_REQUEST_HANDLER execute @2
|
|
||||||
<0000000002624408> Routine failure. Fail
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
GET_REQUEST_HANDLER thr_main @4
|
|
||||||
<0000000002624408> (From THREAD) Routine failure. Rescue
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
APPLICATION root's creation
|
|
||||||
<00000000026205A8> Routine failure. Exit
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
@@ -20,14 +20,34 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
source: TCP_STREAM_SOCKET
|
source: TCP_STREAM_SOCKET
|
||||||
|
|
||||||
|
feature -- Status Report
|
||||||
|
|
||||||
|
is_readable: BOOLEAN
|
||||||
|
-- Is readable?
|
||||||
|
do
|
||||||
|
Result := source.is_open_read
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Basic operation
|
feature -- Basic operation
|
||||||
|
|
||||||
|
read_line
|
||||||
|
require
|
||||||
|
is_readable: is_readable
|
||||||
|
do
|
||||||
|
last_string.wipe_out
|
||||||
|
if source.socket_ok then
|
||||||
|
source.read_line_thread_aware
|
||||||
|
last_string.append_string (source.last_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
read_stream (nb_char: INTEGER)
|
read_stream (nb_char: INTEGER)
|
||||||
-- Read a string of at most `nb_char' bound characters
|
-- Read a string of at most `nb_char' bound characters
|
||||||
-- or until end of file.
|
-- or until end of file.
|
||||||
-- Make result available in `last_string'.
|
-- Make result available in `last_string'.
|
||||||
require
|
require
|
||||||
nb_char_positive: nb_char > 0
|
nb_char_positive: nb_char > 0
|
||||||
|
is_readable: is_readable
|
||||||
do
|
do
|
||||||
last_string.wipe_out
|
last_string.wipe_out
|
||||||
if source.socket_ok then
|
if source.socket_ok then
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
inherit
|
inherit
|
||||||
HTTP_REQUEST_HANDLER
|
HTTP_REQUEST_HANDLER
|
||||||
|
|
||||||
SHARED_DOCUMENT_ROOT
|
HTTP_SERVER_SHARED_CONFIGURATION
|
||||||
undefine
|
undefine
|
||||||
default_create
|
default_create
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,16 +4,14 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
class
|
deferred class
|
||||||
HTTP_CONNECTION_HANDLER
|
HTTP_CONNECTION_HANDLER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
THREAD
|
HTTP_HANDLER
|
||||||
|
redefine
|
||||||
HTTP_CONSTANTS
|
make
|
||||||
|
end
|
||||||
create
|
|
||||||
make
|
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
@@ -22,70 +20,26 @@ feature {NONE} -- Initialization
|
|||||||
--
|
--
|
||||||
-- `a_main_server': The main server object
|
-- `a_main_server': The main server object
|
||||||
-- `a_name': The name of this module
|
-- `a_name': The name of this module
|
||||||
require
|
|
||||||
a_main_server_attached: a_main_server /= Void
|
|
||||||
a_name_attached: a_name /= Void
|
|
||||||
do
|
do
|
||||||
main_server := a_main_server
|
Precursor (a_main_server, a_name)
|
||||||
create current_request_message.make_empty
|
|
||||||
create method.make_empty
|
create method.make_empty
|
||||||
create uri.make_empty
|
create uri.make_empty
|
||||||
|
create request_header.make_empty
|
||||||
create request_header_map.make (10)
|
create request_header_map.make (10)
|
||||||
is_stop_requested := False
|
|
||||||
ensure
|
|
||||||
main_server_set: a_main_server ~ main_server
|
|
||||||
current_request_message_attached: current_request_message /= Void
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Inherited Features
|
feature -- Execution
|
||||||
|
|
||||||
execute
|
receive_message_and_send_reply (client_socket: TCP_STREAM_SOCKET)
|
||||||
-- <Precursor>
|
|
||||||
-- Creates a socket and connects to the http server.
|
|
||||||
local
|
local
|
||||||
l_http_socket: detachable TCP_STREAM_SOCKET
|
l_input: HTTP_INPUT_STREAM
|
||||||
l_http_port: INTEGER
|
l_output: HTTP_OUTPUT_STREAM
|
||||||
do
|
do
|
||||||
is_stop_requested := False
|
create l_input.make (client_socket)
|
||||||
l_http_port := main_server_configuration.http_server_port
|
create l_output.make (client_socket)
|
||||||
create l_http_socket.make_server_by_port (l_http_port)
|
|
||||||
if not l_http_socket.is_bound then
|
|
||||||
print ("Socket could not be bound on port " + l_http_port.out )
|
|
||||||
else
|
|
||||||
from
|
|
||||||
l_http_socket.listen (main_server_configuration.max_tcp_clients)
|
|
||||||
print ("%NHTTP Connection Server ready on port " + l_http_port.out +"%N")
|
|
||||||
until
|
|
||||||
is_stop_requested
|
|
||||||
loop
|
|
||||||
l_http_socket.accept
|
|
||||||
if not is_stop_requested then
|
|
||||||
if attached l_http_socket.accepted as l_thread_http_socket then
|
|
||||||
receive_message_and_send_replay (l_thread_http_socket)
|
|
||||||
l_thread_http_socket.cleanup
|
|
||||||
check
|
|
||||||
socket_closed: l_thread_http_socket.is_closed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
l_http_socket.cleanup
|
|
||||||
check
|
|
||||||
socket_is_closed: l_http_socket.is_closed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print ("HTTP Connection Server ends.")
|
|
||||||
rescue
|
|
||||||
print ("HTTP Connection Server shutdown due to exception. Please relaunch manually.")
|
|
||||||
|
|
||||||
if attached l_http_socket as ll_http_socket then
|
analyze_request_message (l_input)
|
||||||
ll_http_socket.cleanup
|
process_request (uri, method, request_header_map, request_header, l_input, l_output)
|
||||||
check
|
|
||||||
socket_is_closed: ll_http_socket.is_closed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
is_stop_requested := True
|
|
||||||
retry
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Request processing
|
feature -- Request processing
|
||||||
@@ -98,70 +52,17 @@ feature -- Request processing
|
|||||||
a_headers_text_attached: a_headers_text /= Void
|
a_headers_text_attached: a_headers_text /= Void
|
||||||
a_input_attached: a_input /= Void
|
a_input_attached: a_input /= Void
|
||||||
a_output_attached: a_output /= Void
|
a_output_attached: a_output /= Void
|
||||||
do
|
deferred
|
||||||
if a_method.is_equal (Get) then
|
|
||||||
execute_get_request (a_uri, a_headers_map, a_headers_text, a_input, a_output)
|
|
||||||
elseif a_method.is_equal (Post) then
|
|
||||||
execute_post_request (a_uri, a_headers_map, a_headers_text, a_input, a_output)
|
|
||||||
elseif a_method.is_equal (Put) then
|
|
||||||
elseif a_method.is_equal (Options) then
|
|
||||||
elseif a_method.is_equal (Head) then
|
|
||||||
elseif a_method.is_equal (Delete) then
|
|
||||||
elseif a_method.is_equal (Trace) then
|
|
||||||
elseif a_method.is_equal (Connect) then
|
|
||||||
else
|
|
||||||
debug
|
|
||||||
print ("Method [" + a_method + "] not supported")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
execute_get_request (a_uri: STRING; a_headers_map: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
|
|
||||||
local
|
|
||||||
l_http_request : HTTP_REQUEST_HANDLER
|
|
||||||
do
|
|
||||||
create {GET_REQUEST_HANDLER} l_http_request.make (a_input, a_output)
|
|
||||||
l_http_request.set_uri (a_uri)
|
|
||||||
l_http_request.process
|
|
||||||
-- client_socket.put_string (l_http_request.answer.reply_header + l_http_request.answer.reply_text)
|
|
||||||
end
|
|
||||||
|
|
||||||
execute_post_request (a_uri: STRING; a_headers_map: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM)
|
|
||||||
local
|
|
||||||
l_http_request : HTTP_REQUEST_HANDLER
|
|
||||||
do
|
|
||||||
check not_yet_implemented: False end
|
|
||||||
create {POST_REQUEST_HANDLER} l_http_request.make (a_input, a_output)
|
|
||||||
l_http_request.set_uri (a_uri)
|
|
||||||
l_http_request.process
|
|
||||||
-- client_socket.put_string (l_http_request.answer.reply_header + l_http_request.answer.reply_text)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Access
|
|
||||||
|
|
||||||
is_stop_requested: BOOLEAN
|
|
||||||
-- Set true to stop accept loop
|
|
||||||
|
|
||||||
feature {NONE} -- Access
|
feature {NONE} -- Access
|
||||||
|
|
||||||
|
request_header: STRING
|
||||||
|
-- Header' source
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
main_server: HTTP_SERVER
|
|
||||||
-- The main server object
|
|
||||||
|
|
||||||
main_server_configuration: HTTP_SERVER_CONFIGURATION
|
|
||||||
-- The main server's configuration
|
|
||||||
do
|
|
||||||
Result := main_server.configuration
|
|
||||||
end
|
|
||||||
|
|
||||||
current_request_message: STRING
|
|
||||||
-- Stores the current request message received from http server
|
|
||||||
|
|
||||||
Max_fragments: INTEGER = 1000
|
|
||||||
-- Defines the maximum number of fragments that can be received
|
|
||||||
|
|
||||||
method: STRING
|
method: STRING
|
||||||
-- http verb
|
-- http verb
|
||||||
|
|
||||||
@@ -172,54 +73,7 @@ feature {NONE} -- Access
|
|||||||
-- http_version
|
-- http_version
|
||||||
--| unused for now
|
--| unused for now
|
||||||
|
|
||||||
feature -- Status setting
|
feature -- Parsing
|
||||||
|
|
||||||
shutdown
|
|
||||||
-- Stops the thread
|
|
||||||
do
|
|
||||||
is_stop_requested := True
|
|
||||||
end
|
|
||||||
|
|
||||||
feature {NONE} -- Implementation
|
|
||||||
|
|
||||||
read_string_from_socket (a_socket: TCP_STREAM_SOCKET; a_n: NATURAL): STRING
|
|
||||||
-- Reads characters from the socket and concatenates them to a string
|
|
||||||
--
|
|
||||||
-- `a_socket': The socket to read from
|
|
||||||
-- `a_n': The number of characters to read
|
|
||||||
-- `Result': The created string
|
|
||||||
require
|
|
||||||
socket_is_open: not a_socket.is_closed
|
|
||||||
local
|
|
||||||
l_read_size: INTEGER
|
|
||||||
l_buf: detachable STRING
|
|
||||||
do
|
|
||||||
create Result.make (a_n.as_integer_32)
|
|
||||||
from
|
|
||||||
l_read_size := 0
|
|
||||||
Result := ""
|
|
||||||
l_buf := ""
|
|
||||||
until
|
|
||||||
l_buf.is_equal ("%R")
|
|
||||||
loop
|
|
||||||
a_socket.read_line_thread_aware
|
|
||||||
l_buf := a_socket.last_string
|
|
||||||
if l_buf /= Void then
|
|
||||||
Result.append (l_buf)
|
|
||||||
end
|
|
||||||
if l_buf.is_equal ("%R") then
|
|
||||||
a_socket.set_nodelay
|
|
||||||
a_socket.put_string ("HTTP/1.1 100 Continue%/13/%/10/%/13/%/10/")
|
|
||||||
a_socket.close_socket
|
|
||||||
end
|
|
||||||
|
|
||||||
l_read_size := Result.count
|
|
||||||
end
|
|
||||||
ensure
|
|
||||||
Result_attached: Result /= Void
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- New implementation
|
|
||||||
|
|
||||||
parse_http_request_line (line: STRING)
|
parse_http_request_line (line: STRING)
|
||||||
require
|
require
|
||||||
@@ -237,63 +91,44 @@ feature -- New implementation
|
|||||||
not_void_method: method /= Void
|
not_void_method: method /= Void
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- New Implementation
|
|
||||||
|
|
||||||
receive_message_and_send_replay (client_socket: TCP_STREAM_SOCKET)
|
analyze_request_message (a_input: HTTP_INPUT_STREAM)
|
||||||
require
|
|
||||||
socket_attached: client_socket /= Void
|
|
||||||
-- socket_valid: client_socket.is_open_read and then client_socket.is_open_write
|
|
||||||
a_http_socket:client_socket /= Void and then not client_socket.is_closed
|
|
||||||
local
|
|
||||||
l_headers_text: detachable STRING
|
|
||||||
l_input: HTTP_INPUT_STREAM
|
|
||||||
l_output: HTTP_OUTPUT_STREAM
|
|
||||||
do
|
|
||||||
parse_request_line (client_socket)
|
|
||||||
l_headers_text := receive_message_internal (client_socket)
|
|
||||||
|
|
||||||
create l_input.make (client_socket)
|
|
||||||
create l_output.make (client_socket)
|
|
||||||
process_request (uri, method, request_header_map, l_headers_text, l_input, l_output)
|
|
||||||
end
|
|
||||||
|
|
||||||
parse_request_line (socket: NETWORK_STREAM_SOCKET)
|
|
||||||
require
|
require
|
||||||
socket: socket /= Void and then not socket.is_closed
|
input_redable: a_input /= Void and then not a_input.is_readable
|
||||||
do
|
|
||||||
socket.read_line
|
|
||||||
parse_request_line_internal (socket.last_string)
|
|
||||||
end
|
|
||||||
|
|
||||||
receive_message_internal (socket: TCP_STREAM_SOCKET) : STRING
|
|
||||||
require
|
|
||||||
socket: socket /= Void and then not socket.is_closed
|
|
||||||
local
|
local
|
||||||
end_of_stream : BOOLEAN
|
end_of_stream : BOOLEAN
|
||||||
pos : INTEGER
|
pos : INTEGER
|
||||||
line : STRING
|
line : STRING
|
||||||
|
txt: STRING
|
||||||
do
|
do
|
||||||
|
create txt.make (64)
|
||||||
|
a_input.read_line
|
||||||
|
line := a_input.last_string
|
||||||
|
analyze_request_line (line)
|
||||||
|
txt.append (line)
|
||||||
|
txt.append_character ('%N')
|
||||||
|
|
||||||
|
request_header := txt
|
||||||
from
|
from
|
||||||
socket.read_line_thread_aware
|
a_input.read_line
|
||||||
Result := ""
|
|
||||||
until
|
until
|
||||||
end_of_stream
|
end_of_stream
|
||||||
loop
|
loop
|
||||||
line := socket.last_string
|
line := a_input.last_string
|
||||||
print ("%N" +line+ "%N")
|
print ("%N" +line+ "%N")
|
||||||
pos := line.index_of (':',1)
|
pos := line.index_of (':',1)
|
||||||
request_header_map.put (line.substring (pos + 1, line.count), line.substring (1,pos-1))
|
request_header_map.put (line.substring (pos + 1, line.count), line.substring (1,pos-1))
|
||||||
Result.append (line)
|
txt.append (line)
|
||||||
Result.append_character ('%N')
|
txt.append_character ('%N')
|
||||||
if not line.is_equal("%R") and socket.socket_ok then
|
if line.is_empty or else line[1] = '%R' then
|
||||||
socket.read_line_thread_aware
|
|
||||||
else
|
|
||||||
end_of_stream := True
|
end_of_stream := True
|
||||||
end
|
else
|
||||||
|
a_input.read_line
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
parse_request_line_internal (line: STRING)
|
analyze_request_line (line: STRING)
|
||||||
require
|
require
|
||||||
line /= Void
|
line /= Void
|
||||||
local
|
local
|
||||||
@@ -310,7 +145,6 @@ feature -- New Implementation
|
|||||||
end
|
end
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
main_server_attached: main_server /= Void
|
request_header_attached: request_header /= Void
|
||||||
current_request_message_attached: current_request_message /= Void
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
123
server/http_handler.e
Normal file
123
server/http_handler.e
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {HTTP_CONNECTION_HANDLER}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
HTTP_HANDLER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
THREAD
|
||||||
|
|
||||||
|
HTTP_CONSTANTS
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_main_server: like main_server; a_name: STRING)
|
||||||
|
-- Creates a {HTTP_HANDLER}, assigns the main_server and initialize various values
|
||||||
|
--
|
||||||
|
-- `a_main_server': The main server object
|
||||||
|
-- `a_name': The name of this module
|
||||||
|
require
|
||||||
|
a_main_server_attached: a_main_server /= Void
|
||||||
|
a_name_attached: a_name /= Void
|
||||||
|
do
|
||||||
|
main_server := a_main_server
|
||||||
|
is_stop_requested := False
|
||||||
|
ensure
|
||||||
|
main_server_set: a_main_server ~ main_server
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Inherited Features
|
||||||
|
|
||||||
|
execute
|
||||||
|
-- <Precursor>
|
||||||
|
-- Creates a socket and connects to the http server.
|
||||||
|
local
|
||||||
|
l_http_socket: detachable TCP_STREAM_SOCKET
|
||||||
|
l_http_port: INTEGER
|
||||||
|
do
|
||||||
|
is_stop_requested := False
|
||||||
|
l_http_port := main_server_configuration.http_server_port
|
||||||
|
create l_http_socket.make_server_by_port (l_http_port)
|
||||||
|
if not l_http_socket.is_bound then
|
||||||
|
print ("Socket could not be bound on port " + l_http_port.out )
|
||||||
|
else
|
||||||
|
from
|
||||||
|
l_http_socket.listen (main_server_configuration.max_tcp_clients)
|
||||||
|
print ("%NHTTP Connection Server ready on port " + l_http_port.out +"%N")
|
||||||
|
until
|
||||||
|
is_stop_requested
|
||||||
|
loop
|
||||||
|
l_http_socket.accept
|
||||||
|
if not is_stop_requested then
|
||||||
|
if attached l_http_socket.accepted as l_thread_http_socket then
|
||||||
|
receive_message_and_send_reply (l_thread_http_socket)
|
||||||
|
l_thread_http_socket.cleanup
|
||||||
|
check
|
||||||
|
socket_closed: l_thread_http_socket.is_closed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
l_http_socket.cleanup
|
||||||
|
check
|
||||||
|
socket_is_closed: l_http_socket.is_closed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print ("HTTP Connection Server ends.")
|
||||||
|
rescue
|
||||||
|
print ("HTTP Connection Server shutdown due to exception. Please relaunch manually.")
|
||||||
|
|
||||||
|
if attached l_http_socket as ll_http_socket then
|
||||||
|
ll_http_socket.cleanup
|
||||||
|
check
|
||||||
|
socket_is_closed: ll_http_socket.is_closed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
is_stop_requested := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
is_stop_requested: BOOLEAN
|
||||||
|
-- Set true to stop accept loop
|
||||||
|
|
||||||
|
feature {NONE} -- Access
|
||||||
|
|
||||||
|
main_server: HTTP_SERVER
|
||||||
|
-- The main server object
|
||||||
|
|
||||||
|
main_server_configuration: HTTP_SERVER_CONFIGURATION
|
||||||
|
-- The main server's configuration
|
||||||
|
do
|
||||||
|
Result := main_server.configuration
|
||||||
|
end
|
||||||
|
|
||||||
|
Max_fragments: INTEGER = 1000
|
||||||
|
-- Defines the maximum number of fragments that can be received
|
||||||
|
|
||||||
|
feature -- Status setting
|
||||||
|
|
||||||
|
shutdown
|
||||||
|
-- Stops the thread
|
||||||
|
do
|
||||||
|
is_stop_requested := True
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Execution
|
||||||
|
|
||||||
|
receive_message_and_send_reply (client_socket: TCP_STREAM_SOCKET)
|
||||||
|
require
|
||||||
|
socket_attached: client_socket /= Void
|
||||||
|
-- socket_valid: client_socket.is_open_read and then client_socket.is_open_write
|
||||||
|
a_http_socket:client_socket /= Void and then not client_socket.is_closed
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
invariant
|
||||||
|
main_server_attached: main_server /= Void
|
||||||
|
|
||||||
|
end
|
||||||
@@ -70,7 +70,7 @@ feature -- Implementation
|
|||||||
done
|
done
|
||||||
loop
|
loop
|
||||||
if socket.socket_ok then
|
if socket.socket_ok then
|
||||||
done := receive_message_and_send_replay (socket)
|
done := receive_message_and_send_reply (socket)
|
||||||
request_header_map.wipe_out
|
request_header_map.wipe_out
|
||||||
else
|
else
|
||||||
done := True
|
done := True
|
||||||
@@ -80,7 +80,7 @@ feature -- Implementation
|
|||||||
io.put_new_line
|
io.put_new_line
|
||||||
end
|
end
|
||||||
|
|
||||||
receive_message_and_send_replay (client_socket: NETWORK_STREAM_SOCKET): BOOLEAN
|
receive_message_and_send_reply (client_socket: NETWORK_STREAM_SOCKET): BOOLEAN
|
||||||
require
|
require
|
||||||
socket_attached: client_socket /= Void
|
socket_attached: client_socket /= Void
|
||||||
socket_valid: client_socket.is_open_read and then client_socket.is_open_write
|
socket_valid: client_socket.is_open_read and then client_socket.is_open_write
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class
|
|||||||
HTTP_SERVER
|
HTTP_SERVER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
SHARED_DOCUMENT_ROOT
|
HTTP_SERVER_SHARED_CONFIGURATION
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
@@ -20,7 +20,7 @@ feature -- Initialization
|
|||||||
configuration := cfg
|
configuration := cfg
|
||||||
end
|
end
|
||||||
|
|
||||||
setup (a_http_handler : HTTP_CONNECTION_HANDLER)
|
setup (a_http_handler : HTTP_HANDLER)
|
||||||
require
|
require
|
||||||
a_http_handler_valid: a_http_handler /= Void
|
a_http_handler_valid: a_http_handler /= Void
|
||||||
do
|
do
|
||||||
@@ -29,7 +29,7 @@ feature -- Initialization
|
|||||||
stop_requested := False
|
stop_requested := False
|
||||||
set_server_configuration (configuration)
|
set_server_configuration (configuration)
|
||||||
a_http_handler.launch
|
a_http_handler.launch
|
||||||
run
|
a_http_handler.join
|
||||||
end
|
end
|
||||||
|
|
||||||
shutdown_server
|
shutdown_server
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
note
|
|
||||||
description: "Summary description for {SHARED_DOCUMENT_ROOT}."
|
|
||||||
author: ""
|
|
||||||
date: "$Date$"
|
|
||||||
revision: "$Revision$"
|
|
||||||
|
|
||||||
class
|
|
||||||
SHARED_DOCUMENT_ROOT
|
|
||||||
|
|
||||||
obsolete "Use HTTP_SERVER_SHARED_CONFIGURATION"
|
|
||||||
|
|
||||||
inherit
|
|
||||||
HTTP_SERVER_SHARED_CONFIGURATION
|
|
||||||
|
|
||||||
end
|
|
||||||
Reference in New Issue
Block a user