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

    +
    +
    + + +
    + +
    +
    + + +
    + +