From 64cf2b69365f1e83115739897f5de78a397d60af Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Thu, 26 May 2011 17:23:21 +0200 Subject: [PATCH 1/9] A few change to make it more customizable and prepare integration to EiffelWebReloaded (see on github) --- application.e | 15 +- configuration/http_server_configuration.e | 60 ++++++++ .../http_server_shared_configuration.e | 45 ++++++ http_server.e | 56 -------- io/http_input_stream.e | 44 ++++++ io/http_output_stream.e | 31 +++++ nino.ecf | 24 ++-- request/get_request_handler.e | 74 +++++++--- request/head_request_handler.e | 8 +- request/http_request_handler.e | 106 ++++++++++++--- request/post_request_handler.e | 113 +++------------- response/http_response.e | 78 +++++++---- .../http_connection_handler.e | 128 ++++++++++++------ http_constants.e => server/http_constants.e | 7 - .../http_encoding_facilities.e | 0 .../http_protocol_handler.e | 0 server/http_server.e | 61 +++++++++ .../shared_document_root.e | 9 +- .../shared_http_request_handlers.e | 2 +- .../shared_uri_contents_types.e | 0 .../tcp_stream_socket.e | 8 +- .../uri_contents_types.e | 0 webroot/post/index.html | 19 +++ 23 files changed, 590 insertions(+), 298 deletions(-) create mode 100644 configuration/http_server_configuration.e create mode 100644 configuration/http_server_shared_configuration.e delete mode 100644 http_server.e create mode 100644 io/http_input_stream.e create mode 100644 io/http_output_stream.e rename http_connection_handler.e => server/http_connection_handler.e (63%) rename http_constants.e => server/http_constants.e (92%) rename http_encoding_facilities.e => server/http_encoding_facilities.e (100%) rename http_protocol_handler.e => server/http_protocol_handler.e (100%) create mode 100644 server/http_server.e rename shared_document_root.e => server/shared_document_root.e (58%) rename shared_http_request_handlers.e => server/shared_http_request_handlers.e (93%) rename shared_uri_contents_types.e => server/shared_uri_contents_types.e (100%) rename tcp_stream_socket.e => server/tcp_stream_socket.e (86%) rename uri_contents_types.e => server/uri_contents_types.e (100%) create mode 100644 webroot/post/index.html diff --git a/application.e b/application.e index ab05454b..6c206526 100644 --- a/application.e +++ b/application.e @@ -18,9 +18,20 @@ feature {NONE} -- Initialization -- Run application. local l_server : HTTP_SERVER + l_cfg: HTTP_SERVER_CONFIGURATION + l_http_handler : HTTP_CONNECTION_HANDLER do - create l_server.make - l_server.setup + create l_cfg.make + l_cfg.http_server_port := 9_000 + l_cfg.document_root := default_document_root + + create l_server.make (l_cfg) + create l_http_handler.make (l_server, "HTTP_HANDLER") + l_server.setup (l_http_handler) end +feature -- Access + + default_document_root: STRING = "webroot" + end diff --git a/configuration/http_server_configuration.e b/configuration/http_server_configuration.e new file mode 100644 index 00000000..9c21ecf2 --- /dev/null +++ b/configuration/http_server_configuration.e @@ -0,0 +1,60 @@ +note + description: "Summary description for {HTTP_SERVER_CONFIGURATION}." + date: "$Date$" + revision: "$Revision$" + +class + HTTP_SERVER_CONFIGURATION + +create + make + +feature {NONE} -- Initialization + + make + do + http_server_port := 9_000 + max_tcp_clients := 100 + socket_accept_timeout := 1_000 + socket_connect_timeout := 5_000 + document_root := "htdocs" + end + +feature -- Access + + Server_details : STRING = "Server : NANO Eiffel Server" + + document_root: STRING assign set_document_root + http_server_port: INTEGER assign set_http_server_port + max_tcp_clients: INTEGER assign set_max_tcp_clients + socket_accept_timeout: INTEGER assign set_socket_accept_timeout + socket_connect_timeout: INTEGER assign set_socket_connect_timeout + +feature -- Element change + + set_http_server_port (v: like http_server_port) + do + http_server_port := v + end + + set_document_root (v: like document_root) + do + document_root := v + end + + set_max_tcp_clients (v: like max_tcp_clients) + do + max_tcp_clients := v + end + + set_socket_accept_timeout (v: like socket_accept_timeout) + do + socket_accept_timeout := v + end + + set_socket_connect_timeout (v: like socket_connect_timeout) + do + socket_connect_timeout := v + end + +end diff --git a/configuration/http_server_shared_configuration.e b/configuration/http_server_shared_configuration.e new file mode 100644 index 00000000..e5cc62ec --- /dev/null +++ b/configuration/http_server_shared_configuration.e @@ -0,0 +1,45 @@ +note + description: "Summary description for {HTTP_SERVER_SHARED_CONFIGURATION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTP_SERVER_SHARED_CONFIGURATION + +feature -- Access + + server_configuration: detachable HTTP_SERVER_CONFIGURATION + -- Shared configuration + do + if attached server_configuration_cell.item as l_cfg then + Result := l_cfg + end + end + + document_root: STRING_8 + -- Shared document root + do + if attached server_configuration as l_cfg then + Result := l_cfg.document_root + else + Result := "" + end + end + +feature -- Element change + + set_server_configuration (a_cfg: like server_configuration) + -- Set `server_configuration' to `a_cfg'. + do + server_configuration_cell.replace (a_cfg) + end + +feature {NONE} -- Implementation + + server_configuration_cell: CELL [detachable HTTP_SERVER_CONFIGURATION] + once ("PROCESS") + create Result.put (Void) + end + +end diff --git a/http_server.e b/http_server.e deleted file mode 100644 index e6e73edf..00000000 --- a/http_server.e +++ /dev/null @@ -1,56 +0,0 @@ -note - description: "Summary description for {HTTP_SERVER}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - HTTP_SERVER -inherit - SHARED_DOCUMENT_ROOT -create - make -feature -- Initialization - make - do - - end - - setup - local - l_http_handler : HTTP_CONNECTION_HANDLER - do - print("%N%N%N") - print ("Starting Web Application Server:%N") - stop := False - document_root_cell.put (document_root) - create l_http_handler.make (current,"HTTP_HANDLER") - l_http_handler.launch - run - end - - shutdown_server - do - stop := True - end - -feature -- Access - stop: BOOLEAN - -- Stops the server - - document_root: STRING = "./webroot" - -feature {NONE} -- implementation - - run - -- Start the server - local - l_thread: EXECUTION_ENVIRONMENT - do - create l_thread - from until stop loop - l_thread.sleep (1000000) - end - - end -end diff --git a/io/http_input_stream.e b/io/http_input_stream.e new file mode 100644 index 00000000..bd85fafd --- /dev/null +++ b/io/http_input_stream.e @@ -0,0 +1,44 @@ +note + description: "Summary description for {HTTP_INPUT_STREAM}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTP_INPUT_STREAM + +create + make + +feature {NONE} -- Initialization + + make (a_socket: like source) + do + source := a_socket + create last_string.make_empty + end + + source: TCP_STREAM_SOCKET + +feature -- Basic operation + + read_stream (nb_char: INTEGER) + -- Read a string of at most `nb_char' bound characters + -- or until end of file. + -- Make result available in `last_string'. + require + nb_char_positive: nb_char > 0 + do + last_string.wipe_out + if source.socket_ok then + source.read_stream_thread_aware (nb_char) + last_string.append_string (source.last_string) + end + end + +feature -- Access + + last_string: STRING + -- Last string read + +end diff --git a/io/http_output_stream.e b/io/http_output_stream.e new file mode 100644 index 00000000..a3d37a6f --- /dev/null +++ b/io/http_output_stream.e @@ -0,0 +1,31 @@ +note + description: "Summary description for {HTTP_OUTPUT_STREAM}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTP_OUTPUT_STREAM + +create + make + +feature {NONE} -- Initialization + + make (a_socket: like target) + do + target := a_socket + end + + target: TCP_STREAM_SOCKET + +feature -- Basic operation + + put_string (s: STRING) + -- Write string `s' to `target' + do + target.put_string (s) + end + + +end diff --git a/nino.ecf b/nino.ecf index 5170547d..5f07f73c 100644 --- a/nino.ecf +++ b/nino.ecf @@ -1,20 +1,20 @@ - + - - diff --git a/request/get_request_handler.e b/request/get_request_handler.e index bf1b1f2d..2aa269d9 100644 --- a/request/get_request_handler.e +++ b/request/get_request_handler.e @@ -2,40 +2,63 @@ GET_REQUEST_HANDLER inherit - SHARED_DOCUMENT_ROOT - - SHARED_URI_CONTENTS_TYPES - HTTP_REQUEST_HANDLER + SHARED_DOCUMENT_ROOT + undefine + default_create + end + + SHARED_URI_CONTENTS_TYPES + undefine + default_create + end + HTTP_CONSTANTS + undefine + default_create + end create - default_create + make -feature +feature {NONE} -- Initialization + + make (a_input: like input; a_output: like output) + do + default_create + input := a_input + output := a_output + end + +feature -- Access + + input: HTTP_INPUT_STREAM + + output: HTTP_OUTPUT_STREAM + +feature -- Execution process -- process the request and create an answer local fname: STRING_8 f: RAW_FILE - ctype, extension: STRING_8 + ctype, extension: detachable STRING_8 do - create answer.make - if request_uri.is_equal ("/") then + answer.reset + if script_name.is_equal ("/") then process_default answer.set_content_type ("text/html") else - fname := Document_root_cell.item.twin - fname.append (request_uri) + create fname.make_from_string (Document_root) + fname.append (script_name) debug - print ("URI name: " + fname) + print ("URI filename: " + fname) end - create f.make (fname) - create answer.make + create f.make (real_filename (fname)) if f.exists then - extension := Ct_table.extension (request_uri) + extension := Ct_table.extension (script_name) ctype := Ct_table.content_types.item (extension) if f.is_directory then process_directory (f) @@ -58,11 +81,18 @@ feature answer.set_reply_text ("Not found on this server") end end - answer.set_content_length (answer.reply_text.count.out) + if attached answer.reply_text as t then + answer.set_content_length (t.count) + else + answer.set_content_length (0) + end + + --| Output the result + output.put_string (answer.reply_header + answer.reply_text) end process_default - -- Return a defaul response + -- Return a default response local html: STRING_8 do @@ -118,14 +148,14 @@ feature html2: STRING_8 htmldir: STRING_8 path: STRING_8 - index: INTEGER_32 do answer.set_reply_text ("") html1 := " NINO HTTPD " + " " + " " + "

Welcome to NINO HTTPD!

" + "

Default page " html2 := "

" + " " + " " - path := f.name.twin - index := path.last_index_of ('/', path.count) - path.remove_substring (1, index) + path := script_name + if path[path.count] = '/' then + path.remove_tail (1) + end create l_dir.make_open_read (f.name) files := l_dir.linear_representation from @@ -134,7 +164,7 @@ feature until files.after loop - htmldir := htmldir + "
  • " + files.item_for_iteration + "
  • %N" + htmldir := htmldir + "
  • " + files.item_for_iteration + "
  • %N" files.forth end htmldir := htmldir + "" diff --git a/request/head_request_handler.e b/request/head_request_handler.e index 748b9799..bf0cdd54 100644 --- a/request/head_request_handler.e +++ b/request/head_request_handler.e @@ -20,7 +20,7 @@ inherit feature - process is + process -- process the request and create an answer local fname: STRING @@ -57,7 +57,7 @@ feature end end - process_default is + process_default -- local html : STRING @@ -76,7 +76,7 @@ feature end - process_text_file (f: FILE) is + process_text_file (f: FILE) -- send a text file reply require valid_f: f /= Void @@ -94,7 +94,7 @@ feature f.close end - process_raw_file (f: FILE) is + process_raw_file (f: FILE) -- send a raw file reply require valid_f: f /= Void diff --git a/request/http_request_handler.e b/request/http_request_handler.e index 6d174a9f..0043ff0d 100644 --- a/request/http_request_handler.e +++ b/request/http_request_handler.e @@ -1,36 +1,45 @@ deferred class HTTP_REQUEST_HANDLER -feature - set_uri (new_uri: STRING) - -- set new URI - require - valid_uri: new_uri /= Void - do - request_uri := new_uri +inherit + ANY + redefine + default_create end +feature {NONE} -- Initialization + + default_create + do + Precursor + create request_uri.make_empty + create script_name.make_empty + create query_string.make_empty + create answer + create headers.make (0) + end + +feature -- Access + request_uri: STRING -- requested url - set_data (new_data: STRING) - -- set new data - do - data := new_data - end + script_name: STRING + -- Script name - data: STRING + query_string: STRING + -- Query string + + data: detachable STRING -- the entire request message - headers : HASH_TABLE [STRING, STRING] -- Provides access to the request's HTTP headers, for example: -- headers["Content-Type"] is "text/plain" + answer: HTTP_RESPONSE + -- reply to this request - set_headers ( a_header : HASH_TABLE [STRING, STRING] ) - do - headers := a_header - end +feature -- Execution process -- process the request and create an answer @@ -39,15 +48,68 @@ feature deferred end - answer: HTTP_RESPONSE - -- reply to this request +feature -- Recycle reset -- reinit the fields do - request_uri := Void + request_uri.wipe_out + script_name.wipe_out + query_string.wipe_out data := Void - answer := Void + answer.reset + end + +feature -- Element change + + set_uri (new_uri: STRING) + -- set new URI + require + valid_uri: new_uri /= Void + local + p: INTEGER + do + request_uri := new_uri + p := new_uri.index_of ('?', 1) + if p > 0 then + script_name := new_uri.substring (1, p - 1) + query_string := new_uri.substring (p + 1, new_uri.count) + else + script_name := new_uri.string + query_string := "" + end + end + + set_data (new_data: STRING) + -- set new data + do + data := new_data + end + + set_headers ( a_header : HASH_TABLE [STRING, STRING] ) + do + headers := a_header + end + +feature {NONE} -- Implementation + + real_filename (fn: STRING): STRING + -- Real filename from url-path `fn' + --| Find a better design for this piece of code + --| Eventually in a spec/$ISE_PLATFORM/ specific cluster + do + if {PLATFORM}.is_windows then + create Result.make_from_string (fn) + Result.replace_substring_all ("/", "\") + if Result[Result.count] = '\' then + Result.remove_tail (1) + end + else + Result := fn + if Result[Result.count] = '/' then + Result := Result.substring (1, Result.count - 1) + end + end end end diff --git a/request/post_request_handler.e b/request/post_request_handler.e index 3658d28f..0dadf245 100644 --- a/request/post_request_handler.e +++ b/request/post_request_handler.e @@ -8,108 +8,35 @@ class POST_REQUEST_HANDLER inherit + GET_REQUEST_HANDLER + redefine + process + end - SHARED_DOCUMENT_ROOT +create + make - SHARED_URI_CONTENTS_TYPES +feature -- Execution - HTTP_REQUEST_HANDLER - - HTTP_CONSTANTS - -feature - - - process is + process -- process the request and create an answer local - fname: STRING - f: RAW_FILE - ctype, extension: STRING + l_data: STRING + s: STRING + n: INTEGER do - fname := document_root_cell.item.twin - fname.append (request_uri) - debug - print ("URI name: " + fname ) - end - create f.make (fname) - create answer.make - if f.exists then - extension := ct_table.extension (request_uri) - ctype := ct_table.content_types.item (extension) - -- TODO: This code could be improved to avoid string - -- comparisons - if ctype = Void then - process_default - answer.set_content_type ("text/html") - else - if ctype.is_equal ("text/html") then - process_text_file (f) - else - process_raw_file (f) - end - answer.set_content_type (ctype) - end - else - answer.set_status_code (not_found) - answer.set_reason_phrase (not_found_message) - answer.set_reply_text ("Not found on this server%N%R") - end - end - - process_default is - -- - local - html : STRING - do - answer.set_reply_text ("") - html := " Micro HTTPD " + - " " + - " " + - "

    Welcome to Micro HTTPD!

    "+ - "

    Default page " + - - "

    " + - " " + - " " - answer.append_reply_text (html) - end - - - process_text_file (f: FILE) is - -- send a text file reply - require - valid_f: f /= Void - do - f.open_read from - answer.set_reply_text ("") - f.read_line - until f.end_of_file + n := 1_024 + input.read_stream (n) + s := input.last_string + create l_data.make_empty + until + s.count < n loop - answer.append_reply_text (f.last_string) - answer.append_reply_text (crlf) - f.read_line + l_data.append_string (s) + input.read_stream (n) end - f.close + Precursor end - process_raw_file (f: FILE) is - -- send a raw file reply - require - valid_f: f /= Void - do - -- this is not quite right.... - f.open_read - from - answer.set_reply_text ("") - until f.end_of_file - loop - f.read_stream (1024) - answer.append_reply_text (f.last_string) - end - f.close - end - - end diff --git a/response/http_response.e b/response/http_response.e index 0faf6456..0c4b0d8e 100644 --- a/response/http_response.e +++ b/response/http_response.e @@ -2,12 +2,38 @@ class HTTP_RESPONSE inherit - HTTP_CONSTANTS + redefine + default_create + end create + default_create - make +feature -- creation + + default_create + do + Precursor + set_defaults + end + + set_defaults + -- Set default values for the reply + do + status_code := ok + create content_length_data.make_empty + reason_phrase := ok_message + content_type_data := text_html + set_reply_text (Void) + end + +feature -- Recycle + + reset + do + set_defaults + end feature -- response header fields @@ -17,11 +43,19 @@ feature -- response header fields content_length_data : STRING -- length - set_content_length (new_content_length: STRING) + reason_phrase: STRING + -- message, if any + + content_type_data: STRING + -- type of content in this reply (eg. text/html) + +feature -- Element change + + set_content_length (new_content_length: INTEGER) require - not_void: new_content_length /= Void + positive_or_zero: new_content_length >= 0 do - content_length_data := new_content_length + content_length_data := new_content_length.out end set_status_code (new_status_code: STRING) @@ -31,9 +65,6 @@ feature -- response header fields status_code := new_status_code end - reason_phrase: STRING - -- message, if any - set_reason_phrase (new_reason_phrase: STRING) require not_void: new_reason_phrase /= Void @@ -41,9 +72,6 @@ feature -- response header fields reason_phrase := new_reason_phrase end - content_type_data: STRING - -- type of content in this reply (eg. text/html) - set_content_type (new_content_type: STRING) require not_void: new_content_type /= Void @@ -51,18 +79,7 @@ feature -- response header fields content_type_data := new_content_type end -feature -- creation - - make - do - -- set default values for the reply - status_code := ok - reason_phrase := ok_message - content_type_data := text_html - end - -feature -- access these to send a reply - +feature -- Access: send reply reply_header: STRING -- header @@ -73,7 +90,7 @@ feature -- access these to send a reply Result.extend (' ') Result.append (reason_phrase) Result.append (crlf) - Result.append (Server_datails) + Result.append ({HTTP_SERVER_CONFIGURATION}.Server_details) Result.append (crlf) Result.append (Content_type + ": ") Result.append (content_type_data) @@ -89,7 +106,7 @@ feature -- access these to send a reply reply_header_continue: STRING -- header do - Result :=http_version_1_1.twin + Result := http_version_1_1.twin Result.extend (' ') Result.append (status_code) Result.extend (' ') @@ -100,14 +117,19 @@ feature -- access these to send a reply -- then keep the connection alive end - reply_text: STRING -- reply text - set_reply_text (new_text: STRING) +feature -- Change element: send reply + + set_reply_text (new_text: detachable STRING) -- text could be Void do - reply_text := new_text + if new_text = Void then + create reply_text.make_empty + else + reply_text := new_text + end end append_reply_text (more_text: STRING) diff --git a/http_connection_handler.e b/server/http_connection_handler.e similarity index 63% rename from http_connection_handler.e rename to server/http_connection_handler.e index 455f6631..7dfb2359 100644 --- a/http_connection_handler.e +++ b/server/http_connection_handler.e @@ -8,9 +8,10 @@ class HTTP_CONNECTION_HANDLER inherit - THREAD + HTTP_CONSTANTS + create make @@ -43,15 +44,17 @@ feature -- Inherited Features -- 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 - create l_http_socket.make_server_by_port ({HTTP_CONSTANTS}.Http_server_port) + 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 " + {HTTP_CONSTANTS}.Http_server_port.out ) + print ("Socket could not be bound on port " + l_http_port.out ) else from - l_http_socket.listen ({HTTP_CONSTANTS}.Max_tcp_clients) - print ("%NHTTP Connection Server ready on port " + {HTTP_CONSTANTS}.Http_server_port.out +"%N") + 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 @@ -85,34 +88,90 @@ feature -- Inherited Features retry end +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 ... + require + a_uri_attached: a_uri /= Void + a_method_attached: a_method /= Void + a_headers_text_attached: a_headers_text /= Void + a_input_attached: a_input /= Void + a_output_attached: a_output /= Void + 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 +-- 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 request_header_map : HASH_TABLE [STRING,STRING] - -- Containts 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 - -- http verb + method: STRING + -- http verb - uri : STRING - -- http endpoint + uri: STRING + -- http endpoint + + version: detachable STRING + -- http_version + --| unused for now - version : STRING - -- http_version feature -- Status setting shutdown @@ -123,8 +182,6 @@ feature -- Status setting 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 -- @@ -162,11 +219,8 @@ feature {NONE} -- Implementation Result_attached: Result /= Void end - - feature -- New implementation - parse_http_request_line (line: STRING) require line /= Void @@ -184,37 +238,24 @@ feature -- New implementation end feature -- New Implementation + receive_message_and_send_replay (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 local - message: detachable STRING - l_http_request : HTTP_REQUEST_HANDLER + l_headers_text: detachable STRING + l_input: HTTP_INPUT_STREAM + l_output: HTTP_OUTPUT_STREAM do parse_request_line (client_socket) - message := receive_message_internal (client_socket) - if method.is_equal (Get) then - create {GET_REQUEST_HANDLER} l_http_request - l_http_request.set_uri (uri) - l_http_request.process --- client_socket.send_message (l_http_request.answer.reply_header + l_http_request.answer.reply_text) - client_socket.put_string (l_http_request.answer.reply_header + l_http_request.answer.reply_text) - elseif method.is_equal (Post) then - elseif method.is_equal (Put) then - elseif method.is_equal (Options) then - elseif method.is_equal (Head) then - elseif method.is_equal (Delete) then - elseif method.is_equal (Trace) then - elseif method.is_equal (Connect) then - else - debug - print ("Method not supported") - end - end - end + 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 @@ -240,10 +281,11 @@ feature -- New Implementation loop line := socket.last_string 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)) - Result.append(socket.last_string) - if not socket.last_string.is_equal("%R") and socket.socket_ok then + Result.append (line) + Result.append_character ('%N') + if not line.is_equal("%R") and socket.socket_ok then socket.read_line_thread_aware else end_of_stream := True diff --git a/http_constants.e b/server/http_constants.e similarity index 92% rename from http_constants.e rename to server/http_constants.e index b263b76b..791ba309 100644 --- a/http_constants.e +++ b/server/http_constants.e @@ -81,13 +81,6 @@ feature -- content types text_html: STRING = "text/html" -feature -- Network - Server_datails : STRING = "Server : NANO Eiffel Server" - Http_server_port: INTEGER = 9000 - Max_tcp_clients: INTEGER = 100 - Socket_accept_timeout: INTEGER = 1000 - Socket_connect_timeout: INTEGER = 5000 - feature -- General Header Fields -- There are a few header fields which have general applicability for both request and response messages, diff --git a/http_encoding_facilities.e b/server/http_encoding_facilities.e similarity index 100% rename from http_encoding_facilities.e rename to server/http_encoding_facilities.e diff --git a/http_protocol_handler.e b/server/http_protocol_handler.e similarity index 100% rename from http_protocol_handler.e rename to server/http_protocol_handler.e diff --git a/server/http_server.e b/server/http_server.e new file mode 100644 index 00000000..a9e22a3b --- /dev/null +++ b/server/http_server.e @@ -0,0 +1,61 @@ +note + description: "Summary description for {HTTP_SERVER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTP_SERVER + +inherit + SHARED_DOCUMENT_ROOT + +create + make + +feature -- Initialization + + make (cfg: like configuration) + do + configuration := cfg + end + + setup (a_http_handler : HTTP_CONNECTION_HANDLER) + require + a_http_handler_valid: a_http_handler /= Void + do + print("%N%N%N") + print ("Starting Web Application Server:%N") + stop_requested := False + set_server_configuration (configuration) + a_http_handler.launch + run + end + + shutdown_server + do + stop_requested := True + end + +feature -- Access + + configuration: HTTP_SERVER_CONFIGURATION + -- Configuration of the server + + stop_requested: BOOLEAN + -- Stops the server + +feature {NONE} -- implementation + + run + -- Start the server + local + e: EXECUTION_ENVIRONMENT + do + create e + from until stop_requested loop + e.sleep (1_000_000) + end + end + +end diff --git a/shared_document_root.e b/server/shared_document_root.e similarity index 58% rename from shared_document_root.e rename to server/shared_document_root.e index 6b17bb59..cc516ee7 100644 --- a/shared_document_root.e +++ b/server/shared_document_root.e @@ -6,11 +6,10 @@ note class SHARED_DOCUMENT_ROOT -feature - document_root_cell: CELL [STRING] - once ("PROCESS") - create Result.put (Void) - end +obsolete "Use HTTP_SERVER_SHARED_CONFIGURATION" + +inherit + HTTP_SERVER_SHARED_CONFIGURATION end diff --git a/shared_http_request_handlers.e b/server/shared_http_request_handlers.e similarity index 93% rename from shared_http_request_handlers.e rename to server/shared_http_request_handlers.e index 8cee2ca1..851d012c 100644 --- a/shared_http_request_handlers.e +++ b/server/shared_http_request_handlers.e @@ -2,7 +2,7 @@ class SHARED_HTTP_REQUEST_HANDLERS feature - http_request_handlers: HASH_TABLE [HTTP_REQUEST_HANDLER, STRING] is + http_request_handlers: HASH_TABLE [HTTP_REQUEST_HANDLER, STRING] local a_handler: HTTP_REQUEST_HANDLER once diff --git a/shared_uri_contents_types.e b/server/shared_uri_contents_types.e similarity index 100% rename from shared_uri_contents_types.e rename to server/shared_uri_contents_types.e diff --git a/tcp_stream_socket.e b/server/tcp_stream_socket.e similarity index 86% rename from tcp_stream_socket.e rename to server/tcp_stream_socket.e index 8647c27f..ce9068b9 100644 --- a/tcp_stream_socket.e +++ b/server/tcp_stream_socket.e @@ -1,11 +1,11 @@ note description: "Summary description for {TCP_STREAM_SOCKET}." - author: "" date: "$Date$" revision: "$Revision$" class TCP_STREAM_SOCKET + inherit NETWORK_STREAM_SOCKET @@ -15,7 +15,8 @@ create create {NETWORK_STREAM_SOCKET} make_from_descriptor_and_address -feature +feature -- Basic operation + send_message (a_msg: STRING) local a_package : PACKET @@ -25,6 +26,7 @@ feature create c_string.make (a_msg) create a_data.make_from_pointer (c_string.item, a_msg.count + 1) create a_package.make_from_managed_pointer (a_data) - Current.send (a_package, 1) + send (a_package, 1) end + end diff --git a/uri_contents_types.e b/server/uri_contents_types.e similarity index 100% rename from uri_contents_types.e rename to server/uri_contents_types.e diff --git a/webroot/post/index.html b/webroot/post/index.html new file mode 100644 index 00000000..85df7158 --- /dev/null +++ b/webroot/post/index.html @@ -0,0 +1,19 @@ + + + POST example + + +

    POST example

    +
    +
    + + +
    + +
    +
    + + +
    + + From c553bd1e1e5866f1830a3a94658b7d1c58b019f8 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 27 May 2011 13:07:06 +0200 Subject: [PATCH 2/9] 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) --- application.e | 4 +- application_handler.e | 57 +++++++ exception_trace.log | 47 ------ io/http_input_stream.e | 20 +++ request/get_request_handler.e | 2 +- server/http_connection_handler.e | 248 +++++-------------------------- server/http_handler.e | 123 +++++++++++++++ server/http_protocol_handler.e | 4 +- server/http_server.e | 6 +- server/shared_document_root.e | 15 -- 10 files changed, 249 insertions(+), 277 deletions(-) create mode 100644 application_handler.e delete mode 100644 exception_trace.log create mode 100644 server/http_handler.e delete mode 100644 server/shared_document_root.e diff --git a/application.e b/application.e index 6c206526..39c86209 100644 --- a/application.e +++ b/application.e @@ -19,14 +19,14 @@ feature {NONE} -- Initialization local l_server : HTTP_SERVER l_cfg: HTTP_SERVER_CONFIGURATION - l_http_handler : HTTP_CONNECTION_HANDLER + l_http_handler : HTTP_HANDLER do create l_cfg.make l_cfg.http_server_port := 9_000 l_cfg.document_root := default_document_root 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) end diff --git a/application_handler.e b/application_handler.e new file mode 100644 index 00000000..9a63a82a --- /dev/null +++ b/application_handler.e @@ -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 diff --git a/exception_trace.log b/exception_trace.log deleted file mode 100644 index e44d7f4e..00000000 --- a/exception_trace.log +++ /dev/null @@ -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 -------------------------------------------------------------------------------- diff --git a/io/http_input_stream.e b/io/http_input_stream.e index bd85fafd..9dc67f73 100644 --- a/io/http_input_stream.e +++ b/io/http_input_stream.e @@ -20,14 +20,34 @@ feature {NONE} -- Initialization source: TCP_STREAM_SOCKET +feature -- Status Report + + is_readable: BOOLEAN + -- Is readable? + do + Result := source.is_open_read + end + 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 a string of at most `nb_char' bound characters -- or until end of file. -- Make result available in `last_string'. require nb_char_positive: nb_char > 0 + is_readable: is_readable do last_string.wipe_out if source.socket_ok then diff --git a/request/get_request_handler.e b/request/get_request_handler.e index 2aa269d9..e37d77b2 100644 --- a/request/get_request_handler.e +++ b/request/get_request_handler.e @@ -4,7 +4,7 @@ inherit HTTP_REQUEST_HANDLER - SHARED_DOCUMENT_ROOT + HTTP_SERVER_SHARED_CONFIGURATION undefine default_create end diff --git a/server/http_connection_handler.e b/server/http_connection_handler.e index 7dfb2359..3ed23376 100644 --- a/server/http_connection_handler.e +++ b/server/http_connection_handler.e @@ -4,16 +4,14 @@ note date: "$Date$" revision: "$Revision$" -class +deferred class HTTP_CONNECTION_HANDLER inherit - THREAD - - HTTP_CONSTANTS - -create - make + HTTP_HANDLER + redefine + make + end feature {NONE} -- Initialization @@ -22,70 +20,26 @@ feature {NONE} -- Initialization -- -- `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 - create current_request_message.make_empty + Precursor (a_main_server, a_name) create method.make_empty create uri.make_empty + create request_header.make_empty 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 -feature -- Inherited Features +feature -- Execution - execute - -- - -- Creates a socket and connects to the http server. + receive_message_and_send_reply (client_socket: TCP_STREAM_SOCKET) local - l_http_socket: detachable TCP_STREAM_SOCKET - l_http_port: INTEGER + l_input: HTTP_INPUT_STREAM + l_output: HTTP_OUTPUT_STREAM 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_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.") + create l_input.make (client_socket) + create l_output.make (client_socket) - 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 + analyze_request_message (l_input) + process_request (uri, method, request_header_map, request_header, l_input, l_output) end feature -- Request processing @@ -98,70 +52,17 @@ feature -- Request processing a_headers_text_attached: a_headers_text /= Void a_input_attached: a_input /= Void a_output_attached: a_output /= Void - 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 + deferred 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 + request_header: STRING + -- Header' source + request_header_map : HASH_TABLE [STRING,STRING] -- 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 -- http verb @@ -172,54 +73,7 @@ feature {NONE} -- Access -- http_version --| unused for now -feature -- Status setting - - 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 +feature -- Parsing parse_http_request_line (line: STRING) require @@ -237,63 +91,44 @@ feature -- New implementation not_void_method: method /= Void end -feature -- New Implementation - receive_message_and_send_replay (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 - 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) + analyze_request_message (a_input: HTTP_INPUT_STREAM) require - socket: socket /= Void and then not socket.is_closed - 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 + input_redable: a_input /= Void and then not a_input.is_readable local end_of_stream : BOOLEAN pos : INTEGER line : STRING + txt: STRING 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 - socket.read_line_thread_aware - Result := "" + a_input.read_line until end_of_stream loop - line := socket.last_string + line := a_input.last_string print ("%N" +line+ "%N") pos := line.index_of (':',1) request_header_map.put (line.substring (pos + 1, line.count), line.substring (1,pos-1)) - Result.append (line) - Result.append_character ('%N') - if not line.is_equal("%R") and socket.socket_ok then - socket.read_line_thread_aware - else + txt.append (line) + txt.append_character ('%N') + if line.is_empty or else line[1] = '%R' then end_of_stream := True - end + else + a_input.read_line + end end end - parse_request_line_internal (line: STRING) + analyze_request_line (line: STRING) require line /= Void local @@ -310,7 +145,6 @@ feature -- New Implementation end invariant - main_server_attached: main_server /= Void - current_request_message_attached: current_request_message /= Void + request_header_attached: request_header /= Void end diff --git a/server/http_handler.e b/server/http_handler.e new file mode 100644 index 00000000..80369127 --- /dev/null +++ b/server/http_handler.e @@ -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 + -- + -- 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 diff --git a/server/http_protocol_handler.e b/server/http_protocol_handler.e index bb1995dd..6be59b67 100644 --- a/server/http_protocol_handler.e +++ b/server/http_protocol_handler.e @@ -70,7 +70,7 @@ feature -- Implementation done loop if socket.socket_ok then - done := receive_message_and_send_replay (socket) + done := receive_message_and_send_reply (socket) request_header_map.wipe_out else done := True @@ -80,7 +80,7 @@ feature -- Implementation io.put_new_line end - receive_message_and_send_replay (client_socket: NETWORK_STREAM_SOCKET): BOOLEAN + receive_message_and_send_reply (client_socket: NETWORK_STREAM_SOCKET): BOOLEAN require socket_attached: client_socket /= Void socket_valid: client_socket.is_open_read and then client_socket.is_open_write diff --git a/server/http_server.e b/server/http_server.e index a9e22a3b..3ef61c09 100644 --- a/server/http_server.e +++ b/server/http_server.e @@ -8,7 +8,7 @@ class HTTP_SERVER inherit - SHARED_DOCUMENT_ROOT + HTTP_SERVER_SHARED_CONFIGURATION create make @@ -20,7 +20,7 @@ feature -- Initialization configuration := cfg end - setup (a_http_handler : HTTP_CONNECTION_HANDLER) + setup (a_http_handler : HTTP_HANDLER) require a_http_handler_valid: a_http_handler /= Void do @@ -29,7 +29,7 @@ feature -- Initialization stop_requested := False set_server_configuration (configuration) a_http_handler.launch - run + a_http_handler.join end shutdown_server diff --git a/server/shared_document_root.e b/server/shared_document_root.e deleted file mode 100644 index cc516ee7..00000000 --- a/server/shared_document_root.e +++ /dev/null @@ -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 From 54b95650c5b6ccb2532ab873be14993b9bf22f05 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 27 May 2011 15:21:30 +0200 Subject: [PATCH 3/9] Moving things around to make it more structured. and turn into library --- .gitignore | 1 + nino.ecf | 4 ++-- README => src/README | 0 .../http_server_configuration.e | 0 .../http_server_shared_configuration.e | 0 {server => src}/http_connection_handler.e | 0 {server => src}/http_constants.e | 0 {server => src}/http_encoding_facilities.e | 0 {server => src}/http_handler.e | 0 {server => src}/http_protocol_handler.e | 0 {server => src}/http_server.e | 0 {io => src/io}/http_input_stream.e | 0 {io => src/io}/http_output_stream.e | 0 .../request}/get_request_handler.e | 0 .../request}/head_request_handler.e | 0 .../request}/http_request_handler.e | 0 .../request}/post_request_handler.e | 0 {response => src/response}/http_response.e | 0 .../shared_http_request_handlers.e | 0 {server => src}/shared_uri_contents_types.e | 0 {server => src}/tcp_stream_socket.e | 0 {server => src}/uri_contents_types.e | 0 application.e => web_server/application.e | 0 .../application_handler.e | 0 web_server/web_server.ecf | 21 ++++++++++++++++++ .../webroot}/demo1/img/gradient_light.jpg | Bin .../demo1/jquery.scrollTo-1.4.2/changes.txt | 0 .../jquery.scrollTo-min.js | 0 .../jquery.scrollTo-1.4.2/jquery.scrollTo.js | 0 .../webroot}/demo1/script.js | 0 .../webroot}/demo1/styles.css | 0 .../webroot}/demo1/template.html | 0 .../webroot}/demo2/demo.html | 0 .../webroot}/demo2/img/background.jpg | Bin .../webroot}/demo2/img/button_bg.jpg | Bin .../webroot}/demo2/img/dot.png | Bin .../webroot}/demo2/script.js | 0 .../webroot}/demo2/styles.css | 0 .../example/fonts/DINMittelschriftStd.otf | Bin .../example/fonts/MyriadPro-LightCond.otf | Bin .../example/fonts/MyriadPro-SemiboldCond.otf | Bin .../webroot}/example/fonts/stan0755.ttf | Bin .../webroot}/example/fonts/tahoma.ttf | Bin .../webroot}/example/fonts/tahomabd.ttf | Bin .../webroot}/example/fonts/trebuc.ttf | Bin .../webroot}/example/fonts/trebucbd.ttf | Bin .../webroot}/example/html/contentpage.html | 0 .../webroot}/example/html/css/styles.css | 0 .../webroot}/example/html/images/b_footer.jpg | Bin .../webroot}/example/html/images/btn_1.jpg | Bin .../example/html/images/btn_1_over.jpg | Bin .../webroot}/example/html/images/btn_2.jpg | Bin .../example/html/images/btn_2_over.jpg | Bin .../webroot}/example/html/images/btn_3.jpg | Bin .../example/html/images/btn_3_over.jpg | Bin .../webroot}/example/html/images/btn_4.jpg | Bin .../example/html/images/btn_4_over.jpg | Bin .../webroot}/example/html/images/btn_5.jpg | Bin .../example/html/images/btn_5_over.jpg | Bin .../webroot}/example/html/images/btn_6.jpg | Bin .../example/html/images/btn_6_over.jpg | Bin .../example/html/images/client_login.jpg | Bin .../webroot}/example/html/images/lines-07.jpg | Bin .../webroot}/example/html/images/lines-09.jpg | Bin .../webroot}/example/html/images/lines-11.jpg | Bin .../webroot}/example/html/images/lines-13.jpg | Bin .../webroot}/example/html/images/lines.jpg | Bin .../webroot}/example/html/images/main-03.jpg | Bin .../webroot}/example/html/images/main-15.jpg | Bin .../webroot}/example/html/images/main.jpg | Bin .../webroot}/example/html/images/news-19.jpg | Bin .../webroot}/example/html/images/news-20.jpg | Bin .../webroot}/example/html/images/news.jpg | Bin .../example/html/images/services-23.jpg | Bin .../example/html/images/services-25.jpg | Bin .../webroot}/example/html/images/services.jpg | Bin .../example/html/images/spotlight-24.jpg | Bin .../example/html/images/spotlight.jpg | Bin .../example/html/images/welcome-18.jpg | Bin .../webroot}/example/html/images/welcome.jpg | Bin .../webroot}/example/html/index.html | 0 .../webroot}/example/jpeg/template276.jpg | Bin .../webroot}/example/psd/index.psd | Bin .../webroot}/example/readme.html | 0 .../webroot}/html/images.html | 0 .../webroot}/html/images/btn_1.jpg | Bin .../webroot}/html/images/pulpit.jpg | Bin .../webroot}/html/simple.html | 0 .../webroot}/html5/dataset.html | 0 .../webroot}/post/index.html | 0 90 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .gitignore rename README => src/README (100%) rename {configuration => src/configuration}/http_server_configuration.e (100%) rename {configuration => src/configuration}/http_server_shared_configuration.e (100%) rename {server => src}/http_connection_handler.e (100%) rename {server => src}/http_constants.e (100%) rename {server => src}/http_encoding_facilities.e (100%) rename {server => src}/http_handler.e (100%) rename {server => src}/http_protocol_handler.e (100%) rename {server => src}/http_server.e (100%) rename {io => src/io}/http_input_stream.e (100%) rename {io => src/io}/http_output_stream.e (100%) rename {request => src/request}/get_request_handler.e (100%) rename {request => src/request}/head_request_handler.e (100%) rename {request => src/request}/http_request_handler.e (100%) rename {request => src/request}/post_request_handler.e (100%) rename {response => src/response}/http_response.e (100%) rename {server => src}/shared_http_request_handlers.e (100%) rename {server => src}/shared_uri_contents_types.e (100%) rename {server => src}/tcp_stream_socket.e (100%) rename {server => src}/uri_contents_types.e (100%) rename application.e => web_server/application.e (100%) rename application_handler.e => web_server/application_handler.e (100%) create mode 100644 web_server/web_server.ecf rename {webroot => web_server/webroot}/demo1/img/gradient_light.jpg (100%) rename {webroot => web_server/webroot}/demo1/jquery.scrollTo-1.4.2/changes.txt (100%) rename {webroot => web_server/webroot}/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo-min.js (100%) rename {webroot => web_server/webroot}/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo.js (100%) rename {webroot => web_server/webroot}/demo1/script.js (100%) rename {webroot => web_server/webroot}/demo1/styles.css (100%) rename {webroot => web_server/webroot}/demo1/template.html (100%) rename {webroot => web_server/webroot}/demo2/demo.html (100%) rename {webroot => web_server/webroot}/demo2/img/background.jpg (100%) rename {webroot => web_server/webroot}/demo2/img/button_bg.jpg (100%) rename {webroot => web_server/webroot}/demo2/img/dot.png (100%) rename {webroot => web_server/webroot}/demo2/script.js (100%) rename {webroot => web_server/webroot}/demo2/styles.css (100%) rename {webroot => web_server/webroot}/example/fonts/DINMittelschriftStd.otf (100%) rename {webroot => web_server/webroot}/example/fonts/MyriadPro-LightCond.otf (100%) rename {webroot => web_server/webroot}/example/fonts/MyriadPro-SemiboldCond.otf (100%) rename {webroot => web_server/webroot}/example/fonts/stan0755.ttf (100%) rename {webroot => web_server/webroot}/example/fonts/tahoma.ttf (100%) rename {webroot => web_server/webroot}/example/fonts/tahomabd.ttf (100%) rename {webroot => web_server/webroot}/example/fonts/trebuc.ttf (100%) rename {webroot => web_server/webroot}/example/fonts/trebucbd.ttf (100%) rename {webroot => web_server/webroot}/example/html/contentpage.html (100%) rename {webroot => web_server/webroot}/example/html/css/styles.css (100%) rename {webroot => web_server/webroot}/example/html/images/b_footer.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_1.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_1_over.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_2.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_2_over.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_3.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_3_over.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_4.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_4_over.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_5.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_5_over.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_6.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/btn_6_over.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/client_login.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/lines-07.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/lines-09.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/lines-11.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/lines-13.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/lines.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/main-03.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/main-15.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/main.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/news-19.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/news-20.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/news.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/services-23.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/services-25.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/services.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/spotlight-24.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/spotlight.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/welcome-18.jpg (100%) rename {webroot => web_server/webroot}/example/html/images/welcome.jpg (100%) rename {webroot => web_server/webroot}/example/html/index.html (100%) rename {webroot => web_server/webroot}/example/jpeg/template276.jpg (100%) rename {webroot => web_server/webroot}/example/psd/index.psd (100%) rename {webroot => web_server/webroot}/example/readme.html (100%) rename {webroot => web_server/webroot}/html/images.html (100%) rename {webroot => web_server/webroot}/html/images/btn_1.jpg (100%) rename {webroot => web_server/webroot}/html/images/pulpit.jpg (100%) rename {webroot => web_server/webroot}/html/simple.html (100%) rename {webroot => web_server/webroot}/html5/dataset.html (100%) rename {webroot => web_server/webroot}/post/index.html (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6342e5c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +EIFGENs diff --git a/nino.ecf b/nino.ecf index 5f07f73c..4fa6a143 100644 --- a/nino.ecf +++ b/nino.ecf @@ -1,5 +1,5 @@ - + @@ -15,6 +15,6 @@ - + diff --git a/README b/src/README similarity index 100% rename from README rename to src/README diff --git a/configuration/http_server_configuration.e b/src/configuration/http_server_configuration.e similarity index 100% rename from configuration/http_server_configuration.e rename to src/configuration/http_server_configuration.e diff --git a/configuration/http_server_shared_configuration.e b/src/configuration/http_server_shared_configuration.e similarity index 100% rename from configuration/http_server_shared_configuration.e rename to src/configuration/http_server_shared_configuration.e diff --git a/server/http_connection_handler.e b/src/http_connection_handler.e similarity index 100% rename from server/http_connection_handler.e rename to src/http_connection_handler.e diff --git a/server/http_constants.e b/src/http_constants.e similarity index 100% rename from server/http_constants.e rename to src/http_constants.e diff --git a/server/http_encoding_facilities.e b/src/http_encoding_facilities.e similarity index 100% rename from server/http_encoding_facilities.e rename to src/http_encoding_facilities.e diff --git a/server/http_handler.e b/src/http_handler.e similarity index 100% rename from server/http_handler.e rename to src/http_handler.e diff --git a/server/http_protocol_handler.e b/src/http_protocol_handler.e similarity index 100% rename from server/http_protocol_handler.e rename to src/http_protocol_handler.e diff --git a/server/http_server.e b/src/http_server.e similarity index 100% rename from server/http_server.e rename to src/http_server.e diff --git a/io/http_input_stream.e b/src/io/http_input_stream.e similarity index 100% rename from io/http_input_stream.e rename to src/io/http_input_stream.e diff --git a/io/http_output_stream.e b/src/io/http_output_stream.e similarity index 100% rename from io/http_output_stream.e rename to src/io/http_output_stream.e diff --git a/request/get_request_handler.e b/src/request/get_request_handler.e similarity index 100% rename from request/get_request_handler.e rename to src/request/get_request_handler.e diff --git a/request/head_request_handler.e b/src/request/head_request_handler.e similarity index 100% rename from request/head_request_handler.e rename to src/request/head_request_handler.e diff --git a/request/http_request_handler.e b/src/request/http_request_handler.e similarity index 100% rename from request/http_request_handler.e rename to src/request/http_request_handler.e diff --git a/request/post_request_handler.e b/src/request/post_request_handler.e similarity index 100% rename from request/post_request_handler.e rename to src/request/post_request_handler.e diff --git a/response/http_response.e b/src/response/http_response.e similarity index 100% rename from response/http_response.e rename to src/response/http_response.e diff --git a/server/shared_http_request_handlers.e b/src/shared_http_request_handlers.e similarity index 100% rename from server/shared_http_request_handlers.e rename to src/shared_http_request_handlers.e diff --git a/server/shared_uri_contents_types.e b/src/shared_uri_contents_types.e similarity index 100% rename from server/shared_uri_contents_types.e rename to src/shared_uri_contents_types.e diff --git a/server/tcp_stream_socket.e b/src/tcp_stream_socket.e similarity index 100% rename from server/tcp_stream_socket.e rename to src/tcp_stream_socket.e diff --git a/server/uri_contents_types.e b/src/uri_contents_types.e similarity index 100% rename from server/uri_contents_types.e rename to src/uri_contents_types.e diff --git a/application.e b/web_server/application.e similarity index 100% rename from application.e rename to web_server/application.e diff --git a/application_handler.e b/web_server/application_handler.e similarity index 100% rename from application_handler.e rename to web_server/application_handler.e diff --git a/web_server/web_server.ecf b/web_server/web_server.ecf new file mode 100644 index 00000000..826dfa8b --- /dev/null +++ b/web_server/web_server.ecf @@ -0,0 +1,21 @@ + + + + + + /EIFGENs$ + /CVS$ + /.svn$ + /.git$ + + + + + + + + + + diff --git a/webroot/demo1/img/gradient_light.jpg b/web_server/webroot/demo1/img/gradient_light.jpg similarity index 100% rename from webroot/demo1/img/gradient_light.jpg rename to web_server/webroot/demo1/img/gradient_light.jpg diff --git a/webroot/demo1/jquery.scrollTo-1.4.2/changes.txt b/web_server/webroot/demo1/jquery.scrollTo-1.4.2/changes.txt similarity index 100% rename from webroot/demo1/jquery.scrollTo-1.4.2/changes.txt rename to web_server/webroot/demo1/jquery.scrollTo-1.4.2/changes.txt diff --git a/webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo-min.js b/web_server/webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo-min.js similarity index 100% rename from webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo-min.js rename to web_server/webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo-min.js diff --git a/webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo.js b/web_server/webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo.js similarity index 100% rename from webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo.js rename to web_server/webroot/demo1/jquery.scrollTo-1.4.2/jquery.scrollTo.js diff --git a/webroot/demo1/script.js b/web_server/webroot/demo1/script.js similarity index 100% rename from webroot/demo1/script.js rename to web_server/webroot/demo1/script.js diff --git a/webroot/demo1/styles.css b/web_server/webroot/demo1/styles.css similarity index 100% rename from webroot/demo1/styles.css rename to web_server/webroot/demo1/styles.css diff --git a/webroot/demo1/template.html b/web_server/webroot/demo1/template.html similarity index 100% rename from webroot/demo1/template.html rename to web_server/webroot/demo1/template.html diff --git a/webroot/demo2/demo.html b/web_server/webroot/demo2/demo.html similarity index 100% rename from webroot/demo2/demo.html rename to web_server/webroot/demo2/demo.html diff --git a/webroot/demo2/img/background.jpg b/web_server/webroot/demo2/img/background.jpg similarity index 100% rename from webroot/demo2/img/background.jpg rename to web_server/webroot/demo2/img/background.jpg diff --git a/webroot/demo2/img/button_bg.jpg b/web_server/webroot/demo2/img/button_bg.jpg similarity index 100% rename from webroot/demo2/img/button_bg.jpg rename to web_server/webroot/demo2/img/button_bg.jpg diff --git a/webroot/demo2/img/dot.png b/web_server/webroot/demo2/img/dot.png similarity index 100% rename from webroot/demo2/img/dot.png rename to web_server/webroot/demo2/img/dot.png diff --git a/webroot/demo2/script.js b/web_server/webroot/demo2/script.js similarity index 100% rename from webroot/demo2/script.js rename to web_server/webroot/demo2/script.js diff --git a/webroot/demo2/styles.css b/web_server/webroot/demo2/styles.css similarity index 100% rename from webroot/demo2/styles.css rename to web_server/webroot/demo2/styles.css diff --git a/webroot/example/fonts/DINMittelschriftStd.otf b/web_server/webroot/example/fonts/DINMittelschriftStd.otf similarity index 100% rename from webroot/example/fonts/DINMittelschriftStd.otf rename to web_server/webroot/example/fonts/DINMittelschriftStd.otf diff --git a/webroot/example/fonts/MyriadPro-LightCond.otf b/web_server/webroot/example/fonts/MyriadPro-LightCond.otf similarity index 100% rename from webroot/example/fonts/MyriadPro-LightCond.otf rename to web_server/webroot/example/fonts/MyriadPro-LightCond.otf diff --git a/webroot/example/fonts/MyriadPro-SemiboldCond.otf b/web_server/webroot/example/fonts/MyriadPro-SemiboldCond.otf similarity index 100% rename from webroot/example/fonts/MyriadPro-SemiboldCond.otf rename to web_server/webroot/example/fonts/MyriadPro-SemiboldCond.otf diff --git a/webroot/example/fonts/stan0755.ttf b/web_server/webroot/example/fonts/stan0755.ttf similarity index 100% rename from webroot/example/fonts/stan0755.ttf rename to web_server/webroot/example/fonts/stan0755.ttf diff --git a/webroot/example/fonts/tahoma.ttf b/web_server/webroot/example/fonts/tahoma.ttf similarity index 100% rename from webroot/example/fonts/tahoma.ttf rename to web_server/webroot/example/fonts/tahoma.ttf diff --git a/webroot/example/fonts/tahomabd.ttf b/web_server/webroot/example/fonts/tahomabd.ttf similarity index 100% rename from webroot/example/fonts/tahomabd.ttf rename to web_server/webroot/example/fonts/tahomabd.ttf diff --git a/webroot/example/fonts/trebuc.ttf b/web_server/webroot/example/fonts/trebuc.ttf similarity index 100% rename from webroot/example/fonts/trebuc.ttf rename to web_server/webroot/example/fonts/trebuc.ttf diff --git a/webroot/example/fonts/trebucbd.ttf b/web_server/webroot/example/fonts/trebucbd.ttf similarity index 100% rename from webroot/example/fonts/trebucbd.ttf rename to web_server/webroot/example/fonts/trebucbd.ttf diff --git a/webroot/example/html/contentpage.html b/web_server/webroot/example/html/contentpage.html similarity index 100% rename from webroot/example/html/contentpage.html rename to web_server/webroot/example/html/contentpage.html diff --git a/webroot/example/html/css/styles.css b/web_server/webroot/example/html/css/styles.css similarity index 100% rename from webroot/example/html/css/styles.css rename to web_server/webroot/example/html/css/styles.css diff --git a/webroot/example/html/images/b_footer.jpg b/web_server/webroot/example/html/images/b_footer.jpg similarity index 100% rename from webroot/example/html/images/b_footer.jpg rename to web_server/webroot/example/html/images/b_footer.jpg diff --git a/webroot/example/html/images/btn_1.jpg b/web_server/webroot/example/html/images/btn_1.jpg similarity index 100% rename from webroot/example/html/images/btn_1.jpg rename to web_server/webroot/example/html/images/btn_1.jpg diff --git a/webroot/example/html/images/btn_1_over.jpg b/web_server/webroot/example/html/images/btn_1_over.jpg similarity index 100% rename from webroot/example/html/images/btn_1_over.jpg rename to web_server/webroot/example/html/images/btn_1_over.jpg diff --git a/webroot/example/html/images/btn_2.jpg b/web_server/webroot/example/html/images/btn_2.jpg similarity index 100% rename from webroot/example/html/images/btn_2.jpg rename to web_server/webroot/example/html/images/btn_2.jpg diff --git a/webroot/example/html/images/btn_2_over.jpg b/web_server/webroot/example/html/images/btn_2_over.jpg similarity index 100% rename from webroot/example/html/images/btn_2_over.jpg rename to web_server/webroot/example/html/images/btn_2_over.jpg diff --git a/webroot/example/html/images/btn_3.jpg b/web_server/webroot/example/html/images/btn_3.jpg similarity index 100% rename from webroot/example/html/images/btn_3.jpg rename to web_server/webroot/example/html/images/btn_3.jpg diff --git a/webroot/example/html/images/btn_3_over.jpg b/web_server/webroot/example/html/images/btn_3_over.jpg similarity index 100% rename from webroot/example/html/images/btn_3_over.jpg rename to web_server/webroot/example/html/images/btn_3_over.jpg diff --git a/webroot/example/html/images/btn_4.jpg b/web_server/webroot/example/html/images/btn_4.jpg similarity index 100% rename from webroot/example/html/images/btn_4.jpg rename to web_server/webroot/example/html/images/btn_4.jpg diff --git a/webroot/example/html/images/btn_4_over.jpg b/web_server/webroot/example/html/images/btn_4_over.jpg similarity index 100% rename from webroot/example/html/images/btn_4_over.jpg rename to web_server/webroot/example/html/images/btn_4_over.jpg diff --git a/webroot/example/html/images/btn_5.jpg b/web_server/webroot/example/html/images/btn_5.jpg similarity index 100% rename from webroot/example/html/images/btn_5.jpg rename to web_server/webroot/example/html/images/btn_5.jpg diff --git a/webroot/example/html/images/btn_5_over.jpg b/web_server/webroot/example/html/images/btn_5_over.jpg similarity index 100% rename from webroot/example/html/images/btn_5_over.jpg rename to web_server/webroot/example/html/images/btn_5_over.jpg diff --git a/webroot/example/html/images/btn_6.jpg b/web_server/webroot/example/html/images/btn_6.jpg similarity index 100% rename from webroot/example/html/images/btn_6.jpg rename to web_server/webroot/example/html/images/btn_6.jpg diff --git a/webroot/example/html/images/btn_6_over.jpg b/web_server/webroot/example/html/images/btn_6_over.jpg similarity index 100% rename from webroot/example/html/images/btn_6_over.jpg rename to web_server/webroot/example/html/images/btn_6_over.jpg diff --git a/webroot/example/html/images/client_login.jpg b/web_server/webroot/example/html/images/client_login.jpg similarity index 100% rename from webroot/example/html/images/client_login.jpg rename to web_server/webroot/example/html/images/client_login.jpg diff --git a/webroot/example/html/images/lines-07.jpg b/web_server/webroot/example/html/images/lines-07.jpg similarity index 100% rename from webroot/example/html/images/lines-07.jpg rename to web_server/webroot/example/html/images/lines-07.jpg diff --git a/webroot/example/html/images/lines-09.jpg b/web_server/webroot/example/html/images/lines-09.jpg similarity index 100% rename from webroot/example/html/images/lines-09.jpg rename to web_server/webroot/example/html/images/lines-09.jpg diff --git a/webroot/example/html/images/lines-11.jpg b/web_server/webroot/example/html/images/lines-11.jpg similarity index 100% rename from webroot/example/html/images/lines-11.jpg rename to web_server/webroot/example/html/images/lines-11.jpg diff --git a/webroot/example/html/images/lines-13.jpg b/web_server/webroot/example/html/images/lines-13.jpg similarity index 100% rename from webroot/example/html/images/lines-13.jpg rename to web_server/webroot/example/html/images/lines-13.jpg diff --git a/webroot/example/html/images/lines.jpg b/web_server/webroot/example/html/images/lines.jpg similarity index 100% rename from webroot/example/html/images/lines.jpg rename to web_server/webroot/example/html/images/lines.jpg diff --git a/webroot/example/html/images/main-03.jpg b/web_server/webroot/example/html/images/main-03.jpg similarity index 100% rename from webroot/example/html/images/main-03.jpg rename to web_server/webroot/example/html/images/main-03.jpg diff --git a/webroot/example/html/images/main-15.jpg b/web_server/webroot/example/html/images/main-15.jpg similarity index 100% rename from webroot/example/html/images/main-15.jpg rename to web_server/webroot/example/html/images/main-15.jpg diff --git a/webroot/example/html/images/main.jpg b/web_server/webroot/example/html/images/main.jpg similarity index 100% rename from webroot/example/html/images/main.jpg rename to web_server/webroot/example/html/images/main.jpg diff --git a/webroot/example/html/images/news-19.jpg b/web_server/webroot/example/html/images/news-19.jpg similarity index 100% rename from webroot/example/html/images/news-19.jpg rename to web_server/webroot/example/html/images/news-19.jpg diff --git a/webroot/example/html/images/news-20.jpg b/web_server/webroot/example/html/images/news-20.jpg similarity index 100% rename from webroot/example/html/images/news-20.jpg rename to web_server/webroot/example/html/images/news-20.jpg diff --git a/webroot/example/html/images/news.jpg b/web_server/webroot/example/html/images/news.jpg similarity index 100% rename from webroot/example/html/images/news.jpg rename to web_server/webroot/example/html/images/news.jpg diff --git a/webroot/example/html/images/services-23.jpg b/web_server/webroot/example/html/images/services-23.jpg similarity index 100% rename from webroot/example/html/images/services-23.jpg rename to web_server/webroot/example/html/images/services-23.jpg diff --git a/webroot/example/html/images/services-25.jpg b/web_server/webroot/example/html/images/services-25.jpg similarity index 100% rename from webroot/example/html/images/services-25.jpg rename to web_server/webroot/example/html/images/services-25.jpg diff --git a/webroot/example/html/images/services.jpg b/web_server/webroot/example/html/images/services.jpg similarity index 100% rename from webroot/example/html/images/services.jpg rename to web_server/webroot/example/html/images/services.jpg diff --git a/webroot/example/html/images/spotlight-24.jpg b/web_server/webroot/example/html/images/spotlight-24.jpg similarity index 100% rename from webroot/example/html/images/spotlight-24.jpg rename to web_server/webroot/example/html/images/spotlight-24.jpg diff --git a/webroot/example/html/images/spotlight.jpg b/web_server/webroot/example/html/images/spotlight.jpg similarity index 100% rename from webroot/example/html/images/spotlight.jpg rename to web_server/webroot/example/html/images/spotlight.jpg diff --git a/webroot/example/html/images/welcome-18.jpg b/web_server/webroot/example/html/images/welcome-18.jpg similarity index 100% rename from webroot/example/html/images/welcome-18.jpg rename to web_server/webroot/example/html/images/welcome-18.jpg diff --git a/webroot/example/html/images/welcome.jpg b/web_server/webroot/example/html/images/welcome.jpg similarity index 100% rename from webroot/example/html/images/welcome.jpg rename to web_server/webroot/example/html/images/welcome.jpg diff --git a/webroot/example/html/index.html b/web_server/webroot/example/html/index.html similarity index 100% rename from webroot/example/html/index.html rename to web_server/webroot/example/html/index.html diff --git a/webroot/example/jpeg/template276.jpg b/web_server/webroot/example/jpeg/template276.jpg similarity index 100% rename from webroot/example/jpeg/template276.jpg rename to web_server/webroot/example/jpeg/template276.jpg diff --git a/webroot/example/psd/index.psd b/web_server/webroot/example/psd/index.psd similarity index 100% rename from webroot/example/psd/index.psd rename to web_server/webroot/example/psd/index.psd diff --git a/webroot/example/readme.html b/web_server/webroot/example/readme.html similarity index 100% rename from webroot/example/readme.html rename to web_server/webroot/example/readme.html diff --git a/webroot/html/images.html b/web_server/webroot/html/images.html similarity index 100% rename from webroot/html/images.html rename to web_server/webroot/html/images.html diff --git a/webroot/html/images/btn_1.jpg b/web_server/webroot/html/images/btn_1.jpg similarity index 100% rename from webroot/html/images/btn_1.jpg rename to web_server/webroot/html/images/btn_1.jpg diff --git a/webroot/html/images/pulpit.jpg b/web_server/webroot/html/images/pulpit.jpg similarity index 100% rename from webroot/html/images/pulpit.jpg rename to web_server/webroot/html/images/pulpit.jpg diff --git a/webroot/html/simple.html b/web_server/webroot/html/simple.html similarity index 100% rename from webroot/html/simple.html rename to web_server/webroot/html/simple.html diff --git a/webroot/html5/dataset.html b/web_server/webroot/html5/dataset.html similarity index 100% rename from webroot/html5/dataset.html rename to web_server/webroot/html5/dataset.html diff --git a/webroot/post/index.html b/web_server/webroot/post/index.html similarity index 100% rename from webroot/post/index.html rename to web_server/webroot/post/index.html From 720351871b3c74ed9cc730eaa01083a5515d38bd Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 27 May 2011 16:03:50 +0200 Subject: [PATCH 4/9] fixed typo in assertion --- src/http_connection_handler.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http_connection_handler.e b/src/http_connection_handler.e index 3ed23376..d8a0e2c5 100644 --- a/src/http_connection_handler.e +++ b/src/http_connection_handler.e @@ -94,7 +94,7 @@ feature -- Parsing analyze_request_message (a_input: HTTP_INPUT_STREAM) require - input_redable: a_input /= Void and then not a_input.is_readable + input_readable: a_input /= Void and then a_input.is_readable local end_of_stream : BOOLEAN pos : INTEGER From e5e9f9486ed6eba5457ed24091c9f1aba9ec01f1 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 27 May 2011 19:08:35 +0200 Subject: [PATCH 5/9] Added force_single_threaded option Modified the interface of process request default port is now 80 --- nino.ecf | 8 +++++- src/configuration/http_server_configuration.e | 10 +++++++- src/http_connection_handler.e | 25 ++++++++++++++----- src/http_server.e | 8 ++++-- web_server/application_handler.e | 10 +++++--- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/nino.ecf b/nino.ecf index 4fa6a143..992aff1d 100644 --- a/nino.ecf +++ b/nino.ecf @@ -15,6 +15,12 @@ - + + + head_request_handler.e + shared_http_request_handlers.e + http_protocol_handler.e + + diff --git a/src/configuration/http_server_configuration.e b/src/configuration/http_server_configuration.e index 9c21ecf2..e7547db2 100644 --- a/src/configuration/http_server_configuration.e +++ b/src/configuration/http_server_configuration.e @@ -13,11 +13,12 @@ feature {NONE} -- Initialization make do - http_server_port := 9_000 + http_server_port := 80 max_tcp_clients := 100 socket_accept_timeout := 1_000 socket_connect_timeout := 5_000 document_root := "htdocs" + force_single_threaded := False end feature -- Access @@ -29,6 +30,7 @@ feature -- Access max_tcp_clients: INTEGER assign set_max_tcp_clients socket_accept_timeout: INTEGER assign set_socket_accept_timeout socket_connect_timeout: INTEGER assign set_socket_connect_timeout + force_single_threaded: BOOLEAN assign set_force_single_threaded feature -- Element change @@ -57,4 +59,10 @@ feature -- Element change socket_connect_timeout := v end + set_force_single_threaded (v: like force_single_threaded) + do + force_single_threaded := v + end + + end diff --git a/src/http_connection_handler.e b/src/http_connection_handler.e index d8a0e2c5..86295545 100644 --- a/src/http_connection_handler.e +++ b/src/http_connection_handler.e @@ -34,28 +34,39 @@ feature -- Execution local l_input: HTTP_INPUT_STREAM l_output: HTTP_OUTPUT_STREAM + l_remote_info: detachable like remote_info do create l_input.make (client_socket) create l_output.make (client_socket) + create l_remote_info + if attached client_socket.address as l_addr then + l_remote_info.addr := l_addr.host_address.host_address + l_remote_info.hostname := l_addr.host_address.host_name + l_remote_info.port := l_addr.port + end + remote_info := l_remote_info + analyze_request_message (l_input) - process_request (uri, method, request_header_map, request_header, l_input, l_output) + process_request (Current, l_input, l_output) end 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 (a_handler: HTTP_CONNECTION_HANDLER; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM) -- Process request ... require - a_uri_attached: a_uri /= Void - a_method_attached: a_method /= Void - a_headers_text_attached: a_headers_text /= Void + a_handler_attached: a_handler /= Void + a_uri_attached: a_handler.uri /= Void + a_method_attached: a_handler.method /= Void + a_header_map_attached: a_handler.request_header_map /= Void + a_header_text_attached: a_handler.request_header /= Void a_input_attached: a_input /= Void a_output_attached: a_output /= Void deferred end -feature {NONE} -- Access +feature -- Access request_header: STRING -- Header' source @@ -73,6 +84,8 @@ feature {NONE} -- Access -- http_version --| unused for now + remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER] + feature -- Parsing parse_http_request_line (line: STRING) diff --git a/src/http_server.e b/src/http_server.e index 3ef61c09..e3652845 100644 --- a/src/http_server.e +++ b/src/http_server.e @@ -28,8 +28,12 @@ feature -- Initialization print ("Starting Web Application Server:%N") stop_requested := False set_server_configuration (configuration) - a_http_handler.launch - a_http_handler.join + if configuration.force_single_threaded then + a_http_handler.execute + else + a_http_handler.launch + a_http_handler.join + end end shutdown_server diff --git a/web_server/application_handler.e b/web_server/application_handler.e index 9a63a82a..78277160 100644 --- a/web_server/application_handler.e +++ b/web_server/application_handler.e @@ -15,13 +15,17 @@ create 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 (a_handler: HTTP_CONNECTION_HANDLER; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM) -- Process request ... + local + a_method: STRING do + a_method := a_handler.method + if a_method.is_equal (Get) then - execute_get_request (a_uri, a_headers_map, a_headers_text, a_input, a_output) + execute_get_request (a_handler.uri, a_handler.request_header_map, a_handler.request_header, 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) + execute_post_request (a_handler.uri, a_handler.request_header_map, a_handler.request_header, 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 From c544da356155944c04ed3254a276579a303af351 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 27 May 2011 19:44:50 +0200 Subject: [PATCH 6/9] Reset values after processing the request Added port information when starting the server --- src/http_connection_handler.e | 16 ++++++++++++++-- src/http_server.e | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/http_connection_handler.e b/src/http_connection_handler.e index 86295545..7472fde4 100644 --- a/src/http_connection_handler.e +++ b/src/http_connection_handler.e @@ -22,10 +22,16 @@ feature {NONE} -- Initialization -- `a_name': The name of this module do Precursor (a_main_server, a_name) + reset + end + + reset + do create method.make_empty create uri.make_empty create request_header.make_empty create request_header_map.make (10) + remote_info := Void end feature -- Execution @@ -39,13 +45,14 @@ feature -- Execution create l_input.make (client_socket) create l_output.make (client_socket) + reset + create l_remote_info if attached client_socket.address as l_addr then l_remote_info.addr := l_addr.host_address.host_address l_remote_info.hostname := l_addr.host_address.host_name l_remote_info.port := l_addr.port end - remote_info := l_remote_info analyze_request_message (l_input) process_request (Current, l_input, l_output) @@ -112,6 +119,7 @@ feature -- Parsing end_of_stream : BOOLEAN pos : INTEGER line : STRING + val: STRING txt: STRING do create txt.make (64) @@ -130,7 +138,11 @@ feature -- Parsing line := a_input.last_string print ("%N" +line+ "%N") pos := line.index_of (':',1) - request_header_map.put (line.substring (pos + 1, line.count), line.substring (1,pos-1)) + val := line.substring (pos + 1, line.count) + if val[val.count] = '%R' then + val.remove_tail (1) + end + request_header_map.put (val, line.substring (1,pos-1)) txt.append (line) txt.append_character ('%N') if line.is_empty or else line[1] = '%R' then diff --git a/src/http_server.e b/src/http_server.e index e3652845..0bfe0186 100644 --- a/src/http_server.e +++ b/src/http_server.e @@ -25,7 +25,7 @@ feature -- Initialization a_http_handler_valid: a_http_handler /= Void do print("%N%N%N") - print ("Starting Web Application Server:%N") + print ("Starting Web Application Server (port="+ configuration.http_server_port.out +"):%N") stop_requested := False set_server_configuration (configuration) if configuration.force_single_threaded then From 824750e7482dd6cd68364e98ca28fcabe68106c1 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 27 May 2011 22:05:56 +0200 Subject: [PATCH 7/9] Don't forget to reset request data --- src/http_connection_handler.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http_connection_handler.e b/src/http_connection_handler.e index 7472fde4..48872289 100644 --- a/src/http_connection_handler.e +++ b/src/http_connection_handler.e @@ -45,7 +45,6 @@ feature -- Execution create l_input.make (client_socket) create l_output.make (client_socket) - reset create l_remote_info if attached client_socket.address as l_addr then @@ -56,6 +55,7 @@ feature -- Execution analyze_request_message (l_input) process_request (Current, l_input, l_output) + reset end feature -- Request processing From f22f42c4639c2fb68903a87ca394f7504c4c13c2 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Mon, 30 May 2011 11:31:53 +0200 Subject: [PATCH 8/9] Fixed nino.ecf by removing the root class since this is a library config file. --- nino.ecf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nino.ecf b/nino.ecf index 992aff1d..ba85255c 100644 --- a/nino.ecf +++ b/nino.ecf @@ -1,12 +1,12 @@ - + + /.git$ /EIFGENs$ /CVS$ /.svn$ - /.git$