From 7f27a6c7970ef259e67fc72c871c27a10d116a38 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 13 Mar 2015 16:26:07 +0100 Subject: [PATCH 01/33] First steps to provide a concurrent compliant EWF connector. --- .../ewsgi/connectors/httpd/dev/app_counter.e | 38 +++ .../connectors/httpd/dev/app_wsf_execution.e | 56 ++++ .../httpd/dev/app_wsf_httpd_request_handler.e | 36 ++ .../httpd/dev/httpd_connector_dev.e | 51 +++ .../httpd/dev/wsf/wsf_httpd_request_handler.e | 264 +++++++++++++++ .../wsf/wsf_httpd_request_handler_factory.e | 30 ++ .../ewsgi/connectors/httpd/httpd-safe.ecf | 74 ++++ .../server/ewsgi/connectors/httpd/license.lic | 10 + .../none/httpd_connection_handler.e | 101 ++++++ .../concurrency/none/httpd_request_handler.e | 30 ++ .../none/httpd_request_handler_factory.e | 16 + .../scoop/httpd_connection_handler.e | 160 +++++++++ .../concurrency/scoop/httpd_request_handler.e | 111 ++++++ .../scoop/httpd_request_handler_factory.e | 21 ++ .../concurrency/scoop/pool/concurrent_pool.e | 181 ++++++++++ .../scoop/pool/concurrent_pool_factory.e | 19 ++ .../scoop/pool/concurrent_pool_item.e | 47 +++ .../thread/httpd_connection_handler.e | 111 ++++++ .../thread/httpd_request_handler.e | 45 +++ .../thread/httpd_request_handler_factory.e | 16 + .../concurrency/thread/pool/pooled_thread.e | 121 +++++++ .../concurrency/thread/pool/thread_pool.e | 228 +++++++++++++ .../configuration/httpd_configuration_i.e | 209 ++++++++++++ .../connectors/httpd/src/httpd/httpd-safe.ecf | 63 ++++ .../connectors/httpd/src/httpd/httpd.ecf | 62 ++++ .../src/httpd/httpd_connection_handler_i.e | 84 +++++ .../httpd/src/httpd/httpd_controller.e | 22 ++ .../httpd/src/httpd/httpd_debug_facilities.e | 40 +++ .../connectors/httpd/src/httpd/httpd_logger.e | 27 ++ .../httpd/httpd_request_handler_factory_i.e | 26 ++ .../httpd/src/httpd/httpd_request_handler_i.e | 278 +++++++++++++++ .../httpd/src/httpd/httpd_server_i.e | 316 ++++++++++++++++++ .../src/httpd/network/httpd_stream_socket.e | 252 ++++++++++++++ .../src/httpd/network/tcp_stream_socket.e | 92 +++++ .../src/httpd/no_ssl/httpd_configuration.e | 71 ++++ .../httpd/src/httpd/no_ssl/httpd_server.e | 27 ++ .../httpd/src/httpd/ssl/httpd_configuration.e | 82 +++++ .../httpd/src/httpd/ssl/httpd_server.e | 35 ++ .../src/httpd/ssl/httpd_stream_ssl_socket.e | 139 ++++++++ .../src/httpd/ssl/ssl_tcp_stream_socket.e | 72 ++++ .../httpd/src/wgi_httpd_error_stream.e | 70 ++++ .../httpd/src/wgi_httpd_input_stream.e | 100 ++++++ .../httpd/src/wgi_httpd_output_stream.e | 104 ++++++ .../httpd/src/wgi_httpd_response_stream.e | 50 +++ .../ewsgi/specification/request/wgi_request.e | 4 +- .../specification/response/wgi_response.e | 4 +- .../implementation/wgi_request_from_table.e | 10 +- library/server/ewsgi/src/wgi_exporter.e | 10 + library/server/wsf/src/wsf_execution.e | 43 +++ library/server/wsf/src/wsf_request.e | 6 +- library/server/wsf/src/wsf_response.e | 2 +- 51 files changed, 4053 insertions(+), 13 deletions(-) create mode 100644 library/server/ewsgi/connectors/httpd/dev/app_counter.e create mode 100644 library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e create mode 100644 library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e create mode 100644 library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e create mode 100644 library/server/ewsgi/connectors/httpd/httpd-safe.ecf create mode 100644 library/server/ewsgi/connectors/httpd/license.lic create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler_factory.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler_factory.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/pooled_thread.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/thread_pool.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/configuration/httpd_configuration_i.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd.ecf create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_controller.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_logger.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_factory_i.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_configuration.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_server.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_configuration.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_server.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_stream_ssl_socket.e create mode 100644 library/server/ewsgi/connectors/httpd/src/httpd/ssl/ssl_tcp_stream_socket.e create mode 100644 library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e create mode 100644 library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e create mode 100644 library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e create mode 100644 library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e create mode 100644 library/server/ewsgi/src/wgi_exporter.e create mode 100644 library/server/wsf/src/wsf_execution.e diff --git a/library/server/ewsgi/connectors/httpd/dev/app_counter.e b/library/server/ewsgi/connectors/httpd/dev/app_counter.e new file mode 100644 index 00000000..1e4a6489 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/dev/app_counter.e @@ -0,0 +1,38 @@ +note + description: "Summary description for {APP_COUNTER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + APP_COUNTER + +create + put + +feature + + item: INTEGER + + put, replace (i: INTEGER) + do + item := i + end + + next_item: INTEGER + do + Result := item + 1 + item := Result + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e b/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e new file mode 100644 index 00000000..b4e817a5 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e @@ -0,0 +1,56 @@ +note + description: "Summary description for {APP_WSF_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + APP_WSF_EXECUTION + +inherit + WSF_EXECUTION + +create + make + +feature -- Execution + + execute + local + s: STRING + do + s := "Hello Concurrent EWF" + s.append (" (counter=") + s.append_integer (next_cell_counter_item (counter_cell)) + s.append (")%N") + + response.set_status_code (200) + response.put_header_line ("X-EWF-Dev: v1.0") + response.header.put_content_type_text_plain + response.header.put_content_length (s.count) + + response.put_string (s) + end + + next_cell_counter_item (cl: like counter_cell): INTEGER + do + Result := cl.next_item + end + + counter_cell: separate APP_COUNTER + once ("PROCESS") + create Result.put (0) + end + + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e new file mode 100644 index 00000000..e2c3c00f --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e @@ -0,0 +1,36 @@ +note + description: "Summary description for {APP_WSF_HTTPD_REQUEST_HANDLER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + APP_WSF_HTTPD_REQUEST_HANDLER + +inherit + WSF_HTTPD_REQUEST_HANDLER + +create + make + +feature -- Execute + + do_more (req: WGI_REQUEST; res: WGI_RESPONSE) + local + exec: WSF_EXECUTION + do + create {APP_WSF_EXECUTION} exec.make (req, res) + exec.execute + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e new file mode 100644 index 00000000..89bc7bea --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e @@ -0,0 +1,51 @@ +note + description: "[ + Objects that ... + ]" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONNECTOR_DEV + +create + make + +feature {NONE} -- Initialization + + make + -- Initialize `Current'. + local + server: HTTPD_SERVER + fac: separate WSF_HTTPD_REQUEST_HANDLER_FACTORY [APP_WSF_EXECUTION] + do + print ("Hello%N") + create fac + create server.make (fac) + server.configuration.set_http_server_port (9090) + server.launch + end + +feature -- Status + +feature -- Access + +feature -- Change + +feature {NONE} -- Implementation + +invariant +-- invariant_clause: True + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e new file mode 100644 index 00000000..c5730b33 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e @@ -0,0 +1,264 @@ +note + description: "Summary description for {WSF_HTTPD_REQUEST_HANDLER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_HTTPD_REQUEST_HANDLER [G -> WSF_EXECUTION create make end] + +inherit + HTTPD_REQUEST_HANDLER + + WGI_EXPORTER + + REFACTORING_HELPER + +create + make + +feature -- Request processing + + process_request (a_socket: HTTPD_STREAM_SOCKET) + -- Process request ... + local + l_input: WGI_INPUT_STREAM + l_output: WGI_OUTPUT_STREAM + l_error: WGI_ERROR_STREAM + req: WGI_REQUEST_FROM_TABLE + res: detachable WGI_HTTPD_RESPONSE_STREAM + + exec: WSF_EXECUTION + retried: BOOLEAN + do + if not retried then + create {WGI_HTTPD_INPUT_STREAM} l_input.make (a_socket) + create {WGI_HTTPD_OUTPUT_STREAM} l_output.make (a_socket) + create {WGI_HTTPD_ERROR_STREAM} l_error.make_stderr (a_socket.descriptor.out) + + create req.make (httpd_environment (a_socket), l_input, Void) + create res.make (l_output, l_error) + + req.set_meta_string_variable ("RAW_HEADER_DATA", request_header) + + exec := new_execution (req, res) + exec.execute + res.push + else + end + rescue + if not retried then + retried := True + retry + end + end + + new_execution (req: WGI_REQUEST; res: WGI_RESPONSE): WSF_EXECUTION + do + create {G} Result.make (req, res) + end + + base: detachable READABLE_STRING_8 + do + --TODO + to_implement ("Base url support") + end + + httpd_environment (a_socket: HTTPD_STREAM_SOCKET): STRING_TABLE [READABLE_STRING_8] + local + p: INTEGER + l_request_uri, l_script_name, l_query_string, l_path_info: STRING + l_server_name, l_server_port: detachable STRING + l_headers_map: HASH_TABLE [STRING, STRING] + vn: STRING + + e: EXECUTION_ENVIRONMENT + enc: URL_ENCODER + utf: UTF_CONVERTER + do + l_request_uri := uri + l_headers_map := request_header_map + create e + create enc + if attached e.starting_environment as vars then + create Result.make_equal (vars.count) + across + vars as c + loop + Result.force (utf.utf_32_string_to_utf_8_string_8 (c.item), utf.utf_32_string_to_utf_8_string_8 (c.key)) + end + else + create Result.make (0) + end + + --| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `Result' + from + l_headers_map.start + until + l_headers_map.after + loop + create vn.make_from_string (l_headers_map.key_for_iteration.as_upper) + vn.replace_substring_all ("-", "_") + if + vn.starts_with ("CONTENT_") and then + (vn.same_string_general ({WGI_META_NAMES}.content_type) or vn.same_string_general ({WGI_META_NAMES}.content_length)) + then + --| Keep this name + else + vn.prepend ("HTTP_") + end + add_environment_variable (l_headers_map.item_for_iteration, vn, Result) + l_headers_map.forth + end + + --| Specific cases + + p := l_request_uri.index_of ('?', 1) + if p > 0 then + l_script_name := l_request_uri.substring (1, p - 1) + l_query_string := l_request_uri.substring (p + 1, l_request_uri.count) + else + l_script_name := l_request_uri.string + l_query_string := "" + end + if attached l_headers_map.item ("Host") as l_host then + check has_host: Result.has ("HTTP_HOST") end +-- set_environment_variable (l_host, "HTTP_HOST", Result) + p := l_host.index_of (':', 1) + if p > 0 then + l_server_name := l_host.substring (1, p - 1) + l_server_port := l_host.substring (p+1, l_host.count) + else + l_server_name := l_host + l_server_port := "80" -- Default + end + else + check host_available: False end + end + + if attached l_headers_map.item ("Authorization") as l_authorization then + check has_authorization: Result.has ("HTTP_AUTHORIZATION") end +-- set_environment_variable (l_authorization, "HTTP_AUTHORIZATION", Result) + p := l_authorization.index_of (' ', 1) + if p > 0 then + set_environment_variable (l_authorization.substring (1, p - 1), "AUTH_TYPE", Result) + end + end + + set_environment_variable ("CGI/1.1", "GATEWAY_INTERFACE", Result) + set_environment_variable (l_query_string, "QUERY_STRING", Result) + + if attached remote_info as l_remote_info then + set_environment_variable (l_remote_info.addr, "REMOTE_ADDR", Result) + set_environment_variable (l_remote_info.hostname, "REMOTE_HOST", Result) + set_environment_variable (l_remote_info.port.out, "REMOTE_PORT", Result) +-- set_environment_variable (Void, "REMOTE_IDENT", Result) +-- set_environment_variable (Void, "REMOTE_USER", Result) + end + + set_environment_variable (l_request_uri, "REQUEST_URI", Result) + set_environment_variable (method, "REQUEST_METHOD", Result) + + set_environment_variable (l_script_name, "SCRIPT_NAME", Result) + set_environment_variable (l_server_name, "SERVER_NAME", Result) + set_environment_variable (l_server_port, "SERVER_PORT", Result) + set_environment_variable (version, "SERVER_PROTOCOL", Result) + set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result) + + --| Apply `base' value + if attached base as l_base and then l_request_uri /= Void then + if l_request_uri.starts_with (l_base) then + l_path_info := l_request_uri.substring (l_base.count + 1, l_request_uri.count) + p := l_path_info.index_of ('?', 1) + if p > 0 then + l_path_info.keep_head (p - 1) + end + Result.force (l_base, "SCRIPT_NAME") + else + -- This should not happen, this means the `base' is not correctly set. + -- It is better to consider base as empty, rather than having empty PATH_INFO + check valid_base_value: False end + + l_path_info := l_request_uri + p := l_request_uri.index_of ('?', 1) + if p > 0 then + l_path_info := l_request_uri.substring (1, p - 1) + else + l_path_info := l_request_uri.string + end + Result.force ("", "SCRIPT_NAME") + end + --| In order to have same path value for PATH_INFO on various connectors and servers + --| the multiple slashes must be stripped to single slash. + --| tested with: CGI+apache, libfcgi+apache on Windows and Linux + --| + --| For example: "////abc/def///end////" to "/abc/def/end/" ? + convert_multiple_slashes_to_single (l_path_info) + Result.force (enc.decoded_utf_8_string (l_path_info), "PATH_INFO") + end + end + + add_environment_variable (a_value: detachable STRING; a_var_name: READABLE_STRING_GENERAL; env: STRING_TABLE [READABLE_STRING_8]) + -- Add variable `a_var_name => a_value' to `env' + do + if a_value /= Void then + if env.has_key (a_var_name) and then attached env.found_item as l_existing_value then + --| Check http://www.ietf.org/rfc/rfc3875 4.1.18 + check find_proper_rewrite_for_same_header: False end + env.force (l_existing_value + " " + a_value, a_var_name) + else + env.force (a_value, a_var_name) + end + end + end + + set_environment_variable (a_value: detachable STRING; a_var_name: READABLE_STRING_GENERAL; env: STRING_TABLE [READABLE_STRING_8]) + -- Add variable `a_var_name => a_value' to `env' + do + if a_value /= Void then + env.force (a_value, a_var_name) + end + end + +feature {NONE} -- Implementation + + convert_multiple_slashes_to_single (s: STRING_8) + -- Replace multiple slashes sequence by a single slash character. + local + i,n: INTEGER + do + from + i := 1 + n := s.count + until + i > n + loop + if s[i] = '/' then + -- Remove following slashes '/'. + from + i := i + 1 + until + i > n or s[i] /= '/' + loop + s.remove (i) + n := n - 1 + end + else + i := i + 1 + end + end + end + + + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e new file mode 100644 index 00000000..94b667f4 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e @@ -0,0 +1,30 @@ +note + description: "Summary description for {WSF_HTTPD_REQUEST_HANDLER_FACTORY}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_HTTPD_REQUEST_HANDLER_FACTORY [G -> WSF_EXECUTION create make end] + +inherit + HTTPD_REQUEST_HANDLER_FACTORY + +feature -- Factory + + new_handler: separate WSF_HTTPD_REQUEST_HANDLER [G] + do + create Result.make + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf new file mode 100644 index 00000000..38f010d3 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -0,0 +1,74 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + + + + + + + + + + /ssl$ + /EIFGENs$ + /no_ssl$ + /concurrency$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /httpd$ + + + + + + + + + diff --git a/library/server/ewsgi/connectors/httpd/license.lic b/library/server/ewsgi/connectors/httpd/license.lic new file mode 100644 index 00000000..d4d72876 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e new file mode 100644 index 00000000..79ae936a --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e @@ -0,0 +1,101 @@ +note + description: "Summary description for {HTTPD_CONNECTION_HANDLER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONNECTION_HANDLER + +inherit + HTTPD_CONNECTION_HANDLER_I + +create + make + +feature {NONE} -- Initialization + + initialize + do + end + +feature -- Access + + is_shutdown_requested: BOOLEAN + + shutdown_requested (a_server: like server): BOOLEAN + do + -- FIXME: we should probably remove this possibility, check with EWF if this is needed. + Result := a_server.controller.shutdown_requested + end + +feature -- Execution + + process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + -- Process incoming connection + -- note that the precondition matters for scoop synchronization. + do + is_shutdown_requested := is_shutdown_requested or shutdown_requested (server) + if is_shutdown_requested then + a_socket.cleanup + elseif attached server.factory.new_handler as h then + process_connection_handler (h, a_socket) + else + check is_not_full: False end + a_socket.cleanup + end + update_is_shutdown_requested + end + + process_connection_handler (hdl: HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) + require + not hdl.has_error + do + --| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection + --| also handle permanent connection...? + + hdl.set_client_socket (a_socket) + if not hdl.has_error then +-- hdl.set_logger (server) + hdl.execute + else + log ("Internal error (set_client_socket failed)") + end + rescue + log ("Releasing handler after exception!") + hdl.release + a_socket.cleanup + end + + update_is_shutdown_requested + do + is_shutdown_requested := shutdown_requested (server) + end + + shutdown + do + if not is_shutdown_requested then + is_shutdown_requested := True + server.controller.shutdown + end + end + +feature {HTTPD_SERVER_I} -- Status report + + wait_for_completion + -- Wait until Current is ready for shutdown + do + -- no concurrency, then current task should be done. + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e new file mode 100644 index 00000000..1e607c5e --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e @@ -0,0 +1,30 @@ +note + description : "Concurrent specific feature to implemente HTTPD_REQUEST_HANDLER" + author : "$Author$" + date : "$Date$" + revision : "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER + +inherit + HTTPD_REQUEST_HANDLER_I + +feature -- Change + + set_client_socket (a_socket: HTTPD_STREAM_SOCKET) + do + client_socket := a_socket + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler_factory.e new file mode 100644 index 00000000..8bff0870 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler_factory.e @@ -0,0 +1,16 @@ +note + description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER_FACTORY + +inherit + HTTPD_REQUEST_HANDLER_FACTORY_I + +note + copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e new file mode 100644 index 00000000..fcf5c3d7 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -0,0 +1,160 @@ +note + description: "Summary description for {HTTPD_CONNECTION_HANDLER}." + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONNECTION_HANDLER + +inherit + HTTPD_CONNECTION_HANDLER_I + redefine + initialize + end + +create + make + +feature {NONE} -- Initialization + + initialize + local + n: INTEGER + p: like pool + do + n := max_concurrent_connections (server) + create p.make (n) + initialize_pool (p, n) + pool := p + end + + initialize_pool (p: like pool; n: INTEGER) + do + p.set_count (n) + end + +feature -- Access + + is_shutdown_requested: BOOLEAN + + max_concurrent_connections (a_server: like server): INTEGER + do + Result := a_server.configuration.max_concurrent_connections + end + +feature {HTTPD_SERVER_I} -- Execution + + shutdown + do + if not is_shutdown_requested then + is_shutdown_requested := True + pool_gracefull_stop (pool) + end + end + + pool_gracefull_stop (p: like pool) + do + p.gracefull_stop + end + + process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + -- + do + debug ("dbglog") + dbglog (generator + ".before process_incoming_connection {"+ a_socket.descriptor.out +"} -- SCOOP WAIT!") + end +-- if is_shutdown_requested then +-- a_socket.cleanup +-- else + process_connection_on_pool (a_socket, pool) -- Wait on not pool.is_full or is_stop_requested +-- end + debug ("dbglog") + dbglog (generator + ".after process_incoming_connection {"+ a_socket.descriptor.out +"}") + end + end + + process_connection_on_pool (a_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) + -- Process incoming connection + -- note that the precondition matters for scoop synchronization. + require + concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested + do + debug ("dbglog") + dbglog (generator + ".ENTER process_connection {"+ a_socket.descriptor.out +"}") + end + if is_shutdown_requested then + a_socket.cleanup + elseif attached a_pool.separate_item (factory) as h then + process_request_handler (h, a_socket) + else + check is_not_full: False end + a_socket.cleanup + end + debug ("dbglog") + dbglog (generator + ".LEAVE process_connection {"+ a_socket.descriptor.out +"}") + end + end + + process_request_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) + require + not hdl.has_error + do + --| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection + --| also handle permanent connection...? + + debug ("dbglog") + dbglog (generator + ".ENTER process_request_handler {"+ a_socket.descriptor.out +"}") + end + + hdl.set_client_socket (a_socket) + if hdl.has_error then + log ("Internal error (set_client_socket failed)") + else +-- hdl.set_logger (server) + if attached hdl.separate_execution as l_result then + end + hdl.separate_release + end + debug ("dbglog") + dbglog (generator + ".LEAVE process_request_handler {"+ a_socket.descriptor.out +"}") + end + rescue + log ("Releasing handler after exception!") + hdl.separate_release +-- a_socket.cleanup + end + +feature {HTTPD_SERVER_I} -- Status report + + wait_for_completion + -- Wait until Current is ready for shutdown + do + wait_for_pool_completion (pool) + end + + wait_for_pool_completion (p: like pool) + require + p.is_empty + do + p.terminate + end + +feature {NONE} -- Access + + pool: separate CONCURRENT_POOL [HTTPD_REQUEST_HANDLER] + -- Pool of separate connection handlers. + +invariant + pool_attached: pool /= Void + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e new file mode 100644 index 00000000..2c5754fc --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -0,0 +1,111 @@ +note + description: "[ + Instance of HTTPD_REQUEST_HANDLER will process the incoming connection + and extract information on the request and the server + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER + +inherit + HTTPD_REQUEST_HANDLER_I + redefine +-- set_client_socket, + release, + reset + end + + CONCURRENT_POOL_ITEM + rename + release as release_pool_item + end + +feature {NONE} -- Initialization + + reset + do + if attached client_socket_source as l_sock then + cleanup_separate_socket (l_sock) + end + Precursor + client_socket_source := Void + end + + cleanup_separate_socket (a_socket: attached like client_socket_source) + do + a_socket.cleanup + end + +feature -- Access + + client_socket: detachable HTTPD_STREAM_SOCKET + + client_socket_source: detachable separate HTTPD_STREAM_SOCKET + -- Associated original client socket + -- kept to avoid being closed when disposed, + -- and thus avoid closing related `client_socket'. + +feature -- Change + + set_client_socket (a_socket: separate HTTPD_STREAM_SOCKET) + local + retried: BOOLEAN + do + if retried then + has_error := True + else + create client_socket.make_from_separate (a_socket) + client_socket_source := a_socket + end + rescue + retried := True + retry + end + +feature -- Execution + + separate_execution: BOOLEAN + do + if attached client_socket as s then + execute (s) + end + Result := True + end + +feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation + + separate_release + do + if attached client_socket as s then + release (s) + end + end + + release (a_socket: HTTPD_STREAM_SOCKET) + local + d: STRING + do + d := a_socket.descriptor.out + debug ("dbglog") + dbglog (generator + ".release: ENTER {" + d + "}") + end + Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) + release_pool_item + debug ("dbglog") + dbglog (generator + ".release: LEAVE {" + d + "}") + end + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e new file mode 100644 index 00000000..843fc8e3 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e @@ -0,0 +1,21 @@ +note + description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER_FACTORY + +inherit + HTTPD_REQUEST_HANDLER_FACTORY_I + + CONCURRENT_POOL_FACTORY [HTTPD_REQUEST_HANDLER] + rename + new_separate_item as new_handler + end + +note + copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e new file mode 100644 index 00000000..0bead25a --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e @@ -0,0 +1,181 @@ +note + description: "Summary description for {CONCURRENT_POOL}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + CONCURRENT_POOL [G -> CONCURRENT_POOL_ITEM] + +inherit + HTTPD_DEBUG_FACILITIES + +create + make + +feature {NONE} -- Initialization + + make (n: INTEGER) + do + capacity := n + create items.make_empty (n) +-- create busy_items.make_filled (False, n) + create busy_items.make_empty (n) + end + +feature -- Access + + count: INTEGER + + is_full: BOOLEAN + do + Result := count >= capacity + end + + is_empty: BOOLEAN + do + Result := count = 0 + end + + capacity: INTEGER + + stop_requested: BOOLEAN + +feature -- Access + + separate_item (a_factory: separate CONCURRENT_POOL_FACTORY [G]): detachable separate G + require + is_not_full: not is_full + local + i,n,pos: INTEGER + lst: like busy_items + l_item: detachable separate G + do + if not stop_requested then + from + lst := busy_items + pos := -1 + i := 0 + n := lst.count - 1 + until + i > n or l_item /= Void or pos >= 0 + loop + if not lst [i] then -- is free (i.e not busy) + pos := i + + if items.valid_index (pos) then + l_item := items [pos] + if l_item /= Void then + busy_items [pos] := True + end + end + if l_item = Void then + -- Empty, then let's create one. + l_item := a_factory.new_separate_item + register_item (l_item) + items [pos] := l_item + end + end + i := i + 1 + end + if l_item = Void then + -- Pool is FULL ... + check overcapacity: False end + else + debug ("pool", "dbglog") + dbglog ("Lock pool item #" + pos.out + " (free:"+ (capacity - count).out +"))") + end + count := count + 1 + busy_items [pos] := True + Result := l_item + end + end + end + +feature -- Basic operation + + gracefull_stop + do + stop_requested := True + end + +feature {NONE} -- Internal + + items: SPECIAL [detachable separate G] + + busy_items: SPECIAL [BOOLEAN] + +feature {CONCURRENT_POOL_ITEM} -- Change + + release_item (a_item: separate G) + -- Unregister `a_item' from Current pool. + require + count > 0 + local + i,n,pos: INTEGER + lst: like items + do + -- release handler for reuse + from + lst := items + i := 0 + n := lst.count - 1 + until + i > n or lst [i] = a_item + loop + i := i + 1 + end + if i <= n then + pos := i + busy_items [pos] := False + count := count - 1 +--reuse items [pos] := Void + debug ("pool", "dbglog") + dbglog ("Released pool item #" + i.out + " (free:"+ (capacity - count).out +"))") + end + else + check known_item: False end + end + end + +feature -- Change + + set_count (n: INTEGER) + local + g: detachable separate G + do + capacity := n + items.fill_with (g, 0, n - 1) + busy_items.fill_with (False, 0, n - 1) + end + + terminate + local + l_items: like items + do + l_items := items + l_items.wipe_out + end + +feature {NONE} -- Implementation + +-- new_separate_item: separate G +-- deferred +-- end + + register_item (a_item: separate G) + do + a_item.set_pool (Current) + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e new file mode 100644 index 00000000..497fbb69 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e @@ -0,0 +1,19 @@ +note + description: "Summary description for {CONCURRENT_POOL_FACTORY}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + CONCURRENT_POOL_FACTORY [G -> CONCURRENT_POOL_ITEM] + +feature -- Access + + new_separate_item: separate G + deferred + end + +note + copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e new file mode 100644 index 00000000..c197fd88 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e @@ -0,0 +1,47 @@ +note + description: "Summary description for {CONCURRENT_POOL_ITEM}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + CONCURRENT_POOL_ITEM + +feature {NONE} -- Access + + pool: detachable separate CONCURRENT_POOL [CONCURRENT_POOL_ITEM] + +feature {CONCURRENT_POOL} -- Change + + set_pool (p: like pool) + do + pool := p + end + +feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation + + release + do + if attached pool as p then + pool_release (p) + end + end + +feature {NONE} -- Implementation + + pool_release (p: separate CONCURRENT_POOL [CONCURRENT_POOL_ITEM]) + do + p.release_item (Current) + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e new file mode 100644 index 00000000..d3d1354e --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e @@ -0,0 +1,111 @@ +note + description: "Summary description for {HTTPD_CONNECTION_HANDLER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONNECTION_HANDLER + +inherit + HTTPD_CONNECTION_HANDLER_I + redefine + initialize + end + +create + make + +feature {NONE} -- Initialization + + initialize + local + n: INTEGER + do + n := max_concurrent_connections (server) + create pool.make (n.to_natural_32) + end + +feature -- Access + + is_shutdown_requested: BOOLEAN + + max_concurrent_connections (a_server: like server): INTEGER + do + Result := a_server.configuration.max_concurrent_connections + end + +feature {HTTPD_SERVER_I} -- Execution + + shutdown + do + if not is_shutdown_requested then + is_shutdown_requested := True + pool_gracefull_stop (pool) + end + end + + pool_gracefull_stop (p: like pool) + do + p.terminate + end + + process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + do + if is_shutdown_requested then + a_socket.cleanup + else + process_connection_handler (factory.new_handler, a_socket) + end + end + + process_connection_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) + require + not hdl.has_error + do + debug ("dbglog") + dbglog (generator + ".ENTER process_connection_handler {"+ a_socket.descriptor.out +"}") + end + if not hdl.has_error then +-- hdl.set_logger (server) +-- hdl.set_client_socket (a_socket) + pool.add_work (agent hdl.execute (a_socket)) + else + log ("Internal error (set_client_socket failed)") + end + debug ("dbglog") + dbglog (generator + ".LEAVE process_connection_handler {"+ a_socket.descriptor.out +"}") + end + rescue + log ("Releasing handler after exception!") + hdl.release (a_socket) +-- hdl.client_socket.cleanup + end + +feature {HTTPD_SERVER_I} -- Status report + + wait_for_completion + -- Wait until Current is ready for shutdown + do + pool.wait_for_completion + end + +feature {NONE} -- Access + + pool: THREAD_POOL [HTTPD_REQUEST_HANDLER] --ANY] --POOLED_THREAD [HTTP_REQUEST_HANDLER]] + -- Pool of concurrent connection handlers. + +invariant + pool_attached: pool /= Void + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e new file mode 100644 index 00000000..a119e283 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e @@ -0,0 +1,45 @@ +note + description: "[ + Instance of HTTPD_REQUEST_HANDLER will process the incoming connection + and extract information on the request and the server + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER + +inherit + HTTPD_REQUEST_HANDLER_I + redefine + release + end + +feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation + + release (a_socket: HTTPD_STREAM_SOCKET) + local + d: STRING + do + -- FIXME: for log purpose + d := a_socket.descriptor.out + debug ("dbglog") + dbglog (generator + ".release: ENTER {" + d + "}") + end + Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) + debug ("dbglog") + dbglog (generator + ".release: LEAVE {" + d + "}") + end + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler_factory.e new file mode 100644 index 00000000..8bff0870 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler_factory.e @@ -0,0 +1,16 @@ +note + description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER_FACTORY + +inherit + HTTPD_REQUEST_HANDLER_FACTORY_I + +note + copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/pooled_thread.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/pooled_thread.e new file mode 100644 index 00000000..b39e18be --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/pooled_thread.e @@ -0,0 +1,121 @@ +note + description: "{POOLED_THREAD} is used in combination with {THREAD_POOL} to allow for pooled threads." + legal: "See notice at end of class." + status: "Community Preview 1.0" + date: "$Date: 2009-09-01 19:15:37 -0300 (mar 01 de sep de 2009) $" + revision: "$Revision: 80577 $" + +class + POOLED_THREAD [G] + +inherit + THREAD + rename + make as thread_make + end + +create {THREAD_POOL} + make + +feature {NONE} -- Initialization + + make (a_thread_pool: THREAD_POOL [G]; a_semaphore: SEMAPHORE) + -- `a_thread_pool', the pool in which this thread is managed + -- `a_semaphore' is used for execution suspending + do + thread_make + thread_pool := a_thread_pool + semaphore := a_semaphore + end + +feature {NONE} -- Access + + thread_pool: THREAD_POOL [G] + -- Pool manager in which this thread is pooled + + target: detachable G + -- Target on which the `thread_procedure' should be applied + -- Depending on which launch is used, target is not used + + thread_procedure: detachable PROCEDURE [G, TUPLE] + -- Work that should be executed by the thread + + semaphore: SEMAPHORE + -- Semaphore share with all threads in a thread pool + -- to suspend execution until more work is available + +feature -- Access + + set_target (a_target: G) + -- Sets the target on which the work should be executed + do + target := a_target + end + +feature {NONE} -- Implementation + + execute + -- + local + done: BOOLEAN + do + from + semaphore.wait + thread_procedure := thread_pool.get_work (Current) + until + done + loop + if attached thread_procedure as l_work then + if attached target as t then + l_work.call ([t]) + else + l_work.call (Void) + end + end + if thread_pool.over then + done := True + else + thread_procedure := thread_pool.get_work (Current) + if thread_procedure = Void then + semaphore.wait + thread_procedure := thread_pool.get_work (Current) + end + end + end + thread_pool.thread_terminated (Current) + end + +note + copyright: "2011-2012, Javier Velilla and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + licensing_options: "http://www.eiffel.com/licensing" + copying: "[ + This file is part of Eiffel Software's Eiffel Development Environment. + + Eiffel Software's Eiffel Development Environment is free + software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published + by the Free Software Foundation, version 2 of the License + (available at the URL listed under "license" above). + + Eiffel Software's Eiffel Development Environment is + distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with Eiffel Software's Eiffel Development + Environment; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ]" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end + + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/thread_pool.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/thread_pool.e new file mode 100644 index 00000000..445aadae --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/thread_pool.e @@ -0,0 +1,228 @@ +note + description: "[ + A thread pool manager. Manages threads up to `capacity' and queue after that, + till threads get available again. + ]" + legal: "See notice at end of class." + status: "Community Preview 1.0" + date: "$Date: 2009-09-01 19:15:37 -0300 (mar 01 de sep de 2009) $" + revision: "$Revision: 80577 $" + +class + THREAD_POOL [G] + +inherit + EXECUTION_ENVIRONMENT + +create + make + +feature {NONE} -- Initialization + + make (n: like capacity) + -- Initialize current pool with capacity `n'. + require + n_positive: n > 0 + n_not_too_large: n < {INTEGER_32}.max_value.as_natural_32 + local + i: NATURAL + do + capacity := n + create work_queue.make (n.to_integer_32) + create work_queue_mutex.make + create over_mutex.make + create termination_mutex.make + create work_semaphore.make (capacity.as_integer_32) + from + i := 1 + until + i > capacity + loop + work_semaphore.wait + i := i + 1 + end + initialize_threads + terminated_count := capacity + is_over := False + ensure + capacity_set: capacity = n + work_queue_set: work_queue.is_empty + end + + initialize_threads + -- Launches all threads + local + i: NATURAL + thread: POOLED_THREAD [G] + do + from + i := 1 + until + i > capacity + loop + create thread.make (Current, work_semaphore) + thread.launch + i := i + 1 + end + end + +feature -- Access + + capacity: NATURAL + -- Maximal number of threads allowed (queuing otherwise) + + queue_count: NATURAL + -- Number of items in queue + do + work_queue_mutex.lock + Result := work_queue.count.as_natural_32 + work_queue_mutex.unlock + end + +feature -- Status report + + valid_action (a_action: PROCEDURE [G, TUPLE]): BOOLEAN + -- Is `a_action' a valid action for the current pool. + do + -- There should be no open operands. + Result := a_action.valid_operands (Void) + end + +feature -- Basic operations + + add_work (work: PROCEDURE [G, TUPLE]) + -- Launches a thread with the specified argument `arg'. Reuse of thread if possible. + require + valid_action: valid_action (work) + do + work_queue_mutex.lock + work_queue.extend (work) + if work_queue.count <= capacity.as_integer_32 then + -- Let one thread wake up and do the work + work_semaphore.post + end + work_queue_mutex.unlock + end + + over: BOOLEAN + -- Is the thread pool being terminated? + do + over_mutex.lock + Result := is_over + over_mutex.unlock + end + + thread_terminated (a_thread: POOLED_THREAD [G]) + -- Notifies the thread pool that a thread has terminated its execution. + do + termination_mutex.lock + terminated_count := terminated_count - 1 + termination_mutex.unlock + end + + get_work (requester: POOLED_THREAD [G]): detachable PROCEDURE [G, TUPLE] + -- If there is work to do, it is returned + -- Yields Void otherwise + do + if not over then + work_queue_mutex.lock + if not work_queue.is_empty then + Result := work_queue.item + work_queue.remove + end + work_queue_mutex.unlock + end + end + + wait_for_completion + -- Wait until there is no more work to be completed + local + done: BOOLEAN + do + from + + until + done + loop + work_queue_mutex.lock + done := work_queue.is_empty + work_queue_mutex.unlock + if not done then + sleep (1) + end + end + end + + terminate + -- Terminates all the threads after their execution + do + over_mutex.lock + is_over := True + over_mutex.unlock + from + termination_mutex.lock + until + terminated_count = 0 + loop + work_semaphore.post + termination_mutex.unlock + termination_mutex.lock + end + termination_mutex.unlock + end + +feature {NONE} -- Implementation: Access + + work_queue: ARRAYED_QUEUE [PROCEDURE [G, TUPLE]] + -- Queue that holds unprocessed requests as agents + -- Thread-safe access when accessor holds `queue_mutex' + + work_queue_mutex: MUTEX + -- Mutex for the queue + + work_semaphore: SEMAPHORE + -- Semaphore which hols the number of work to be done. + -- Needed to wake up worker threads + + terminated_count: NATURAL + -- + + is_over: BOOLEAN + -- Is the thread pool being terminated? + + over_mutex: MUTEX + -- Mutex for the `is_over' variable + + termination_mutex: MUTEX +;note + copyright: "2011-2012, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + licensing_options: "http://www.eiffel.com/licensing" + copying: "[ + This file is part of Eiffel Software's Eiffel Development Environment. + + Eiffel Software's Eiffel Development Environment is free + software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published + by the Free Software Foundation, version 2 of the License + (available at the URL listed under "license" above). + + Eiffel Software's Eiffel Development Environment is + distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with Eiffel Software's Eiffel Development + Environment; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ]" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/configuration/httpd_configuration_i.e new file mode 100644 index 00000000..7acf397b --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/configuration/httpd_configuration_i.e @@ -0,0 +1,209 @@ +note + description: "Summary description for {HTTPD_CONFIGURATION_I}." + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_CONFIGURATION_I + +feature {NONE} -- Initialization + + make + do + http_server_port := 80 + max_concurrent_connections := 100 + max_tcp_clients := 100 + socket_accept_timeout := 1_000 + socket_connect_timeout := 5_000 + keep_alive_timeout := 5 + is_secure := False + create ca_crt.make_empty + create ca_key.make_empty + end + +feature -- Access + + Server_details: STRING_8 + deferred + end + + http_server_name: detachable READABLE_STRING_8 assign set_http_server_name + http_server_port: INTEGER assign set_http_server_port + max_tcp_clients: INTEGER assign set_max_tcp_clients + max_concurrent_connections: INTEGER assign set_max_concurrent_connections + 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 + do + Result := (max_concurrent_connections = 0) + end + + is_verbose: BOOLEAN assign set_is_verbose + -- Display verbose message to the output? + + keep_alive_timeout: INTEGER assign set_keep_alive_timeout + -- Persistent connection timeout + -- Timeout unit in Seconds. + + has_ssl_support: BOOLEAN + -- Has SSL support? + deferred + end + +feature -- Access: SSL + + is_secure: BOOLEAN + -- Is SSL/TLS session?. + + ca_crt: STRING + + ca_key: STRING + + ssl_protocol: NATURAL + -- By default protocol is tls 1.2. + +feature -- Element change + + set_http_server_name (v: detachable separate READABLE_STRING_8) + do + if v = Void then + unset_http_server_name +-- http_server_name := Void + else + create {IMMUTABLE_STRING_8} http_server_name.make_from_separate (v) + end + end + + unset_http_server_name + do + http_server_name := Void + end + + set_http_server_port (v: like http_server_port) + do + http_server_port := v + end + + set_max_tcp_clients (v: like max_tcp_clients) + do + max_tcp_clients := v + end + + set_max_concurrent_connections (v: like max_concurrent_connections) + do + max_concurrent_connections := 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 + + set_force_single_threaded (v: like force_single_threaded) + do + if v then + set_max_concurrent_connections (0) + end + end + + set_is_verbose (b: BOOLEAN) + -- Set `is_verbose' to `b' + do + is_verbose := b + end + + set_keep_alive_timeout (a_seconds: like keep_alive_timeout) + -- Set `keep_alive_timeout' with `a_seconds' + do + keep_alive_timeout := a_seconds + ensure + keep_alive_timeout_set: keep_alive_timeout = a_seconds + end + + mark_secure + -- Set is_secure in True + do + if has_ssl_support then + is_secure := True + if http_server_port = 80 then + set_http_server_port (443) + end + else + is_secure := False + end + end + +feature -- Element change + + set_ca_crt (a_value: STRING) + -- Set `ca_crt' with `a_value' + do + ca_crt := a_value + ensure + ca_crt_set: ca_crt = a_value + end + + set_ca_key (a_value: STRING) + -- Set `ca_key' with `a_value' + do + ca_key := a_value + ensure + ca_key_set: ca_key = a_value + end + + set_ssl_protocol (a_version: NATURAL) + -- Set `ssl_protocol' with `a_version' + do + ssl_protocol := a_version + ensure + ssl_protocol_set: ssl_protocol = a_version + end + +feature -- SSL Helpers + + set_ssl_protocol_to_ssl_2_or_3 + -- Set `ssl_protocol' with `Ssl_23'. + deferred + end + + set_ssl_protocol_to_ssl_3 + -- Set `ssl_protocol' with `Ssl_3'. + deferred + end + + set_ssl_protocol_to_tls_1_0 + -- Set `ssl_protocol' with `Tls_1_0'. + deferred + end + + set_ssl_protocol_to_tls_1_1 + -- Set `ssl_protocol' with `Tls_1_1'. + deferred + end + + set_ssl_protocol_to_tls_1_2 + -- Set `ssl_protocol' with `Tls_1_2'. + deferred + end + + set_ssl_protocol_to_dtls_1_0 + -- Set `ssl_protocol' with `Dtls_1_0'. + deferred + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf new file mode 100644 index 00000000..d6691fca --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf @@ -0,0 +1,63 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + + + + + + + + + + + /EIFGENs$ + /concurrency$ + /ssl$ + /no_ssl$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd.ecf b/library/server/ewsgi/connectors/httpd/src/httpd/httpd.ecf new file mode 100644 index 00000000..aa6a08a0 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd.ecf @@ -0,0 +1,62 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + + + + + + + + + + + /EIFGENs$ + /concurrency$ + /ssl$ + /no_ssl$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e new file mode 100644 index 00000000..d9708723 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e @@ -0,0 +1,84 @@ +note + description: "Summary description for {HTTPD_CONNECTION_HANDLER_I}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_CONNECTION_HANDLER_I + +inherit + HTTPD_DEBUG_FACILITIES + +feature {NONE} -- Initialization + + frozen make (a_server: like server) + do + server := a_server + factory := separate_factory (a_server) + initialize + end + + initialize + deferred + end + + separate_factory (a_server: like server): like factory + -- Separate factory from `a_server'. + --| required by SCOOP design. + do + Result := a_server.factory + end + +feature {NONE} -- Access + + factory: separate HTTPD_REQUEST_HANDLER_FACTORY + + server: separate HTTPD_SERVER_I + +feature {HTTPD_SERVER_I} -- Execution + + process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + deferred + end + + shutdown + deferred + end + + wait_for_completion + -- Wait until Current completed any pending task + deferred + end + +feature {HTTPD_SERVER} -- Status report + + is_shutdown_requested: BOOLEAN + deferred + end + +feature {NONE} -- Output + + log (a_message: separate READABLE_STRING_8) + -- Log `a_message' + do + -- FIXME: Concurrency issue on `server' + separate_server_log (server, a_message) + end + + separate_server_log (a_server: like server; a_message: separate READABLE_STRING_8) + do + a_server.log (a_message) + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_controller.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_controller.e new file mode 100644 index 00000000..8693a71d --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_controller.e @@ -0,0 +1,22 @@ +note + description: "Summary description for {HTTPD_CONTROLLER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONTROLLER + +feature -- Operation + + shutdown + do + shutdown_requested := True + end + + shutdown_requested: BOOLEAN + +;note + copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e new file mode 100644 index 00000000..ac1b0051 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e @@ -0,0 +1,40 @@ +note + description: "Summary description for {HTTPD_DEBUG_FACILITIES}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_DEBUG_FACILITIES + +feature {NONE} -- Output + + dbglog (m: READABLE_STRING_8) + require + not m.ends_with_general ("%N") + do + debug ("dbglog") + print ("[EWF/DBG] <#" + processor_id_from_object (Current).out + "> " + m + "%N") + end + end + +feature -- runtime + + frozen processor_id_from_object (a_object: separate ANY): INTEGER_32 + external + "C inline use %"eif_scoop.h%"" + alias + "RTS_PID(eif_access($a_object))" + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_logger.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_logger.e new file mode 100644 index 00000000..c9668af9 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_logger.e @@ -0,0 +1,27 @@ +note + description: "Summary description for {HTTPD_LOGGER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_LOGGER + +feature -- Logs + + log (a_message: separate READABLE_STRING_8) + -- Log `a_message' + deferred + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_factory_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_factory_i.e new file mode 100644 index 00000000..940d7a0a --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_factory_i.e @@ -0,0 +1,26 @@ +note + description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY_I}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER_FACTORY_I + +feature -- Factory + + new_handler: separate HTTPD_REQUEST_HANDLER + deferred + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e new file mode 100644 index 00000000..5be6fca8 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -0,0 +1,278 @@ +note + description: "Summary description for {HTTPD_REQUEST_HANDLER_I}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_REQUEST_HANDLER_I + +inherit + HTTPD_DEBUG_FACILITIES + +feature {NONE} -- Initialization + + make + do + reset + end + + reset + do + has_error := False + version := Void + remote_info := Void + +-- if attached client_socket as l_sock then +-- l_sock.cleanup +-- end +-- client_socket := Void + + -- FIXME: optimize to just wipe_out if needed + create method.make_empty + create uri.make_empty + create request_header.make_empty + create request_header_map.make (10) + end + +feature -- Access + +-- client_socket: detachable TCP_STREAM_SOCKET + + request_header: STRING + -- Header' source + + request_header_map: HASH_TABLE [STRING, STRING] + -- Contains key:value of the header + + method: STRING + -- http verb + + uri: STRING + -- http endpoint + + version: detachable STRING + -- http_version + --| unused for now + + remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER] + -- Information related to remote client + +feature -- Settings + + is_verbose: BOOLEAN + +feature -- Status report + + has_error: BOOLEAN + -- Error occurred during `analyze_request_message' + +feature -- Change + +-- set_client_socket (a_socket: separate TCP_STREAM_SOCKET) +-- require +-- socket_attached: a_socket /= Void +-- socket_valid: a_socket.is_open_read and then a_socket.is_open_write +-- a_http_socket: not a_socket.is_closed +-- deferred +-- ensure +-- attached client_socket as s implies s.descriptor = a_socket.descriptor +-- end + + set_is_verbose (b: BOOLEAN) + do + is_verbose := b + end + +feature -- Execution + + execute (a_socket: HTTPD_STREAM_SOCKET) + require + socket_attached: a_socket /= Void + socket_valid: a_socket.is_open_read and then a_socket.is_open_write + a_http_socket: not a_socket.is_closed + local + l_remote_info: detachable like remote_info + l_continue: BOOLEAN + do + if a_socket.is_closed then + debug ("dbglog") + dbglog (generator + ".execute {socket is Closed!}") + end + else + debug ("dbglog") + dbglog (generator + ".ENTER execute {" + a_socket.descriptor.out + "}") + end + from until l_continue loop + if a_socket.ready_for_reading then + l_continue := True + create l_remote_info + if attached a_socket.peer_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 + remote_info := l_remote_info + end + analyze_request_message (a_socket) + else + log (generator + ".WAITING execute {" + a_socket.descriptor.out + "}") + end + end + + if has_error then +-- check catch_bad_incoming_connection: False end + if is_verbose then +-- check invalid_incoming_request: False end + log ("ERROR: invalid HTTP incoming request") + end + else + process_request (a_socket) + end + debug ("dbglog") + dbglog (generator + ".LEAVE execute {" + a_socket.descriptor.out + "}") + end + end +-- release (a_socket) + end + + release (a_socket: HTTPD_STREAM_SOCKET) + do + a_socket.cleanup + reset + end + +feature -- Request processing + + process_request (a_socket: HTTPD_STREAM_SOCKET) + -- Process request ... + require + no_error: not has_error + a_uri_attached: uri /= Void + a_method_attached: method /= Void + a_header_map_attached: request_header_map /= Void + a_header_text_attached: request_header /= Void + a_socket_attached: a_socket /= Void + deferred + end + +feature -- Parsing + + analyze_request_message (a_socket: HTTPD_STREAM_SOCKET) + -- Analyze message extracted from `a_socket' as HTTP request + require + input_readable: a_socket /= Void and then a_socket.is_open_read + local + end_of_stream: BOOLEAN + pos, n: INTEGER + line: detachable STRING + k, val: STRING + txt: STRING + l_is_verbose: BOOLEAN + do + create txt.make (64) + request_header := txt + if a_socket.is_readable and then attached next_line (a_socket) as l_request_line and then not l_request_line.is_empty then + txt.append (l_request_line) + txt.append_character ('%N') + analyze_request_line (l_request_line) + else + has_error := True + end + l_is_verbose := is_verbose + if not has_error or l_is_verbose then + -- if `is_verbose' we can try to print the request, even if it is a bad HTTP request + from + line := next_line (a_socket) + until + line = Void or end_of_stream + loop + n := line.count + if l_is_verbose then + log (line) + end + pos := line.index_of (':', 1) + if pos > 0 then + k := line.substring (1, pos - 1) + if line [pos + 1].is_space then + pos := pos + 1 + end + if line [n] = '%R' then + n := n - 1 + end + val := line.substring (pos + 1, n) + request_header_map.put (val, k) + end + txt.append (line) + txt.append_character ('%N') + if line.is_empty or else line [1] = '%R' then + end_of_stream := True + else + line := next_line (a_socket) + end + end + end + end + + analyze_request_line (line: STRING) + -- Analyze `line' as a HTTP request line + require + valid_line: line /= Void and then not line.is_empty + local + pos, next_pos: INTEGER + do + if is_verbose then + log ("%N## Parse HTTP request line ##") + log (line) + end + pos := line.index_of (' ', 1) + method := line.substring (1, pos - 1) + next_pos := line.index_of (' ', pos + 1) + uri := line.substring (pos + 1, next_pos - 1) + version := line.substring (next_pos + 1, line.count) + has_error := method.is_empty + end + + next_line (a_socket: HTTPD_STREAM_SOCKET): detachable STRING + -- Next line fetched from `a_socket' is available. + require + is_readable: a_socket.is_open_read + do + if a_socket.socket_ok then + a_socket.read_line_thread_aware + Result := a_socket.last_string + end + end + +feature -- Output + + logger: detachable HTTPD_LOGGER + + set_logger (a_logger: like logger) + do + logger := a_logger + end + + log (m: STRING) + do + if attached logger as l_logger then + l_logger.log (m) + else + io.put_string (m + "%N") + end + end + +invariant + request_header_attached: request_header /= Void + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e new file mode 100644 index 00000000..c0f92b47 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e @@ -0,0 +1,316 @@ +note + description: "Summary description for {HTTPD_SERVER_I}." + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_SERVER_I + +inherit + HTTPD_DEBUG_FACILITIES + + HTTPD_LOGGER + +feature {NONE} -- Initialization + + make (a_factory: like factory) + -- `a_cfg': server configuration + -- `a_factory': connection handler builder + do + make_configured (create {like configuration}.make, a_factory) + end + + make_configured (a_cfg: like configuration; a_factory: like factory) + -- `a_cfg': server configuration + -- `a_factory': connection handler builder + do + configuration := a_cfg + factory := a_factory + + build_controller + + initialize + end + + build_controller + -- Build `controller'. + do + create controller + end + + initialize + -- Initialize Current server. + do + is_shutdown_requested := False + end + +feature -- Access + + is_verbose: BOOLEAN + -- Is verbose for output messages. + + configuration: HTTPD_CONFIGURATION + -- Associated server configuration. + + controller: separate HTTPD_CONTROLLER + + factory: separate HTTPD_REQUEST_HANDLER_FACTORY + +feature -- Access: listening + + port: INTEGER + -- Effective listening port. + --| If 0 then it is not launched successfully! + +feature -- Status: listening + + is_launched: BOOLEAN + -- Server launched and listening on `port' + + is_terminated: BOOLEAN + -- Is terminated? + + is_shutdown_requested: BOOLEAN + -- Set true to stop accept loop + +feature {NONE} -- Access: server + + request_counter: INTEGER + -- request counter, incremented for each new incoming connection. + +feature -- Execution + + launch + do + apply_configuration + is_terminated := False + if is_verbose then + log ("%N%NStarting Web Application Server (port=" + configuration.http_server_port.out + "):%N") + end + is_shutdown_requested := False + listen + on_terminated + end + + on_terminated + require + is_terminated + do + if is_terminated then + log ("%N%NTerminating Web Application Server (port="+ port.out +"):%N") + end + if attached output as o then + o.flush + o.close + end + end + + shutdown_server + do + debug ("dbglog") + dbglog ("Shutdown requested") + end + is_shutdown_requested := True + controller_shutdown (controller) + end + + controller_shutdown (ctl: attached like controller) + do + ctl.shutdown + end + +feature -- Listening + + listen + -- + -- Creates a socket and connects to the http server. + -- `a_server': The main server object + local + l_listening_socket, + l_accepted_socket: detachable HTTPD_STREAM_SOCKET + l_http_port: INTEGER + l_connection_handler: HTTPD_CONNECTION_HANDLER + do + is_terminated := False + is_launched := False + port := 0 + is_shutdown_requested := False + l_http_port := configuration.http_server_port + + if + attached configuration.http_server_name as l_servername and then + attached (create {INET_ADDRESS_FACTORY}).create_from_name (l_servername) as l_addr + then + l_listening_socket := new_listening_socket (l_addr, l_http_port) + else + l_listening_socket := new_listening_socket (Void, l_http_port) + end + + if not l_listening_socket.is_bound then + if is_verbose then + log ("Socket could not be bound on port " + l_http_port.out) + end + else + l_http_port := l_listening_socket.port + create l_connection_handler.make (Current) + from + l_listening_socket.listen (configuration.max_tcp_clients) + if is_verbose and then configuration.is_secure then + log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/") + elseif is_verbose then + log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") + end + on_launched (l_http_port) + until + is_shutdown_requested + loop + l_listening_socket.accept + if not is_shutdown_requested then + l_accepted_socket := l_listening_socket.accepted + if l_accepted_socket /= Void then + request_counter := request_counter + 1 + if is_verbose then + log ("#" + request_counter.out + "# Incoming connection...(socket:" + l_accepted_socket.descriptor.out + ")") + end + debug ("dbglog") + dbglog (generator + ".before process_incoming_connection {" + l_accepted_socket.descriptor.out + "}" ) + end + l_connection_handler.process_incoming_connection (l_accepted_socket) + debug ("dbglog") + dbglog (generator + ".after process_incoming_connection {" + l_accepted_socket.descriptor.out + "}") + end + end + end + update_is_shutdown_requested (l_connection_handler) + end + wait_for_connection_handler_completion (l_connection_handler) + l_listening_socket.cleanup + check + socket_is_closed: l_listening_socket.is_closed + end + end + if is_launched then + on_stopped + end + if is_verbose then + log ("HTTP Connection Server ends.") + end + rescue + log ("HTTP Connection Server shutdown due to exception. Please relaunch manually.") + + if l_listening_socket /= Void then + l_listening_socket.cleanup + check + listening_socket_is_closed: l_listening_socket.is_closed + end + end + if is_launched then + on_stopped + end + is_shutdown_requested := True + retry + end + +feature {NONE} -- Factory + + new_listening_socket (a_addr: detachable INET_ADDRESS; a_http_port: INTEGER): HTTPD_STREAM_SOCKET + do + if a_addr /= Void then + create Result.make_server_by_address_and_port (a_addr, a_http_port) + else + create Result.make_server_by_port (a_http_port) + end + end + +feature {NONE} -- Helpers + + wait_for_connection_handler_completion (h: HTTPD_CONNECTION_HANDLER) + do + h.wait_for_completion + debug ("dbglog") + dbglog ("Shutdown ready from connection_handler point of view") + end + end + + update_is_shutdown_requested (a_connection_handler: HTTPD_CONNECTION_HANDLER) + do + is_shutdown_requested := is_shutdown_requested or shutdown_requested (controller) + if is_shutdown_requested then + a_connection_handler.shutdown + end + end + + shutdown_requested (a_controller: separate HTTPD_CONTROLLER): BOOLEAN + -- Shutdown requested on concurrent `a_controller'? + do + Result := a_controller.shutdown_requested + end + +feature -- Event + + on_launched (a_port: INTEGER) + -- Server launched using port `a_port' + require + not_launched: not is_launched + do + is_launched := True + port := a_port + ensure + is_launched: is_launched + end + + on_stopped + -- Server stopped + require + is_launched: is_launched + do + is_launched := False + is_terminated := True + ensure + stopped: not is_launched + end + +feature -- Configuration change + + apply_configuration + require + is_not_launched: not is_launched + do + is_verbose := configuration.is_verbose + end + +feature -- Output + + output: detachable FILE + + set_log_output (f: FILE) + do + output := f + end + + log (a_message: separate READABLE_STRING_8) + -- Log `a_message' + local + m: STRING + do + create m.make_from_separate (a_message) + if attached output as o then + o.put_string (m) + o.put_new_line + else + io.error.put_string (m) + io.error.put_new_line + end + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e new file mode 100644 index 00000000..ff4a6361 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e @@ -0,0 +1,252 @@ +note + description: "[ + Summary description for {HTTPD_STREAM_SOCKET} + that can be used for http or https connection. + ]" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_STREAM_SOCKET + +create + make_server_by_address_and_port, + make_server_by_port, + make_from_separate + +create {HTTPD_STREAM_SOCKET} + make + +feature {NONE} -- Initialization + + make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER) + do + create {TCP_STREAM_SOCKET} socket.make_server_by_address_and_port (an_address, a_port) + end + + make_server_by_port (a_port: INTEGER) + do + create {TCP_STREAM_SOCKET} socket.make_server_by_port (a_port) + end + + make_from_separate (s: separate HTTPD_STREAM_SOCKET) + require + descriptor_available: s.descriptor_available + do + create {TCP_STREAM_SOCKET} socket.make_from_separate (s.socket) + end + + retrieve_socket (s: HTTPD_STREAM_SOCKET): INTEGER + do + Result := s.socket.descriptor + end + +feature -- Access + + last_string: STRING + do + Result := socket.last_string + end + + last_character: CHARACTER + do + Result := socket.last_character + end + + peer_address: detachable NETWORK_SOCKET_ADDRESS + -- Peer address of socket + do + if attached {NETWORK_SOCKET_ADDRESS} socket.peer_address as l_peer_address then + Result := l_peer_address + end + end + +feature -- Input + + read_line_thread_aware + do + socket.read_line_thread_aware + end + + read_stream_thread_aware (nb: INTEGER) + do + socket.read_stream_thread_aware (nb) + end + + read_stream (nb: INTEGER) + do + socket.read_stream (nb) + end + + read_character + do + socket.read_character + end + + bytes_read: INTEGER + do + Result := socket.bytes_read + end + +feature -- Output + + send_message (a_msg: STRING) + do + put_string (a_msg) + end + + put_readable_string_8 (s: READABLE_STRING_8) + -- Write readable string `s' to socket. + do + if attached {TCP_STREAM_SOCKET} socket as l_tcp_stream_socket then + l_tcp_stream_socket.put_readable_string_8 (s) + else + put_string (s) + end + end + + put_string (s: STRING) + do + socket.put_string (s) + end + + put_character (c: CHARACTER) + do + socket.put_character (c) + end + +feature -- Status Report + + descriptor_available: BOOLEAN + -- Is descriptor available? + do + Result := socket.descriptor_available + end + + descriptor: INTEGER + do + Result := socket.descriptor + end + + port: INTEGER + do + if attached {TCP_STREAM_SOCKET} socket as l_socket then + Result := l_socket.port + end + end + + is_blocking: BOOLEAN + do + Result := socket.is_blocking + end + + is_bound: BOOLEAN + do + if attached {TCP_STREAM_SOCKET} socket as l_socket then + Result := l_socket.is_bound + end + end + + socket_ok: BOOLEAN + do + Result := socket.socket_ok + end + + is_open_read: BOOLEAN + do + Result := socket.is_open_read + end + + is_open_write: BOOLEAN + do + Result := socket.is_open_write + end + + is_closed: BOOLEAN + do + Result := socket.is_closed + end + + is_readable: BOOLEAN + do + Result := socket.is_readable + end + + cleanup + do + socket.cleanup + end + + ready_for_writing: BOOLEAN + do + if attached {TCP_STREAM_SOCKET} socket as l_socket then + Result := l_socket.ready_for_writing + end + end + + listen (a_queue: INTEGER) + do + socket.listen (a_queue) + end + + accept + do + socket.accept + end + + set_blocking + do + socket.set_blocking + end + + set_non_blocking + do + socket.set_non_blocking + end + + readable: BOOLEAN + do + Result := socket.readable + end + + ready_for_reading: BOOLEAN + do + if attached {TCP_STREAM_SOCKET} socket as l_socket then + Result := l_socket.ready_for_reading + end + end + + try_ready_for_reading: BOOLEAN + do + if attached {TCP_STREAM_SOCKET} socket as l_socket then + Result := l_socket.try_ready_for_reading + end + end + + accepted: detachable HTTPD_STREAM_SOCKET + do + if attached socket.accepted as l_accepted then + create Result.make (l_accepted) + end + end + +feature {HTTPD_STREAM_SOCKET} -- Implementation + + make (a_socket: STREAM_SOCKET) + do + socket := a_socket + end + + socket: STREAM_SOCKET + +;note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e new file mode 100644 index 00000000..1713779d --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e @@ -0,0 +1,92 @@ +note + description: "Summary description for {TCP_STREAM_SOCKET}." + date: "$Date$" + revision: "$Revision$" + +class + TCP_STREAM_SOCKET + +inherit + NETWORK_STREAM_SOCKET + redefine + make + end + +create + make_server_by_address_and_port, + make_server_by_port, + make_from_separate + +create {NETWORK_STREAM_SOCKET} + make_from_descriptor_and_address, + make_empty + +feature {NONE} -- Initialization + + make + -- Create a network stream socket. + do + Precursor + set_reuse_address + end + + make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER) + -- Create server socket on `an_address' and `a_port'. + require + valid_port: a_port >= 0 + do + make + create address.make_from_address_and_port (an_address, a_port) + bind + end + + make_from_separate (s: separate STREAM_SOCKET) + require + descriptor_available: s.descriptor_available + do + create_from_descriptor (s.descriptor) + end + +feature -- Basic operation + + send_message (a_msg: STRING) + do + put_string (a_msg) + end + +feature -- Output + + put_readable_string_8 (s: READABLE_STRING_8) + -- Write readable string `s' to socket. + local + ext: C_STRING + do + create ext.make (s) + put_managed_pointer (ext.managed_data, 0, s.count) + end + +feature -- Status report + + try_ready_for_reading: BOOLEAN + -- Is data available for reading from the socket right now? + require + socket_exists: exists + local + retval: INTEGER + do + retval := c_select_poll_with_timeout (descriptor, True, 0) + Result := (retval > 0) + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_configuration.e b/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_configuration.e new file mode 100644 index 00000000..b62114ff --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_configuration.e @@ -0,0 +1,71 @@ +note + description: "Summary description for {HTTPD_CONFIGURATION}." + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONFIGURATION + +inherit + HTTPD_CONFIGURATION_I + +create + make + +feature -- Status + + Server_details: STRING_8 = "Server : NINO Eiffel Server" + + has_ssl_support: BOOLEAN = False + -- Precursor + +feature -- SSL Helpers + + set_ssl_protocol_to_ssl_2_or_3 + -- Set `ssl_protocol' with `Ssl_23'. + do + -- Ignored + end + + set_ssl_protocol_to_ssl_3 + -- Set `ssl_protocol' with `Ssl_3'. + do + -- Ignored + end + + set_ssl_protocol_to_tls_1_0 + -- Set `ssl_protocol' with `Tls_1_0'. + do + -- Ignored + end + + set_ssl_protocol_to_tls_1_1 + -- Set `ssl_protocol' with `Tls_1_1'. + do + -- Ignored + end + + set_ssl_protocol_to_tls_1_2 + -- Set `ssl_protocol' with `Tls_1_2'. + do + -- Ignored + end + + set_ssl_protocol_to_dtls_1_0 + -- Set `ssl_protocol' with `Dtls_1_0'. + do + -- Ignored + end + + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_server.e b/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_server.e new file mode 100644 index 00000000..8787e1fc --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_server.e @@ -0,0 +1,27 @@ +note + description: "[ + httpd server + ]" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_SERVER + +inherit + HTTPD_SERVER_I + +create + make + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_configuration.e b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_configuration.e new file mode 100644 index 00000000..275fd5e4 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_configuration.e @@ -0,0 +1,82 @@ +note + description: "Summary description for {HTTPD_CONFIGURATION}." + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_CONFIGURATION + +inherit + HTTPD_CONFIGURATION_I + redefine + make + end + +create + make + +feature {NONE} -- Initialization + + make + do + Precursor + ssl_protocol := {SSL_PROTOCOL}.tls_1_2 + end + +feature -- Access + + Server_details: STRING_8 = "Server : NINO Eiffel Server (https)" + + has_ssl_support: BOOLEAN = True + -- Precursor + +feature -- SSL Helpers + + set_ssl_protocol_to_ssl_2_or_3 + -- Set `ssl_protocol' with `Ssl_23'. + do + set_ssl_protocol ({SSL_PROTOCOL}.Ssl_23) + end + + set_ssl_protocol_to_ssl_3 + -- Set `ssl_protocol' with `Ssl_3'. + do + set_ssl_protocol ({SSL_PROTOCOL}.Ssl_3) + end + + set_ssl_protocol_to_tls_1_0 + -- Set `ssl_protocol' with `Tls_1_0'. + do + set_ssl_protocol ({SSL_PROTOCOL}.Tls_1_0) + end + + set_ssl_protocol_to_tls_1_1 + -- Set `ssl_protocol' with `Tls_1_1'. + do + set_ssl_protocol ({SSL_PROTOCOL}.Tls_1_1) + end + + set_ssl_protocol_to_tls_1_2 + -- Set `ssl_protocol' with `Tls_1_2'. + do + set_ssl_protocol ({SSL_PROTOCOL}.Tls_1_2) + end + + set_ssl_protocol_to_dtls_1_0 + -- Set `ssl_protocol' with `Dtls_1_0'. + do + set_ssl_protocol ({SSL_PROTOCOL}.Dtls_1_0) + end + + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_server.e b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_server.e new file mode 100644 index 00000000..4045aa29 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_server.e @@ -0,0 +1,35 @@ +note + description: "[ + SSL enabled server + ]" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_SERVER + +inherit + HTTPD_SERVER_I + redefine + new_listening_socket + end + +create + make + +feature {NONE} -- Factory + + new_listening_socket (a_addr: detachable INET_ADDRESS; a_http_port: INTEGER): HTTPD_STREAM_SOCKET + do + if configuration.is_secure then + if a_addr /= Void then + create {HTTPD_STREAM_SSL_SOCKET} Result.make_ssl_server_by_address_and_port (a_addr, a_http_port, configuration.ssl_protocol, configuration.ca_crt, configuration.ca_key) + else + create {HTTPD_STREAM_SSL_SOCKET} Result.make_ssl_server_by_port (a_http_port, configuration.ssl_protocol, configuration.ca_crt, configuration.ca_key) + end + else + Result := Precursor (a_addr, a_http_port) + end + end + +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_stream_ssl_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_stream_ssl_socket.e new file mode 100644 index 00000000..e1f25ca0 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_stream_ssl_socket.e @@ -0,0 +1,139 @@ +note + description: "[ + Summary description for {HTTPD_STREAM_SSL_SOCKET} + that can be used for http or https connection. + ]" + date: "$Date$" + revision: "$Revision$" + +class + HTTPD_STREAM_SSL_SOCKET + +inherit + HTTPD_STREAM_SOCKET + redefine + port, + is_bound, + ready_for_writing, + ready_for_reading, + try_ready_for_reading, + put_readable_string_8 + end + +create + make_ssl_server_by_address_and_port, make_ssl_server_by_port, + make_server_by_address_and_port, make_server_by_port + +create {HTTPD_STREAM_SOCKET} + make + +feature {NONE} -- Initialization + + make_ssl_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING) + local + l_socket: SSL_TCP_STREAM_SOCKET + do + create l_socket.make_server_by_address_and_port (an_address, a_port) + l_socket.set_tls_protocol (a_ssl_protocol) + socket := l_socket + set_certificates (a_crt, a_key) + end + + make_ssl_server_by_port (a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING) + local + l_socket: SSL_TCP_STREAM_SOCKET + do + create l_socket.make_server_by_port (a_port) + l_socket.set_tls_protocol (a_ssl_protocol) + socket := l_socket + set_certificates (a_crt, a_key) + end + +feature -- Output + + put_readable_string_8 (s: READABLE_STRING_8) + -- + do + if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then + l_ssl_socket.put_readable_string_8 (s) + else + Precursor (s) + end + end + +feature -- Status Report + + port: INTEGER + -- + do + if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then + Result := l_ssl_socket.port + else + Result := Precursor + end + end + + is_bound: BOOLEAN + -- + do + if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then + Result := l_ssl_socket.is_bound + else + Result := Precursor + end + end + + ready_for_writing: BOOLEAN + -- + do + if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then + Result := l_ssl_socket.ready_for_writing + else + Result := Precursor + end + end + + ready_for_reading: BOOLEAN + -- + do + if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then + Result := l_ssl_socket.ready_for_reading + else + Result := Precursor + end + end + + try_ready_for_reading: BOOLEAN + do + if attached {SSL_TCP_STREAM_SOCKET} socket as l_socket then + Result := l_socket.try_ready_for_reading + else + Result := Precursor + end + end + +feature {HTTPD_STREAM_SOCKET} -- Implementation + + set_certificates (a_crt: STRING; a_key: STRING) + local + a_file_name: FILE_NAME + do + if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then + create a_file_name.make_from_string (a_crt) + l_socket.set_certificate_file_name (a_file_name) + create a_file_name.make_from_string (a_key) + l_socket.set_key_file_name (a_file_name) + end + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/ssl_tcp_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/ssl_tcp_stream_socket.e new file mode 100644 index 00000000..c4f5e668 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/httpd/ssl/ssl_tcp_stream_socket.e @@ -0,0 +1,72 @@ +note + description: "Summary description for {SSL_TCP_STREAM_SOCKET}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + SSL_TCP_STREAM_SOCKET + +inherit + + SSL_NETWORK_STREAM_SOCKET + +create + make_server_by_address_and_port, make_server_by_port + +create {SSL_NETWORK_STREAM_SOCKET} + make_from_descriptor_and_address + +feature {NONE} -- Initialization + + make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER) + -- Create server socket on `an_address' and `a_port'. + require + valid_port: a_port >= 0 + do + make + create address.make_from_address_and_port (an_address, a_port) + bind + end + +feature -- Basic operation + + send_message (a_msg: STRING) + do + put_string (a_msg) + end + +feature -- Output + + put_readable_string_8 (s: READABLE_STRING_8) + -- Write readable string `s' to socket. + local + ext: C_STRING + do + create ext.make (s) + put_managed_pointer (ext.managed_data, 0, s.count) + end + +feature -- Status report + + try_ready_for_reading: BOOLEAN + -- Is data available for reading from the socket right now? + require + socket_exists: exists + local + retval: INTEGER + do + retval := c_select_poll_with_timeout (descriptor, True, 0) + Result := (retval > 0) + end + +feature {NONE}-- Implementation + + + + +note + copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + +end diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e new file mode 100644 index 00000000..3cb84e31 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e @@ -0,0 +1,70 @@ +note + description: "Summary description for WGI_HTTPD_ERROR_STREAM." + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + WGI_HTTPD_ERROR_STREAM + +inherit + WGI_ERROR_STREAM + +create + make, + make_stderr, + make_stdout + +feature {NONE} -- Initialization + + make (a_identifier: READABLE_STRING_8; a_file: PLAIN_TEXT_FILE) + do + identifier := a_identifier + output := a_file + end + + make_stderr (a_identifier: READABLE_STRING_8) + do + make (a_identifier, io.error) + end + + make_stdout (a_identifier: READABLE_STRING_8) + do + make (a_identifier, io.error) + end + +feature -- Access + + identifier: READABLE_STRING_8 + + output: FILE + +feature -- Error + + put_error (a_message: READABLE_STRING_8) + local + s: STRING + do + create s.make (a_message.count + identifier.count + 4) + s.append_character ('[') + s.append (identifier) + s.append_character (']') + s.append_character (' ') + s.append (a_message) + s.append_character ('%N') + -- Display it at once. + output.put_string (s) + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e new file mode 100644 index 00000000..878db547 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e @@ -0,0 +1,100 @@ +note + description: "Summary description for {WGI_HTTPD_INPUT_STREAM}." + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + WGI_HTTPD_INPUT_STREAM + +inherit + WGI_INPUT_STREAM + +create + make + +feature {NONE} -- Initialization + + make (a_source: like source) + do + create last_string.make_empty + set_source (a_source) + end + +feature {WGI_NINO_CONNECTOR, WGI_SERVICE} -- Nino + + set_source (i: like source) + do + source := i + end + + source: HTTPD_STREAM_SOCKET + +feature -- Input + + read_character + -- Read the next character in input stream. + -- Make the result available in `last_character'. + local + src: like source + do + src := source + if src.readable then + src.read_character + last_character := src.last_character + else + last_character := '%U' + end + end + + read_string (nb: INTEGER) + local + src: like source + do + src := source + last_string.wipe_out + if src.readable then + src.read_stream_thread_aware (nb) + last_string.append_string (src.last_string) + end + end + +feature -- Access + + last_string: STRING_8 + -- Last string read + -- (Note: this query *might* return the same object. + -- Therefore a clone should be used if the result + -- is to be kept beyond the next call to this feature. + -- However `last_string' is not shared between input objects.) + + last_character: CHARACTER_8 + -- Last item read + +feature -- Status report + + is_open_read: BOOLEAN + -- Can items be read from input stream? + do + Result := source.is_open_read + end + + end_of_input: BOOLEAN + -- Has the end of input stream been reached? + do + Result := not source.try_ready_for_reading + end + +;note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e new file mode 100644 index 00000000..a57095cf --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e @@ -0,0 +1,104 @@ +note + description: "Summary description for {WGI_HTTPD_OUTPUT_STREAM}." + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + WGI_HTTPD_OUTPUT_STREAM + +inherit + WGI_OUTPUT_STREAM + + HTTP_STATUS_CODE_MESSAGES + export + {NONE} all + end + +create + make + +feature {NONE} -- Initialization + + make (a_target: like target) + do + set_target (a_target) + end + +feature {WGI_NINO_CONNECTOR, WGI_SERVICE} -- Nino + + set_target (o: like target) + do + target := o + end + + target: HTTPD_STREAM_SOCKET + +feature -- Status writing + + put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8) + -- + local + s: STRING + m: detachable READABLE_STRING_8 + do + create s.make (16) + s.append ({HTTP_CONSTANTS}.http_version_1_1) + s.append_character (' ') + s.append_integer (a_code) + m := a_reason_phrase + if m = Void then + m := http_status_code_message (a_code) + end + if m /= Void then + s.append_character (' ') + s.append_string (m) + end + put_header_line (s) + end + +feature -- Output + + put_readable_string_8 (s: READABLE_STRING_8) + -- Send `s' to http client + do + target.put_readable_string_8 (s) + end + + put_string (s: READABLE_STRING_8) + -- Send `s' to http client + do + target.put_readable_string_8 (s) + end + + put_character (c: CHARACTER_8) + do + target.put_character (c) + end + +feature -- Status report + + is_open_write: BOOLEAN + -- Can items be written to output stream? + do + Result := target.is_open_write + end + +feature -- Basic operations + + flush + do + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e new file mode 100644 index 00000000..acc8a3cd --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e @@ -0,0 +1,50 @@ +note + description: "[ + WGI Response implemented using stream buffer + + ]" + date: "$Date$" + revision: "$Revision$" + +class + WGI_HTTPD_RESPONSE_STREAM + +inherit + WGI_RESPONSE_STREAM + redefine + put_header_text + end + +create + make + +feature -- Header output operation + + put_header_text (a_text: READABLE_STRING_8) + local + o: like output + do + o := output + o.put_string (a_text) + + -- Nino does not support persistent connection for now + o.put_string ("Connection: close") + o.put_crlf + + -- end of headers + o.put_crlf + + header_committed := True + end + +;note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/specification/request/wgi_request.e b/library/server/ewsgi/specification/request/wgi_request.e index 5054650b..85a9660e 100644 --- a/library/server/ewsgi/specification/request/wgi_request.e +++ b/library/server/ewsgi/specification/request/wgi_request.e @@ -157,7 +157,7 @@ feature -- Eiffel WGI access deferred end - wgi_connector: WGI_CONNECTOR + wgi_connector: detachable WGI_CONNECTOR -- Associated Eiffel WGI connector deferred end @@ -685,7 +685,7 @@ invariant path_info_identical: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info) note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/specification/response/wgi_response.e b/library/server/ewsgi/specification/response/wgi_response.e index 8d8f9de5..d0192a5a 100644 --- a/library/server/ewsgi/specification/response/wgi_response.e +++ b/library/server/ewsgi/specification/response/wgi_response.e @@ -6,7 +6,7 @@ note deferred class WGI_RESPONSE -feature {WGI_CONNECTOR, WGI_SERVICE} -- Commit +feature {WGI_CONNECTOR, WGI_SERVICE, WGI_EXPORTER} -- Commit push -- Commit and push response @@ -156,7 +156,7 @@ feature -- Error reporting end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/src/implementation/wgi_request_from_table.e b/library/server/ewsgi/src/implementation/wgi_request_from_table.e index 57d7513f..988d0c99 100644 --- a/library/server/ewsgi/src/implementation/wgi_request_from_table.e +++ b/library/server/ewsgi/src/implementation/wgi_request_from_table.e @@ -57,7 +57,7 @@ feature -- EWSGI access wgi_implementation: STRING = "Eiffel Web Framework 0.1" - wgi_connector: WGI_CONNECTOR + wgi_connector: detachable WGI_CONNECTOR feature -- Access: CGI meta parameters @@ -289,7 +289,7 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1 do Result := meta_string_variable ({WGI_META_NAMES}.http_range) end - + http_content_range: detachable READABLE_STRING_8 -- Partial range of selected representation enclosed in message payload do @@ -301,8 +301,8 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1 do Result := meta_string_variable ({WGI_META_NAMES}.http_content_encoding) end - - + + feature -- Access: Extension to CGI meta parameters - 1.1 request_uri: READABLE_STRING_8 @@ -507,7 +507,7 @@ invariant empty_string_unchanged: empty_string.is_empty note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/src/wgi_exporter.e b/library/server/ewsgi/src/wgi_exporter.e new file mode 100644 index 00000000..7fd4e349 --- /dev/null +++ b/library/server/ewsgi/src/wgi_exporter.e @@ -0,0 +1,10 @@ +note + description: "Summary description for {WGI_EXPORTER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WGI_EXPORTER + +end diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e new file mode 100644 index 00000000..582fb6d2 --- /dev/null +++ b/library/server/wsf/src/wsf_execution.e @@ -0,0 +1,43 @@ +note + description: "Summary description for {WSF_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_EXECUTION + +--create +-- make + +feature {NONE} -- Initialization + + make (req: WGI_REQUEST; res: WGI_RESPONSE) + do + create request.make_from_wgi (req) + create response.make_from_wgi (res) + end + + request: WSF_REQUEST + + response: WSF_RESPONSE + +feature -- Execution + + execute + deferred + ensure + response.status_is_set + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index b36f8fd6..5f17f910 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -41,7 +41,7 @@ inherit {NONE} all end -create {WSF_TO_WGI_SERVICE} +create {WSF_TO_WGI_SERVICE, WSF_EXECUTION} make_from_wgi convert @@ -426,7 +426,7 @@ feature -- Eiffel WGI access Result := wgi_request.wgi_implementation end - wgi_connector: WGI_CONNECTOR + wgi_connector: detachable WGI_CONNECTOR -- Associated Eiffel WGI connector do Result := wgi_request.wgi_connector @@ -2173,7 +2173,7 @@ invariant wgi_request.content_type /= Void implies content_type /= Void note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e index f983f9d3..a158fda3 100644 --- a/library/server/wsf/src/wsf_response.e +++ b/library/server/wsf/src/wsf_response.e @@ -19,7 +19,7 @@ note class WSF_RESPONSE -create {WSF_TO_WGI_SERVICE} +create {WSF_TO_WGI_SERVICE, WSF_EXECUTION} make_from_wgi create {WSF_RESPONSE} From 557b11f4e677b2cd96be5280abf645ce772f7045 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 17 Mar 2015 09:48:11 +0100 Subject: [PATCH 02/33] First attempt to use `{NETWORK_STREAM_SOCKET}.accept_to' --- .../scoop/httpd_connection_handler.e | 39 ++++++----------- .../concurrency/scoop/httpd_request_handler.e | 43 +++++-------------- .../src/httpd/httpd_connection_handler_i.e | 4 +- .../httpd/src/httpd/httpd_request_handler_i.e | 23 +++------- .../httpd/src/httpd/httpd_server_i.e | 32 ++++++-------- .../src/httpd/network/httpd_stream_socket.e | 38 ++++++++++++++-- .../src/httpd/network/tcp_stream_socket.e | 10 +++-- 7 files changed, 88 insertions(+), 101 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e index fcf5c3d7..79afe9f5 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -57,45 +57,33 @@ feature {HTTPD_SERVER_I} -- Execution p.gracefull_stop end - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) - -- + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) do - debug ("dbglog") - dbglog (generator + ".before process_incoming_connection {"+ a_socket.descriptor.out +"} -- SCOOP WAIT!") - end --- if is_shutdown_requested then --- a_socket.cleanup --- else - process_connection_on_pool (a_socket, pool) -- Wait on not pool.is_full or is_stop_requested --- end - debug ("dbglog") - dbglog (generator + ".after process_incoming_connection {"+ a_socket.descriptor.out +"}") - end + accept_connection_on_pool (a_listening_socket, pool) -- Wait on not pool.is_full or is_stop_requested end - process_connection_on_pool (a_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) - -- Process incoming connection + accept_connection_on_pool (a_listening_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) + -- Process accept connection -- note that the precondition matters for scoop synchronization. require concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested do debug ("dbglog") - dbglog (generator + ".ENTER process_connection {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".ENTER accept_connection_on_pool") end if is_shutdown_requested then - a_socket.cleanup + -- Cancel elseif attached a_pool.separate_item (factory) as h then - process_request_handler (h, a_socket) + process_request_handler_on_accept (h, a_listening_socket) else check is_not_full: False end - a_socket.cleanup end debug ("dbglog") - dbglog (generator + ".LEAVE process_connection {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".LEAVE accept_connection_on_pool") end end - process_request_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) + process_request_handler_on_accept (hdl: separate HTTPD_REQUEST_HANDLER; a_listening_socket: HTTPD_STREAM_SOCKET) require not hdl.has_error do @@ -103,20 +91,21 @@ feature {HTTPD_SERVER_I} -- Execution --| also handle permanent connection...? debug ("dbglog") - dbglog (generator + ".ENTER process_request_handler {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".ENTER process_request_handler_on_accept") end - hdl.set_client_socket (a_socket) + hdl.accept_from_listening_socket (a_listening_socket) if hdl.has_error then - log ("Internal error (set_client_socket failed)") + log ("Internal error (accept_from_listening_socket failed)") else -- hdl.set_logger (server) if attached hdl.separate_execution as l_result then + end hdl.separate_release end debug ("dbglog") - dbglog (generator + ".LEAVE process_request_handler {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".LEAVE process_request_handler_on_accept") end rescue log ("Releasing handler after exception!") diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e index 2c5754fc..1f41852d 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -12,9 +12,7 @@ deferred class inherit HTTPD_REQUEST_HANDLER_I redefine --- set_client_socket, - release, - reset + release end CONCURRENT_POOL_ITEM @@ -22,42 +20,23 @@ inherit release as release_pool_item end -feature {NONE} -- Initialization - - reset - do - if attached client_socket_source as l_sock then - cleanup_separate_socket (l_sock) - end - Precursor - client_socket_source := Void - end - - cleanup_separate_socket (a_socket: attached like client_socket_source) - do - a_socket.cleanup - end - -feature -- Access - - client_socket: detachable HTTPD_STREAM_SOCKET - - client_socket_source: detachable separate HTTPD_STREAM_SOCKET - -- Associated original client socket - -- kept to avoid being closed when disposed, - -- and thus avoid closing related `client_socket'. - feature -- Change - set_client_socket (a_socket: separate HTTPD_STREAM_SOCKET) + accept_from_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) local retried: BOOLEAN + s: like client_socket do if retried then has_error := True else - create client_socket.make_from_separate (a_socket) - client_socket_source := a_socket + create s.make_empty + client_socket := s + a_listening_socket.accept_to (s) + if not s.is_created then + has_error := True + client_socket := Void + end end rescue retried := True @@ -99,7 +78,7 @@ feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e index d9708723..99d4acc0 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e @@ -38,7 +38,7 @@ feature {NONE} -- Access feature {HTTPD_SERVER_I} -- Execution - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) deferred end @@ -72,7 +72,7 @@ feature {NONE} -- Output end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e index 5be6fca8..dd3ce531 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -23,21 +23,22 @@ feature {NONE} -- Initialization version := Void remote_info := Void --- if attached client_socket as l_sock then --- l_sock.cleanup --- end --- client_socket := Void + if attached client_socket as l_sock then + l_sock.cleanup + end + client_socket := Void -- FIXME: optimize to just wipe_out if needed create method.make_empty create uri.make_empty create request_header.make_empty create request_header_map.make (10) + end feature -- Access --- client_socket: detachable TCP_STREAM_SOCKET + client_socket: detachable HTTPD_STREAM_SOCKET request_header: STRING -- Header' source @@ -69,16 +70,6 @@ feature -- Status report feature -- Change --- set_client_socket (a_socket: separate TCP_STREAM_SOCKET) --- require --- socket_attached: a_socket /= Void --- socket_valid: a_socket.is_open_read and then a_socket.is_open_write --- a_http_socket: not a_socket.is_closed --- deferred --- ensure --- attached client_socket as s implies s.descriptor = a_socket.descriptor --- end - set_is_verbose (b: BOOLEAN) do is_verbose := b @@ -265,7 +256,7 @@ invariant request_header_attached: request_header /= Void note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e index c0f92b47..ff9adcb9 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e @@ -126,8 +126,7 @@ feature -- Listening -- Creates a socket and connects to the http server. -- `a_server': The main server object local - l_listening_socket, - l_accepted_socket: detachable HTTPD_STREAM_SOCKET + l_listening_socket: detachable HTTPD_STREAM_SOCKET l_http_port: INTEGER l_connection_handler: HTTPD_CONNECTION_HANDLER do @@ -164,23 +163,18 @@ feature -- Listening until is_shutdown_requested loop - l_listening_socket.accept - if not is_shutdown_requested then - l_accepted_socket := l_listening_socket.accepted - if l_accepted_socket /= Void then - request_counter := request_counter + 1 - if is_verbose then - log ("#" + request_counter.out + "# Incoming connection...(socket:" + l_accepted_socket.descriptor.out + ")") - end - debug ("dbglog") - dbglog (generator + ".before process_incoming_connection {" + l_accepted_socket.descriptor.out + "}" ) - end - l_connection_handler.process_incoming_connection (l_accepted_socket) - debug ("dbglog") - dbglog (generator + ".after process_incoming_connection {" + l_accepted_socket.descriptor.out + "}") - end - end + request_counter := request_counter + 1 + if is_verbose then + log ("#" + request_counter.out + "# Waiting connection...(listening socket:" + l_listening_socket.descriptor.out + ")") end + debug ("dbglog") + dbglog (generator + ".before process_waiting_incoming_connection") + end + l_connection_handler.accept_incoming_connection (l_listening_socket) + debug ("dbglog") + dbglog (generator + ".after process_waiting_incoming_connection") + end + update_is_shutdown_requested (l_connection_handler) end wait_for_connection_handler_completion (l_connection_handler) @@ -304,7 +298,7 @@ feature -- Output end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e index ff4a6361..4cf3f162 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e @@ -12,7 +12,8 @@ class create make_server_by_address_and_port, make_server_by_port, - make_from_separate + make_from_separate, + make_empty create {HTTPD_STREAM_SOCKET} make @@ -36,6 +37,11 @@ feature {NONE} -- Initialization create {TCP_STREAM_SOCKET} socket.make_from_separate (s.socket) end + make_empty + do + create {TCP_STREAM_SOCKET} socket.make_empty + end + retrieve_socket (s: HTTPD_STREAM_SOCKET): INTEGER do Result := s.socket.descriptor @@ -147,6 +153,13 @@ feature -- Status Report end end + is_created: BOOLEAN + do + if attached {NETWORK_SOCKET} socket as l_socket then + Result := l_socket.is_created + end + end + socket_ok: BOOLEAN do Result := socket.socket_ok @@ -194,6 +207,18 @@ feature -- Status Report socket.accept end + accept_to (other: separate HTTPD_STREAM_SOCKET) + -- Accept a new connection on listen socket. + -- Socket of accepted connection is available in `other'. + do + if + attached {NETWORK_STREAM_SOCKET} socket as l_socket and then + attached {separate NETWORK_STREAM_SOCKET} other.socket as l_other_socket + then + l_socket.accept_to (l_other_socket) + end + end + set_blocking do socket.set_blocking @@ -225,7 +250,7 @@ feature -- Status Report accepted: detachable HTTPD_STREAM_SOCKET do - if attached socket.accepted as l_accepted then + if attached {NETWORK_STREAM_SOCKET} socket.accepted as l_accepted then create Result.make (l_accepted) end end @@ -239,8 +264,15 @@ feature {HTTPD_STREAM_SOCKET} -- Implementation socket: STREAM_SOCKET + network_stream_socket: detachable NETWORK_STREAM_SOCKET + do + if attached {NETWORK_STREAM_SOCKET} socket as s then + Result := s + end + end + ;note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e index 1713779d..2e88f192 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e @@ -15,11 +15,11 @@ inherit create make_server_by_address_and_port, make_server_by_port, - make_from_separate + make_from_separate, + make_empty create {NETWORK_STREAM_SOCKET} - make_from_descriptor_and_address, - make_empty + make_from_descriptor_and_address feature {NONE} -- Initialization @@ -27,7 +27,9 @@ feature {NONE} -- Initialization -- Create a network stream socket. do Precursor - set_reuse_address + debug + set_reuse_address + end end make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER) From 0970de5dc680112113a223ae1da5024ccafade26 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 17 Mar 2015 15:52:15 +0100 Subject: [PATCH 03/33] Experiment to avoid pseudo sequential execution --- .../httpd/dev/httpd_connector_dev.e | 1 + .../scoop/httpd_connection_handler.e | 4 ++- .../concurrency/scoop/httpd_request_handler.e | 32 ++++++++++++++++--- .../httpd/src/httpd/httpd_request_handler_i.e | 4 +++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e index 89bc7bea..80dfcd4e 100644 --- a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e +++ b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e @@ -23,6 +23,7 @@ feature {NONE} -- Initialization print ("Hello%N") create fac create server.make (fac) + server.configuration.set_max_concurrent_connections (100) server.configuration.set_http_server_port (9090) server.launch end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e index 79afe9f5..60141ef7 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -94,7 +94,9 @@ feature {HTTPD_SERVER_I} -- Execution dbglog (generator + ".ENTER process_request_handler_on_accept") end - hdl.accept_from_listening_socket (a_listening_socket) + hdl.set_listening_socket (a_listening_socket) + +-- hdl.accept_from_listening_socket (a_listening_socket) if hdl.has_error then log ("Internal error (accept_from_listening_socket failed)") else diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e index 1f41852d..638d41fc 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -22,6 +22,11 @@ inherit feature -- Change + set_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) + do + listening_socket := a_listening_socket + end + accept_from_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) local retried: BOOLEAN @@ -32,8 +37,21 @@ feature -- Change else create s.make_empty client_socket := s + debug ("dbglog") + dbglog ("before accept_to") + end + print ("[EWF/DBG] <#" + processor_id_from_object (Current).out + "> accept_to%N") a_listening_socket.accept_to (s) - if not s.is_created then + + if s.is_created then + debug ("dbglog") + dbglog ("after accept_to " + s.descriptor.out) + end + else + debug ("dbglog") + dbglog ("after accept_to ERROR") + end + has_error := True client_socket := Void end @@ -47,10 +65,16 @@ feature -- Execution separate_execution: BOOLEAN do - if attached client_socket as s then - execute (s) + Result := False + if attached listening_socket as l_listening_socket then + accept_from_listening_socket (l_listening_socket) + if not has_error then + if attached client_socket as s then + execute (s) + Result := True + end + end end - Result := True end feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e index dd3ce531..e1d376cd 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -28,6 +28,8 @@ feature {NONE} -- Initialization end client_socket := Void + listening_socket := Void + -- FIXME: optimize to just wipe_out if needed create method.make_empty create uri.make_empty @@ -40,6 +42,8 @@ feature -- Access client_socket: detachable HTTPD_STREAM_SOCKET + listening_socket: detachable separate HTTPD_STREAM_SOCKET + request_header: STRING -- Header' source From 3da80fce0dccc4b77d600f28b2fa4dda5f7adfdf Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 20 Mar 2015 13:37:54 +0100 Subject: [PATCH 04/33] Finally SCOOP supported. --- .../connectors/httpd/dev/app_wsf_execution.e | 12 ++++ .../httpd/dev/httpd_connector_dev.e | 7 +- .../ewsgi/connectors/httpd/httpd-safe.ecf | 19 ++++-- .../scoop/httpd_connection_handler.e | 46 +++++-------- .../concurrency/scoop/httpd_request_handler.e | 67 ++++++------------- .../scoop/httpd_request_handler_factory.e | 9 ++- .../concurrency/scoop/pool/concurrent_pool.e | 7 +- .../scoop/pool/concurrent_pool_factory.e | 15 ++++- .../httpd/src/httpd/httpd_debug_facilities.e | 15 ++++- .../httpd/src/httpd/httpd_request_handler_i.e | 35 +++++++--- .../httpd/src/httpd/httpd_server_i.e | 10 +-- .../src/httpd/network/httpd_stream_socket.e | 8 +++ 12 files changed, 143 insertions(+), 107 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e b/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e index b4e817a5..2a87ee9c 100644 --- a/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e +++ b/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e @@ -10,6 +10,8 @@ class inherit WSF_EXECUTION + SHARED_EXECUTION_ENVIRONMENT + create make @@ -18,12 +20,22 @@ feature -- Execution execute local s: STRING + i64: INTEGER_64 do s := "Hello Concurrent EWF" s.append (" (counter=") s.append_integer (next_cell_counter_item (counter_cell)) s.append (")%N") + if attached {WSF_STRING} request.query_parameter ("sleep") as p_sleep then + if attached p_sleep.value.is_integer then + s.append ("sleep for ") + i64 := p_sleep.value.to_integer_64 * {INTEGER_64} 1_000_000_000 + s.append_integer_64 (i64) + execution_environment.sleep (i64) + end + end + response.set_status_code (200) response.put_header_line ("X-EWF-Dev: v1.0") response.header.put_content_type_text_plain diff --git a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e index 80dfcd4e..a12bc301 100644 --- a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e +++ b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e @@ -17,12 +17,17 @@ feature {NONE} -- Initialization make -- Initialize `Current'. local - server: HTTPD_SERVER + server: separate HTTPD_SERVER fac: separate WSF_HTTPD_REQUEST_HANDLER_FACTORY [APP_WSF_EXECUTION] do print ("Hello%N") create fac create server.make (fac) + launch_server (server) + end + + launch_server (server: separate HTTPD_SERVER) + do server.configuration.set_max_concurrent_connections (100) server.configuration.set_http_server_port (9090) server.launch diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf index 38f010d3..51f30ddd 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -7,15 +7,19 @@ /\.git$ /\.svn$ - - - + + + @@ -27,12 +31,13 @@ + - /ssl$ + /concurrency$ /EIFGENs$ /no_ssl$ - /concurrency$ + /ssl$ @@ -68,6 +73,10 @@ + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e index 60141ef7..1bd658cc 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -59,14 +59,16 @@ feature {HTTPD_SERVER_I} -- Execution accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) do - accept_connection_on_pool (a_listening_socket, pool) -- Wait on not pool.is_full or is_stop_requested + accept_connection_on_pool (pool, a_listening_socket) -- Wait on not pool.is_full or is_stop_requested end - accept_connection_on_pool (a_listening_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) + accept_connection_on_pool (a_pool: like pool; a_listening_socket: HTTPD_STREAM_SOCKET) -- Process accept connection -- note that the precondition matters for scoop synchronization. require concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested + local + cl: separate HTTPD_STREAM_SOCKET do debug ("dbglog") dbglog (generator + ".ENTER accept_connection_on_pool") @@ -74,7 +76,9 @@ feature {HTTPD_SERVER_I} -- Execution if is_shutdown_requested then -- Cancel elseif attached a_pool.separate_item (factory) as h then - process_request_handler_on_accept (h, a_listening_socket) + cl := separate_client_socket (h) + a_listening_socket.accept_to (cl) + process_handler (h) else check is_not_full: False end end @@ -83,36 +87,16 @@ feature {HTTPD_SERVER_I} -- Execution end end - process_request_handler_on_accept (hdl: separate HTTPD_REQUEST_HANDLER; a_listening_socket: HTTPD_STREAM_SOCKET) - require - not hdl.has_error + separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET do - --| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection - --| also handle permanent connection...? + Result := hdl.client_socket + end - debug ("dbglog") - dbglog (generator + ".ENTER process_request_handler_on_accept") - end - - hdl.set_listening_socket (a_listening_socket) - --- hdl.accept_from_listening_socket (a_listening_socket) - if hdl.has_error then - log ("Internal error (accept_from_listening_socket failed)") - else --- hdl.set_logger (server) - if attached hdl.separate_execution as l_result then - - end - hdl.separate_release - end - debug ("dbglog") - dbglog (generator + ".LEAVE process_request_handler_on_accept") - end - rescue - log ("Releasing handler after exception!") - hdl.separate_release --- a_socket.cleanup + process_handler (hdl: separate HTTPD_REQUEST_HANDLER) + require + hdl.is_connected + do + hdl.separate_execute end feature {HTTPD_SERVER_I} -- Status report diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e index 638d41fc..9f20e627 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -20,77 +20,52 @@ inherit release as release_pool_item end -feature -- Change +feature -- Status report - set_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) + is_connected: BOOLEAN + -- Is handler connected to incoming request via `client_socket'? do - listening_socket := a_listening_socket + Result := client_socket.descriptor_available end - accept_from_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) +feature -- Execution + + separate_execute local retried: BOOLEAN - s: like client_socket do if retried then - has_error := True + release (client_socket) else - create s.make_empty - client_socket := s - debug ("dbglog") - dbglog ("before accept_to") - end - print ("[EWF/DBG] <#" + processor_id_from_object (Current).out + "> accept_to%N") - a_listening_socket.accept_to (s) - - if s.is_created then - debug ("dbglog") - dbglog ("after accept_to " + s.descriptor.out) - end - else - debug ("dbglog") - dbglog ("after accept_to ERROR") - end - - has_error := True - client_socket := Void + if + not has_error and then + is_connected + then + execute (client_socket) end + separate_release end rescue retried := True retry end -feature -- Execution - - separate_execution: BOOLEAN - do - Result := False - if attached listening_socket as l_listening_socket then - accept_from_listening_socket (l_listening_socket) - if not has_error then - if attached client_socket as s then - execute (s) - Result := True - end - end - end - end - feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation separate_release do - if attached client_socket as s then - release (s) - end + release (client_socket) end - release (a_socket: HTTPD_STREAM_SOCKET) + release (a_socket: detachable HTTPD_STREAM_SOCKET) local d: STRING do - d := a_socket.descriptor.out + if a_socket /= Void then + d := a_socket.descriptor.out + else + d := "N/A" + end debug ("dbglog") dbglog (generator + ".release: ENTER {" + d + "}") end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e index 843fc8e3..56fa78d6 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e @@ -16,6 +16,13 @@ inherit end note - copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e index 0bead25a..a26156da 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e @@ -88,6 +88,7 @@ feature -- Access count := count + 1 busy_items [pos] := True Result := l_item + a_factory.update_item (l_item) end end end @@ -159,17 +160,13 @@ feature -- Change feature {NONE} -- Implementation --- new_separate_item: separate G --- deferred --- end - register_item (a_item: separate G) do a_item.set_pool (Current) end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e index 497fbb69..51205fb3 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e @@ -9,11 +9,24 @@ deferred class feature -- Access + update_item (a_item: separate G) + -- Update `a_item' for optionally purpose. + do + end + new_separate_item: separate G + -- New separated object of type {G}. deferred end note - copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e index ac1b0051..77704e5b 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e @@ -12,9 +12,20 @@ feature {NONE} -- Output dbglog (m: READABLE_STRING_8) require not m.ends_with_general ("%N") + local + s: STRING do debug ("dbglog") - print ("[EWF/DBG] <#" + processor_id_from_object (Current).out + "> " + m + "%N") + create s.make (24) + s.append ("[EWF/DBG] <#") + s.append_integer (processor_id_from_object (Current)) + s.append ("> ") + s.append (generator) + s.append (create {STRING}.make_filled (' ', (46 - s.count).max (0))) + s.append (" | ") + s.append (m) + s.append ("%N") + print (s) end end @@ -28,7 +39,7 @@ feature -- runtime end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e index e1d376cd..2411d637 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -23,12 +23,10 @@ feature {NONE} -- Initialization version := Void remote_info := Void - if attached client_socket as l_sock then + if attached internal_client_socket as l_sock then l_sock.cleanup end - client_socket := Void - - listening_socket := Void + internal_client_socket := Void -- FIXME: optimize to just wipe_out if needed create method.make_empty @@ -36,13 +34,24 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) + is_waiting := False end feature -- Access - client_socket: detachable HTTPD_STREAM_SOCKET + internal_client_socket: detachable HTTPD_STREAM_SOCKET - listening_socket: detachable separate HTTPD_STREAM_SOCKET + client_socket: HTTPD_STREAM_SOCKET + local + s: like internal_client_socket + do + s := internal_client_socket + if s = Void then + create s.make_empty + internal_client_socket := s + end + Result := s + end request_header: STRING -- Header' source @@ -69,6 +78,8 @@ feature -- Settings feature -- Status report + is_waiting: BOOLEAN + has_error: BOOLEAN -- Error occurred during `analyze_request_message' @@ -96,7 +107,7 @@ feature -- Execution end else debug ("dbglog") - dbglog (generator + ".ENTER execute {" + a_socket.descriptor.out + "}") + dbglog (generator + ".execute {" + a_socket.descriptor.out + "} ENTER") end from until l_continue loop if a_socket.ready_for_reading then @@ -110,7 +121,7 @@ feature -- Execution end analyze_request_message (a_socket) else - log (generator + ".WAITING execute {" + a_socket.descriptor.out + "}") + log (generator + ".execute {" + a_socket.descriptor.out + "} WAITING") end end @@ -124,15 +135,17 @@ feature -- Execution process_request (a_socket) end debug ("dbglog") - dbglog (generator + ".LEAVE execute {" + a_socket.descriptor.out + "}") + dbglog (generator + ".execute {" + a_socket.descriptor.out + "} LEAVE") end end -- release (a_socket) end - release (a_socket: HTTPD_STREAM_SOCKET) + release (a_socket: detachable HTTPD_STREAM_SOCKET) do - a_socket.cleanup + if a_socket /= Void then + a_socket.cleanup + end reset end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e index ff9adcb9..c8b0f494 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e @@ -154,10 +154,12 @@ feature -- Listening create l_connection_handler.make (Current) from l_listening_socket.listen (configuration.max_tcp_clients) - if is_verbose and then configuration.is_secure then - log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/") - elseif is_verbose then - log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") + if is_verbose then + if configuration.is_secure then + log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/") + else + log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") + end end on_launched (l_http_port) until diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e index 4cf3f162..e9221910 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e @@ -46,6 +46,14 @@ feature {NONE} -- Initialization do Result := s.socket.descriptor end +feature -- Change + + set_accept_timeout (n: INTEGER) + do + if attached {NETWORK_STREAM_SOCKET} socket as l_socket then + l_socket.set_accept_timeout (500_000) + end + end feature -- Access From ddf73077b37cb014aa0a895f8d12b496fdc216bf Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 20 Mar 2015 15:48:54 +0100 Subject: [PATCH 05/33] Support for concurrencies: none, thread and SCOOP --- .../ewsgi/connectors/httpd/httpd-safe.ecf | 6 ++ .../none/httpd_connection_handler.e | 39 ++++------- .../concurrency/none/httpd_request_handler.e | 7 +- .../scoop/httpd_connection_handler.e | 2 +- .../concurrency/scoop/httpd_request_handler.e | 43 ++---------- .../thread/httpd_connection_handler.e | 43 +++++------- .../thread/httpd_request_handler.e | 12 ++-- .../httpd/src/httpd/httpd_request_handler_i.e | 65 +++++++++++++------ 8 files changed, 93 insertions(+), 124 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf index 51f30ddd..c308c705 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -80,4 +80,10 @@ + + + + + + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e index 79ae936a..f420c4d7 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e @@ -31,42 +31,25 @@ feature -- Access feature -- Execution - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) - -- Process incoming connection - -- note that the precondition matters for scoop synchronization. + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) + local + cl: HTTPD_STREAM_SOCKET do is_shutdown_requested := is_shutdown_requested or shutdown_requested (server) if is_shutdown_requested then - a_socket.cleanup - elseif attached server.factory.new_handler as h then - process_connection_handler (h, a_socket) + -- Cancel + elseif attached factory.new_handler as h then + cl := h.client_socket + a_listening_socket.accept_to (cl) + if h.is_connected then + h.execute + end else check is_not_full: False end - a_socket.cleanup end update_is_shutdown_requested end - process_connection_handler (hdl: HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) - require - not hdl.has_error - do - --| FIXME jfiat [2011/11/03] : should use a Pool of Threads/Handler to process this connection - --| also handle permanent connection...? - - hdl.set_client_socket (a_socket) - if not hdl.has_error then --- hdl.set_logger (server) - hdl.execute - else - log ("Internal error (set_client_socket failed)") - end - rescue - log ("Releasing handler after exception!") - hdl.release - a_socket.cleanup - end - update_is_shutdown_requested do is_shutdown_requested := shutdown_requested (server) @@ -89,7 +72,7 @@ feature {HTTPD_SERVER_I} -- Status report end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e index 1e607c5e..535255c4 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e @@ -10,15 +10,10 @@ deferred class inherit HTTPD_REQUEST_HANDLER_I -feature -- Change - set_client_socket (a_socket: HTTPD_STREAM_SOCKET) - do - client_socket := a_socket - end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e index 1bd658cc..e90c89d4 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -96,7 +96,7 @@ feature {HTTPD_SERVER_I} -- Execution require hdl.is_connected do - hdl.separate_execute + hdl.safe_execute end feature {HTTPD_SERVER_I} -- Status report diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e index 9f20e627..4055f7e2 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -20,56 +20,21 @@ inherit release as release_pool_item end -feature -- Status report - - is_connected: BOOLEAN - -- Is handler connected to incoming request via `client_socket'? - do - Result := client_socket.descriptor_available - end - -feature -- Execution - - separate_execute - local - retried: BOOLEAN - do - if retried then - release (client_socket) - else - if - not has_error and then - is_connected - then - execute (client_socket) - end - separate_release - end - rescue - retried := True - retry - end - feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation - separate_release - do - release (client_socket) - end - - release (a_socket: detachable HTTPD_STREAM_SOCKET) + release local d: STRING do - if a_socket /= Void then - d := a_socket.descriptor.out + if attached internal_client_socket as l_socket then + d := l_socket.descriptor.out else d := "N/A" end debug ("dbglog") dbglog (generator + ".release: ENTER {" + d + "}") end - Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) + Precursor {HTTPD_REQUEST_HANDLER_I} release_pool_item debug ("dbglog") dbglog (generator + ".release: LEAVE {" + d + "}") diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e index d3d1354e..d6bebdc1 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e @@ -50,36 +50,27 @@ feature {HTTPD_SERVER_I} -- Execution p.terminate end - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) + local + cl: separate HTTPD_STREAM_SOCKET do - if is_shutdown_requested then - a_socket.cleanup - else - process_connection_handler (factory.new_handler, a_socket) + debug ("dbglog") + dbglog (generator + ".ENTER accept_connection {"+ a_listening_socket.descriptor.out +"}") + end + + if is_shutdown_requested then + -- cancel + elseif attached factory.new_handler as h then + cl := h.client_socket + a_listening_socket.accept_to (cl) + if h.is_connected then + pool.add_work (agent h.safe_execute) + end end - end - process_connection_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) - require - not hdl.has_error - do debug ("dbglog") - dbglog (generator + ".ENTER process_connection_handler {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".LEAVE accept_incoming_connection {"+ a_listening_socket.descriptor.out +"}") end - if not hdl.has_error then --- hdl.set_logger (server) --- hdl.set_client_socket (a_socket) - pool.add_work (agent hdl.execute (a_socket)) - else - log ("Internal error (set_client_socket failed)") - end - debug ("dbglog") - dbglog (generator + ".LEAVE process_connection_handler {"+ a_socket.descriptor.out +"}") - end - rescue - log ("Releasing handler after exception!") - hdl.release (a_socket) --- hdl.client_socket.cleanup end feature {HTTPD_SERVER_I} -- Status report @@ -99,7 +90,7 @@ invariant pool_attached: pool /= Void note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e index a119e283..e053bfe7 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e @@ -17,23 +17,27 @@ inherit feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation - release (a_socket: HTTPD_STREAM_SOCKET) + release local d: STRING do -- FIXME: for log purpose - d := a_socket.descriptor.out + if attached internal_client_socket as l_socket then + d := l_socket.descriptor.out + else + d := "N/A" + end debug ("dbglog") dbglog (generator + ".release: ENTER {" + d + "}") end - Precursor {HTTPD_REQUEST_HANDLER_I} (a_socket) + Precursor {HTTPD_REQUEST_HANDLER_I} debug ("dbglog") dbglog (generator + ".release: LEAVE {" + d + "}") end end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e index 2411d637..8d85e5f0 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -34,7 +34,14 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) - is_waiting := False + end + +feature -- Status report + + is_connected: BOOLEAN + -- Is handler connected to incoming request via `client_socket'? + do + Result := client_socket.descriptor_available end feature -- Access @@ -78,8 +85,6 @@ feature -- Settings feature -- Status report - is_waiting: BOOLEAN - has_error: BOOLEAN -- Error occurred during `analyze_request_message' @@ -92,36 +97,60 @@ feature -- Change feature -- Execution - execute (a_socket: HTTPD_STREAM_SOCKET) + safe_execute + local + retried: BOOLEAN + do + if retried then + release + else + if + not has_error and then + is_connected + then + execute + end + release + end + rescue + retried := True + retry + end + + execute require - socket_attached: a_socket /= Void - socket_valid: a_socket.is_open_read and then a_socket.is_open_write - a_http_socket: not a_socket.is_closed + is_connected: is_connected local l_remote_info: detachable like remote_info l_continue: BOOLEAN + l_socket: like client_socket do - if a_socket.is_closed then + l_socket := client_socket + check + socket_attached: l_socket /= Void + socket_valid: l_socket.is_open_read and then l_socket.is_open_write + end + if l_socket.is_closed then debug ("dbglog") dbglog (generator + ".execute {socket is Closed!}") end else debug ("dbglog") - dbglog (generator + ".execute {" + a_socket.descriptor.out + "} ENTER") + dbglog (generator + ".execute socket=" + l_socket.descriptor.out + " ENTER") end from until l_continue loop - if a_socket.ready_for_reading then + if l_socket.ready_for_reading then l_continue := True create l_remote_info - if attached a_socket.peer_address as l_addr then + if attached l_socket.peer_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 remote_info := l_remote_info end - analyze_request_message (a_socket) + analyze_request_message (l_socket) else - log (generator + ".execute {" + a_socket.descriptor.out + "} WAITING") + log (generator + ".execute socket=" + l_socket.descriptor.out + "} WAITING") end end @@ -132,20 +161,16 @@ feature -- Execution log ("ERROR: invalid HTTP incoming request") end else - process_request (a_socket) + process_request (l_socket) end debug ("dbglog") - dbglog (generator + ".execute {" + a_socket.descriptor.out + "} LEAVE") + dbglog (generator + ".execute {" + l_socket.descriptor.out + "} LEAVE") end end --- release (a_socket) end - release (a_socket: detachable HTTPD_STREAM_SOCKET) + release do - if a_socket /= Void then - a_socket.cleanup - end reset end From bf0eb9a02de2d7faf2d0998a330da363529e46e4 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 24 Mar 2015 23:21:49 +0100 Subject: [PATCH 06/33] Added SCOOP support for WSF. WSF_SERVICE is deeply changed, and addition of WSF_EXECUTION. Todo: code cleaning, removing useless things. --- examples/debug/debug.ecf | 14 +- .../debug/launcher/any/application_launcher.e | 4 +- .../launcher/any/application_launcher_i.e | 50 +++-- .../launcher/default/application_launcher.e | 4 +- .../launcher/default/application_launcher_i.e | 8 +- examples/debug/src/ewf_debug_execution.e | 27 +++ examples/debug/src/ewf_debug_server.e | 18 +- examples/simple/simple.ecf | 8 + examples/simple_file/home.html | 10 +- examples/simple_file/service_file.e | 14 +- examples/simple_file/service_file.ecf | 4 +- examples/simple_file/service_file_execution.e | 26 +++ .../connectors/cgi/src/wgi_cgi_connector.e | 26 +-- .../httpd/dev/httpd_connector_dev.e | 31 +-- .../ewsgi/connectors/httpd/httpd-safe.ecf | 11 +- .../none/httpd_connection_handler.e | 2 +- .../httpd/src/httpd/httpd_server_i.e | 2 + .../httpd/src/wgi_httpd_connector.e | 183 ++++++++++++++++++ .../httpd/src/wgi_httpd_input_stream.e | 2 +- .../httpd/src/wgi_httpd_output_stream.e | 2 +- .../wgi_httpd_request_handler.e} | 47 +++-- .../src/wgi_httpd_request_handler_factory.e | 41 ++++ .../libfcgi/src/wgi_libfcgi_connector.e | 26 +-- .../connectors/nino/src/wgi_nino_connector.e | 29 ++- .../connectors/nino/src/wgi_nino_handler.e | 4 +- .../ewsgi/specification/request/wgi_request.e | 2 +- .../ewsgi/specification/service/wgi_service.e | 14 -- .../implementation/wgi_request_from_table.e | 2 +- library/server/ewsgi/src/wgi_execution.e | 54 ++++++ .../connector/cgi/wsf_cgi_service_launcher.e | 20 +- library/server/wsf/connector/httpd-safe.ecf | 22 +++ .../httpd/wsf_httpd_service_launcher.e | 168 ++++++++++++++++ .../libfcgi/wsf_libfcgi_service_launcher.e | 18 +- .../nino/wsf_nino_service_launcher.e | 54 +++--- .../cgi/wsf_default_service_launcher.e | 10 +- library/server/wsf/default/httpd-safe.ecf | 17 ++ .../httpd/wsf_default_response_service.e | 24 +++ .../wsf/default/httpd/wsf_default_service.e | 22 +++ .../httpd/wsf_default_service_launcher.e} | 19 +- .../wsf/default/nino/wsf_default_service.e | 4 +- .../nino/wsf_default_service_launcher.e | 8 +- .../wsf/extension/handler/wsf_debug_handler.e | 16 +- .../wsf/extension/wsf_debug_information.e | 28 ++- .../wsf/src/service/wsf_default_service_i.e | 6 +- .../wsf/src/service/wsf_launchable_service.e | 6 +- library/server/wsf/src/service/wsf_service.e | 20 +- .../wsf/src/service/wsf_service_launcher.e | 24 +-- .../wsf/src/service/wsf_to_wgi_service.e | 41 +--- library/server/wsf/src/wsf_execution.e | 69 ++++++- library/server/wsf/src/wsf_request.e | 4 +- library/server/wsf/src/wsf_response.e | 2 +- 51 files changed, 951 insertions(+), 316 deletions(-) create mode 100644 examples/debug/src/ewf_debug_execution.e create mode 100644 examples/simple_file/service_file_execution.e create mode 100644 library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e rename library/server/ewsgi/connectors/httpd/{dev/wsf/wsf_httpd_request_handler.e => src/wgi_httpd_request_handler.e} (88%) create mode 100644 library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e create mode 100644 library/server/ewsgi/src/wgi_execution.e create mode 100644 library/server/wsf/connector/httpd-safe.ecf create mode 100644 library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e create mode 100644 library/server/wsf/default/httpd-safe.ecf create mode 100644 library/server/wsf/default/httpd/wsf_default_response_service.e create mode 100644 library/server/wsf/default/httpd/wsf_default_service.e rename library/server/{ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e => wsf/default/httpd/wsf_default_service_launcher.e} (59%) diff --git a/examples/debug/debug.ecf b/examples/debug/debug.ecf index 7b1f2b7b..26bf2100 100644 --- a/examples/debug/debug.ecf +++ b/examples/debug/debug.ecf @@ -18,12 +18,20 @@ + - - + + + + + + + + + @@ -32,7 +40,7 @@ - + diff --git a/examples/debug/launcher/any/application_launcher.e b/examples/debug/launcher/any/application_launcher.e index 0ef505c3..bb184d0a 100644 --- a/examples/debug/launcher/any/application_launcher.e +++ b/examples/debug/launcher/any/application_launcher.e @@ -8,10 +8,10 @@ note revision: "$Revision: 36 $" class - APPLICATION_LAUNCHER + APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G] feature -- Custom diff --git a/examples/debug/launcher/any/application_launcher_i.e b/examples/debug/launcher/any/application_launcher_i.e index 0744c801..22f94cab 100644 --- a/examples/debug/launcher/any/application_launcher_i.e +++ b/examples/debug/launcher/any/application_launcher_i.e @@ -10,24 +10,26 @@ note revision: "$Revision: 36 $" deferred class - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end] inherit SHARED_EXECUTION_ENVIRONMENT feature -- Execution - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local nature: like launcher_nature do nature := launcher_nature - if nature = Void or else nature = nature_nino then - launch_nino (a_service, opts) + if nature = Void or else nature = nature_httpd then + launch_httpd (opts) + elseif nature = nature_nino then + launch_nino (opts) elseif nature = nature_cgi then - launch_cgi (a_service, opts) + launch_cgi (opts) elseif nature = nature_libfcgi then - launch_libfcgi (a_service, opts) + launch_libfcgi (opts) else -- bye bye (create {EXCEPTIONS}).die (-1) @@ -43,14 +45,16 @@ feature {NONE} -- Access --| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time. local p: PATH - l_entry_name: READABLE_STRING_32 ext: detachable READABLE_STRING_32 do create p.make_from_string (execution_environment.arguments.command_name) if attached p.entry as l_entry then - ext := l_entry.extension + ext := l_entry.extension end if ext /= Void then + if ext.same_string (nature_httpd) then + Result := nature_httpd + end if ext.same_string (nature_nino) then Result := nature_nino end @@ -61,39 +65,51 @@ feature {NONE} -- Access Result := nature_libfcgi end end + Result := nature_httpd + end + +feature {NONE} -- nino + + nature_httpd: STRING = "httpd" + + launch_httpd (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + local + launcher: WSF_HTTPD_SERVICE_LAUNCHER [G] + do + create launcher.make_and_launch (opts) end feature {NONE} -- nino nature_nino: STRING = "nino" - launch_nino (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_nino (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_NINO_SERVICE_LAUNCHER + launcher: WSF_NINO_SERVICE_LAUNCHER [G] do - create launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) end feature {NONE} -- cgi nature_cgi: STRING = "cgi" - launch_cgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_cgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_CGI_SERVICE_LAUNCHER + launcher: WSF_CGI_SERVICE_LAUNCHER [G] do - create launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) end feature {NONE} -- libfcgi nature_libfcgi: STRING = "libfcgi" - launch_libfcgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_libfcgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_LIBFCGI_SERVICE_LAUNCHER + launcher: WSF_LIBFCGI_SERVICE_LAUNCHER [G] do - create launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) end diff --git a/examples/debug/launcher/default/application_launcher.e b/examples/debug/launcher/default/application_launcher.e index 0ef505c3..bb184d0a 100644 --- a/examples/debug/launcher/default/application_launcher.e +++ b/examples/debug/launcher/default/application_launcher.e @@ -8,10 +8,10 @@ note revision: "$Revision: 36 $" class - APPLICATION_LAUNCHER + APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G] feature -- Custom diff --git a/examples/debug/launcher/default/application_launcher_i.e b/examples/debug/launcher/default/application_launcher_i.e index 2cd4a73d..ef8f0037 100644 --- a/examples/debug/launcher/default/application_launcher_i.e +++ b/examples/debug/launcher/default/application_launcher_i.e @@ -10,15 +10,15 @@ note revision: "$Revision: 36 $" deferred class - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end] feature -- Execution - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_SERVICE_LAUNCHER + launcher: WSF_SERVICE_LAUNCHER [G] do - create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) + create {WSF_DEFAULT_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts) end end diff --git a/examples/debug/src/ewf_debug_execution.e b/examples/debug/src/ewf_debug_execution.e new file mode 100644 index 00000000..f75c44c2 --- /dev/null +++ b/examples/debug/src/ewf_debug_execution.e @@ -0,0 +1,27 @@ +note + description: "Summary description for {EWF_DEBUG_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + EWF_DEBUG_EXECUTION + +inherit + WSF_EXECUTION + +create + make + +feature -- Execution + + execute + local + dbg: WSF_DEBUG_HANDLER + do + response.put_error ("DEBUG uri=" + request.request_uri + "%N") + create dbg.make + dbg.execute_starts_with ("", request, response) + end + +end diff --git a/examples/debug/src/ewf_debug_server.e b/examples/debug/src/ewf_debug_server.e index 3725bfc9..17f6f954 100644 --- a/examples/debug/src/ewf_debug_server.e +++ b/examples/debug/src/ewf_debug_server.e @@ -14,7 +14,7 @@ inherit initialize end - APPLICATION_LAUNCHER + APPLICATION_LAUNCHER [EWF_DEBUG_EXECUTION] create make_and_launch @@ -30,14 +30,14 @@ feature {NONE} -- Initialization -- set_service_option ("base", "/www-debug/debug_service.fcgi/") end - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - local - dbg: WSF_DEBUG_HANDLER - do - res.put_error ("DEBUG" + req.request_uri + "%N") - create dbg.make - dbg.execute_starts_with ("", req, res) - end +-- execute (req: WSF_REQUEST; res: WSF_RESPONSE) +-- local +-- dbg: WSF_DEBUG_HANDLER +-- do +-- res.put_error ("OH NO uri=" + req.request_uri + "%N") +-- create dbg.make +-- dbg.execute_starts_with ("", req, res) +-- end end diff --git a/examples/simple/simple.ecf b/examples/simple/simple.ecf index d0fccfd8..4bf050c9 100644 --- a/examples/simple/simple.ecf +++ b/examples/simple/simple.ecf @@ -13,6 +13,14 @@ + + + + + + - - + + diff --git a/examples/simple_file/service_file_execution.e b/examples/simple_file/service_file_execution.e new file mode 100644 index 00000000..4fc0aacf --- /dev/null +++ b/examples/simple_file/service_file_execution.e @@ -0,0 +1,26 @@ +note + description: "Summary description for {SERVICE_FILE_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + SERVICE_FILE_EXECUTION + +inherit + WSF_EXECUTION + +create + make + +feature {NONE} -- Initialization + + execute + local + f: WSF_FILE_RESPONSE + do + create f.make_html ("home.html") + response.send (f) + end + +end diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e index f330b4ab..d5c95cf0 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e @@ -4,21 +4,11 @@ note revision: "$Revision$" class - WGI_CGI_CONNECTOR + WGI_CGI_CONNECTOR [G -> WGI_EXECUTION create make end] inherit WGI_CONNECTOR -create - make - -feature {NONE} -- Initialization - - make (a_service: like service) - do - service := a_service - end - feature -- Access Name: STRING_8 = "CGI" @@ -27,24 +17,23 @@ feature -- Access Version: STRING_8 = "0.1" -- Version of Current connector -feature {NONE} -- Access - - service: WGI_SERVICE - -- Gateway Service - feature -- Execution launch local req: WGI_REQUEST_FROM_TABLE res: detachable WGI_RESPONSE_STREAM + exec: detachable WGI_EXECUTION rescued: BOOLEAN do if not rescued then create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment, create {WGI_CGI_INPUT_STREAM}.make, Current) create res.make (create {WGI_CGI_OUTPUT_STREAM}.make, create {WGI_CGI_ERROR_STREAM}.make) - service.execute (req, res) + create {G} exec.make (req, res) + exec.execute + res.flush res.push + exec.clean else if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then if res /= Void then @@ -59,6 +48,9 @@ feature -- Execution res.push end end + if exec /= Void then + exec.clean + end end rescue if not rescued then diff --git a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e index a12bc301..9353f5c3 100644 --- a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e +++ b/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e @@ -17,33 +17,16 @@ feature {NONE} -- Initialization make -- Initialize `Current'. local - server: separate HTTPD_SERVER - fac: separate WSF_HTTPD_REQUEST_HANDLER_FACTORY [APP_WSF_EXECUTION] + conn: WGI_HTTPD_CONNECTOR [APP_WSF_EXECUTION] do - print ("Hello%N") - create fac - create server.make (fac) - launch_server (server) + print ("Starting httpd server ...%N") + + create conn.make + conn.set_port_number (9090) + conn.set_max_concurrent_connections (100) + conn.launch end - launch_server (server: separate HTTPD_SERVER) - do - server.configuration.set_max_concurrent_connections (100) - server.configuration.set_http_server_port (9090) - server.launch - end - -feature -- Status - -feature -- Access - -feature -- Change - -feature {NONE} -- Implementation - -invariant --- invariant_clause: True - note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf index c308c705..cd28afb9 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -7,8 +7,9 @@ /\.git$ /\.svn$ - @@ -31,13 +32,12 @@ - - /concurrency$ + /ssl$ /EIFGENs$ /no_ssl$ - /ssl$ + /concurrency$ @@ -73,11 +73,12 @@ - + diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e index f420c4d7..54ca8b74 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e @@ -42,7 +42,7 @@ feature -- Execution cl := h.client_socket a_listening_socket.accept_to (cl) if h.is_connected then - h.execute + h.safe_execute end else check is_not_full: False end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e index c8b0f494..86205296 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e @@ -16,6 +16,8 @@ feature {NONE} -- Initialization make (a_factory: like factory) -- `a_cfg': server configuration -- `a_factory': connection handler builder + require + fac_is_separated: {PLATFORM}.is_scoop_capable implies not attached {HTTPD_REQUEST_HANDLER_FACTORY} a_factory do make_configured (create {like configuration}.make, a_factory) end diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e new file mode 100644 index 00000000..639f6e21 --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e @@ -0,0 +1,183 @@ +note + description: "Summary description for {WGI_HTTPD_CONNECTOR}." + author: "" + todo: "[ + Check if server and configuration has to be 'separate' ? + currently yes, due to WGI_REQUEST.wgi_connector setting. + But we may get rid of this one... + See `{WGI_REQUEST}.wgi_connector' and `{WSF_REQUEST}.wgi_connector' ... + ]" + date: "$Date$" + revision: "$Revision$" + +class + WGI_HTTPD_CONNECTOR [G -> WGI_EXECUTION create make end] + +inherit + WGI_CONNECTOR + +create + make, + make_with_base + +feature {NONE} -- Initialization + + make + local + fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G] + do + -- Callbacks + create on_launched_actions + create on_stopped_actions + + -- Server + create fac + create server.make (fac) + configuration := server_configuration (server) + + set_factory_connector (Current, fac) + end + + make_with_base (a_base: like base) + require + a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies a_base.starts_with ("/") + do + make + set_base (a_base) + end + + set_factory_connector (conn: detachable separate WGI_CONNECTOR; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) + do + fac.set_connector (conn) + end + +feature -- Access + + name: STRING_8 = "httpd" + -- Name of Current connector + + version: STRING_8 = "0.1" + -- Version of Current connector + +feature -- Access + + server: separate HTTPD_SERVER + + configuration: separate HTTPD_CONFIGURATION + + server_configuration (a_server: like server): like configuration + do + Result := a_server.configuration + end + +feature -- Access + + base: detachable READABLE_STRING_8 + -- Root url base + +feature -- Status report + + launched: BOOLEAN + -- Server launched and listening on `port' + + port: INTEGER + -- Listening port. + --| 0: not launched + +feature -- Callbacks + + on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when launched + + on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when stopped + +feature -- Element change + + on_launched (a_port: INTEGER) + -- Server launched + do + launched := True + port := a_port + on_launched_actions.call ([Current]) + end + + on_stopped + -- Server stopped + do + on_stopped_actions.call ([Current]) + launched := False + port := 0 + end + +feature -- Element change + + set_base (b: like base) + require + b_starts_with_slash: (b /= Void and then not b.is_empty) implies b.starts_with ("/") + do + base := b + ensure + valid_base: (attached base as l_base and then not l_base.is_empty) implies l_base.starts_with ("/") + end + + set_port_number (a_port_number: INTEGER) + require + a_port_number_positive_or_zero: a_port_number >= 0 + do + set_port_on_configuration (a_port_number, configuration) + end + + set_max_concurrent_connections (nb: INTEGER) + do + + end + +feature {NONE} -- Implementation + + set_port_on_configuration (a_port_number: INTEGER; cfg: like configuration) + do + cfg.set_http_server_port (a_port_number) + end + + set_max_concurrent_connections_on_configuration (nb: INTEGER; cfg: like configuration) + do + cfg.set_max_concurrent_connections (nb) + end + +feature -- Server + + launch + do + launched := False + port := 0 + launch_server (server) + end + + configure_server (a_configuration: like configuration) + do + if a_configuration.is_verbose then + if attached base as l_base then + io.error.put_string ("Base=" + l_base + "%N") + end + end + end + + launch_server (a_server: like server) + do + configure_server (a_server.configuration) + a_server.launch + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end + diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e index 878db547..ce34a558 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e @@ -22,7 +22,7 @@ feature {NONE} -- Initialization set_source (a_source) end -feature {WGI_NINO_CONNECTOR, WGI_SERVICE} -- Nino +feature {WGI_HTTPD_CONNECTOR, WGI_SERVICE} -- Nino set_source (i: like source) do diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e index a57095cf..c581bc79 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e @@ -26,7 +26,7 @@ feature {NONE} -- Initialization set_target (a_target) end -feature {WGI_NINO_CONNECTOR, WGI_SERVICE} -- Nino +feature {WGI_HTTPD_CONNECTOR, WGI_SERVICE} -- Nino set_target (o: like target) do diff --git a/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e similarity index 88% rename from library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e rename to library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e index c5730b33..f0bdc24a 100644 --- a/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e @@ -1,11 +1,11 @@ note - description: "Summary description for {WSF_HTTPD_REQUEST_HANDLER}." + description: "Summary description for {WGI_HTTPD_REQUEST_HANDLER}." author: "" date: "$Date$" revision: "$Revision$" class - WSF_HTTPD_REQUEST_HANDLER [G -> WSF_EXECUTION create make end] + WGI_HTTPD_REQUEST_HANDLER [G -> WGI_EXECUTION create make end] inherit HTTPD_REQUEST_HANDLER @@ -15,7 +15,18 @@ inherit REFACTORING_HELPER create - make + make, + make_with_connector + +feature {NONE} -- Initialization + + make_with_connector (conn: like connector) + do + make + connector := conn + end + + connector: detachable separate WGI_CONNECTOR feature -- Request processing @@ -27,8 +38,7 @@ feature -- Request processing l_error: WGI_ERROR_STREAM req: WGI_REQUEST_FROM_TABLE res: detachable WGI_HTTPD_RESPONSE_STREAM - - exec: WSF_EXECUTION + exec: detachable WGI_EXECUTION retried: BOOLEAN do if not retried then @@ -36,15 +46,33 @@ feature -- Request processing create {WGI_HTTPD_OUTPUT_STREAM} l_output.make (a_socket) create {WGI_HTTPD_ERROR_STREAM} l_error.make_stderr (a_socket.descriptor.out) - create req.make (httpd_environment (a_socket), l_input, Void) + create req.make (httpd_environment (a_socket), l_input, connector) create res.make (l_output, l_error) req.set_meta_string_variable ("RAW_HEADER_DATA", request_header) - exec := new_execution (req, res) + create {G} exec.make (req, res) exec.execute + res.flush res.push + exec.clean else + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
")
+							res.put_string (l_trace)
+							res.put_string ("
") + end + res.push + end + end + if exec /= Void then + exec.clean + end end rescue if not retried then @@ -53,11 +81,6 @@ feature -- Request processing end end - new_execution (req: WGI_REQUEST; res: WGI_RESPONSE): WSF_EXECUTION - do - create {G} Result.make (req, res) - end - base: detachable READABLE_STRING_8 do --TODO diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e new file mode 100644 index 00000000..c2b2d5ef --- /dev/null +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e @@ -0,0 +1,41 @@ +note + description: "Summary description for {WGI_HTTPD_REQUEST_HANDLER_FACTORY}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WGI_HTTPD_REQUEST_HANDLER_FACTORY [G -> WGI_EXECUTION create make end] + +inherit + HTTPD_REQUEST_HANDLER_FACTORY + +feature -- Access + + connector: detachable separate WGI_CONNECTOR + +feature -- Element change + + set_connector (conn: like connector) + do + connector := conn + end + +feature -- Factory + + new_handler: separate WGI_HTTPD_REQUEST_HANDLER [G] + do + create Result.make_with_connector (connector) + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e index 2bb63746..1b994d85 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e @@ -6,19 +6,19 @@ note revision: "$Revision$" class - WGI_LIBFCGI_CONNECTOR + WGI_LIBFCGI_CONNECTOR [G -> WGI_EXECUTION create make end] inherit WGI_CONNECTOR - -create - make + redefine + default_create + end feature {NONE} -- Initialization - make (a_service: like service) + default_create do - service := a_service + Precursor create fcgi.make create input.make (fcgi) create output.make (fcgi) @@ -32,11 +32,6 @@ feature -- Access Version: STRING_8 = "0.1" -- Version of Current connector -feature {NONE} -- Access - - service: WGI_SERVICE - -- Gateway Service - feature -- Server launch @@ -59,14 +54,18 @@ feature -- Execution local req: WGI_REQUEST_FROM_TABLE res: detachable WGI_RESPONSE_STREAM + exec: detachable WGI_EXECUTION rescued: BOOLEAN do if not rescued then a_input.reset create req.make (vars, a_input, Current) create res.make (a_output, a_output) - service.execute (req, res) + create {G} exec.make (req, res) + exec.execute + res.flush res.push + exec.clean else if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then if res /= Void then @@ -81,6 +80,9 @@ feature -- Execution res.push end end + if exec /= Void then + exec.clean + end end rescue if not rescued then diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 431001af..03696fd6 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -4,7 +4,7 @@ note revision: "$Revision$" class - WGI_NINO_CONNECTOR + WGI_NINO_CONNECTOR [G -> WGI_EXECUTION create make end] inherit WGI_CONNECTOR @@ -118,7 +118,7 @@ feature -- Server do launched := False port := 0 - create {WGI_NINO_HANDLER} l_http_handler.make_with_callback (server, Current) + create {WGI_NINO_HANDLER [G]} l_http_handler.make_with_callback (server, Current) if configuration.is_verbose then if attached base as l_base then io.error.put_string ("Base=" + l_base + "%N") @@ -128,17 +128,40 @@ feature -- Server end process_request (env: STRING_TABLE [READABLE_STRING_8]; a_headers_text: STRING; a_socket: TCP_STREAM_SOCKET) + -- Process request ... local req: WGI_REQUEST_FROM_TABLE res: detachable WGI_NINO_RESPONSE_STREAM + exec: detachable WGI_EXECUTION retried: BOOLEAN do if not retried then create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current) create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), create {WGI_NINO_ERROR_STREAM}.make_stderr (a_socket.descriptor.out)) req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) - service.execute (req, res) + + create {G} exec.make (req, res) + exec.execute + res.flush res.push + exec.clean + else + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
")
+							res.put_string (l_trace)
+							res.put_string ("
") + end + res.push + end + end + if exec /= Void then + exec.clean + end end rescue if not retried then diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e index 528a48c1..d1bd11db 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e @@ -5,7 +5,7 @@ note revision : "$Revision$" class - WGI_NINO_HANDLER + WGI_NINO_HANDLER [G -> WGI_EXECUTION create make end] inherit HTTP_CONNECTION_HANDLER @@ -27,7 +27,7 @@ feature {NONE} -- Initialization callback := a_callback end - callback: WGI_NINO_CONNECTOR + callback: WGI_NINO_CONNECTOR [G] feature -- Access diff --git a/library/server/ewsgi/specification/request/wgi_request.e b/library/server/ewsgi/specification/request/wgi_request.e index 85a9660e..00c57111 100644 --- a/library/server/ewsgi/specification/request/wgi_request.e +++ b/library/server/ewsgi/specification/request/wgi_request.e @@ -157,7 +157,7 @@ feature -- Eiffel WGI access deferred end - wgi_connector: detachable WGI_CONNECTOR + wgi_connector: detachable separate WGI_CONNECTOR -- Associated Eiffel WGI connector deferred end diff --git a/library/server/ewsgi/specification/service/wgi_service.e b/library/server/ewsgi/specification/service/wgi_service.e index 910bbc42..e13d9468 100644 --- a/library/server/ewsgi/specification/service/wgi_service.e +++ b/library/server/ewsgi/specification/service/wgi_service.e @@ -11,20 +11,6 @@ note deferred class WGI_SERVICE -feature {WGI_CONNECTOR} -- Execution - - execute (req: WGI_REQUEST; res: WGI_RESPONSE) - -- Execute the request - -- See `req.input' for input stream - -- `req.meta_variables' for the CGI meta variable - -- and `res' for output buffer - require - res_status_unset: not res.status_is_set - deferred - ensure - res_status_set: res.status_is_set - end - note copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/src/implementation/wgi_request_from_table.e b/library/server/ewsgi/src/implementation/wgi_request_from_table.e index 988d0c99..8a0b30cc 100644 --- a/library/server/ewsgi/src/implementation/wgi_request_from_table.e +++ b/library/server/ewsgi/src/implementation/wgi_request_from_table.e @@ -57,7 +57,7 @@ feature -- EWSGI access wgi_implementation: STRING = "Eiffel Web Framework 0.1" - wgi_connector: detachable WGI_CONNECTOR + wgi_connector: detachable separate WGI_CONNECTOR feature -- Access: CGI meta parameters diff --git a/library/server/ewsgi/src/wgi_execution.e b/library/server/ewsgi/src/wgi_execution.e new file mode 100644 index 00000000..204be494 --- /dev/null +++ b/library/server/ewsgi/src/wgi_execution.e @@ -0,0 +1,54 @@ +note + description: "Summary description for {WGI_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WGI_EXECUTION + +--create +-- make + +feature {NONE} -- Initialization + + make (req: WGI_REQUEST; res: WGI_RESPONSE) + do + request := req + response := res + end + +feature {NONE} -- Access + + request: WGI_REQUEST + + response: WGI_RESPONSE + +feature -- Execution + + execute + -- Execute the request based on `request' and `response'. + deferred + ensure + status_is_set: response.status_is_set + end + +feature -- Cleaning + + clean + -- Clean request data. + do + end + + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/connector/cgi/wsf_cgi_service_launcher.e b/library/server/wsf/connector/cgi/wsf_cgi_service_launcher.e index 9d7693af..b82e1680 100644 --- a/library/server/wsf/connector/cgi/wsf_cgi_service_launcher.e +++ b/library/server/wsf/connector/cgi/wsf_cgi_service_launcher.e @@ -18,40 +18,36 @@ note revision: "$Revision$" class - WSF_CGI_SERVICE_LAUNCHER + WSF_CGI_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_SERVICE_LAUNCHER + WSF_SERVICE_LAUNCHER [G] create make, - make_and_launch, - make_callback, - make_callback_and_launch - + make_and_launch + feature {NONE} -- Initialization initialize do - create connector.make (Current) + create connector end feature -- Execution launch do - if attached connector as conn then - conn.launch - end + connector.launch end feature -- Status report - connector: detachable WGI_CGI_CONNECTOR + connector: WGI_CGI_CONNECTOR [G] -- Default service name ;note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/connector/httpd-safe.ecf b/library/server/wsf/connector/httpd-safe.ecf new file mode 100644 index 00000000..c5d577f6 --- /dev/null +++ b/library/server/wsf/connector/httpd-safe.ecf @@ -0,0 +1,22 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + diff --git a/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e b/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e new file mode 100644 index 00000000..4644ae61 --- /dev/null +++ b/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e @@ -0,0 +1,168 @@ +note + description: "[ + Component to launch the service using the default connector + + Eiffel Web httpd for this class + + + The httpd default connector support options: + port: numeric such as 8099 (or equivalent string as "8099") + base: base_url (very specific to standalone server) + verbose: to display verbose output, useful for Nino + force_single_threaded: use only one thread, useful for Nino + + check WSF_SERVICE_LAUNCHER for more documentation + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_HTTPD_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] + +inherit + WSF_SERVICE_LAUNCHER [G] + redefine + launchable + end + +create + make, + make_and_launch + +feature {NONE} -- Initialization + + initialize + local + conn: like connector + do + create on_launched_actions + create on_stopped_actions + + port_number := 80 --| Default, but quite often, this port is already used ... + base_url := "" + + if attached options as opts then + if attached {READABLE_STRING_GENERAL} opts.option ("server_name") as l_server_name then + server_name := l_server_name.to_string_8 + end + if attached {INTEGER} opts.option ("port") as l_port then + port_number := l_port + elseif + attached {READABLE_STRING_GENERAL} opts.option ("port") as l_port_str and then + l_port_str.is_integer + then + port_number := l_port_str.as_string_8.to_integer + end + if attached {READABLE_STRING_GENERAL} opts.option ("base") as l_base_str then + base_url := l_base_str.as_string_8 + end + if attached {BOOLEAN} opts.option ("force_single_threaded") as l_single_threaded then + single_threaded := l_single_threaded + elseif attached {READABLE_STRING_GENERAL} opts.option ("force_single_threaded") as l_single_threaded_str then + single_threaded := l_single_threaded_str.as_lower.same_string ("true") + end + if attached {BOOLEAN} opts.option ("verbose") as l_verbose then + verbose := l_verbose + elseif attached {READABLE_STRING_GENERAL} opts.option ("verbose") as l_verbose_str then + verbose := l_verbose_str.as_lower.same_string ("true") + end + end + + create conn.make + connector := conn + conn.on_launched_actions.extend (agent on_launched) + conn.on_stopped_actions.extend (agent on_stopped) + conn.set_base (base_url) + + update_configuration (conn.configuration) + end + +feature -- Execution + + update_configuration (cfg: separate HTTPD_CONFIGURATION) + do + if single_threaded then + cfg.set_force_single_threaded (True) + end + cfg.set_is_verbose (verbose) + if attached server_name as l_server_name then + cfg.set_http_server_name (l_server_name) + end +-- conn.set_port_number (port_number) + cfg.http_server_port := port_number + end + + launch + -- + -- using `port_number', `base_url', `verbose' and `single_threaded' + local + conn: like connector + do + conn := connector + conn.set_base (base_url) + debug ("nino") + if verbose then + io.error.put_string ("Launching Nino web server on port " + port_number.out) + if attached server_name as l_name then + io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N") + else + io.error.put_string ("%N http://localhost:" + port_number.out + "/" + base_url + "%N") + end + end + end + update_configuration (conn.configuration) + conn.launch + end + +feature -- Callback + + on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when launched + + on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when stopped + +feature {NONE} -- Implementation + + on_launched (conn: WGI_CONNECTOR) + do + on_launched_actions.call ([conn]) + end + + on_stopped (conn: WGI_CONNECTOR) + do + on_stopped_actions.call ([conn]) + end + + port_number: INTEGER + + server_name: detachable READABLE_STRING_8 + + base_url: READABLE_STRING_8 + + verbose: BOOLEAN + + single_threaded: BOOLEAN + +feature -- Status report + + connector: WGI_HTTPD_CONNECTOR [G] + -- Default connector + + launchable: BOOLEAN + do + Result := Precursor and port_number >= 0 + end + +;note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e b/library/server/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e index 5eca65f0..284b3d71 100644 --- a/library/server/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e +++ b/library/server/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e @@ -18,40 +18,36 @@ note revision: "$Revision$" class - WSF_LIBFCGI_SERVICE_LAUNCHER + WSF_LIBFCGI_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_SERVICE_LAUNCHER + WSF_SERVICE_LAUNCHER [G] create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch feature {NONE} -- Initialization initialize do - create connector.make (Current) + create connector end feature -- Execution launch do - if attached connector as conn then - conn.launch - end + connector.launch end feature -- Status report - connector: detachable WGI_LIBFCGI_CONNECTOR + connector: WGI_LIBFCGI_CONNECTOR [G] -- Default service name ;note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/connector/nino/wsf_nino_service_launcher.e b/library/server/wsf/connector/nino/wsf_nino_service_launcher.e index 7fa62a9e..553f20fe 100644 --- a/library/server/wsf/connector/nino/wsf_nino_service_launcher.e +++ b/library/server/wsf/connector/nino/wsf_nino_service_launcher.e @@ -17,19 +17,17 @@ note revision: "$Revision$" class - WSF_NINO_SERVICE_LAUNCHER + WSF_NINO_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_SERVICE_LAUNCHER + WSF_SERVICE_LAUNCHER [G] redefine launchable end create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch feature {NONE} -- Initialization @@ -70,9 +68,10 @@ feature {NONE} -- Initialization end end create conn.make (Current) + connector := conn + conn.on_launched_actions.extend (agent on_launched) conn.on_stopped_actions.extend (agent on_stopped) - connector := conn conn.set_base (base_url) if single_threaded then conn.configuration.set_force_single_threaded (True) @@ -85,29 +84,30 @@ feature -- Execution launch -- -- using `port_number', `base_url', `verbose' and `single_threaded' + local + conn: like connector do - if attached connector as conn then - conn.set_base (base_url) - if single_threaded then - conn.configuration.set_force_single_threaded (True) - end - conn.configuration.set_is_verbose (verbose) - debug ("nino") - if verbose then - io.error.put_string ("Launching Nino web server on port " + port_number.out) - if attached server_name as l_name then - io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N") - else - io.error.put_string ("%N http://localhost:" + port_number.out + "/" + base_url + "%N") - end + conn := connector + conn.set_base (base_url) + if single_threaded then + conn.configuration.set_force_single_threaded (True) + end + conn.configuration.set_is_verbose (verbose) + debug ("nino") + if verbose then + io.error.put_string ("Launching Nino web server on port " + port_number.out) + if attached server_name as l_name then + io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N") + else + io.error.put_string ("%N http://localhost:" + port_number.out + "/" + base_url + "%N") end end - if attached server_name as l_server_name then - conn.configuration.set_http_server_name (l_server_name) - end - conn.configuration.http_server_port := port_number - conn.launch end + if attached server_name as l_server_name then + conn.configuration.set_http_server_name (l_server_name) + end + conn.configuration.http_server_port := port_number + conn.launch end feature -- Callback @@ -142,7 +142,7 @@ feature {NONE} -- Implementation feature -- Status report - connector: detachable WGI_NINO_CONNECTOR + connector: WGI_NINO_CONNECTOR [G] -- Default connector launchable: BOOLEAN @@ -151,7 +151,7 @@ feature -- Status report end ;note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/cgi/wsf_default_service_launcher.e b/library/server/wsf/default/cgi/wsf_default_service_launcher.e index 9c2df057..a6ba4e6c 100644 --- a/library/server/wsf/default/cgi/wsf_default_service_launcher.e +++ b/library/server/wsf/default/cgi/wsf_default_service_launcher.e @@ -5,19 +5,17 @@ note revision: "$Revision$" class - WSF_DEFAULT_SERVICE_LAUNCHER + WSF_DEFAULT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_CGI_SERVICE_LAUNCHER + WSF_CGI_SERVICE_LAUNCHER [G] create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/httpd-safe.ecf b/library/server/wsf/default/httpd-safe.ecf new file mode 100644 index 00000000..c60d7c8e --- /dev/null +++ b/library/server/wsf/default/httpd-safe.ecf @@ -0,0 +1,17 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + diff --git a/library/server/wsf/default/httpd/wsf_default_response_service.e b/library/server/wsf/default/httpd/wsf_default_response_service.e new file mode 100644 index 00000000..0cefc7da --- /dev/null +++ b/library/server/wsf/default/httpd/wsf_default_response_service.e @@ -0,0 +1,24 @@ +note + description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_RESPONSE_SERVICE + +inherit + WSF_DEFAULT_SERVICE + + WSF_RESPONSE_SERVICE + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/default/httpd/wsf_default_service.e b/library/server/wsf/default/httpd/wsf_default_service.e new file mode 100644 index 00000000..a19fb656 --- /dev/null +++ b/library/server/wsf/default/httpd/wsf_default_service.e @@ -0,0 +1,22 @@ +note + description: "Summary description for {WSF_DEFAULT_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_SERVICE [G -> WSF_EXECUTION create make end] + +inherit + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER [G]] + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e b/library/server/wsf/default/httpd/wsf_default_service_launcher.e similarity index 59% rename from library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e rename to library/server/wsf/default/httpd/wsf_default_service_launcher.e index 94b667f4..3a91dafd 100644 --- a/library/server/ewsgi/connectors/httpd/dev/wsf/wsf_httpd_request_handler_factory.e +++ b/library/server/wsf/default/httpd/wsf_default_service_launcher.e @@ -1,21 +1,19 @@ note - description: "Summary description for {WSF_HTTPD_REQUEST_HANDLER_FACTORY}." - author: "" + description: "[ + Default launcher for WSF_SERVICE based on {WSF_HTTPD_SERVICE_LAUNCHER} + ]" date: "$Date$" revision: "$Revision$" class - WSF_HTTPD_REQUEST_HANDLER_FACTORY [G -> WSF_EXECUTION create make end] + WSF_DEFAULT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - HTTPD_REQUEST_HANDLER_FACTORY + WSF_HTTPD_SERVICE_LAUNCHER [G] -feature -- Factory - - new_handler: separate WSF_HTTPD_REQUEST_HANDLER [G] - do - create Result.make - end +create + make, + make_and_launch note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" @@ -27,4 +25,5 @@ note Website http://www.eiffel.com Customer support http://support.eiffel.com ]" + end diff --git a/library/server/wsf/default/nino/wsf_default_service.e b/library/server/wsf/default/nino/wsf_default_service.e index dd76ca78..c29c7047 100644 --- a/library/server/wsf/default/nino/wsf_default_service.e +++ b/library/server/wsf/default/nino/wsf_default_service.e @@ -4,10 +4,10 @@ note revision: "$Revision$" deferred class - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [G -> WSF_EXECUTION create make end] inherit - WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER] + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER [G]] note copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" diff --git a/library/server/wsf/default/nino/wsf_default_service_launcher.e b/library/server/wsf/default/nino/wsf_default_service_launcher.e index aab44c4f..01b0dc35 100644 --- a/library/server/wsf/default/nino/wsf_default_service_launcher.e +++ b/library/server/wsf/default/nino/wsf_default_service_launcher.e @@ -6,16 +6,14 @@ note revision: "$Revision$" class - WSF_DEFAULT_SERVICE_LAUNCHER + WSF_DEFAULT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_NINO_SERVICE_LAUNCHER + WSF_NINO_SERVICE_LAUNCHER [G] create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch note copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" diff --git a/library/server/wsf/extension/handler/wsf_debug_handler.e b/library/server/wsf/extension/handler/wsf_debug_handler.e index 55ef3cfd..d4b7d954 100644 --- a/library/server/wsf/extension/handler/wsf_debug_handler.e +++ b/library/server/wsf/extension/handler/wsf_debug_handler.e @@ -67,7 +67,11 @@ feature -- Access create p.make_with_body (s) - if {PLATFORM}.is_windows and req.wgi_connector.name.is_case_insensitive_equal ("cgi") then + if + {PLATFORM}.is_windows and then + attached req.wgi_connector as conn and then + is_cgi_connector (conn) + then --| FIXME: the CGI connector add %R for any single %N character, so update the Content-Length accordingly. -- Dirty hack to handle correctly CGI on Windows, since it seems "abc%N" will be sent as "abc%R%N" l_len := 0 @@ -96,9 +100,17 @@ feature -- Access res.send (p) end + is_cgi_connector (conn: separate WGI_CONNECTOR): BOOLEAN + local + s: STRING + do + create s.make_from_separate (conn.name) + Result := s.is_case_insensitive_equal_general ("cgi") + end + note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/extension/wsf_debug_information.e b/library/server/wsf/extension/wsf_debug_information.e index e320fd2f..5854ca93 100644 --- a/library/server/wsf/extension/wsf_debug_information.e +++ b/library/server/wsf/extension/wsf_debug_information.e @@ -61,12 +61,32 @@ feature -- Execution a_output.append (" version=") a_output.append (req.wgi_version) a_output.append (" connector=%"") - a_output.append (req.wgi_connector.name) - a_output.append (" connector-version=") - a_output.append (req.wgi_connector.version) + if attached req.wgi_connector as conn then + append_connector_name_to (conn, a_output) + a_output.append ("%" connector-version=") + append_connector_version_to (conn, a_output) + else + a_output.append ("none") + end a_output.append (eol) end + append_connector_name_to (conn: separate WGI_CONNECTOR; a_output: STRING) + local + s: STRING + do + create s.make_from_separate (conn.name) + a_output.append (s) + end + + append_connector_version_to (conn: separate WGI_CONNECTOR; a_output: STRING) + local + s: STRING + do + create s.make_from_separate (conn.version) + a_output.append (s) + end + append_cgi_variables_to (req: WSF_REQUEST; res: WSF_RESPONSE; a_output: STRING) do a_output.append ("CGI variables:") @@ -385,7 +405,7 @@ feature -- Constants invariant note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/service/wsf_default_service_i.e b/library/server/wsf/src/service/wsf_default_service_i.e index b54b86d6..6e479586 100644 --- a/library/server/wsf/src/service/wsf_default_service_i.e +++ b/library/server/wsf/src/service/wsf_default_service_i.e @@ -4,18 +4,18 @@ note revision: "$Revision$" deferred class - WSF_DEFAULT_SERVICE_I [G -> WSF_SERVICE_LAUNCHER create make_and_launch end] + WSF_DEFAULT_SERVICE_I [G -> WSF_SERVICE_LAUNCHER [WSF_EXECUTION] create make_and_launch end] inherit WSF_LAUNCHABLE_SERVICE feature {NONE} -- Initialization - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local l_launcher: G do - create l_launcher.make_and_launch (a_service, opts) + create l_launcher.make_and_launch (opts) end note diff --git a/library/server/wsf/src/service/wsf_launchable_service.e b/library/server/wsf/src/service/wsf_launchable_service.e index fa8aa1d4..cdc8550e 100644 --- a/library/server/wsf/src/service/wsf_launchable_service.e +++ b/library/server/wsf/src/service/wsf_launchable_service.e @@ -14,7 +14,7 @@ feature {NONE} -- Initialization frozen make_and_launch do initialize - launch (Current, service_options) + launch (service_options) end initialize @@ -25,7 +25,7 @@ feature {NONE} -- Initialization service_options: detachable WSF_SERVICE_LAUNCHER_OPTIONS - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) deferred end @@ -47,7 +47,7 @@ feature -- Default service options end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/service/wsf_service.e b/library/server/wsf/src/service/wsf_service.e index 38aef9ac..38b8715e 100644 --- a/library/server/wsf/src/service/wsf_service.e +++ b/library/server/wsf/src/service/wsf_service.e @@ -10,26 +10,8 @@ note deferred class WSF_SERVICE -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Execute the request - -- See `req.input' for input stream - -- `req.meta_variables' for the CGI meta variable - -- and `res' for output buffer - deferred - end - -feature -- Conversion - - to_wgi_service: WGI_SERVICE - -- Adapt Current WSF Service to plug into WGI component - do - create {WSF_TO_WGI_SERVICE} Result.make_from_service (Current) - end - note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/service/wsf_service_launcher.e b/library/server/wsf/src/service/wsf_service_launcher.e index bf60ab56..5ac1ed97 100644 --- a/library/server/wsf/src/service/wsf_service_launcher.e +++ b/library/server/wsf/src/service/wsf_service_launcher.e @@ -32,45 +32,31 @@ note revision: "$Revision$" deferred class - WSF_SERVICE_LAUNCHER + WSF_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit WSF_TO_WGI_SERVICE feature {NONE} -- Initialization - frozen make (a_service: like service; a_options: like options) + frozen make (a_options: like options) do - make_from_service (a_service) options := a_options initialize ensure - service_set: service = a_service options_set: options = a_options launchable: launchable end - frozen make_and_launch (a_service: like service; a_options: like options) + frozen make_and_launch (a_options: like options) do - make (a_service, a_options) + make (a_options) launch end - frozen make_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; a_options: like options) - do - make (create {WSF_CALLBACK_SERVICE}.make (a_callback), a_options) - end - - frozen make_callback_and_launch (a_callback: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; a_options: like options) - do - make (create {WSF_CALLBACK_SERVICE}.make (a_callback), a_options) - end - initialize -- Initialize Current using `options' if attached -- and build the connector - require - service_set: service /= Void deferred ensure connector_attached: connector /= Void @@ -120,7 +106,7 @@ invariant connector_attached: connector /= Void note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/service/wsf_to_wgi_service.e b/library/server/wsf/src/service/wsf_to_wgi_service.e index e78a8fa0..10d6d841 100644 --- a/library/server/wsf/src/service/wsf_to_wgi_service.e +++ b/library/server/wsf/src/service/wsf_to_wgi_service.e @@ -13,47 +13,8 @@ class inherit WGI_SERVICE -create - make_from_service - -feature {NONE} -- Make - - make_from_service (a_service: like service) - -- Make from WSF_SERVICE `a_service' - do - service := a_service - end - - service: WSF_SERVICE - -- Associated WSF_SERVICE - -feature {WGI_CONNECTOR} -- Implementation: Execution - - execute (req: WGI_REQUEST; res: WGI_RESPONSE) - -- Delegate the WGI processing to the WSF_SERVICE object - -- - local - w_res: detachable WSF_RESPONSE - w_req: detachable WSF_REQUEST - do - create w_res.make_from_wgi (res) - create w_req.make_from_wgi (req) - service.execute (w_req, w_res) - w_req.destroy - rescue - if w_res /= Void then - if not (w_res.status_committed or w_res.header_committed) then - w_res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error) - end - w_res.flush - end - if w_req /= Void then - w_req.destroy - end - end - note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e index 582fb6d2..b99b89c0 100644 --- a/library/server/wsf/src/wsf_execution.e +++ b/library/server/wsf/src/wsf_execution.e @@ -7,6 +7,17 @@ note deferred class WSF_EXECUTION +inherit + WGI_EXECUTION + rename + request as wgi_request, + response as wgi_response + redefine + make, + execute, + clean + end + --create -- make @@ -14,24 +25,72 @@ feature {NONE} -- Initialization make (req: WGI_REQUEST; res: WGI_RESPONSE) do - create request.make_from_wgi (req) - create response.make_from_wgi (res) + Precursor (req, res) + create request.make_from_wgi (wgi_request) + create response.make_from_wgi (wgi_response) end +feature {NONE} -- Access + request: WSF_REQUEST + -- Access to request data. + -- Header, Query, Post, Input data.. response: WSF_RESPONSE + -- Access to output stream, back to the client. + +feature -- Status report + + message_writable: BOOLEAN + do + Result := response.message_writable + end + +feature -- Helpers + + put_character (c: CHARACTER_8) + require + message_writable: message_writable + do + response.put_character (c) + end + + put_string (s: READABLE_STRING_8) + require + message_writable: message_writable + do + response.put_string (s) + end + + put_error (err: READABLE_STRING_8) + require + message_writable: message_writable + do + response.put_error (err) + end feature -- Execution execute + -- Execute Current `request', + -- getting data from `request' + -- and response to client via `response'. deferred - ensure - response.status_is_set + ensure then + status_is_set: response.status_is_set + end + +feature -- Cleaning + + clean + -- Precursor + do + Precursor + request.destroy end note - copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index 5f17f910..ed082696 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -41,7 +41,7 @@ inherit {NONE} all end -create {WSF_TO_WGI_SERVICE, WSF_EXECUTION} +create {WSF_TO_WGI_SERVICE, WSF_EXECUTION, WGI_EXPORTER} make_from_wgi convert @@ -426,7 +426,7 @@ feature -- Eiffel WGI access Result := wgi_request.wgi_implementation end - wgi_connector: detachable WGI_CONNECTOR + wgi_connector: detachable separate WGI_CONNECTOR -- Associated Eiffel WGI connector do Result := wgi_request.wgi_connector diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e index a158fda3..d7964568 100644 --- a/library/server/wsf/src/wsf_response.e +++ b/library/server/wsf/src/wsf_response.e @@ -19,7 +19,7 @@ note class WSF_RESPONSE -create {WSF_TO_WGI_SERVICE, WSF_EXECUTION} +create {WSF_TO_WGI_SERVICE, WSF_EXECUTION, WGI_EXPORTER} make_from_wgi create {WSF_RESPONSE} From b4a9c92ffcca111db1f1c78be23a02a9a2ebc492 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 25 Mar 2015 14:56:38 +0100 Subject: [PATCH 07/33] Migrated simple, simple_file and upload_image example. Adapted EWF accordingly. --- examples/upload_image/src/image_uploader.e | 223 +------------- .../src/image_uploader_execution.e | 261 ++++++++++++++++ .../ewsgi/connectors/nino/src/nino_service.e | 48 ++- .../connectors/nino/src/wgi_nino_connector.e | 20 +- .../connector}/wgi_execution.e | 0 .../connector}/wgi_exporter.e | 0 .../nino/wsf_nino_service_launcher.e | 2 +- .../nino/wsf_default_response_service.e | 8 +- .../service/wsf_routed_skeleton_execution.e | 291 ++++++++++++++++++ .../wsf_uri_helper_for_routed_execution.e | 60 ++++ ...uri_template_helper_for_routed_execution.e | 73 +++++ .../server/wsf/router/wsf_routed_execution.e | 76 +++++ library/server/wsf/src/wsf_execution.e | 8 + 13 files changed, 808 insertions(+), 262 deletions(-) create mode 100644 examples/upload_image/src/image_uploader_execution.e rename library/server/ewsgi/{src => specification/connector}/wgi_execution.e (100%) rename library/server/ewsgi/{src => specification/connector}/wgi_exporter.e (100%) create mode 100644 library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e create mode 100644 library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e create mode 100644 library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e create mode 100644 library/server/wsf/router/wsf_routed_execution.e diff --git a/examples/upload_image/src/image_uploader.e b/examples/upload_image/src/image_uploader.e index 02bbbd69..06f1037d 100644 --- a/examples/upload_image/src/image_uploader.e +++ b/examples/upload_image/src/image_uploader.e @@ -10,16 +10,7 @@ class inherit ANY - WSF_ROUTED_SKELETON_SERVICE - undefine - requires_proxy - end - - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE - - WSF_NO_PROXY_POLICY - - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [IMAGE_UPLOADER_EXECUTION] SHARED_EXECUTION_ENVIRONMENT @@ -31,224 +22,12 @@ feature {NONE} -- Initialization make -- Initialize Current do - initialize_router - - -- To use particular port number (as 9090) with Nino connector -- Uncomment the following line set_service_option ("port", 9090) make_and_launch end - setup_router - -- Setup router - local - www: WSF_FILE_SYSTEM_HANDLER - do - map_uri_template_agent_with_request_methods ("/upload/{name}{?nb}", agent execute_upload_put, router.methods_put) - map_uri_template_agent ("/upload{?nb}", agent execute_upload) - - create www.make_with_path (document_root) - www.set_directory_index (<<"index.html">>) - www.set_not_found_handler (agent execute_not_found) - router.handle_with_request_methods ("", www, router.methods_GET) - end - -feature -- Configuration - - document_root: PATH - -- Document root to look for files or directories - once - Result := execution_environment.current_working_path.extended ("htdocs") - ensure - not Result.name.ends_with (Operating_environment.directory_separator.out) - end - - files_root: PATH - -- Uploaded files will be stored in `files_root' folder - once - Result := document_root.extended ("files") - end - -feature -- Execution - - execute_not_found (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE) - -- `uri' is not found, redirect to default page - do - res.redirect_now_with_content (req.script_url ("/"), uri + ": not found.%NRedirection to " + req.script_url ("/"), "text/html") - end - - execute_upload (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Upload page is requested, either GET or POST - -- On GET display the web form to upload file, by passing ?nb=5 you can upload 5 images - -- On POST display the uploaded files - local - l_body: STRING_8 - l_safe_filename: STRING_8 - fn: PATH - page: WSF_HTML_PAGE_RESPONSE - n: INTEGER - do - if req.is_request_method ("GET") or else not req.has_uploaded_file then - create page.make - page.set_title ("EWF: Upload file") - page.add_style (req.script_url ("style.css"), "all") - create l_body.make_empty - page.set_body (l_body) - l_body.append ("

EWF: Upload image file

%N") - l_body.append ("
%N") - if attached {WSF_STRING} req.query_parameter ("nb") as p_nb and then p_nb.is_integer then - n := p_nb.integer_value - else - n := 1 - end - if attached {WSF_STRING} req.query_parameter ("demo") as p_demo then - fn := document_root.extended (p_demo.value) - l_body.append ("File:
%N") - end - - from - until - n = 0 - loop - l_body.append ("File:
%N") - n := n - 1 - end - l_body.append (" %N
") - res.send (page) - else - create l_body.make (255) - l_body.append ("

EWF: Uploaded files

%N") - l_body.append ("
    ") - n := 0 - across - req.uploaded_files as c - loop - n := n + 1 - l_body.append ("
  • ") - l_body.append ("
    " + c.item.name + "=" + html_encode (c.item.filename) + " size=" + c.item.size.out + " type=" + c.item.content_type + "
    ") - l_safe_filename := c.item.safe_filename - fn := files_root.extended (l_safe_filename) - if c.item.move_to (fn.name) then - if c.item.content_type.starts_with ("image") then - l_body.append ("%N") - else - l_body.append ("File " + html_encode (c.item.filename) + " is not a supported image
    %N") - end - end - l_body.append ("
  • ") - end - - l_body.append ("
") - - create page.make - page.set_title ("EWF: uploaded image") - page.add_style ("../style.css", "all") - page.set_body (l_body) - res.send (page) - end - end - - execute_upload_put (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Upload page is requested, PUT - require - is_put_request_method: req.is_put_request_method - local - l_body: STRING_8 - l_safe_filename: detachable READABLE_STRING_32 - fn: PATH - page: WSF_HTML_PAGE_RESPONSE - n: INTEGER - do - create l_body.make (255) - l_body.append ("

EWF: Uploaded files

%N") - l_body.append ("
    ") - n := 0 - if attached {WSF_STRING} req.path_parameter ("name") as p_name then - l_safe_filename := p_name.value - end - if l_safe_filename = Void or else l_safe_filename.is_empty then - l_safe_filename := "input_data" - end - if n = 0 and req.content_length_value > 0 then - if attached new_temporary_output_file ("tmp-uploaded-file_" + n.out) as f then - req.read_input_data_into_file (f) - f.close - fn := files_root.extended (l_safe_filename) - f.rename_file (fn.name) - l_body.append ("
  • ") - l_body.append ("
    Input data : size=" + f.count.out + " (" + req.content_length_value.out + ")
    ") - l_body.append ("%N"+ html_encode (l_safe_filename) +"") - l_body.append ("
  • ") - end - end - l_body.append ("
") - - create page.make - page.set_title ("EWF: uploaded image") - page.add_style ("../style.css", "all") - page.set_body (l_body) - res.send (page) - end - - -feature {NONE} -- Encoder - - new_temporary_output_file (n: detachable READABLE_STRING_8): detachable FILE - local - bp: detachable PATH - d: DIRECTORY - i: INTEGER - do - create bp.make_current - create d.make_with_path (bp) - if not d.exists then - d.recursive_create_dir - end - if n /= Void then - bp := bp.extended ("tmp-download-" + n) - else - bp := bp.extended ("tmp") - end - from - i := 0 - until - Result /= Void or i > 100 - loop - i := i + 1 - create {RAW_FILE} Result.make_with_path (bp.appended ("__" + i.out)) - if Result.exists then - Result := Void - else - Result.open_write - end - end - ensure - Result /= Void implies Result.is_open_write - end - - url_encode (s: READABLE_STRING_32): STRING_8 - -- URL Encode `s' as Result - do - Result := url_encoder.encoded_string (s) - end - - url_encoder: URL_ENCODER - once - create Result - end - - html_encode (s: READABLE_STRING_32): STRING_8 - -- HTML Encode `s' as Result - do - Result := html_encoder.encoded_string (s) - end - - html_encoder: HTML_ENCODER - once - create Result - end - note copyright: "2011-2012, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/examples/upload_image/src/image_uploader_execution.e b/examples/upload_image/src/image_uploader_execution.e new file mode 100644 index 00000000..84f51c87 --- /dev/null +++ b/examples/upload_image/src/image_uploader_execution.e @@ -0,0 +1,261 @@ +note + description: "Summary description for {IMAGE_UPLOADER_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + IMAGE_UPLOADER_EXECUTION + +inherit + WSF_EXECUTION + redefine + initialize + end + + WSF_ROUTED_SKELETON_EXECUTION + undefine + requires_proxy + end + + WSF_NO_PROXY_POLICY + + WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + +create + make + +feature {NONE} -- Initialization + + initialize + do + Precursor + initialize_router + end + + setup_router + -- Setup router + local + www: WSF_FILE_SYSTEM_HANDLER + do + map_uri_template_agent_with_request_methods ("/upload/{name}{?nb}", agent execute_upload_put, router.methods_put) + map_uri_template_agent ("/upload{?nb}", agent execute_upload) + + create www.make (document_root) + www.set_directory_index (<<"index.html">>) + www.set_not_found_handler (agent execute_not_found) + router.handle_with_request_methods ("", www, router.methods_GET) + end + +feature -- Configuration + + document_root: READABLE_STRING_8 + -- Document root to look for files or directories + local + e: EXECUTION_ENVIRONMENT + dn: DIRECTORY_NAME + once + create e + create dn.make_from_string (e.current_working_directory) + dn.extend ("htdocs") + Result := dn.string + if Result [Result.count] = Operating_environment.directory_separator then + Result := Result.substring (1, Result.count - 1) + end + ensure + not Result.ends_with (Operating_environment.directory_separator.out) + end + + files_root: READABLE_STRING_8 + -- Uploaded files will be stored in `files_root' folder + local + dn: DIRECTORY_NAME + once + create dn.make_from_string (document_root) + dn.extend ("files") + Result := dn.string + end + +feature -- Execution + + execute_not_found (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE) + -- `uri' is not found, redirect to default page + do + res.redirect_now_with_content (req.script_url ("/"), uri + ": not found.%NRedirection to " + req.script_url ("/"), "text/html") + end + + execute_upload (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Upload page is requested, either GET or POST + -- On GET display the web form to upload file, by passing ?nb=5 you can upload 5 images + -- On POST display the uploaded files + local + l_body: STRING_8 + l_safe_filename: STRING_8 + fn: PATH + page: WSF_HTML_PAGE_RESPONSE + n: INTEGER + do + if req.is_request_method ("GET") or else not req.has_uploaded_file then + create page.make + page.set_title ("EWF: Upload file") + page.add_style (req.script_url ("style.css"), "all") + create l_body.make_empty + page.set_body (l_body) + l_body.append ("

EWF: Upload image file

%N") + l_body.append ("
%N") + if attached {WSF_STRING} req.query_parameter ("nb") as p_nb and then p_nb.is_integer then + n := p_nb.integer_value + else + n := 1 + end + if attached {WSF_STRING} req.query_parameter ("demo") as p_demo then + create fn.make_from_string (document_root) + fn := fn.extended (p_demo.value) + l_body.append ("File:
%N") + end + + from + until + n = 0 + loop + l_body.append ("File:
%N") + n := n - 1 + end + l_body.append (" %N
") + res.send (page) + else + create l_body.make (255) + l_body.append ("

EWF: Uploaded files

%N") + l_body.append ("
    ") + n := 0 + across + req.uploaded_files as c + loop + n := n + 1 + l_body.append ("
  • ") + l_body.append ("
    " + c.item.name + "=" + html_encode (c.item.filename) + " size=" + c.item.size.out + " type=" + c.item.content_type + "
    ") + create fn.make_from_string (files_root) + l_safe_filename := c.item.safe_filename + fn := fn.extended (l_safe_filename) + if c.item.move_to (fn.name) then + if c.item.content_type.starts_with ("image") then + l_body.append ("%N") + else + l_body.append ("File " + html_encode (c.item.filename) + " is not a supported image
    %N") + end + end + l_body.append ("
  • ") + end + + l_body.append ("
") + + create page.make + page.set_title ("EWF: uploaded image") + page.add_style ("../style.css", "all") + page.set_body (l_body) + res.send (page) + end + end + + execute_upload_put (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Upload page is requested, PUT + require + is_put_request_method: req.is_put_request_method + local + l_body: STRING_8 + l_safe_filename: detachable READABLE_STRING_32 + fn: PATH + page: WSF_HTML_PAGE_RESPONSE + n: INTEGER + do + create l_body.make (255) + l_body.append ("

EWF: Uploaded files

%N") + l_body.append ("
    ") + n := 0 + if attached {WSF_STRING} req.path_parameter ("name") as p_name then + l_safe_filename := p_name.value + end + if l_safe_filename = Void or else l_safe_filename.is_empty then + l_safe_filename := "input_data" + end + if n = 0 and req.content_length_value > 0 then + if attached new_temporary_output_file ("tmp-uploaded-file_" + n.out) as f then + req.read_input_data_into_file (f) + f.close + create fn.make_from_string (files_root) + fn := fn.extended (l_safe_filename) + f.rename_file (fn.name) + l_body.append ("
  • ") + l_body.append ("
    Input data : size=" + f.count.out + " (" + req.content_length_value.out + ")
    ") + l_body.append ("%N"+ html_encode (l_safe_filename) +"") + l_body.append ("
  • ") + end + end + l_body.append ("
") + + create page.make + page.set_title ("EWF: uploaded image") + page.add_style ("../style.css", "all") + page.set_body (l_body) + res.send (page) + end + + +feature {NONE} -- Encoder + + new_temporary_output_file (n: detachable READABLE_STRING_8): detachable FILE + local + bp: detachable PATH + d: DIRECTORY + i: INTEGER + do + create bp.make_current + create d.make_with_path (bp) + if not d.exists then + d.recursive_create_dir + end + if n /= Void then + bp := bp.extended ("tmp-download-" + n) + else + bp := bp.extended ("tmp") + end + from + i := 0 + until + Result /= Void or i > 100 + loop + i := i + 1 + create {RAW_FILE} Result.make_with_path (bp.appended ("__" + i.out)) + if Result.exists then + Result := Void + else + Result.open_write + end + end + ensure + Result /= Void implies Result.is_open_write + end + + url_encode (s: READABLE_STRING_32): STRING_8 + -- URL Encode `s' as Result + do + Result := url_encoder.encoded_string (s) + end + + url_encoder: URL_ENCODER + once + create Result + end + + html_encode (s: READABLE_STRING_32): STRING_8 + -- HTML Encode `s' as Result + do + Result := html_encoder.encoded_string (s) + end + + html_encoder: HTML_ENCODER + once + create Result + end + +end diff --git a/library/server/ewsgi/connectors/nino/src/nino_service.e b/library/server/ewsgi/connectors/nino/src/nino_service.e index fd020b39..8f596a28 100644 --- a/library/server/ewsgi/connectors/nino/src/nino_service.e +++ b/library/server/ewsgi/connectors/nino/src/nino_service.e @@ -4,50 +4,48 @@ note revision: "$Revision$" class - NINO_SERVICE + NINO_SERVICE [G -> WGI_EXECUTION create make end] create make, - make_custom, - make_with_callback, - make_custom_with_callback + make_custom feature {NONE} -- Implementation - make (a_service: WGI_SERVICE) + make -- Initialize `Current'. do - make_custom (a_service, Void) + make_custom (Void) end - make_custom (a_service: WGI_SERVICE; a_base_url: detachable STRING) + make_custom (a_base_url: detachable STRING) -- Initialize `Current'. require base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/") do - create connector.make_with_base (a_service, a_base_url) + create connector.make_with_base (a_base_url) end - make_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]) - -- Initialize `Current'. - do - make_custom_with_callback (a_callback, Void) - end +-- make_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]) +-- -- Initialize `Current'. +-- do +-- make_custom_with_callback (a_callback, Void) +-- end - make_custom_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]; a_base_url: detachable STRING) - -- Initialize `Current'. - require - base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/") - local - app: WGI_AGENT_SERVICE - do - create app.make (a_callback) - make_custom (app, a_base_url) - end +-- make_custom_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]; a_base_url: detachable STRING) +-- -- Initialize `Current'. +-- require +-- base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/") +-- local +-- app: WGI_AGENT_SERVICE +-- do +-- create app.make (a_callback) +-- make_custom (app, a_base_url) +-- end feature -- Access - connector: WGI_NINO_CONNECTOR + connector: WGI_NINO_CONNECTOR [G] -- Web server connector feature -- Status report @@ -104,7 +102,7 @@ feature -- Server end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 03696fd6..7543a0df 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -15,11 +15,11 @@ create feature {NONE} -- Initialization - make (a_service: like service) + make --(a_service: like service) local cfg: HTTP_SERVER_CONFIGURATION do - service := a_service +-- service := a_service create cfg.make create server.make (cfg) @@ -29,11 +29,11 @@ feature {NONE} -- Initialization create on_stopped_actions end - make_with_base (a_service: like service; a_base: like base) + make_with_base (a_base: like base) require a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies a_base.starts_with ("/") do - make (a_service) + make -- (a_service) set_base (a_base) end @@ -45,10 +45,10 @@ feature -- Access version: STRING_8 = "0.1" -- Version of Current connector -feature {NONE} -- Access +--feature {NONE} -- Access - service: WGI_SERVICE - -- Gateway Service +-- service: WGI_SERVICE +-- -- Gateway Service feature -- Access @@ -139,7 +139,7 @@ feature -- Server create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current) create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), create {WGI_NINO_ERROR_STREAM}.make_stderr (a_socket.descriptor.out)) req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) - + create {G} exec.make (req, res) exec.execute res.flush @@ -161,7 +161,7 @@ feature -- Server end if exec /= Void then exec.clean - end + end end rescue if not retried then @@ -171,7 +171,7 @@ feature -- Server end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/src/wgi_execution.e b/library/server/ewsgi/specification/connector/wgi_execution.e similarity index 100% rename from library/server/ewsgi/src/wgi_execution.e rename to library/server/ewsgi/specification/connector/wgi_execution.e diff --git a/library/server/ewsgi/src/wgi_exporter.e b/library/server/ewsgi/specification/connector/wgi_exporter.e similarity index 100% rename from library/server/ewsgi/src/wgi_exporter.e rename to library/server/ewsgi/specification/connector/wgi_exporter.e diff --git a/library/server/wsf/connector/nino/wsf_nino_service_launcher.e b/library/server/wsf/connector/nino/wsf_nino_service_launcher.e index 553f20fe..35038b09 100644 --- a/library/server/wsf/connector/nino/wsf_nino_service_launcher.e +++ b/library/server/wsf/connector/nino/wsf_nino_service_launcher.e @@ -67,7 +67,7 @@ feature {NONE} -- Initialization verbose := l_verbose_str.as_lower.same_string ("true") end end - create conn.make (Current) + create conn.make --(Current) connector := conn conn.on_launched_actions.extend (agent on_launched) diff --git a/library/server/wsf/default/nino/wsf_default_response_service.e b/library/server/wsf/default/nino/wsf_default_response_service.e index 0cefc7da..db3fddc6 100644 --- a/library/server/wsf/default/nino/wsf_default_response_service.e +++ b/library/server/wsf/default/nino/wsf_default_response_service.e @@ -4,15 +4,15 @@ note revision: "$Revision$" deferred class - WSF_DEFAULT_RESPONSE_SERVICE + WSF_DEFAULT_RESPONSE_SERVICE [G -> WSF_EXECUTION create make end] inherit - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [G] - WSF_RESPONSE_SERVICE + WSF_RESPONSE_SERVICE [G] note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e b/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e new file mode 100644 index 00000000..7daacd25 --- /dev/null +++ b/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e @@ -0,0 +1,291 @@ +note + description: "Summary description for {WSF_ROUTED_SKELETON_EXECUTION}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_ROUTED_SKELETON_EXECUTION + +inherit + WSF_ROUTED_EXECUTION + redefine + execute + end + + WSF_SYSTEM_OPTIONS_ACCESS_POLICY + + WSF_PROXY_USE_POLICY + +feature -- Execution + + execute + -- If the service is available, and request URI is not too long, dispatch the request + -- and if handler is not found, execute the default procedure `execute_default'. + local + l_sess: WSF_ROUTER_SESSION + req: WSF_REQUEST; res: WSF_RESPONSE + do + req := request + res := response + + --| When we reach here, the request has already passed check for 400 (Bad request), + --| which is implemented in WSF_REQUEST.make_from_wgi (when it calls `analyze'). + if unavailable then + handle_unavailable (res) + elseif requires_proxy (req) then + handle_use_proxy (req, res) + elseif + maximum_uri_length > 0 and then + req.request_uri.count.to_natural_32 > maximum_uri_length + then + handle_request_uri_too_long (res) + elseif + req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) and then + req.request_uri.same_string ("*") + then + handle_server_options (req, res) + else + create l_sess + router.dispatch (req, res, l_sess) + if not l_sess.dispatched then + execute_default + end + end + end + +feature -- Measurement + + maximum_uri_length: NATURAL + -- Maximum length in characters (or zero for no limit) permitted + -- for {WSF_REQUEST}.request_uri + +feature -- Status report + + unavailable: BOOLEAN + -- Is service currently unavailable? + + unavailablity_message: detachable READABLE_STRING_8 + -- Message to be included as text of response body for {HTTP_STATUS_CODE}.service_unavailable + + unavailability_duration: NATURAL + -- Delta seconds for service unavailability (0 if not known) + + unavailable_until: detachable DATE_TIME + -- Time at which service becomes available again (if known) + +feature -- Status setting + + set_available + -- Set `unavailable' to `False'. + do + unavailable := False + unavailablity_message := Void + unavailable_until := Void + ensure + available: unavailable = False + unavailablity_message_detached: unavailablity_message = Void + unavailable_until_detached: unavailable_until = Void + end + + set_unavailable (a_message: READABLE_STRING_8; a_duration: NATURAL; a_until: detachable DATE_TIME) + -- Set `unavailable' to `True'. + require + a_message_attached: a_message /= Void + a_duration_xor_a_until: a_duration > 0 implies a_until = Void + do + unavailable := True + unavailablity_message := a_message + unavailability_duration := a_duration + ensure + unavailable: unavailable = True + unavailablity_message_aliased: unavailablity_message = a_message + unavailability_duration_set: unavailability_duration = a_duration + unavailable_until_aliased: unavailable_until = a_until + end + + set_maximum_uri_length (a_len: NATURAL) + -- Set `maximum_uri_length' to `a_len'. + -- Can pass zero to mean no restrictions. + do + maximum_uri_length := a_len + ensure + maximum_uri_length_set: maximum_uri_length = a_len + end + +feature {NONE} -- Implementation + + handle_unavailable (res: WSF_RESPONSE) + -- Write "Service unavailable" response to `res'. + require + unavailable: unavailable + res_attached: res /= Void + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + check attached unavailablity_message as m then + -- invariant `unavailability_message_attached' plus precondition `unavailable' + h.put_content_length (m.count) + h.put_current_date + res.set_status_code ({HTTP_STATUS_CODE}.service_unavailable) + if unavailability_duration > 0 then + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, unavailability_duration.out) + elseif attached unavailable_until as u then + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, + h.date_to_rfc1123_http_date_format (u)) + end + res.put_header_text (h.string) + res.put_string (m) + end + ensure + response_status_is_set: res.status_is_set + status_is_service_unavailable: res.status_code = {HTTP_STATUS_CODE}.service_unavailable + body_sent: res.message_committed and then res.transfered_content_length > 0 + body_content_was_unavailablity_message: True -- doesn't seem to be any way to check + end + + handle_request_uri_too_long (res: WSF_RESPONSE) + -- Write "Request URI too long" response into `res'. + require + res_attached: res /= Void + local + h: HTTP_HEADER + m: READABLE_STRING_8 + do + create h.make + h.put_content_type_text_plain + h.put_current_date + m := "Maximum permitted length for request URI is " + maximum_uri_length.out + " characters" + h.put_content_length (m.count) + res.set_status_code ({HTTP_STATUS_CODE}.request_uri_too_long) + res.put_header_text (h.string) + res.put_string (m) + ensure + response_status_is_set: res.status_is_set + status_is_request_uri_too_long: res.status_code = {HTTP_STATUS_CODE}.request_uri_too_long + body_sent: res.message_committed and then res.transfered_content_length > 0 + end + + frozen handle_server_options (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write response to OPTIONS * into `res'. + require + req_attached: req /= Void + res_attached: res /= Void + method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) + server_options_requested: req.request_uri.same_string ("*") + do + --| First check if forbidden. + --| (N.B. authentication requires an absoluteURI (RFC3617 page 3), and so cannot be used for OPTIONS *. + --| Otherwise construct an Allow response automatically from the router. + if is_system_options_forbidden (req) then + handle_system_options_forbidden (req, res) + else + handle_system_options (req, res) + end + ensure + response_status_is_set: res.status_is_set + valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or + res.status_code = {HTTP_STATUS_CODE}.not_found or res.status_code = {HTTP_STATUS_CODE}.ok + header_sent: res.header_committed and res.message_committed + end + + frozen handle_system_options_forbidden (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write a 403 Forbidden or a 404 Not found response into `res'. + require + req_attached: req /= Void + res_attached: res /= Void + method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) + server_options_requested: req.request_uri.same_string ("*") + local + m: detachable READABLE_STRING_8 + h: HTTP_HEADER + do + m := system_options_forbidden_text (req) + if attached {READABLE_STRING_8} m as l_msg then + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_content_length (l_msg.count) + res.set_status_code ({HTTP_STATUS_CODE}.forbidden) + res.put_header_text (h.string) + res.put_string (l_msg) + else + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_content_length (0) + res.set_status_code ({HTTP_STATUS_CODE}.not_found) + res.put_header_text (h.string) + end + ensure + response_status_is_set: res.status_is_set + valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or + res.status_code = {HTTP_STATUS_CODE}.not_found + header_sent: res.header_committed + message_sent: res.message_committed + end + + handle_system_options (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write response to OPTIONS * into `res'. + -- This may be redefined by the user, but normally this will not be necessary. + require + req_attached: req /= Void + res_attached: res /= Void + method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) + server_options_requested: req.request_uri.same_string ("*") + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_allow (router.all_allowed_methods) + h.put_content_length (0) + res.set_status_code ({HTTP_STATUS_CODE}.ok) + res.put_header_text (h.string) + ensure + response_status_is_set: res.status_is_set + response_code_ok: res.status_code = {HTTP_STATUS_CODE}.ok + header_sent: res.header_committed and res.message_committed + empty_body: res.transfered_content_length = 0 + end + + frozen handle_use_proxy (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write Use Proxy response `res'. + require + res_attached: res /= Void + req_attached: req /= Void + proxy_required: requires_proxy (req) + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_location (proxy_server (req).string) + h.put_content_length (0) + res.put_header_lines (h) + res.set_status_code ({HTTP_STATUS_CODE}.use_proxy) + ensure + response_status_is_set: res.status_is_set + response_code_use_proxy: res.status_code = {HTTP_STATUS_CODE}.use_proxy + end + +invariant + + unavailability_message_attached: unavailable implies attached unavailablity_message as m and then + m.count > 0 + unavailability_duration_xor_unavailable_until: unavailability_duration > 0 implies unavailable_until = Void + +;note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e b/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e new file mode 100644 index 00000000..ee087582 --- /dev/null +++ b/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e @@ -0,0 +1,60 @@ +note + description: "Facilities inheritance to add URI base routing to a routed execution" + + date: "$Date$" + revision: "$Revision$" + +deferred class WSF_URI_HELPER_FOR_ROUTED_EXECUTION + +feature -- Access + + router: WSF_ROUTER + -- Router used to dispatch the request according to the WSF_REQUEST object + -- and associated request methods; + -- This should not be implemented by descendants. Instead, you gain an effective + -- version by also inheriting from WSF_ROUTED_EXECUTION, or one of it's descendants. + deferred + ensure + router_not_void: Result /= Void + end + +feature -- Mapping helper: uri + + map_uri (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER) + -- Map `h' as handler for `a_uri' + do + map_uri_with_request_methods (a_uri, h, Void) + end + + map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `h' as handler for `a_uri' for request methods `rqst_methods'. + do + router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, h), rqst_methods) + end + +feature -- Mapping helper: uri agent + + map_uri_agent (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) + -- Map `proc' as handler for `a_uri' + do + map_uri_agent_with_request_methods (a_uri, proc, Void) + end + + map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `proc' as handler for `a_uri' for request methods `rqst_methods'. + do + map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_HANDLER}.make (proc), rqst_methods) + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e b/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e new file mode 100644 index 00000000..223b8292 --- /dev/null +++ b/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e @@ -0,0 +1,73 @@ +note + description: "Facilities inheritance to add URI template-base routing to a routed execution" + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + +feature -- Access + + router: WSF_ROUTER + -- Router used to dispatch the request according to the WSF_REQUEST object + -- and associated request methods; + -- This should not be implemented by descendants. Instead, you gain an effective + -- version by also inheriting from WSF_ROUTED_SERVICE, or one of it's descendants. + deferred + ensure + router_not_void: Result /= Void + end + +feature -- Mapping helper: uri template + + map_uri_template (a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER) + -- Map `h' as handler for `a_tpl' + require + a_tpl_attached: a_tpl /= Void + h_attached: h /= Void + do + map_uri_template_with_request_methods (a_tpl, h, Void) + end + + map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `h' as handler for `a_tpl' for request methods `rqst_methods'. + require + a_tpl_attached: a_tpl /= Void + h_attached: h /= Void + do + router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods) + end + +feature -- Mapping helper: uri template agent + + map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) + -- Map `proc' as handler for `a_tpl' + require + a_tpl_attached: a_tpl /= Void + proc_attached: proc /= Void + do + map_uri_template_agent_with_request_methods (a_tpl, proc, Void) + end + + map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) + -- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'. + require + a_tpl_attached: a_tpl /= Void + proc_attached: proc /= Void + do + map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods) + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/wsf/router/wsf_routed_execution.e b/library/server/wsf/router/wsf_routed_execution.e new file mode 100644 index 00000000..40581dcc --- /dev/null +++ b/library/server/wsf/router/wsf_routed_execution.e @@ -0,0 +1,76 @@ +note + description: "Summary description for {WSF_ROUTED_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_ROUTED_EXECUTION + +feature -- Router + + initialize_router + -- Initialize router + do + create_router + setup_router + end + + create_router + -- Create `router' + --| could be redefine to initialize with proper capacity + do + create router.make (10) + ensure + router_created: router /= Void + end + + setup_router + -- Setup `router' + require + router_created: router /= Void + deferred + end + +feature -- Access + + request: WSF_REQUEST + deferred + end + + response: WSF_RESPONSE + deferred + end + + router: WSF_ROUTER + -- Router used to dispatch the request according to the WSF_REQUEST object + -- and associated request methods + +feature -- Execution + + execute + -- Dispatch the request + -- and if handler is not found, execute the default procedure `execute_default'. + local + sess: WSF_ROUTER_SESSION + do + create sess + router.dispatch (request, response, sess) + if not sess.dispatched then + execute_default + end + ensure + response_status_is_set: response.status_is_set + end + + execute_default + -- Dispatch requests without a matching handler. + local + msg: WSF_DEFAULT_ROUTER_RESPONSE + do + create msg.make_with_router (request, router) + msg.set_documentation_included (True) + response.send (msg) + end + +end diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e index b99b89c0..9af7db08 100644 --- a/library/server/wsf/src/wsf_execution.e +++ b/library/server/wsf/src/wsf_execution.e @@ -28,6 +28,14 @@ feature {NONE} -- Initialization Precursor (req, res) create request.make_from_wgi (wgi_request) create response.make_from_wgi (wgi_response) + initialize + end + + initialize + -- Initialize Current object. + --| To be redefined if needed. + do + end feature {NONE} -- Access From 7d2ce8a77f45931651aaeeb39b45dd2ec2189b0a Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 25 Mar 2015 22:22:57 +0100 Subject: [PATCH 08/33] Implemented support for base url in httpd connector. --- .../server/ewsgi/connectors/cgi/cgi-safe.ecf | 3 +- library/server/ewsgi/connectors/cgi/cgi.ecf | 1 + .../connectors/cgi/src/wgi_cgi_connector.e | 38 ++++++++----- .../ewsgi/connectors/httpd/httpd-safe.ecf | 50 +--------------- .../connectors/httpd/src/httpd/httpd-safe.ecf | 3 +- .../httpd/src/wgi_httpd_connector.e | 14 ++++- .../httpd/src/wgi_httpd_request_handler.e | 57 ++++++++++++------- .../src/wgi_httpd_request_handler_factory.e | 2 +- .../ewsgi/connectors/libfcgi/libfcgi-safe.ecf | 3 +- .../ewsgi/connectors/libfcgi/libfcgi.ecf | 1 + .../libfcgi/src/wgi_libfcgi_connector.e | 39 ++++++++----- .../connectors/nino/src/wgi_nino_connector.e | 43 +++++++------- .../specification/connector/wgi_execution.e | 15 ++++- .../httpd/wsf_httpd_service_launcher.e | 2 +- .../uri/helpers/wsf_uri_routed_service.e | 27 --------- .../helpers/wsf_uri_template_routed_service.e | 27 --------- .../wsf/src/service/wsf_response_service.e | 4 +- .../wsf/src/service/wsf_service_launcher.e | 3 - library/server/wsf/src/wsf_execution.e | 34 +++++++---- 19 files changed, 168 insertions(+), 198 deletions(-) delete mode 100644 library/server/wsf/router/support/uri/helpers/wsf_uri_routed_service.e delete mode 100644 library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_routed_service.e diff --git a/library/server/ewsgi/connectors/cgi/cgi-safe.ecf b/library/server/ewsgi/connectors/cgi/cgi-safe.ecf index 8d0eaded..cdeca882 100644 --- a/library/server/ewsgi/connectors/cgi/cgi-safe.ecf +++ b/library/server/ewsgi/connectors/cgi/cgi-safe.ecf @@ -1,5 +1,5 @@ - + @@ -12,6 +12,7 @@ + diff --git a/library/server/ewsgi/connectors/cgi/cgi.ecf b/library/server/ewsgi/connectors/cgi/cgi.ecf index c8df2ee7..df9c6f5b 100644 --- a/library/server/ewsgi/connectors/cgi/cgi.ecf +++ b/library/server/ewsgi/connectors/cgi/cgi.ecf @@ -12,6 +12,7 @@ +
diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e index d5c95cf0..c40b7a28 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e @@ -9,6 +9,10 @@ class inherit WGI_CONNECTOR + SHARED_HTML_ENCODER + + SHARED_EXECUTION_ENVIRONMENT + feature -- Access Name: STRING_8 = "CGI" @@ -27,27 +31,14 @@ feature -- Execution rescued: BOOLEAN do if not rescued then - create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment, create {WGI_CGI_INPUT_STREAM}.make, Current) + create req.make (execution_environment.starting_environment, create {WGI_CGI_INPUT_STREAM}.make, Current) create res.make (create {WGI_CGI_OUTPUT_STREAM}.make, create {WGI_CGI_ERROR_STREAM}.make) create {G} exec.make (req, res) exec.execute - res.flush res.push exec.clean else - if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then - if res /= Void then - if not res.status_is_set then - res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) - end - if res.message_writable then - res.put_string ("
")
-							res.put_string (l_trace)
-							res.put_string ("
") - end - res.push - end - end + process_rescue (res) if exec /= Void then exec.clean end @@ -59,6 +50,23 @@ feature -- Execution end end + process_rescue (res: detachable WGI_RESPONSE) + do + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
")
+						res.put_string (html_encoder.encoded_string (l_trace))
+						res.put_string ("
") + end + res.push + end + end + end + note copyright: "2011-2015, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf index cd28afb9..0213ebef 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/httpd-safe.ecf @@ -16,55 +16,7 @@ - - - - - - - - - - - - - - - - - /ssl$ - /EIFGENs$ - /no_ssl$ - /concurrency$ - - - - - - - - - - - - - - - - - - - - - - - - - - - + /httpd$ diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf index d6691fca..83338d1e 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf @@ -10,9 +10,8 @@ - + - diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e index 639f6e21..5f5f0b06 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e @@ -46,7 +46,7 @@ feature {NONE} -- Initialization set_base (a_base) end - set_factory_connector (conn: detachable separate WGI_CONNECTOR; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) + set_factory_connector (conn: detachable separate WGI_HTTPD_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) do fac.set_connector (conn) end @@ -129,8 +129,15 @@ feature -- Element change end set_max_concurrent_connections (nb: INTEGER) + require + nb_positive_or_zero: nb >= 0 do + set_max_concurrent_connections_on_configuration (nb, configuration) + end + set_is_verbose (b: BOOLEAN) + do + set_is_verbose_on_configuration (b, configuration) end feature {NONE} -- Implementation @@ -145,6 +152,11 @@ feature {NONE} -- Implementation cfg.set_max_concurrent_connections (nb) end + set_is_verbose_on_configuration (b: BOOLEAN; cfg: like configuration) + do + cfg.set_is_verbose (b) + end + feature -- Server launch diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e index f0bdc24a..de6863ad 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e @@ -14,6 +14,8 @@ inherit REFACTORING_HELPER + SHARED_HTML_ENCODER + create make, make_with_connector @@ -26,7 +28,21 @@ feature {NONE} -- Initialization connector := conn end - connector: detachable separate WGI_CONNECTOR + connector: detachable separate WGI_HTTPD_CONNECTOR [G] + + base: detachable IMMUTABLE_STRING_8 + do + if attached connector as conn then + if attached connector_base (conn) as l_base then + create Result.make_from_separate (l_base) + end + end + end + + connector_base (conn: separate WGI_HTTPD_CONNECTOR [G]): detachable separate READABLE_STRING_8 + do + Result := conn.base + end feature -- Request processing @@ -53,23 +69,10 @@ feature -- Request processing create {G} exec.make (req, res) exec.execute - res.flush res.push exec.clean else - if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then - if res /= Void then - if not res.status_is_set then - res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) - end - if res.message_writable then - res.put_string ("
")
-							res.put_string (l_trace)
-							res.put_string ("
") - end - res.push - end - end + process_rescue (res) if exec /= Void then exec.clean end @@ -81,10 +84,21 @@ feature -- Request processing end end - base: detachable READABLE_STRING_8 + process_rescue (res: detachable WGI_RESPONSE) do - --TODO - to_implement ("Base url support") + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
")
+						res.put_string (html_encoder.encoded_string (l_trace))
+						res.put_string ("
") + end + res.push + end + end end httpd_environment (a_socket: HTTPD_STREAM_SOCKET): STRING_TABLE [READABLE_STRING_8] @@ -93,6 +107,7 @@ feature -- Request processing l_request_uri, l_script_name, l_query_string, l_path_info: STRING l_server_name, l_server_port: detachable STRING l_headers_map: HASH_TABLE [STRING, STRING] + l_base: detachable READABLE_STRING_8 vn: STRING e: EXECUTION_ENVIRONMENT @@ -189,7 +204,11 @@ feature -- Request processing set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result) --| Apply `base' value - if attached base as l_base and then l_request_uri /= Void then + l_base := base + if l_base = Void then + l_base := "" + end + if l_request_uri /= Void then if l_request_uri.starts_with (l_base) then l_path_info := l_request_uri.substring (l_base.count + 1, l_request_uri.count) p := l_path_info.index_of ('?', 1) diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e index c2b2d5ef..f69d0893 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e @@ -12,7 +12,7 @@ inherit feature -- Access - connector: detachable separate WGI_CONNECTOR + connector: detachable separate WGI_HTTPD_CONNECTOR [G] feature -- Element change diff --git a/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf b/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf index 689dcbf5..7cc2a211 100644 --- a/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf +++ b/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf @@ -1,5 +1,5 @@ - + @@ -13,6 +13,7 @@ + diff --git a/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf b/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf index a95e88d0..80279ae1 100644 --- a/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf +++ b/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf @@ -13,6 +13,7 @@ + diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e index 1b994d85..2bd68609 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e @@ -14,11 +14,16 @@ inherit default_create end + SHARED_HTML_ENCODER + redefine + default_create + end + feature {NONE} -- Initialization default_create do - Precursor + Precursor {WGI_CONNECTOR} create fcgi.make create input.make (fcgi) create output.make (fcgi) @@ -63,23 +68,10 @@ feature -- Execution create res.make (a_output, a_output) create {G} exec.make (req, res) exec.execute - res.flush res.push exec.clean else - if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then - if res /= Void then - if not res.status_is_set then - res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) - end - if res.message_writable then - res.put_string ("
")
-							res.put_string (l_trace)
-							res.put_string ("
") - end - res.push - end - end + process_rescue (res) if exec /= Void then exec.clean end @@ -90,6 +82,23 @@ feature -- Execution retry end end + + process_rescue (res: detachable WGI_RESPONSE) + do + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
")
+						res.put_string (html_encoder.encoded_string (l_trace))
+						res.put_string ("
") + end + res.push + end + end + end feature -- Input/Output diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 7543a0df..524659ac 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -9,18 +9,18 @@ class inherit WGI_CONNECTOR + SHARED_HTML_ENCODER + create make, make_with_base feature {NONE} -- Initialization - make --(a_service: like service) + make local cfg: HTTP_SERVER_CONFIGURATION do --- service := a_service - create cfg.make create server.make (cfg) @@ -45,11 +45,6 @@ feature -- Access version: STRING_8 = "0.1" -- Version of Current connector ---feature {NONE} -- Access - --- service: WGI_SERVICE --- -- Gateway Service - feature -- Access server: HTTP_SERVER @@ -142,23 +137,10 @@ feature -- Server create {G} exec.make (req, res) exec.execute - res.flush res.push exec.clean else - if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then - if res /= Void then - if not res.status_is_set then - res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) - end - if res.message_writable then - res.put_string ("
")
-							res.put_string (l_trace)
-							res.put_string ("
") - end - res.push - end - end + process_rescue (res) if exec /= Void then exec.clean end @@ -170,6 +152,23 @@ feature -- Server end end + process_rescue (res: detachable WGI_RESPONSE) + do + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
")
+						res.put_string (html_encoder.encoded_string (l_trace))
+						res.put_string ("
") + end + res.push + end + end + end + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/specification/connector/wgi_execution.e b/library/server/ewsgi/specification/connector/wgi_execution.e index 204be494..deb0734c 100644 --- a/library/server/ewsgi/specification/connector/wgi_execution.e +++ b/library/server/ewsgi/specification/connector/wgi_execution.e @@ -30,7 +30,15 @@ feature -- Execution -- Execute the request based on `request' and `response'. deferred ensure - status_is_set: response.status_is_set + is_valid_end_of_execution: is_valid_end_of_execution + end + +feature -- Status report + + is_valid_end_of_execution: BOOLEAN + -- Last `execute' completed in valid state? + do + Result := True end feature -- Cleaning @@ -40,6 +48,11 @@ feature -- Cleaning do end +invariant + + wgi_request_set: request /= Void + wgi_response_set: response /= Void + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" diff --git a/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e b/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e index 4644ae61..6738c80f 100644 --- a/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e +++ b/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e @@ -79,7 +79,7 @@ feature {NONE} -- Initialization feature -- Execution - update_configuration (cfg: separate HTTPD_CONFIGURATION) + update_configuration (cfg: like connector.configuration) do if single_threaded then cfg.set_force_single_threaded (True) diff --git a/library/server/wsf/router/support/uri/helpers/wsf_uri_routed_service.e b/library/server/wsf/router/support/uri/helpers/wsf_uri_routed_service.e deleted file mode 100644 index 4575190a..00000000 --- a/library/server/wsf/router/support/uri/helpers/wsf_uri_routed_service.e +++ /dev/null @@ -1,27 +0,0 @@ -note - description: "Summary description for {WSF_URI_ROUTED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_URI_ROUTED_SERVICE - -obsolete "Inherit from WSF_ROUTED_SERVICE and WSF_URI_HELPER_FOR_ROUTED_SERVICE [2013-mar-19]" - -inherit - WSF_ROUTED_SERVICE - - WSF_URI_HELPER_FOR_ROUTED_SERVICE - -note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_routed_service.e b/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_routed_service.e deleted file mode 100644 index 91052448..00000000 --- a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_routed_service.e +++ /dev/null @@ -1,27 +0,0 @@ -note - description: "Summary description for {WSF_URI_TEMPLATE_ROUTED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_URI_TEMPLATE_ROUTED_SERVICE - -obsolete "Inherit from WSF_ROUTED_SERVICE and WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE [2013-mar-19]" - -inherit - WSF_ROUTED_SERVICE - - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE - -note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/src/service/wsf_response_service.e b/library/server/wsf/src/service/wsf_response_service.e index 383d9cdd..5b375e19 100644 --- a/library/server/wsf/src/service/wsf_response_service.e +++ b/library/server/wsf/src/service/wsf_response_service.e @@ -8,7 +8,7 @@ note revision: "$Revision$" deferred class - WSF_RESPONSE_SERVICE + WSF_RESPONSE_SERVICE [G -> WSF_EXECUTION create make end] inherit WSF_SERVICE @@ -29,7 +29,7 @@ feature -- Execution end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/service/wsf_service_launcher.e b/library/server/wsf/src/service/wsf_service_launcher.e index 5ac1ed97..2568a5e0 100644 --- a/library/server/wsf/src/service/wsf_service_launcher.e +++ b/library/server/wsf/src/service/wsf_service_launcher.e @@ -34,9 +34,6 @@ note deferred class WSF_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] -inherit - WSF_TO_WGI_SERVICE - feature {NONE} -- Initialization frozen make (a_options: like options) diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e index 9af7db08..ea559543 100644 --- a/library/server/wsf/src/wsf_execution.e +++ b/library/server/wsf/src/wsf_execution.e @@ -15,7 +15,8 @@ inherit redefine make, execute, - clean + clean, + is_valid_end_of_execution end --create @@ -47,8 +48,24 @@ feature {NONE} -- Access response: WSF_RESPONSE -- Access to output stream, back to the client. +feature -- Execution + + execute + -- Execute Current `request', + -- getting data from `request' + -- and response to client via `response'. + deferred + end + feature -- Status report + is_valid_end_of_execution: BOOLEAN + -- + do + --| Note: overwrite precursor implementation + Result := Precursor and response.status_is_set + end + message_writable: BOOLEAN do Result := response.message_writable @@ -77,16 +94,6 @@ feature -- Helpers response.put_error (err) end -feature -- Execution - - execute - -- Execute Current `request', - -- getting data from `request' - -- and response to client via `response'. - deferred - ensure then - status_is_set: response.status_is_set - end feature -- Cleaning @@ -97,6 +104,11 @@ feature -- Cleaning request.destroy end +invariant + + wsf_request_set: request /= Void + wsf_response_set: response /= Void + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" From 4907bc3085c1077733d52eb56670ea75ff1ec7ce Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 31 Mar 2015 14:50:20 +0200 Subject: [PATCH 09/33] Migrated most of the example and library to new design. --- .../custom-template/src/application.e | 81 +----- .../src/application_execution.e | 60 +++++ .../examples/custom/src/application.e | 81 +----- .../custom/src/application_execution.e | 60 +++++ .../wsf_js_widget/examples/demo/application.e | 148 +---------- .../examples/demo/application_execution.e | 114 +++++++++ examples/debug/debug.ecf | 6 +- .../launcher/any/application_launcher_i.e | 16 +- examples/desktop_app/desktop_app.ecf | 9 +- .../src/app_embedded_web_execution.e | 239 ++++++++++++++++++ .../src/app_embedded_web_service.e | 214 +--------------- examples/desktop_app/src/desktop_app.e | 46 +++- .../src/service/embedded_web_execution.e | 63 +++++ .../src/service/embedded_web_service.e | 86 +------ .../shared_embeded_web_service_information.e | 16 +- examples/filter/filter-safe.ecf | 22 +- examples/filter/src/database/database_api.e | 33 ++- .../filter/src/filter/authentication_filter.e | 17 +- examples/filter/src/filter_server.e | 65 +---- examples/filter/src/filter_server_execution.e | 82 ++++++ examples/filter/src/resource/user_handler.e | 10 +- examples/restbucksCRUD/src/restbucks_server.e | 30 +-- .../src/restbucks_server_execution.e | 57 +++++ examples/simple/application.e | 10 +- examples/simple/application_execution.e | 34 +++ examples/simple/simple.ecf | 6 +- examples/simple_file/service_file.ecf | 4 +- .../src/image_uploader_execution.e | 43 +--- .../openid/consumer/demo/application.e | 118 +-------- .../consumer/demo/application_execution.e | 131 ++++++++++ .../http_authorization/example/demo_basic.e | 210 +-------------- .../example/demo_basic_execution.e | 226 +++++++++++++++++ .../ewsgi/connectors/nino/src/nino_service.e | 17 -- .../{httpd => standalone}/dev/app_counter.e | 0 .../dev/app_wsf_execution.e | 0 .../dev/httpd_connector_dev.e | 13 +- .../{httpd => standalone}/license.lic | 0 .../none/httpd_connection_handler.e | 0 .../concurrency/none/httpd_request_handler.e | 0 .../none/httpd_request_handler_factory.e | 0 .../scoop/httpd_connection_handler.e | 0 .../concurrency/scoop/httpd_request_handler.e | 0 .../scoop/httpd_request_handler_factory.e | 0 .../concurrency/scoop/pool/concurrent_pool.e | 0 .../scoop/pool/concurrent_pool_factory.e | 0 .../scoop/pool/concurrent_pool_item.e | 0 .../thread/httpd_connection_handler.e | 0 .../thread/httpd_request_handler.e | 0 .../thread/httpd_request_handler_factory.e | 0 .../concurrency/thread/pool/pooled_thread.e | 0 .../concurrency/thread/pool/thread_pool.e | 0 .../configuration/httpd_configuration_i.e | 0 .../src/httpd/httpd-safe.ecf | 0 .../{httpd => standalone}/src/httpd/httpd.ecf | 0 .../src/httpd/httpd_connection_handler_i.e | 0 .../src/httpd/httpd_controller.e | 0 .../src/httpd/httpd_debug_facilities.e | 0 .../src/httpd/httpd_logger.e | 0 .../httpd/httpd_request_handler_factory_i.e | 0 .../src/httpd/httpd_request_handler_i.e | 106 +++++++- .../src/httpd/httpd_server_i.e | 72 ++++-- .../src/httpd/httpd_server_observer.e | 24 ++ .../src/httpd/network/httpd_stream_socket.e | 0 .../src/httpd/network/tcp_stream_socket.e | 0 .../src/httpd/no_ssl/httpd_configuration.e | 0 .../src/httpd/no_ssl/httpd_server.e | 0 .../src/httpd/ssl/httpd_configuration.e | 0 .../src/httpd/ssl/httpd_server.e | 0 .../src/httpd/ssl/httpd_stream_ssl_socket.e | 0 .../src/httpd/ssl/ssl_tcp_stream_socket.e | 0 .../wgi_httpd_request_handler.e | 24 +- .../wgi_httpd_request_handler_factory.e | 2 +- .../src/wgi_standalone_connector.e} | 89 +++++-- .../src/wgi_standalone_error_stream.e} | 6 +- .../src/wgi_standalone_input_stream.e} | 6 +- .../src/wgi_standalone_output_stream.e} | 6 +- .../src/wgi_standalone_response_stream.e} | 12 +- .../src/wgi_standalone_server_observer.e} | 39 ++- .../standalone-safe.ecf} | 22 +- .../connectors/standalone/standalone.ecf | 23 ++ .../examples/hello_world/src/hello_world.e | 11 +- .../hello_world/src/hello_world_execution.e | 36 +++ .../connector/wgi_execution_factory.e} | 12 +- .../request/wgi_request_cgi_variables.e | 2 +- .../wsf_openshift_service_launcher.e | 10 +- .../{httpd-safe.ecf => standalone-safe.ecf} | 8 +- library/server/wsf/connector/standalone.ecf | 22 ++ .../wsf_standalone_service_launcher.e} | 23 +- .../cgi/wsf_default_response_service.e | 24 -- .../wsf/default/cgi/wsf_default_service.e | 6 +- .../httpd/wsf_default_response_service.e | 24 -- .../libfcgi/wsf_default_response_service.e | 24 -- .../wsf/default/libfcgi/wsf_default_service.e | 6 +- .../libfcgi/wsf_default_service_launcher.e | 10 +- .../openshift/wsf_default_response_service.e | 24 -- .../default/openshift/wsf_default_service.e | 6 +- .../openshift/wsf_default_service_launcher.e | 10 +- .../{httpd-safe.ecf => standalone-safe.ecf} | 8 +- library/server/wsf/default/standalone.ecf | 17 ++ .../wsf_default_service.e | 0 .../wsf_default_service_launcher.e | 4 +- .../router/filter/wsf_filtered_execution.e | 92 +++++++ .../service/wsf_routed_skeleton_execution.e | 4 +- .../router/wsf_filtered_routed_execution.e | 68 +++++ .../server/wsf/router/wsf_routed_execution.e | 45 +++- ...onse_service.e => wsf_execution_factory.e} | 27 +- library/server/wsf/src/wsf_response.e | 2 +- .../server/wsf/tests/echo/src/echo_server.e | 51 +--- .../tests/echo/src/echo_server_execution.e | 59 +++++ library/server/wsf/tests/server/test.e | 36 +-- .../server/wsf/tests/server/test_execution.e | 51 ++++ .../wsf/tests/server/test_execution_i.e | 195 ++++++++++++++ .../server/wsf/tests/server/test_service.e | 178 +------------ .../server/wsf/tests/src/test_wsf_request.e | 11 +- .../tests/src/test_wsf_response_test_suite.e | 13 +- .../server/wsf/tests/src/wsf_service_null.e | 26 -- tests/all-stable-safe.ecf | 3 + .../rootdir/resources/${APP_NAME}.ecf | 34 +-- .../launcher/any/application_launcher_i.e | 44 ++-- .../resources/launcher/application_launcher.e | 4 +- .../launcher/default/application_launcher_i.e | 10 +- .../rootdir/resources/src/${APP_ROOT}.e | 24 +- .../resources/src/${APP_ROOT}_EXECUTION.e | 89 +++++++ tools/estudio_wizard/src/ewf_wizard.e | 37 ++- 124 files changed, 2399 insertions(+), 1789 deletions(-) create mode 100644 draft/library/server/wsf_js_widget/examples/custom-template/src/application_execution.e create mode 100644 draft/library/server/wsf_js_widget/examples/custom/src/application_execution.e create mode 100644 draft/library/server/wsf_js_widget/examples/demo/application_execution.e create mode 100644 examples/desktop_app/src/app_embedded_web_execution.e create mode 100644 examples/desktop_app/src/service/embedded_web_execution.e create mode 100644 examples/filter/src/filter_server_execution.e create mode 100644 examples/restbucksCRUD/src/restbucks_server_execution.e create mode 100644 examples/simple/application_execution.e create mode 100644 library/security/openid/consumer/demo/application_execution.e create mode 100644 library/server/authentication/http_authorization/example/demo_basic_execution.e rename library/server/ewsgi/connectors/{httpd => standalone}/dev/app_counter.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/dev/app_wsf_execution.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/dev/httpd_connector_dev.e (68%) rename library/server/ewsgi/connectors/{httpd => standalone}/license.lic (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/none/httpd_connection_handler.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/none/httpd_request_handler.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/none/httpd_request_handler_factory.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/scoop/httpd_connection_handler.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/scoop/httpd_request_handler.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/scoop/httpd_request_handler_factory.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/scoop/pool/concurrent_pool.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/thread/httpd_connection_handler.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/thread/httpd_request_handler.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/thread/httpd_request_handler_factory.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/thread/pool/pooled_thread.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/concurrency/thread/pool/thread_pool.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/configuration/httpd_configuration_i.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd-safe.ecf (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd.ecf (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_connection_handler_i.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_controller.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_debug_facilities.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_logger.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_request_handler_factory_i.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_request_handler_i.e (71%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/httpd_server_i.e (88%) create mode 100644 library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/network/httpd_stream_socket.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/network/tcp_stream_socket.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/no_ssl/httpd_configuration.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/no_ssl/httpd_server.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/ssl/httpd_configuration.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/ssl/httpd_server.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/ssl/httpd_stream_ssl_socket.e (100%) rename library/server/ewsgi/connectors/{httpd => standalone}/src/httpd/ssl/ssl_tcp_stream_socket.e (100%) rename library/server/ewsgi/connectors/{httpd/src => standalone/src/implementation}/wgi_httpd_request_handler.e (92%) rename library/server/ewsgi/connectors/{httpd/src => standalone/src/implementation}/wgi_httpd_request_handler_factory.e (93%) rename library/server/ewsgi/connectors/{httpd/src/wgi_httpd_connector.e => standalone/src/wgi_standalone_connector.e} (71%) rename library/server/ewsgi/connectors/{httpd/src/wgi_httpd_error_stream.e => standalone/src/wgi_standalone_error_stream.e} (87%) rename library/server/ewsgi/connectors/{httpd/src/wgi_httpd_input_stream.e => standalone/src/wgi_standalone_input_stream.e} (92%) rename library/server/ewsgi/connectors/{httpd/src/wgi_httpd_output_stream.e => standalone/src/wgi_standalone_output_stream.e} (92%) rename library/server/ewsgi/connectors/{httpd/src/wgi_httpd_response_stream.e => standalone/src/wgi_standalone_response_stream.e} (72%) rename library/server/ewsgi/connectors/{httpd/dev/app_wsf_httpd_request_handler.e => standalone/src/wgi_standalone_server_observer.e} (53%) rename library/server/ewsgi/connectors/{httpd/httpd-safe.ecf => standalone/standalone-safe.ecf} (68%) create mode 100644 library/server/ewsgi/connectors/standalone/standalone.ecf create mode 100644 library/server/ewsgi/examples/hello_world/src/hello_world_execution.e rename library/server/{wsf/default/nino/wsf_default_response_service.e => ewsgi/specification/connector/wgi_execution_factory.e} (68%) rename library/server/wsf/connector/{httpd-safe.ecf => standalone-safe.ecf} (77%) create mode 100644 library/server/wsf/connector/standalone.ecf rename library/server/wsf/connector/{httpd/wsf_httpd_service_launcher.e => standalone/wsf_standalone_service_launcher.e} (85%) delete mode 100644 library/server/wsf/default/cgi/wsf_default_response_service.e delete mode 100644 library/server/wsf/default/httpd/wsf_default_response_service.e delete mode 100644 library/server/wsf/default/libfcgi/wsf_default_response_service.e delete mode 100644 library/server/wsf/default/openshift/wsf_default_response_service.e rename library/server/wsf/default/{httpd-safe.ecf => standalone-safe.ecf} (69%) create mode 100644 library/server/wsf/default/standalone.ecf rename library/server/wsf/default/{httpd => standalone}/wsf_default_service.e (100%) rename library/server/wsf/default/{httpd => standalone}/wsf_default_service_launcher.e (82%) create mode 100644 library/server/wsf/router/filter/wsf_filtered_execution.e create mode 100644 library/server/wsf/router/wsf_filtered_routed_execution.e rename library/server/wsf/src/{service/wsf_response_service.e => wsf_execution_factory.e} (50%) create mode 100644 library/server/wsf/tests/echo/src/echo_server_execution.e create mode 100644 library/server/wsf/tests/server/test_execution.e create mode 100644 library/server/wsf/tests/server/test_execution_i.e delete mode 100644 library/server/wsf/tests/src/wsf_service_null.e create mode 100644 tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e diff --git a/draft/library/server/wsf_js_widget/examples/custom-template/src/application.e b/draft/library/server/wsf_js_widget/examples/custom-template/src/application.e index b7c07219..8377165e 100644 --- a/draft/library/server/wsf_js_widget/examples/custom-template/src/application.e +++ b/draft/library/server/wsf_js_widget/examples/custom-template/src/application.e @@ -8,23 +8,11 @@ class inherit - WSF_ROUTED_SERVICE - rename - execute as execute_router - end - - WSF_FILTERED_SERVICE - - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION] redefine initialize end - WSF_FILTER - rename - execute as execute_router - end - create make_and_launch @@ -33,75 +21,8 @@ feature {NONE} -- Initialization initialize -- Initialize current service. do - initialize_router - initialize_filter Precursor set_service_option ("port", 7070) end -feature -- Router and Filter - - create_filter - -- Create `filter' - local - f, l_filter: detachable WSF_FILTER - do - l_filter := Void - - -- Maintenance - create {WSF_MAINTENANCE_FILTER} f - f.set_next (l_filter) - l_filter := f - - -- Logging - create {WSF_LOGGING_FILTER} f - f.set_next (l_filter) - l_filter := f - filter := l_filter - end - - setup_filter - -- Setup `filter' - local - f: WSF_FILTER - do - from - f := filter - until - not attached f.next as l_next - loop - f := l_next - end - f.set_next (Current) - end - - setup_router - do - map_agent_uri ("/", agent execute_hello, Void) - -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" - -- this way, it handles the caching and so on - router.handle_with_request_methods ("/assets", create {WSF_FILE_SYSTEM_HANDLER}.make_hidden ("assets"), router.methods_GET) - end - -feature -- Helper: mapping - - map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS) - do - router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) - end - - -feature -- Execution - - execute_hello (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: EMPTY_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - end diff --git a/draft/library/server/wsf_js_widget/examples/custom-template/src/application_execution.e b/draft/library/server/wsf_js_widget/examples/custom-template/src/application_execution.e new file mode 100644 index 00000000..d40b45ce --- /dev/null +++ b/draft/library/server/wsf_js_widget/examples/custom-template/src/application_execution.e @@ -0,0 +1,60 @@ +note + description: "simple application root class" + date: "$Date$" + revision: "$Revision$" + +class + APPLICATION_EXECUTION + +inherit + + WSF_FILTERED_ROUTED_EXECUTION + +create + make + +feature -- Router and Filter + + create_filter + -- Create `filter' + do + -- Maintenance + create {WSF_MAINTENANCE_FILTER} filter + end + + setup_filter + -- Setup `filter' + do + append_filters (<>) + end + + setup_router + do + map_agent_uri ("/", agent execute_hello, Void) + -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" + -- this way, it handles the caching and so on + router.handle_with_request_methods ("/assets", create {WSF_FILE_SYSTEM_HANDLER}.make_hidden ("assets"), router.methods_GET) + end + +feature -- Helper: mapping + + map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS) + do + router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) + end + + +feature -- Execution + + execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: EMPTY_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + +end diff --git a/draft/library/server/wsf_js_widget/examples/custom/src/application.e b/draft/library/server/wsf_js_widget/examples/custom/src/application.e index b7c07219..8377165e 100644 --- a/draft/library/server/wsf_js_widget/examples/custom/src/application.e +++ b/draft/library/server/wsf_js_widget/examples/custom/src/application.e @@ -8,23 +8,11 @@ class inherit - WSF_ROUTED_SERVICE - rename - execute as execute_router - end - - WSF_FILTERED_SERVICE - - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION] redefine initialize end - WSF_FILTER - rename - execute as execute_router - end - create make_and_launch @@ -33,75 +21,8 @@ feature {NONE} -- Initialization initialize -- Initialize current service. do - initialize_router - initialize_filter Precursor set_service_option ("port", 7070) end -feature -- Router and Filter - - create_filter - -- Create `filter' - local - f, l_filter: detachable WSF_FILTER - do - l_filter := Void - - -- Maintenance - create {WSF_MAINTENANCE_FILTER} f - f.set_next (l_filter) - l_filter := f - - -- Logging - create {WSF_LOGGING_FILTER} f - f.set_next (l_filter) - l_filter := f - filter := l_filter - end - - setup_filter - -- Setup `filter' - local - f: WSF_FILTER - do - from - f := filter - until - not attached f.next as l_next - loop - f := l_next - end - f.set_next (Current) - end - - setup_router - do - map_agent_uri ("/", agent execute_hello, Void) - -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" - -- this way, it handles the caching and so on - router.handle_with_request_methods ("/assets", create {WSF_FILE_SYSTEM_HANDLER}.make_hidden ("assets"), router.methods_GET) - end - -feature -- Helper: mapping - - map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS) - do - router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) - end - - -feature -- Execution - - execute_hello (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: EMPTY_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - end diff --git a/draft/library/server/wsf_js_widget/examples/custom/src/application_execution.e b/draft/library/server/wsf_js_widget/examples/custom/src/application_execution.e new file mode 100644 index 00000000..c7640ef6 --- /dev/null +++ b/draft/library/server/wsf_js_widget/examples/custom/src/application_execution.e @@ -0,0 +1,60 @@ +note + description: "simple application root class" + date: "$Date$" + revision: "$Revision$" + +class + APPLICATION_EXECUTION + +inherit + + WSF_FILTERED_ROUTED_EXECUTION + +create + make + +feature -- Router and Filter + + create_filter + -- Create `filter' + do + -- Maintenance + create {WSF_MAINTENANCE_FILTER} filter + end + + setup_filter + -- Setup `filter' + do + append_filters (<< create {WSF_LOGGING_FILTER} >>) + end + + setup_router + do + map_agent_uri ("/", agent execute_hello, Void) + -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" + -- this way, it handles the caching and so on + router.handle_with_request_methods ("/assets", create {WSF_FILE_SYSTEM_HANDLER}.make_hidden ("assets"), router.methods_GET) + end + +feature -- Helper: mapping + + map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS) + do + router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) + end + + +feature -- Execution + + execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: EMPTY_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + +end diff --git a/draft/library/server/wsf_js_widget/examples/demo/application.e b/draft/library/server/wsf_js_widget/examples/demo/application.e index 99986f57..9da734b8 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/application.e +++ b/draft/library/server/wsf_js_widget/examples/demo/application.e @@ -8,168 +8,22 @@ class inherit - WSF_ROUTED_SERVICE - rename - execute as execute_router - end - - WSF_FILTERED_SERVICE - - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION] redefine initialize end - WSF_FILTER - rename - execute as execute_router - end create make_and_launch feature {NONE} -- Initialization --- tt --- local --- lst: ARRAYED_LIST [READABLE_STRING_GENERAL] --- do --- create lst.make (3) --- lst.compare_objects --- lst.extend ({STRING_32} "abc") --- if lst.has ("abc") then --- print ("found%N") --- end --- end - initialize -- Initialize current service. do --- tt - initialize_router - initialize_filter Precursor set_service_option ("port", 9090) end -feature -- Router and Filter - - create_filter - -- Create `filter' - local - f, l_filter: detachable WSF_FILTER - do - l_filter := Void - - -- Maintenance - create {WSF_MAINTENANCE_FILTER} f - f.set_next (l_filter) - l_filter := f - - -- Logging - create {WSF_LOGGING_FILTER} f - f.set_next (l_filter) - l_filter := f - filter := l_filter - end - - setup_filter - -- Setup `filter' - local - f: WSF_FILTER - do - from - f := filter - until - not attached f.next as l_next - loop - f := l_next - end - f.set_next (Current) - end - - setup_router - do - map_agent_uri ("/", agent execute_hello, Void) - map_agent_uri ("/grid", agent grid_demo, Void) - map_agent_uri ("/repeater", agent repeater_demo, Void) - map_agent_uri ("/slider", agent slider_demo, Void) - map_agent_uri ("/upload", agent upload_demo, Void) - map_agent_uri ("/codeview", agent codeview, Void) - - -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" - -- this way, it handles the caching and so on - router.handle_with_request_methods ("/assets", create {WSF_FILE_SYSTEM_HANDLER}.make_hidden ("assets"), router.methods_GET) - end - -feature -- Helper: mapping - - map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS) - do - router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) - end - -feature -- Execution - - execute_hello (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: SAMPLE_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - grid_demo (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: GRID_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - repeater_demo (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: REPEATER_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - slider_demo (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: SLIDER_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - upload_demo (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: UPLOAD_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - codeview (request: WSF_REQUEST; response: WSF_RESPONSE) - local - page: CODEVIEW_PAGE - do - -- To send a response we need to setup, the status code and - -- the response headers. - create page.make (request, response) - page.execute - end - - end diff --git a/draft/library/server/wsf_js_widget/examples/demo/application_execution.e b/draft/library/server/wsf_js_widget/examples/demo/application_execution.e new file mode 100644 index 00000000..b0582128 --- /dev/null +++ b/draft/library/server/wsf_js_widget/examples/demo/application_execution.e @@ -0,0 +1,114 @@ +note + description: "Summary description for {APPLICATION_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + APPLICATION_EXECUTION + +inherit + WSF_FILTERED_ROUTED_EXECUTION + +create + make + +feature -- Router and Filter + + create_filter + -- Create `filter' + do + -- Maintenance + create {WSF_MAINTENANCE_FILTER} filter + end + + setup_filter + -- Setup `filter' + do + append_filters (<>) + end + + setup_router + do + map_agent_uri ("/", agent execute_hello, Void) + map_agent_uri ("/grid", agent grid_demo, Void) + map_agent_uri ("/repeater", agent repeater_demo, Void) + map_agent_uri ("/slider", agent slider_demo, Void) + map_agent_uri ("/upload", agent upload_demo, Void) + map_agent_uri ("/codeview", agent codeview, Void) + + -- NOTE: you could put all those files in a specific folder, and use WSF_FILE_SYSTEM_HANDLER with "/" + -- this way, it handles the caching and so on + router.handle_with_request_methods ("/assets", create {WSF_FILE_SYSTEM_HANDLER}.make_hidden ("assets"), router.methods_GET) + end + +feature -- Helper: mapping + + map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS) + do + router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) + end + +feature -- Execution + + execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: SAMPLE_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + grid_demo (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: GRID_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + repeater_demo (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: REPEATER_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + slider_demo (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: SLIDER_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + upload_demo (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: UPLOAD_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + + codeview (req: WSF_REQUEST; res: WSF_RESPONSE) + local + page: CODEVIEW_PAGE + do + -- To send a response we need to setup, the status code and + -- the response headers. + create page.make (req, res) + page.execute + end + +end diff --git a/examples/debug/debug.ecf b/examples/debug/debug.ecf index 26bf2100..642cd4cc 100644 --- a/examples/debug/debug.ecf +++ b/examples/debug/debug.ecf @@ -20,15 +20,15 @@ - + - + - + diff --git a/examples/debug/launcher/any/application_launcher_i.e b/examples/debug/launcher/any/application_launcher_i.e index 22f94cab..9e062274 100644 --- a/examples/debug/launcher/any/application_launcher_i.e +++ b/examples/debug/launcher/any/application_launcher_i.e @@ -22,8 +22,8 @@ feature -- Execution nature: like launcher_nature do nature := launcher_nature - if nature = Void or else nature = nature_httpd then - launch_httpd (opts) + if nature = Void or else nature = nature_standalone then + launch_standalone (opts) elseif nature = nature_nino then launch_nino (opts) elseif nature = nature_cgi then @@ -52,8 +52,8 @@ feature {NONE} -- Access ext := l_entry.extension end if ext /= Void then - if ext.same_string (nature_httpd) then - Result := nature_httpd + if ext.same_string (nature_standalone) then + Result := nature_standalone end if ext.same_string (nature_nino) then Result := nature_nino @@ -65,16 +65,16 @@ feature {NONE} -- Access Result := nature_libfcgi end end - Result := nature_httpd + Result := nature_standalone end feature {NONE} -- nino - nature_httpd: STRING = "httpd" + nature_standalone: STRING = "standalone" - launch_httpd (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_standalone (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_HTTPD_SERVICE_LAUNCHER [G] + launcher: WSF_STANDALONE_SERVICE_LAUNCHER [G] do create launcher.make_and_launch (opts) end diff --git a/examples/desktop_app/desktop_app.ecf b/examples/desktop_app/desktop_app.ecf index 78fd6e17..81a0aa50 100644 --- a/examples/desktop_app/desktop_app.ecf +++ b/examples/desktop_app/desktop_app.ecf @@ -7,17 +7,16 @@ - - + - - - + + + /EIFGENs$ /CVS$ diff --git a/examples/desktop_app/src/app_embedded_web_execution.e b/examples/desktop_app/src/app_embedded_web_execution.e new file mode 100644 index 00000000..815e35a6 --- /dev/null +++ b/examples/desktop_app/src/app_embedded_web_execution.e @@ -0,0 +1,239 @@ +note + description: "Summary description for {APP_EMBEDDED_WEB_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + APP_EMBEDDED_WEB_EXECUTION + +inherit + EMBEDDED_WEB_EXECUTION + redefine + initialize + end + +create + make + +feature {NONE} -- Initialization + + initialize + do + Precursor + create request_exit_operation_actions + local_connection_restriction_enabled := True + end + +feature -- Execution + + request_exit_operation_actions: ACTION_SEQUENCE [TUPLE] + + execute + -- Execute the request + -- See `request.input' for input stream + -- `request.meta_variables' for the CGI meta variable + -- and `response' for output buffer + local + router: WSF_ROUTER + sess: detachable WSF_ROUTER_SESSION + m: WSF_HTML_PAGE_RESPONSE + b: STRING + fs: WSF_FILE_SYSTEM_HANDLER + req: like request + do + req := request + + create router.make (3) + router.handle ("/test/{var}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_test)) + router.handle ("/env", create {WSF_URI_AGENT_HANDLER}.make (agent handle_env)) + router.handle ("/exit", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_exit)) + create fs.make_with_path ((create {EXECUTION_ENVIRONMENT}).current_working_path.extended ("files")) + router.handle ("/files", fs) + create sess + router.dispatch (req, response, sess) + if not sess.dispatched then + create m.make + create b.make_from_string ("

Hello Eiffel desktop user

") + b.append ("
  • test
  • ") + b.append ("
  • env
  • ") + b.append ("
  • files
  • ") + b.append ("
  • exit
  • ") + m.set_body (b) + response.send (m) + end + end + + handle_test (req: WSF_REQUEST; res: WSF_RESPONSE) + local + m: WSF_HTML_PAGE_RESPONSE + b: STRING + l_name: READABLE_STRING_32 + do + if attached {WSF_STRING} req.item ("var") as p_name then + l_name := p_name.value + else + l_name := {STRING_32} "Embedded web service and web_browser in vision2 application" + end + create m.make + create b.make_from_string ("

    This is a test about "+ m.html_encoded_string (l_name) +"

    ") + b.append ("
  • back to home
  • ") + if l_name.is_case_insensitive_equal_general ("start") then + b.append ("
  • test javascript+ajax
  • ") + elseif l_name.is_case_insensitive_equal_general ("js") then + b.append ("[ +

    Let AJAX change this text

    + +
    + ]") + m.add_javascript_content ("[ + function loadXMLDoc() + { + var xmlhttp; + if (window.XMLHttpRequest) + {// code for IE7+, Firefox, Chrome, Opera, Safari + xmlhttp=new XMLHttpRequest(); + } + else + {// code for IE6, IE5 + xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + xmlhttp.onreadystatechange=function() + { + if (xmlhttp.readyState==4 && xmlhttp.status==200) + { + document.getElementById("myDiv").innerHTML=xmlhttp.responseText; + } + } + xmlhttp.open("GET","/test/ajax.txt",true); + xmlhttp.send(); + } + ]") + elseif l_name.is_case_insensitive_equal_general ("ajax.txt") then + b := "This is AJAX response ... from " + req.absolute_script_url ("") + end + m.set_body (b) + res.send (m) + end + + handle_env (req: WSF_REQUEST; res: WSF_RESPONSE) + local + s: STRING_8 + p: WSF_PAGE_RESPONSE + v: STRING_8 + do + create s.make (2048) + s.append ("**DEBUG**%N") + req.set_raw_input_data_recorded (True) + + append_iterable_to ("Meta variables:", req.meta_variables, s) + s.append_character ('%N') + + append_iterable_to ("Path parameters", req.path_parameters, s) + s.append_character ('%N') + + append_iterable_to ("Query parameters", req.query_parameters, s) + s.append_character ('%N') + + append_iterable_to ("Form parameters", req.form_parameters, s) + s.append_character ('%N') + + if attached req.content_type as l_type then + s.append ("Content: type=" + l_type.debug_output) + s.append (" length=") + s.append_natural_64 (req.content_length_value) + s.append_character ('%N') + create v.make (req.content_length_value.to_integer_32) + req.read_input_data_into (v) + across + v.split ('%N') as v_cursor + loop + s.append (" |") + s.append (v_cursor.item) + s.append_character ('%N') + end + end + + create p.make_with_body (s) + p.header.put_content_type_text_plain + res.send (p) + end + + handle_exit (req: WSF_REQUEST; res: WSF_RESPONSE) + local + m: WSF_HTML_PAGE_RESPONSE + b: STRING + do + create m.make + create b.make_from_string ("

    Embedded server is about to shutdown

    ") + b.append ("
  • back to home
  • ") + b.append ("
  • Click to confirm exit operation
  • ") + m.set_body (b) + res.send (m) + if attached {separate WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]} req.wgi_connector as conn then + shutdown_server (conn) + end + request_exit_operation_actions.call (Void) + end + + shutdown_server (conn: separate WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]) + do + conn.shutdown_server + end + +feature {NONE} -- Implementation + + append_iterable_to (a_title: READABLE_STRING_8; it: detachable ITERABLE [WSF_VALUE]; s: STRING_8) + local + n: INTEGER + t: READABLE_STRING_8 + v: READABLE_STRING_8 + do + s.append (a_title) + s.append_character (':') + if it /= Void then + across it as c loop + n := n + 1 + end + if n = 0 then + s.append (" empty") + s.append_character ('%N') + else + s.append_character ('%N') + across + it as c + loop + s.append (" - ") + s.append (c.item.url_encoded_name) + t := c.item.generating_type + if t.same_string ("WSF_STRING") then + else + s.append_character (' ') + s.append_character ('{') + s.append (t) + s.append_character ('}') + end + s.append_character ('=') + v := c.item.string_representation.as_string_8 + if v.has ('%N') then + s.append_character ('%N') + across + v.split ('%N') as v_cursor + loop + s.append (" |") + s.append (v_cursor.item) + s.append_character ('%N') + end + else + s.append (v) + s.append_character ('%N') + end + end + end + else + s.append (" none") + s.append_character ('%N') + end + end + +end diff --git a/examples/desktop_app/src/app_embedded_web_service.e b/examples/desktop_app/src/app_embedded_web_service.e index e9ebed88..ed11c24d 100644 --- a/examples/desktop_app/src/app_embedded_web_service.e +++ b/examples/desktop_app/src/app_embedded_web_service.e @@ -8,223 +8,11 @@ class APP_EMBEDDED_WEB_SERVICE inherit - EMBEDDED_WEB_SERVICE - redefine - make - end + EMBEDDED_WEB_SERVICE [APP_EMBEDDED_WEB_EXECUTION] create make feature {NONE} -- Initialization - make - do - Precursor - create request_exit_operation_actions - local_connection_restriction_enabled := True - end - -feature -- Execution - - request_exit_operation_actions: ACTION_SEQUENCE [TUPLE] - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Execute the request - -- See `req.input' for input stream - -- `req.meta_variables' for the CGI meta variable - -- and `res' for output buffer - local - router: WSF_ROUTER - sess: detachable WSF_ROUTER_SESSION - m: WSF_HTML_PAGE_RESPONSE - b: STRING - fs: WSF_FILE_SYSTEM_HANDLER - do - create router.make (3) - router.handle ("/test/{var}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_test)) - router.handle ("/env", create {WSF_URI_AGENT_HANDLER}.make (agent handle_env)) - router.handle ("/exit", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_exit)) - create fs.make_with_path ((create {EXECUTION_ENVIRONMENT}).current_working_path.extended ("files")) - router.handle ("/files", fs) - create sess - router.dispatch (req, res, sess) - if not sess.dispatched then - create m.make - create b.make_from_string ("

    Hello Eiffel desktop user

    ") - b.append ("
  • test
  • ") - b.append ("
  • env
  • ") - b.append ("
  • files
  • ") - b.append ("
  • exit
  • ") - m.set_body (b) - res.send (m) - end - end - - handle_test (req: WSF_REQUEST; res: WSF_RESPONSE) - local - m: WSF_HTML_PAGE_RESPONSE - b: STRING - l_name: READABLE_STRING_32 - do - if attached {WSF_STRING} req.item ("var") as p_name then - l_name := p_name.value - else - l_name := {STRING_32} "Embedded web service and web_browser in vision2 application" - end - create m.make - create b.make_from_string ("

    This is a test about "+ m.html_encoded_string (l_name) +"

    ") - b.append ("
  • back to home
  • ") - if l_name.is_case_insensitive_equal_general ("start") then - b.append ("
  • test javascript+ajax
  • ") - elseif l_name.is_case_insensitive_equal_general ("js") then - b.append ("[ -

    Let AJAX change this text

    - -
    - ]") - m.add_javascript_content ("[ - function loadXMLDoc() - { - var xmlhttp; - if (window.XMLHttpRequest) - {// code for IE7+, Firefox, Chrome, Opera, Safari - xmlhttp=new XMLHttpRequest(); - } - else - {// code for IE6, IE5 - xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); - } - xmlhttp.onreadystatechange=function() - { - if (xmlhttp.readyState==4 && xmlhttp.status==200) - { - document.getElementById("myDiv").innerHTML=xmlhttp.responseText; - } - } - xmlhttp.open("GET","/test/ajax.txt",true); - xmlhttp.send(); - } - ]") - elseif l_name.is_case_insensitive_equal_general ("ajax.txt") then - b := "This is AJAX response ... from " + req.absolute_script_url ("") - end - m.set_body (b) - res.send (m) - end - - handle_env (req: WSF_REQUEST; res: WSF_RESPONSE) - local - s: STRING_8 - p: WSF_PAGE_RESPONSE - v: STRING_8 - do - create s.make (2048) - s.append ("**DEBUG**%N") - req.set_raw_input_data_recorded (True) - - append_iterable_to ("Meta variables:", req.meta_variables, s) - s.append_character ('%N') - - append_iterable_to ("Path parameters", req.path_parameters, s) - s.append_character ('%N') - - append_iterable_to ("Query parameters", req.query_parameters, s) - s.append_character ('%N') - - append_iterable_to ("Form parameters", req.form_parameters, s) - s.append_character ('%N') - - if attached req.content_type as l_type then - s.append ("Content: type=" + l_type.debug_output) - s.append (" length=") - s.append_natural_64 (req.content_length_value) - s.append_character ('%N') - create v.make (req.content_length_value.to_integer_32) - req.read_input_data_into (v) - across - v.split ('%N') as v_cursor - loop - s.append (" |") - s.append (v_cursor.item) - s.append_character ('%N') - end - end - - create p.make_with_body (s) - p.header.put_content_type_text_plain - res.send (p) - end - - handle_exit (req: WSF_REQUEST; res: WSF_RESPONSE) - local - m: WSF_HTML_PAGE_RESPONSE - b: STRING - do - create m.make - create b.make_from_string ("

    Embedded server is about to shutdown

    ") - b.append ("
  • back to home
  • ") - m.set_body (b) - res.send (m) - if attached {WGI_NINO_CONNECTOR} req.wgi_connector as nino then - nino.server.shutdown_server - end - request_exit_operation_actions.call (Void) - end - -feature {NONE} -- Implementation - - append_iterable_to (a_title: READABLE_STRING_8; it: detachable ITERABLE [WSF_VALUE]; s: STRING_8) - local - n: INTEGER - t: READABLE_STRING_8 - v: READABLE_STRING_8 - do - s.append (a_title) - s.append_character (':') - if it /= Void then - across it as c loop - n := n + 1 - end - if n = 0 then - s.append (" empty") - s.append_character ('%N') - else - s.append_character ('%N') - across - it as c - loop - s.append (" - ") - s.append (c.item.url_encoded_name) - t := c.item.generating_type - if t.same_string ("WSF_STRING") then - else - s.append_character (' ') - s.append_character ('{') - s.append (t) - s.append_character ('}') - end - s.append_character ('=') - v := c.item.string_representation.as_string_8 - if v.has ('%N') then - s.append_character ('%N') - across - v.split ('%N') as v_cursor - loop - s.append (" |") - s.append (v_cursor.item) - s.append_character ('%N') - end - else - s.append (v) - s.append_character ('%N') - end - end - end - else - s.append (" none") - s.append_character ('%N') - end - end - end diff --git a/examples/desktop_app/src/desktop_app.e b/examples/desktop_app/src/desktop_app.e index 85aaf27c..a48779f0 100644 --- a/examples/desktop_app/src/desktop_app.e +++ b/examples/desktop_app/src/desktop_app.e @@ -24,18 +24,17 @@ feature {NONE} -- Initialization -- then launch the application. local l_win: like main_window - l_embeded_services: APP_EMBEDDED_WEB_SERVICE + l_embedded_service: APP_EMBEDDED_WEB_SERVICE do default_create create l_win.make main_window := l_win l_win.show - create l_embeded_services.make - l_embeded_services.set_port_number (0) -- Use first available port number + create l_embedded_service.make + l_embedded_service.set_port_number (0) -- Use first available port number - l_embeded_services.on_launched_actions.force (agent on_web_service_launched (l_win)) - l_embeded_services.request_exit_operation_actions.force (agent on_quit) - l_embeded_services.launch + l_embedded_service.on_launched_actions.force (agent on_web_service_launched (l_win, l_embedded_service)) + l_embedded_service.launch launch end @@ -46,11 +45,44 @@ feature {NONE} -- Initialization end end - on_web_service_launched (a_win: attached like main_window) + on_web_service_launched (a_win: attached like main_window; s: APP_EMBEDDED_WEB_SERVICE) do + add_idle_action_kamikaze (agent wait_for_termination (s, Void)) add_idle_action_kamikaze (agent a_win.open_link) end + wait_for_termination (s: APP_EMBEDDED_WEB_SERVICE; a_timeout: detachable EV_TIMEOUT) + local + t: detachable EV_TIMEOUT + do + t := a_timeout + if t /= Void then + t.set_interval (0) + end + if + attached s.observer as obs and then + observer_has_terminaded (obs) + then + if t /= Void then + t.destroy + end + on_quit + else + if t = Void then + create t + t.actions.extend (agent wait_for_termination (s, t)) + else + t.set_interval (1_000) + end + t.set_interval (1_000) + end + end + + observer_has_terminaded (obs: separate WGI_STANDALONE_SERVER_OBSERVER): BOOLEAN + do + Result := obs.terminated + end + feature {NONE} -- Implementation main_window: detachable MAIN_WINDOW diff --git a/examples/desktop_app/src/service/embedded_web_execution.e b/examples/desktop_app/src/service/embedded_web_execution.e new file mode 100644 index 00000000..9ece6bdc --- /dev/null +++ b/examples/desktop_app/src/service/embedded_web_execution.e @@ -0,0 +1,63 @@ +note + description: "Summary description for {EMBEDDED_WEB_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + EMBEDDED_WEB_EXECUTION + +inherit + WSF_EXECUTION + rename + execute as execute_embedded + end + + SHARED_EMBEDED_WEB_SERVICE_INFORMATION + +feature {NONE} -- Execution + + execute_embedded + -- Execute the request + -- See `request.input' for input stream + -- `request.meta_variables' for the CGI meta variable + -- and `response' for output buffer + local + filter: WSF_AGENT_FILTER + m: WSF_PAGE_RESPONSE + do + if local_connection_restriction_enabled then + if + attached request.remote_addr as l_remote_addr and then + l_remote_addr.is_case_insensitive_equal_general ("127.0.0.1") + then + execute + else + create m.make_with_body ("Only local connection is allowed") + m.set_status_code (403) -- Forbidden + response.send (m) + end + else + execute + end + end + + execute + deferred + end + +feature -- Status report + + local_connection_restriction_enabled: BOOLEAN + -- Accept only local connection? + --| based on 127.0.0.1 IP + --| TO IMPROVE + +feature -- Change + + set_local_connection_restriction_enabled (b: BOOLEAN) + do + local_connection_restriction_enabled := b + end + +end diff --git a/examples/desktop_app/src/service/embedded_web_service.e b/examples/desktop_app/src/service/embedded_web_service.e index 995f2393..7b3adc88 100644 --- a/examples/desktop_app/src/service/embedded_web_service.e +++ b/examples/desktop_app/src/service/embedded_web_service.e @@ -5,19 +5,10 @@ note revision: "$Revision$" deferred class - EMBEDDED_WEB_SERVICE + EMBEDDED_WEB_SERVICE [G -> EMBEDDED_WEB_EXECUTION create make end] inherit - THREAD - rename - make as make_thread, - execute as execute_thread - end - WSF_SERVICE - rename - execute as execute_embedded - end SHARED_EMBEDED_WEB_SERVICE_INFORMATION @@ -25,90 +16,35 @@ feature -- Initialization make do - make_thread create on_launched_actions end -feature {NONE} -- Execution +feature -- Execution - execute_embedded (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Execute the request - -- See `req.input' for input stream - -- `req.meta_variables' for the CGI meta variable - -- and `res' for output buffer + launch local - filter: WSF_AGENT_FILTER - m: WSF_PAGE_RESPONSE - do - if local_connection_restriction_enabled then - if - attached req.remote_addr as l_remote_addr and then - l_remote_addr.is_case_insensitive_equal_general ("127.0.0.1") - then - execute (req, res) - else - create m.make_with_body ("Only local connection is allowed") - m.set_status_code (403) -- Forbidden - res.send (m) - end - else - execute (req, res) - end - end - - execute_thread - local - nino: WSF_NINO_SERVICE_LAUNCHER + launcher: WSF_STANDALONE_SERVICE_LAUNCHER [G] opts: WSF_SERVICE_LAUNCHER_OPTIONS do create opts.default_create opts.set_verbose (True) opts.set_option ("port", port_number) - create nino.make (Current, opts) - nino.on_launched_actions.force (agent on_launched) - nino.launch + create launcher.make (opts) + observer := launcher.connector.observer + launcher.on_launched_actions.force (agent on_launched) + launcher.launch end - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Execute the request - -- See `req.input' for input stream - -- `req.meta_variables' for the CGI meta variable - -- and `res' for output buffer - deferred - end + observer: detachable separate WGI_STANDALONE_SERVER_OBSERVER - on_launched (conn: WGI_CONNECTOR) + on_launched (conn: WGI_STANDALONE_CONNECTOR [G]) do - if attached {WGI_NINO_CONNECTOR} conn as nino then - set_port_number (nino.port) - end + set_port_number (conn.port) on_launched_actions.call (Void) end -feature -- Control - - wait - -- Wait for server to be terminated. - do - join - end - feature -- Access on_launched_actions: ACTION_SEQUENCE [TUPLE] -feature -- Status report - - local_connection_restriction_enabled: BOOLEAN - -- Accept only local connection? - --| based on 127.0.0.1 IP - --| TO IMPROVE - -feature -- Change - - set_local_connection_restriction_enabled (b: BOOLEAN) - do - local_connection_restriction_enabled := b - end - end diff --git a/examples/desktop_app/src/service/shared_embeded_web_service_information.e b/examples/desktop_app/src/service/shared_embeded_web_service_information.e index ba04e855..353f21d5 100644 --- a/examples/desktop_app/src/service/shared_embeded_web_service_information.e +++ b/examples/desktop_app/src/service/shared_embeded_web_service_information.e @@ -11,15 +11,25 @@ feature -- Access port_number: INTEGER do - Result := port_number_cell.item + Result := separate_port_number (port_number_cell) end set_port_number (a_port: like port_number) do - port_number_cell.replace (a_port) + separate_set_port_number (port_number_cell, a_port) end - port_number_cell: CELL [INTEGER] + separate_port_number (cl: like port_number_cell): like port_number + do + Result := cl.item + end + + separate_set_port_number (cl: like port_number_cell; a_port: like port_number) + do + cl.replace (a_port) + end + + port_number_cell: separate CELL [INTEGER] once ("process") create Result.put (0) end diff --git a/examples/filter/filter-safe.ecf b/examples/filter/filter-safe.ecf index 537594cf..6d85dcd0 100644 --- a/examples/filter/filter-safe.ecf +++ b/examples/filter/filter-safe.ecf @@ -1,30 +1,36 @@ - + /EIFGENs$ /\.git$ /\.svn$ - - - - - - - + + + + + + + + + + + + diff --git a/examples/filter/src/database/database_api.e b/examples/filter/src/database/database_api.e index 4c0024c0..669ef656 100644 --- a/examples/filter/src/database/database_api.e +++ b/examples/filter/src/database/database_api.e @@ -24,6 +24,24 @@ feature -- Initialization feature -- Access + user_by_id (a_id: INTEGER): detachable USER + do + Result := users.item (a_id) + end + + user_by_name (a_name: READABLE_STRING_GENERAL): detachable USER + do + across + users as c + until + Result /= Void + loop + if attached c.item as u and then a_name.same_string (u.name) then + Result := u + end + end + end + user (a_id: INTEGER; a_name: detachable READABLE_STRING_GENERAL): detachable USER -- User with id `a_id' or name `a_name'. require @@ -32,18 +50,9 @@ feature -- Access n: like {USER}.name do if a_id > 0 then - Result := users.item (a_id) + Result := user_by_id (a_id) elseif a_name /= Void then - n := a_name.as_string_8 - across - users as c - until - Result /= Void - loop - if attached c.item as u and then u.name.same_string (n) then - Result := u - end - end + Result := user_by_name (a_name) end ensure Result /= Void implies ((a_id > 0 and then Result.id = a_id) xor (a_name /= Void and then Result.name.same_string_general (a_name))) @@ -52,6 +61,6 @@ feature -- Access users: HASH_TABLE [USER, INTEGER] ;note - copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others" + copyright: "2011-2015, Olivier Ligot, Jocelyn Fiat and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" end diff --git a/examples/filter/src/filter/authentication_filter.e b/examples/filter/src/filter/authentication_filter.e index c3bf8ae3..072c8aec 100644 --- a/examples/filter/src/filter/authentication_filter.e +++ b/examples/filter/src/filter/authentication_filter.e @@ -48,18 +48,31 @@ feature {NONE} -- Implementation -- Handle forbidden. local h: HTTP_HEADER + s: STRING do create h.make h.put_content_type_text_plain h.put_content_length (a_description.count) h.put_current_date - h.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, "Basic realm=%"User%"") + s := "Basic realm=%"For this demo, use any of: " + across + db_access.users as ic + loop + s.append_character ('(') + s.append (ic.item.name) + s.append_character (':') + s.append (ic.item.password) + s.append_character (')') + s.append_character (' ') + end + s.append_character ('"') + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, s) res.set_status_code ({HTTP_STATUS_CODE}.unauthorized) res.put_header_text (h.string) res.put_string (a_description) end note - copyright: "2011-2014, Olivier Ligot, Jocelyn Fiat and others" + copyright: "2011-2015, Olivier Ligot, Jocelyn Fiat and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" end diff --git a/examples/filter/src/filter_server.e b/examples/filter/src/filter_server.e index dfc9f8fe..2ad4442a 100644 --- a/examples/filter/src/filter_server.e +++ b/examples/filter/src/filter_server.e @@ -8,18 +8,7 @@ class FILTER_SERVER inherit - ANY - - WSF_DEFAULT_SERVICE - - WSF_ROUTED_SERVICE - undefine - execute - end - - WSF_FILTERED_SERVICE - - SHARED_EJSON + WSF_DEFAULT_SERVICE [FILTER_SERVER_EXECUTION] create make @@ -31,9 +20,6 @@ feature {NONE} -- Initialization l_message: STRING l_factory: INET_ADDRESS_FACTORY do - initialize_router - initialize_filter - initialize_json set_service_option ("port", port) create l_message.make_empty l_message.append_string ("Launching filter server at ") @@ -46,60 +32,13 @@ feature {NONE} -- Initialization make_and_launch end - create_filter - -- Create `filter' - do - create {WSF_CORS_FILTER} filter - end - - setup_filter - -- Setup `filter' - local - l_routing_filter: WSF_ROUTING_FILTER - l_logging_filter: WSF_LOGGING_FILTER - do - create l_routing_filter.make (router) - l_routing_filter.set_execute_default_action (agent execute_default) - filter.set_next (l_routing_filter) - - create l_logging_filter - l_routing_filter.set_next (l_logging_filter) - end - - setup_router - -- Setup `router' - local - l_options_filter: WSF_CORS_OPTIONS_FILTER - l_authentication_filter: AUTHENTICATION_FILTER - l_user_filter: USER_HANDLER - l_methods: WSF_REQUEST_METHODS - do - create l_options_filter.make (router) - create l_authentication_filter - create l_user_filter - - l_options_filter.set_next (l_authentication_filter) - l_authentication_filter.set_next (l_user_filter) - - create l_methods - l_methods.enable_options - l_methods.enable_get - router.handle_with_request_methods ("/user/{userid}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent l_options_filter.execute), l_methods) - end - - initialize_json - -- Initialize `json'. - do - json.add_converter (create {JSON_USER_CONVERTER}.make) - end - feature {NONE} -- Implementation port: INTEGER = 9090 -- Port number note - copyright: "2011-2014, Olivier Ligot, Jocelyn Fiat and others" + copyright: "2011-2015, Olivier Ligot, Jocelyn Fiat and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/examples/filter/src/filter_server_execution.e b/examples/filter/src/filter_server_execution.e new file mode 100644 index 00000000..21727ede --- /dev/null +++ b/examples/filter/src/filter_server_execution.e @@ -0,0 +1,82 @@ +note + description : "Filter example." + author : "Olivier Ligot" + date : "$Date$" + revision : "$Revision$" + +class + FILTER_SERVER_EXECUTION + +inherit + WSF_FILTERED_ROUTED_EXECUTION + redefine + initialize + end + + SHARED_EJSON + +create + make + +feature {NONE} -- Initialization + + initialize + do + Precursor + initialize_json + end + + create_filter + -- Create `filter' + do + create {WSF_CORS_FILTER} filter + end + + setup_filter + -- Setup `filter' + local + l_logging_filter: WSF_LOGGING_FILTER + do + create l_logging_filter + filter.set_next (l_logging_filter) + end + + setup_router + -- Setup `router' + local + l_options_filter: WSF_CORS_OPTIONS_FILTER + l_authentication_filter: AUTHENTICATION_FILTER + l_user_filter: USER_HANDLER + l_methods: WSF_REQUEST_METHODS + do + create l_options_filter.make (router) + create l_authentication_filter + create l_user_filter + + l_options_filter.set_next (l_authentication_filter) + l_authentication_filter.set_next (l_user_filter) + + create l_methods + l_methods.enable_options + l_methods.enable_get + router.handle_with_request_methods ("/user/{userid}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent l_options_filter.execute), l_methods) + end + + initialize_json + -- Initialize `json'. + once + -- See SHARED_EJSON, and the once function per thread `json'. + json.add_converter (create {JSON_USER_CONVERTER}.make) + end + +note + copyright: "2011-2015, Olivier Ligot, Jocelyn Fiat and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/examples/filter/src/resource/user_handler.e b/examples/filter/src/resource/user_handler.e index 722ccd03..efcb6698 100644 --- a/examples/filter/src/resource/user_handler.e +++ b/examples/filter/src/resource/user_handler.e @@ -41,7 +41,7 @@ feature -- Basic operations local id : STRING do - if attached req.orig_path_info as orig_path then + if attached req.path_info as orig_path then id := get_user_id_from_path (orig_path) if attached retrieve_user (id) as l_user then if l_user ~ req.execution_variable ("user") then @@ -86,12 +86,14 @@ feature {NONE} -- Implementation retrieve_user (id: STRING) : detachable USER -- Retrieve the user by id if it exist, in other case, Void do - if id.is_integer and then Db_access.users.has (id.to_integer) then - Result := db_access.users.item (id.to_integer) + if id.is_integer then + Result := db_access.user_by_id (id.to_integer) + else + Result := db_access.user_by_name (id) end end note - copyright: "2011-2013, Olivier Ligot, Jocelyn Fiat and others" + copyright: "2011-2015, Olivier Ligot, Jocelyn Fiat and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" end diff --git a/examples/restbucksCRUD/src/restbucks_server.e b/examples/restbucksCRUD/src/restbucks_server.e index 588b2057..68b2e4c4 100644 --- a/examples/restbucksCRUD/src/restbucks_server.e +++ b/examples/restbucksCRUD/src/restbucks_server.e @@ -6,19 +6,7 @@ note class RESTBUCKS_SERVER inherit - - WSF_ROUTED_SKELETON_SERVICE - undefine - requires_proxy - end - - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE - - WSF_HANDLER_HELPER - - WSF_DEFAULT_SERVICE - - WSF_NO_PROXY_POLICY + WSF_DEFAULT_SERVICE [RESTBUCKS_SERVER_EXECUTION] create make @@ -27,26 +15,12 @@ feature {NONE} -- Initialization make do - initialize_router set_service_option ("port", 9090) make_and_launch end - setup_router - local - order_handler: ORDER_HANDLER - doc: WSF_ROUTER_SELF_DOCUMENTATION_HANDLER - do - create order_handler.make_with_router (router) - router.handle_with_request_methods ("/order", order_handler, router.methods_POST) - router.handle_with_request_methods ("/order/{orderid}", order_handler, router.methods_GET + router.methods_DELETE + router.methods_PUT) - create doc.make_hidden (router) - router.handle_with_request_methods ("/api/doc", doc, router.methods_GET) - end - - note - copyright: "2011-2013, Javier Velilla and others" + copyright: "2011-2015, Javier Velilla and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/examples/restbucksCRUD/src/restbucks_server_execution.e b/examples/restbucksCRUD/src/restbucks_server_execution.e new file mode 100644 index 00000000..1637d1c7 --- /dev/null +++ b/examples/restbucksCRUD/src/restbucks_server_execution.e @@ -0,0 +1,57 @@ +note + description : "REST Buck server" + date : "$Date$" + revision : "$Revision$" + +class RESTBUCKS_SERVER_EXECUTION + +inherit + + WSF_ROUTED_SKELETON_EXECUTION + undefine + requires_proxy + redefine + initialize + end + + WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + + WSF_HANDLER_HELPER + + WSF_NO_PROXY_POLICY + +create + make + +feature {NONE} -- Initialization + + initialize + do + Precursor + initialize_router + end + + setup_router + local + order_handler: ORDER_HANDLER + doc: WSF_ROUTER_SELF_DOCUMENTATION_HANDLER + do + create order_handler.make_with_router (router) + router.handle_with_request_methods ("/order", order_handler, router.methods_POST) + router.handle_with_request_methods ("/order/{orderid}", order_handler, router.methods_GET + router.methods_DELETE + router.methods_PUT) + create doc.make_hidden (router) + router.handle_with_request_methods ("/api/doc", doc, router.methods_GET) + end + + +note + copyright: "2011-2015, Javier Velilla and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/examples/simple/application.e b/examples/simple/application.e index 159f0cf4..d1de21d9 100644 --- a/examples/simple/application.e +++ b/examples/simple/application.e @@ -7,7 +7,7 @@ class APPLICATION inherit - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION] redefine initialize end @@ -23,14 +23,6 @@ feature {NONE} -- Initialization set_service_option ("port", 9090) end -feature -- Basic operations - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - do - -- To send a response we need to setup, the status code and - -- the response headers. - res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/plain"], ["Content-Length", "11"]>>) - res.put_string ("Hello World") - end end diff --git a/examples/simple/application_execution.e b/examples/simple/application_execution.e new file mode 100644 index 00000000..decbde71 --- /dev/null +++ b/examples/simple/application_execution.e @@ -0,0 +1,34 @@ +note + description : "simple application execution" + date : "$Date$" + revision : "$Revision$" + +class + APPLICATION_EXECUTION + +inherit + WSF_EXECUTION + +create + make + +feature -- Basic operations + + execute + local + s: STRING + do + -- To send a response we need to setup, the status code and + -- the response headers. + s := "Hello World!" + response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", s.count.out]>>) + response.set_status_code ({HTTP_STATUS_CODE}.ok) + response.header.put_content_type_text_html + response.header.put_content_length (s.count) + if attached request.http_connection as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") then + response.header.put_header_key_value ("Connection", "keep-alive") + end + response.put_string (s) + end + +end diff --git a/examples/simple/simple.ecf b/examples/simple/simple.ecf index 4bf050c9..1f7ea4c9 100644 --- a/examples/simple/simple.ecf +++ b/examples/simple/simple.ecf @@ -13,12 +13,12 @@ - + - + @@ -45,6 +45,6 @@ - + diff --git a/examples/simple_file/service_file.ecf b/examples/simple_file/service_file.ecf index 76534911..2a023343 100644 --- a/examples/simple_file/service_file.ecf +++ b/examples/simple_file/service_file.ecf @@ -6,8 +6,8 @@ - - + + diff --git a/examples/upload_image/src/image_uploader_execution.e b/examples/upload_image/src/image_uploader_execution.e index 84f51c87..68f1d22b 100644 --- a/examples/upload_image/src/image_uploader_execution.e +++ b/examples/upload_image/src/image_uploader_execution.e @@ -8,20 +8,19 @@ class IMAGE_UPLOADER_EXECUTION inherit - WSF_EXECUTION - redefine - initialize - end - WSF_ROUTED_SKELETON_EXECUTION undefine requires_proxy + redefine + initialize end WSF_NO_PROXY_POLICY WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + SHARED_EXECUTION_ENVIRONMENT + create make @@ -41,7 +40,7 @@ feature {NONE} -- Initialization map_uri_template_agent_with_request_methods ("/upload/{name}{?nb}", agent execute_upload_put, router.methods_put) map_uri_template_agent ("/upload{?nb}", agent execute_upload) - create www.make (document_root) + create www.make_with_path (document_root) www.set_directory_index (<<"index.html">>) www.set_not_found_handler (agent execute_not_found) router.handle_with_request_methods ("", www, router.methods_GET) @@ -49,31 +48,16 @@ feature {NONE} -- Initialization feature -- Configuration - document_root: READABLE_STRING_8 + document_root: PATH -- Document root to look for files or directories - local - e: EXECUTION_ENVIRONMENT - dn: DIRECTORY_NAME once - create e - create dn.make_from_string (e.current_working_directory) - dn.extend ("htdocs") - Result := dn.string - if Result [Result.count] = Operating_environment.directory_separator then - Result := Result.substring (1, Result.count - 1) - end - ensure - not Result.ends_with (Operating_environment.directory_separator.out) + Result := execution_environment.current_working_path.extended ("htdocs") end - files_root: READABLE_STRING_8 + files_root: PATH -- Uploaded files will be stored in `files_root' folder - local - dn: DIRECTORY_NAME once - create dn.make_from_string (document_root) - dn.extend ("files") - Result := dn.string + Result := document_root.extended ("files") end feature -- Execution @@ -109,8 +93,7 @@ feature -- Execution n := 1 end if attached {WSF_STRING} req.query_parameter ("demo") as p_demo then - create fn.make_from_string (document_root) - fn := fn.extended (p_demo.value) + fn := document_root.extended (p_demo.value) l_body.append ("File:
    %N") end @@ -134,9 +117,8 @@ feature -- Execution n := n + 1 l_body.append ("
  • ") l_body.append ("
    " + c.item.name + "=" + html_encode (c.item.filename) + " size=" + c.item.size.out + " type=" + c.item.content_type + "
    ") - create fn.make_from_string (files_root) l_safe_filename := c.item.safe_filename - fn := fn.extended (l_safe_filename) + fn := files_root.extended (l_safe_filename) if c.item.move_to (fn.name) then if c.item.content_type.starts_with ("image") then l_body.append ("%N") @@ -182,8 +164,7 @@ feature -- Execution if attached new_temporary_output_file ("tmp-uploaded-file_" + n.out) as f then req.read_input_data_into_file (f) f.close - create fn.make_from_string (files_root) - fn := fn.extended (l_safe_filename) + fn := files_root.extended (l_safe_filename) f.rename_file (fn.name) l_body.append ("
  • ") l_body.append ("
    Input data : size=" + f.count.out + " (" + req.content_length_value.out + ")
    ") diff --git a/library/security/openid/consumer/demo/application.e b/library/security/openid/consumer/demo/application.e index b74ef494..819fa640 100644 --- a/library/security/openid/consumer/demo/application.e +++ b/library/security/openid/consumer/demo/application.e @@ -8,17 +8,8 @@ class inherit - WSF_ROUTED_SKELETON_SERVICE - undefine - requires_proxy - end - - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE - WSF_SERVICE - WSF_NO_PROXY_POLICY - SHARED_EXECUTION_ENVIRONMENT export {NONE} all @@ -31,15 +22,13 @@ feature {NONE} -- Initialization make_and_launch local - launcher: WSF_NINO_SERVICE_LAUNCHER + launcher: WSF_NINO_SERVICE_LAUNCHER [APPLICATION_EXECUTION] opts: WSF_SERVICE_LAUNCHER_OPTIONS do - initialize_router - create opts.make opts.set_verbose (True) opts.set_option ("port", 0) - create launcher.make (Current, opts) + create launcher.make (opts) launcher.on_launched_actions.extend (agent on_launched) launcher.launch end @@ -49,7 +38,7 @@ feature {NONE} -- Initialization e: EXECUTION_ENVIRONMENT cmd: STRING_32 do - if attached {WGI_NINO_CONNECTOR} conn as nino then + if attached {WGI_NINO_CONNECTOR [APPLICATION_EXECUTION]} conn as nino then e := execution_environment create cmd.make (32) if attached e.item ("COMSPEC") as l_comspec then @@ -64,105 +53,4 @@ feature {NONE} -- Initialization end end - setup_router - do - map_uri_template_agent ("/", agent handle_root) - map_uri_template_agent ("/openid", agent handle_openid) - end - - handle_root (req: WSF_REQUEST; res: WSF_RESPONSE) - local - m: WSF_HTML_PAGE_RESPONSE - s: STRING - do - create m.make - m.set_title ("EWF::OpenID demo") - create s.make_empty - s.append ("
    %N") - s.append ("OpenID identifier ") - s.append ("") - s.append ("
    %N") - s.append ("
    %N") - s.append ("OpenID identifier ") - s.append ("") - s.append ("
    %N") - m.set_body (s) - res.send (m) - end - - handle_openid (req: WSF_REQUEST; res: WSF_RESPONSE) - local - m: WSF_HTML_PAGE_RESPONSE - redir: WSF_HTML_DELAYED_REDIRECTION_RESPONSE - s: STRING - o: OPENID_CONSUMER - v: OPENID_CONSUMER_VALIDATION - do - if attached req.string_item ("openid.mode") as l_openid_mode then - create m.make - m.set_title ("EWF::OpenID demo") - create s.make_empty - - if l_openid_mode.same_string ("id_res") then - o := new_openid_consumer (req) - create v.make_from_items (o, req.items_as_string_items) - v.validate - if v.is_valid then - s.append ("
    User authenticated
    ") - s.append ("
      Request items") - across - req.items as c - loop - s.append ("
    • " + c.item.url_encoded_name + "=" + c.item.string_representation + "
    • ") - end - s.append ("
    ") - s.append ("
      Attributes") - across - v.attributes as c - loop - s.append ("
    • " + c.key + "=" + c.item + "
    • ") - end - s.append ("
    ") - else - s.append ("
    User authentication failed!!!
    ") - end - else - s.append ("
    Unexpected OpenID.mode=" + l_openid_mode + "
    ") - end - m.set_body (s) - res.send (m) - elseif attached req.string_item ("openid_identifier") as l_id then - create s.make_empty - - o := new_openid_consumer (req) - s.append ("Testing " + l_id + "
    %N") - s.append ("Return-to" + o.return_url + "
    ") - if attached o.auth_url (l_id) as l_auth_url then - s.append ("Click to sign with " + l_id + "
    ") - create redir.make (l_auth_url, 1) - s.append ("Automatically follow link in " + redir.delay.out + " second(s)
    ") - redir.set_title ("EWF::OpenID demo") - redir.set_body (s) - res.send (redir) - else - create m.make - m.set_title ("EWF::OpenID demo") - m.set_body (s) - res.send (m) - end - else - res.redirect_now ("/") - end - end - - new_openid_consumer (req: WSF_REQUEST): OPENID_CONSUMER - do - create Result.make (req.absolute_script_url ("/openid")) - - Result.ask_email (True) - Result.ask_all_info (False) --- Result.ask_nickname (False) --- Result.ask_fullname (False) --- Result.ask_country (True) - end end diff --git a/library/security/openid/consumer/demo/application_execution.e b/library/security/openid/consumer/demo/application_execution.e new file mode 100644 index 00000000..bfac0f31 --- /dev/null +++ b/library/security/openid/consumer/demo/application_execution.e @@ -0,0 +1,131 @@ +note + description : "OPENID demo application root class" + date : "$Date$" + revision : "$Revision$" + +class + APPLICATION_EXECUTION + +inherit + + WSF_ROUTED_SKELETON_EXECUTION + undefine + requires_proxy + end + + WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + + WSF_NO_PROXY_POLICY + + SHARED_EXECUTION_ENVIRONMENT + export + {NONE} all + end + +create + make + +feature {NONE} -- Initialization + + setup_router + do + map_uri_template_agent ("/", agent handle_root) + map_uri_template_agent ("/openid", agent handle_openid) + end + + handle_root (req: WSF_REQUEST; res: WSF_RESPONSE) + local + m: WSF_HTML_PAGE_RESPONSE + s: STRING + do + create m.make + m.set_title ("EWF::OpenID demo") + create s.make_empty + s.append ("
    %N") + s.append ("OpenID identifier ") + s.append ("") + s.append ("
    %N") + s.append ("
    %N") + s.append ("OpenID identifier ") + s.append ("") + s.append ("
    %N") + m.set_body (s) + res.send (m) + end + + handle_openid (req: WSF_REQUEST; res: WSF_RESPONSE) + local + m: WSF_HTML_PAGE_RESPONSE + redir: WSF_HTML_DELAYED_REDIRECTION_RESPONSE + s: STRING + o: OPENID_CONSUMER + v: OPENID_CONSUMER_VALIDATION + do + if attached req.string_item ("openid.mode") as l_openid_mode then + create m.make + m.set_title ("EWF::OpenID demo") + create s.make_empty + + if l_openid_mode.same_string ("id_res") then + o := new_openid_consumer (req) + create v.make_from_items (o, req.items_as_string_items) + v.validate + if v.is_valid then + s.append ("
    User authenticated
    ") + s.append ("
      Request items") + across + req.items as c + loop + s.append ("
    • " + c.item.url_encoded_name + "=" + c.item.string_representation + "
    • ") + end + s.append ("
    ") + s.append ("
      Attributes") + across + v.attributes as c + loop + s.append ("
    • " + c.key + "=" + c.item + "
    • ") + end + s.append ("
    ") + else + s.append ("
    User authentication failed!!!
    ") + end + else + s.append ("
    Unexpected OpenID.mode=" + l_openid_mode + "
    ") + end + m.set_body (s) + res.send (m) + elseif attached req.string_item ("openid_identifier") as l_id then + create s.make_empty + + o := new_openid_consumer (req) + s.append ("Testing " + l_id + "
    %N") + s.append ("Return-to" + o.return_url + "
    ") + if attached o.auth_url (l_id) as l_auth_url then + s.append ("Click to sign with " + l_id + "
    ") + create redir.make (l_auth_url, 1) + s.append ("Automatically follow link in " + redir.delay.out + " second(s)
    ") + redir.set_title ("EWF::OpenID demo") + redir.set_body (s) + res.send (redir) + else + create m.make + m.set_title ("EWF::OpenID demo") + m.set_body (s) + res.send (m) + end + else + res.redirect_now ("/") + end + end + + new_openid_consumer (req: WSF_REQUEST): OPENID_CONSUMER + do + create Result.make (req.absolute_script_url ("/openid")) + + Result.ask_email (True) + Result.ask_all_info (False) +-- Result.ask_nickname (False) +-- Result.ask_fullname (False) +-- Result.ask_country (True) + end +end diff --git a/library/server/authentication/http_authorization/example/demo_basic.e b/library/server/authentication/http_authorization/example/demo_basic.e index fddbc3ee..f65a77bc 100644 --- a/library/server/authentication/http_authorization/example/demo_basic.e +++ b/library/server/authentication/http_authorization/example/demo_basic.e @@ -7,13 +7,11 @@ class DEMO_BASIC inherit - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [DEMO_BASIC_EXECUTION] redefine initialize end - SHARED_HTML_ENCODER - create make_and_launch @@ -26,210 +24,4 @@ feature {NONE} -- Initialization set_service_option ("verbose", True) end -feature -- Credentials - - is_known_login (a_login: READABLE_STRING_GENERAL): BOOLEAN - -- Is `a_login' a known username? - do - Result := valid_credentials.has (a_login) - end - - is_valid_credential (a_login: READABLE_STRING_GENERAL; a_password: detachable READABLE_STRING_GENERAL): BOOLEAN - -- Is `a_login:a_password' a valid credential? - do - if - a_password /= Void and - attached valid_credentials.item (a_login) as l_passwd - then - Result := a_password.is_case_insensitive_equal (l_passwd) - end - ensure - Result implies is_known_login (a_login) - end - - demo_credential: STRING_32 - -- First valid known credential display for demo in dialog. - do - valid_credentials.start - create Result.make_from_string_general (valid_credentials.key_for_iteration) - Result.append_character (':') - Result.append (valid_credentials.item_for_iteration) - end - - valid_credentials: STRING_TABLE [READABLE_STRING_32] - -- Password indexed by login. - once - create Result.make_caseless (3) - Result.force ("world", "eiffel") - Result.force ("bar", "foo") - Result.force ("password", "user") - ensure - not Result.is_empty - end - -feature -- Basic operations - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- - local - auth: HTTP_AUTHORIZATION - l_authenticated_username: detachable READABLE_STRING_32 - l_invalid_credential: BOOLEAN - do - if attached req.http_authorization as l_http_auth then - create auth.make (l_http_auth) - if attached auth.login as l_login and then is_valid_credential (l_login, auth.password) then - l_authenticated_username := auth.login - else - l_invalid_credential := True - end - end - if l_invalid_credential then - handle_unauthorized ("ERROR: Invalid credential", req, res) - else - if l_authenticated_username /= Void then - handle_authenticated (l_authenticated_username, req, res) - elseif req.path_info.same_string_general ("/login") then - handle_unauthorized ("Please provide credential ...", req, res) - elseif req.path_info.starts_with_general ("/protected/") then - -- any "/protected/*" url - handle_unauthorized ("Protected area, please sign in before", req, res) - else - handle_anonymous (req, res) - end - end - end - - handle_authenticated (a_username: READABLE_STRING_32; req: WSF_REQUEST; res: WSF_RESPONSE) - -- User `a_username' is authenticated, execute request `req' with response `res'. - require - valid_username: not a_username.is_empty - known_username: is_known_login (a_username) - local - s: STRING - page: WSF_HTML_PAGE_RESPONSE - do - create s.make_empty - - append_html_header (req, s) - - s.append ("

    The authenticated user is ") - s.append (html_encoder.general_encoded_string (a_username)) - s.append (" ...

    ") - - append_html_menu (a_username, req, s) - append_html_logout (a_username, req, s) - append_html_footer (req, s) - - create page.make - page.set_body (s) - res.send (page) - end - - handle_anonymous (req: WSF_REQUEST; res: WSF_RESPONSE) - -- No user is authenticated, execute request `req' with response `res'. - local - s: STRING - page: WSF_HTML_PAGE_RESPONSE - do - create s.make_empty - append_html_header (req, s) - - s.append ("Anonymous visitor ...
    ") - - append_html_login (req, s) - append_html_menu (Void, req, s) - append_html_footer (req, s) - - create page.make - page.set_body (s) - res.send (page) - end - - handle_unauthorized (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE) - -- Restricted page, authenticated user is required. - -- Send `a_description' as part of the response. - local - h: HTTP_HEADER - s: STRING - page: WSF_HTML_PAGE_RESPONSE - do - create s.make_from_string (a_description) - - append_html_login (req, s) - append_html_menu (Void, req, s) - append_html_footer (req, s) - - create page.make - page.set_status_code ({HTTP_STATUS_CODE}.unauthorized) - page.header.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, - "Basic realm=%"Please enter a valid username and password (demo [" + html_encoder.encoded_string (demo_credential) + "])%"" - --| warning: for this example: a valid credential is provided in the message, of course that for real application. - ) - page.set_body (s) - res.send (page) - end - -feature -- Helper - - append_html_header (req: WSF_REQUEST; s: STRING) - -- Append header paragraph to `s'. - do - s.append ("

    The current page is " + html_encoder.encoded_string (req.path_info) + "

    ") - end - - append_html_menu (a_username: detachable READABLE_STRING_32; req: WSF_REQUEST; s: STRING) - -- Append menu to `s'. - -- when an user is authenticated, `a_username' is attached. - do - if a_username /= Void then - s.append ("
  • Your account (displayed only is user is authenticated!)
  • ") - end - s.append ("
  • home
  • ") - s.append ("
  • public area
  • ") - s.append ("
  • protected area
  • ") - end - - append_html_login (req: WSF_REQUEST; s: STRING) - -- Append login link to `s'. - do - s.append ("
  • sign in
  • ") - end - - append_html_logout (a_username: detachable READABLE_STRING_32; req: WSF_REQUEST; s: STRING) - -- Append logout link to `s'. - local - l_logout_url: STRING - do - l_logout_url := req.absolute_script_url ("/login") - l_logout_url.replace_substring_all ("://", "://_@") -- Hack to clear http authorization, i.e connect with bad username "_". - s.append ("
  • logout
  • ") - end - - append_html_footer (req: WSF_REQUEST; s: STRING) - -- Append html footer to `s'. - local - hauth: HTTP_AUTHORIZATION - do - s.append ("
    ") - if attached req.http_authorization as l_http_authorization then - s.append ("Has Authorization: header: ") - create hauth.make (req.http_authorization) - if attached hauth.login as l_login then - s.append (" login=" + html_encoder.encoded_string (l_login)+ "") - end - if attached hauth.password as l_password then - s.append (" password=" + html_encoder.encoded_string (l_password)+ "") - end - s.append ("
    ") - end - if attached req.raw_header_data as l_header then - -- Append the raw header data for information - s.append ("Raw header data:") - s.append ("
    ")
    -				s.append (l_header)
    -				s.append ("
    ") - end - end - end diff --git a/library/server/authentication/http_authorization/example/demo_basic_execution.e b/library/server/authentication/http_authorization/example/demo_basic_execution.e new file mode 100644 index 00000000..47926411 --- /dev/null +++ b/library/server/authentication/http_authorization/example/demo_basic_execution.e @@ -0,0 +1,226 @@ +note + description : "simple application root class" + date : "$Date$" + revision : "$Revision$" + +class + DEMO_BASIC_EXECUTION + +inherit + WSF_EXECUTION + + SHARED_HTML_ENCODER + +create + make + +feature -- Credentials + + is_known_login (a_login: READABLE_STRING_GENERAL): BOOLEAN + -- Is `a_login' a known username? + do + Result := valid_credentials.has (a_login) + end + + is_valid_credential (a_login: READABLE_STRING_GENERAL; a_password: detachable READABLE_STRING_GENERAL): BOOLEAN + -- Is `a_login:a_password' a valid credential? + do + if + a_password /= Void and + attached valid_credentials.item (a_login) as l_passwd + then + Result := a_password.is_case_insensitive_equal (l_passwd) + end + ensure + Result implies is_known_login (a_login) + end + + demo_credential: STRING_32 + -- First valid known credential display for demo in dialog. + do + valid_credentials.start + create Result.make_from_string_general (valid_credentials.key_for_iteration) + Result.append_character (':') + Result.append (valid_credentials.item_for_iteration) + end + + valid_credentials: STRING_TABLE [READABLE_STRING_32] + -- Password indexed by login. + once + create Result.make_caseless (3) + Result.force ("world", "eiffel") + Result.force ("bar", "foo") + Result.force ("password", "user") + ensure + not Result.is_empty + end + +feature -- Basic operations + + execute + -- + local + auth: HTTP_AUTHORIZATION + l_authenticated_username: detachable READABLE_STRING_32 + l_invalid_credential: BOOLEAN + req: WSF_REQUEST + res: WSF_RESPONSE + do + req := request + res := response + if attached req.http_authorization as l_http_auth then + create auth.make (l_http_auth) + if attached auth.login as l_login and then is_valid_credential (l_login, auth.password) then + l_authenticated_username := auth.login + else + l_invalid_credential := True + end + end + if l_invalid_credential then + handle_unauthorized ("ERROR: Invalid credential", req, res) + else + if l_authenticated_username /= Void then + handle_authenticated (l_authenticated_username, req, res) + elseif req.path_info.same_string_general ("/login") then + handle_unauthorized ("Please provide credential ...", req, res) + elseif req.path_info.starts_with_general ("/protected/") then + -- any "/protected/*" url + handle_unauthorized ("Protected area, please sign in before", req, res) + else + handle_anonymous (req, res) + end + end + end + + handle_authenticated (a_username: READABLE_STRING_32; req: WSF_REQUEST; res: WSF_RESPONSE) + -- User `a_username' is authenticated, execute request `req' with response `res'. + require + valid_username: not a_username.is_empty + known_username: is_known_login (a_username) + local + s: STRING + page: WSF_HTML_PAGE_RESPONSE + do + create s.make_empty + + append_html_header (req, s) + + s.append ("

    The authenticated user is ") + s.append (html_encoder.general_encoded_string (a_username)) + s.append (" ...

    ") + + append_html_menu (a_username, req, s) + append_html_logout (a_username, req, s) + append_html_footer (req, s) + + create page.make + page.set_body (s) + res.send (page) + end + + handle_anonymous (req: WSF_REQUEST; res: WSF_RESPONSE) + -- No user is authenticated, execute request `req' with response `res'. + local + s: STRING + page: WSF_HTML_PAGE_RESPONSE + do + create s.make_empty + append_html_header (req, s) + + s.append ("Anonymous visitor ...
    ") + + append_html_login (req, s) + append_html_menu (Void, req, s) + append_html_footer (req, s) + + create page.make + page.set_body (s) + res.send (page) + end + + handle_unauthorized (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE) + -- Restricted page, authenticated user is required. + -- Send `a_description' as part of the response. + local + s: STRING + page: WSF_HTML_PAGE_RESPONSE + do + create s.make_from_string (a_description) + + append_html_login (req, s) + append_html_menu (Void, req, s) + append_html_footer (req, s) + + create page.make + page.set_status_code ({HTTP_STATUS_CODE}.unauthorized) + page.header.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, + "Basic realm=%"Please enter a valid username and password (demo [" + html_encoder.encoded_string (demo_credential) + "])%"" + --| warning: for this example: a valid credential is provided in the message, of course that for real application. + ) + page.set_body (s) + res.send (page) + end + +feature -- Helper + + append_html_header (req: WSF_REQUEST; s: STRING) + -- Append header paragraph to `s'. + do + s.append ("

    The current page is " + html_encoder.encoded_string (req.path_info) + "

    ") + end + + append_html_menu (a_username: detachable READABLE_STRING_32; req: WSF_REQUEST; s: STRING) + -- Append menu to `s'. + -- when an user is authenticated, `a_username' is attached. + do + if a_username /= Void then + s.append ("
  • Your account (displayed only is user is authenticated!)
  • ") + end + s.append ("
  • home
  • ") + s.append ("
  • public area
  • ") + s.append ("
  • protected area
  • ") + end + + append_html_login (req: WSF_REQUEST; s: STRING) + -- Append login link to `s'. + do + s.append ("
  • sign in
  • ") + end + + append_html_logout (a_username: detachable READABLE_STRING_32; req: WSF_REQUEST; s: STRING) + -- Append logout link to `s'. + local + l_logout_url: STRING + do + l_logout_url := req.absolute_script_url ("/login") + l_logout_url.replace_substring_all ("://", "://_@") -- Hack to clear http authorization, i.e connect with bad username "_". + s.append ("
  • logout
  • ") + end + + append_html_footer (req: WSF_REQUEST; s: STRING) + -- Append html footer to `s'. + local + hauth: HTTP_AUTHORIZATION + do + s.append ("
    ") + if attached req.http_authorization as l_http_authorization then + s.append ("Has Authorization: header: ") + create hauth.make (req.http_authorization) + if attached hauth.login as l_login then + s.append (" login=" + html_encoder.encoded_string (l_login)+ "") + end + if attached hauth.password as l_password then + s.append (" password=" + html_encoder.encoded_string (l_password)+ "") + end + s.append ("
    ") + end + if attached req.raw_header_data as l_header then + -- Append the raw header data for information + s.append ("Raw header data:") + s.append ("
    ")
    +				s.append (l_header)
    +				s.append ("
    ") + end + end + +end diff --git a/library/server/ewsgi/connectors/nino/src/nino_service.e b/library/server/ewsgi/connectors/nino/src/nino_service.e index 8f596a28..4dcaabeb 100644 --- a/library/server/ewsgi/connectors/nino/src/nino_service.e +++ b/library/server/ewsgi/connectors/nino/src/nino_service.e @@ -26,23 +26,6 @@ feature {NONE} -- Implementation create connector.make_with_base (a_base_url) end --- make_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]) --- -- Initialize `Current'. --- do --- make_custom_with_callback (a_callback, Void) --- end - --- make_custom_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]; a_base_url: detachable STRING) --- -- Initialize `Current'. --- require --- base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/") --- local --- app: WGI_AGENT_SERVICE --- do --- create app.make (a_callback) --- make_custom (app, a_base_url) --- end - feature -- Access connector: WGI_NINO_CONNECTOR [G] diff --git a/library/server/ewsgi/connectors/httpd/dev/app_counter.e b/library/server/ewsgi/connectors/standalone/dev/app_counter.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/dev/app_counter.e rename to library/server/ewsgi/connectors/standalone/dev/app_counter.e diff --git a/library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e b/library/server/ewsgi/connectors/standalone/dev/app_wsf_execution.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/dev/app_wsf_execution.e rename to library/server/ewsgi/connectors/standalone/dev/app_wsf_execution.e diff --git a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/standalone/dev/httpd_connector_dev.e similarity index 68% rename from library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e rename to library/server/ewsgi/connectors/standalone/dev/httpd_connector_dev.e index 9353f5c3..d299ec48 100644 --- a/library/server/ewsgi/connectors/httpd/dev/httpd_connector_dev.e +++ b/library/server/ewsgi/connectors/standalone/dev/httpd_connector_dev.e @@ -17,16 +17,27 @@ feature {NONE} -- Initialization make -- Initialize `Current'. local - conn: WGI_HTTPD_CONNECTOR [APP_WSF_EXECUTION] + conn: WGI_STANDALONE_CONNECTOR [APP_WSF_EXECUTION] do print ("Starting httpd server ...%N") create conn.make + conn.on_launched_actions.extend (agent on_launched) conn.set_port_number (9090) conn.set_max_concurrent_connections (100) conn.launch end + on_launched (conn: WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]) + do + print ("Server listening on port " + conn.port.out + "%N") + end + + on_stopped (conn: WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]) + do + print ("Server terminated%N") + end + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/httpd/license.lic b/library/server/ewsgi/connectors/standalone/license.lic similarity index 100% rename from library/server/ewsgi/connectors/httpd/license.lic rename to library/server/ewsgi/connectors/standalone/license.lic diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_connection_handler.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler_factory.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/none/httpd_request_handler_factory.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler_factory.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler_factory.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler_factory.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler_factory.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_connection_handler.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_connection_handler.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_connection_handler.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler_factory.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/httpd_request_handler_factory.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler_factory.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/pooled_thread.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/pool/pooled_thread.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/pooled_thread.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/pool/pooled_thread.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/thread_pool.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/pool/thread_pool.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/concurrency/thread/pool/thread_pool.e rename to library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/pool/thread_pool.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/configuration/httpd_configuration_i.e rename to library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/standalone/src/httpd/httpd-safe.ecf similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd-safe.ecf rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd-safe.ecf diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd.ecf b/library/server/ewsgi/connectors/standalone/src/httpd/httpd.ecf similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd.ecf rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd.ecf diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_controller.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_controller.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_controller.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_controller.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_debug_facilities.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_debug_facilities.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_debug_facilities.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_logger.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_logger.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_factory_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_factory_i.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_factory_i.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_factory_i.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e similarity index 71% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index 8d85e5f0..b27bb173 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -19,14 +19,19 @@ feature {NONE} -- Initialization reset do - has_error := False - version := Void - remote_info := Void + reset_request + has_error := False if attached internal_client_socket as l_sock then l_sock.cleanup end internal_client_socket := Void + end + + reset_request + do + version := Void + remote_info := Void -- FIXME: optimize to just wipe_out if needed create method.make_empty @@ -34,6 +39,7 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) + keep_alive_enabled := False end feature -- Status report @@ -79,6 +85,24 @@ feature -- Access remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER] -- Information related to remote client + keep_alive_enabled: BOOLEAN + -- Inside a persistent connection? + + is_http_version_1_0: BOOLEAN + do + Result := not attached version as v or else v.same_string ("HTTP/1.0") + end + + is_http_version_1_1: BOOLEAN + do + Result := not attached version as v or else v.same_string ("HTTP/1.1") + end + + is_http_version_2: BOOLEAN + do + Result := not attached version as v or else v.same_string ("HTTP/2.0") + end + feature -- Settings is_verbose: BOOLEAN @@ -93,6 +117,7 @@ feature -- Change set_is_verbose (b: BOOLEAN) do is_verbose := b + print ("set_is_verbose " + b.out + "%N") end feature -- Execution @@ -118,6 +143,33 @@ feature -- Execution end execute + require + is_connected: is_connected + local + l_socket: like client_socket + l_exit: BOOLEAN + n: INTEGER + do + l_socket := client_socket + check + socket_attached: l_socket /= Void + socket_valid: l_socket.is_open_read and then l_socket.is_open_write + end + from + -- Process persistent connection as long the socket is not closed. + n := 0 + until + l_exit + loop + n := n + 1 + -- FIXME: it seems to be called one more time, mostly to see this is done. + execute_request + l_exit := has_error or l_socket.is_closed or not l_socket.is_open_read or not keep_alive_enabled + reset_request + end + end + + execute_request require is_connected: is_connected local @@ -132,14 +184,15 @@ feature -- Execution end if l_socket.is_closed then debug ("dbglog") - dbglog (generator + ".execute {socket is Closed!}") + dbglog (generator + ".execute_request {socket is Closed!}") end else debug ("dbglog") - dbglog (generator + ".execute socket=" + l_socket.descriptor.out + " ENTER") + dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER") end from until l_continue loop - if l_socket.ready_for_reading then + if l_socket.try_ready_for_reading then +-- ready_for_reading then l_continue := True create l_remote_info if attached l_socket.peer_address as l_addr then @@ -150,7 +203,11 @@ feature -- Execution end analyze_request_message (l_socket) else - log (generator + ".execute socket=" + l_socket.descriptor.out + "} WAITING") + has_error := True + l_continue := True + debug ("dbglog") + dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + "} WAITING") + end end end @@ -164,7 +221,7 @@ feature -- Execution process_request (l_socket) end debug ("dbglog") - dbglog (generator + ".execute {" + l_socket.descriptor.out + "} LEAVE") + dbglog (generator + ".execute_request {" + l_socket.descriptor.out + "} LEAVE") end end end @@ -243,6 +300,22 @@ feature -- Parsing line := next_line (a_socket) end end + if not {HTTPD_SERVER}.is_persistent_connection_supported then + keep_alive_enabled := False + elseif is_http_version_1_0 then + keep_alive_enabled := attached request_header_map.item ("Connection") as l_connection and then + l_connection.is_case_insensitive_equal_general ("keep-alive") + else + -- By default HTTP:1/1 support persistent connection. + if + attached request_header_map.item ("Connection") as l_connection and then + l_connection.is_case_insensitive_equal_general ("close") + then + keep_alive_enabled := False + else + keep_alive_enabled := True + end + end end end @@ -251,7 +324,7 @@ feature -- Parsing require valid_line: line /= Void and then not line.is_empty local - pos, next_pos: INTEGER + n, pos, next_pos: INTEGER do if is_verbose then log ("%N## Parse HTTP request line ##") @@ -261,7 +334,11 @@ feature -- Parsing method := line.substring (1, pos - 1) next_pos := line.index_of (' ', pos + 1) uri := line.substring (pos + 1, next_pos - 1) - version := line.substring (next_pos + 1, line.count) + n := line.count + if line[n] = '%R' then + n := n - 1 + end + version := line.substring (next_pos + 1, n) has_error := method.is_empty end @@ -269,11 +346,18 @@ feature -- Parsing -- Next line fetched from `a_socket' is available. require is_readable: a_socket.is_open_read + local + retried: BOOLEAN do - if a_socket.socket_ok then + if retried then + Result := Void + elseif a_socket.socket_ok then a_socket.read_line_thread_aware Result := a_socket.last_string end + rescue + retried := True + retry end feature -- Output diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e similarity index 88% rename from library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e rename to library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e index 86205296..2c3d9c6c 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e @@ -58,6 +58,19 @@ feature -- Access factory: separate HTTPD_REQUEST_HANDLER_FACTORY + is_persistent_connection_supported: BOOLEAN = False + -- Is persistent connection supported? + --| For now, disabled during dev. + +feature -- Callbacks + + observer: detachable separate HTTPD_SERVER_OBSERVER + + set_observer (obs: like observer) + do + observer := obs + end + feature -- Access: listening port: INTEGER @@ -91,22 +104,10 @@ feature -- Execution end is_shutdown_requested := False listen + is_terminated := True on_terminated end - on_terminated - require - is_terminated - do - if is_terminated then - log ("%N%NTerminating Web Application Server (port="+ port.out +"):%N") - end - if attached output as o then - o.flush - o.close - end - end - shutdown_server do debug ("dbglog") @@ -251,8 +252,12 @@ feature -- Event require not_launched: not is_launched do +-- print ("port=" + a_port.out + "%N") is_launched := True port := a_port + if attached observer as obs then + observer_on_launched (obs, a_port) + end ensure is_launched: is_launched end @@ -262,10 +267,43 @@ feature -- Event require is_launched: is_launched do - is_launched := False - is_terminated := True - ensure - stopped: not is_launched + if attached observer as obs then + observer_on_stopped (obs) + end + end + + on_terminated + -- Server terminated + require + is_terminated + do + if is_terminated and is_verbose then + log ("%N%NTerminating Web Application Server (port="+ port.out +"):%N") + end + if attached output as o then + o.flush + o.close + end + if attached observer as obs then + observer_on_terminated (obs) + end + end + +feature {NONE} -- Separate event + + observer_on_launched (obs: attached like observer; a_port: INTEGER) + do + obs.on_launched (a_port) + end + + observer_on_stopped (obs: attached like observer) + do + obs.on_stopped + end + + observer_on_terminated (obs: attached like observer) + do + obs.on_terminated end feature -- Configuration change diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e new file mode 100644 index 00000000..3c64c812 --- /dev/null +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e @@ -0,0 +1,24 @@ +note + description: "Summary description for {HTTPD_SERVER_OBSERVER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_SERVER_OBSERVER + +feature -- Event + + on_launched (a_port: INTEGER) + deferred + end + + on_stopped + deferred + end + + on_terminated + deferred + end + +end diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/network/httpd_stream_socket.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e rename to library/server/ewsgi/connectors/standalone/src/httpd/network/httpd_stream_socket.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/network/tcp_stream_socket.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e rename to library/server/ewsgi/connectors/standalone/src/httpd/network/tcp_stream_socket.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_configuration.e b/library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_configuration.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_configuration.e rename to library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_configuration.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_server.e b/library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_server.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/no_ssl/httpd_server.e rename to library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_server.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_configuration.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_configuration.e rename to library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_server.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_server.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_server.e rename to library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_server.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_stream_ssl_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_stream_ssl_socket.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/ssl/httpd_stream_ssl_socket.e rename to library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_stream_ssl_socket.e diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/ssl/ssl_tcp_stream_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e similarity index 100% rename from library/server/ewsgi/connectors/httpd/src/httpd/ssl/ssl_tcp_stream_socket.e rename to library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e similarity index 92% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e rename to library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e index de6863ad..c709ec8d 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e @@ -26,9 +26,14 @@ feature {NONE} -- Initialization do make connector := conn +-- if conn /= Void then +-- set_is_verbose (is_connector_verbose (conn)) +-- end end - connector: detachable separate WGI_HTTPD_CONNECTOR [G] +feature -- Access + + connector: detachable separate WGI_STANDALONE_CONNECTOR [G] base: detachable IMMUTABLE_STRING_8 do @@ -39,11 +44,18 @@ feature {NONE} -- Initialization end end - connector_base (conn: separate WGI_HTTPD_CONNECTOR [G]): detachable separate READABLE_STRING_8 +feature -- SCOOP helpers + + connector_base (conn: separate WGI_STANDALONE_CONNECTOR [G]): detachable separate READABLE_STRING_8 do Result := conn.base end + is_connector_verbose (conn: separate WGI_STANDALONE_CONNECTOR [G]): BOOLEAN + do + Result := conn.is_verbose + end + feature -- Request processing process_request (a_socket: HTTPD_STREAM_SOCKET) @@ -53,14 +65,14 @@ feature -- Request processing l_output: WGI_OUTPUT_STREAM l_error: WGI_ERROR_STREAM req: WGI_REQUEST_FROM_TABLE - res: detachable WGI_HTTPD_RESPONSE_STREAM + res: detachable WGI_STANDALONE_RESPONSE_STREAM exec: detachable WGI_EXECUTION retried: BOOLEAN do if not retried then - create {WGI_HTTPD_INPUT_STREAM} l_input.make (a_socket) - create {WGI_HTTPD_OUTPUT_STREAM} l_output.make (a_socket) - create {WGI_HTTPD_ERROR_STREAM} l_error.make_stderr (a_socket.descriptor.out) + create {WGI_STANDALONE_INPUT_STREAM} l_input.make (a_socket) + create {WGI_STANDALONE_OUTPUT_STREAM} l_output.make (a_socket) + create {WGI_STANDALONE_ERROR_STREAM} l_error.make_stderr (a_socket.descriptor.out) create req.make (httpd_environment (a_socket), l_input, connector) create res.make (l_output, l_error) diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e similarity index 93% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e rename to library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e index f69d0893..2570bc00 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e @@ -12,7 +12,7 @@ inherit feature -- Access - connector: detachable separate WGI_HTTPD_CONNECTOR [G] + connector: detachable separate WGI_STANDALONE_CONNECTOR [G] feature -- Element change diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e similarity index 71% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e rename to library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e index 5f5f0b06..541b58a8 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_connector.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_HTTPD_CONNECTOR}." + description: "Summary description for {WGI_STANDALONE_CONNECTOR}." author: "" todo: "[ Check if server and configuration has to be 'separate' ? @@ -11,7 +11,7 @@ note revision: "$Revision$" class - WGI_HTTPD_CONNECTOR [G -> WGI_EXECUTION create make end] + WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end] inherit WGI_CONNECTOR @@ -28,14 +28,15 @@ feature {NONE} -- Initialization do -- Callbacks create on_launched_actions - create on_stopped_actions -- Server create fac create server.make (fac) + create observer configuration := server_configuration (server) - + controller := server_controller (server) set_factory_connector (Current, fac) + initialize_server (server) end make_with_base (a_base: like base) @@ -46,11 +47,23 @@ feature {NONE} -- Initialization set_base (a_base) end - set_factory_connector (conn: detachable separate WGI_HTTPD_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) + initialize_server (a_server: like server) + do + a_server.set_observer (observer) + end + +feature {NONE} -- Separate helper + + set_factory_connector (conn: detachable separate WGI_STANDALONE_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) do fac.set_connector (conn) end + server_configuration (a_server: like server): like configuration + do + Result := a_server.configuration + end + feature -- Access name: STRING_8 = "httpd" @@ -63,12 +76,11 @@ feature -- Access server: separate HTTPD_SERVER - configuration: separate HTTPD_CONFIGURATION + controller: separate HTTPD_CONTROLLER - server_configuration (a_server: like server): like configuration - do - Result := a_server.configuration - end + observer: separate WGI_STANDALONE_SERVER_OBSERVER + + configuration: separate HTTPD_CONFIGURATION feature -- Access @@ -82,17 +94,17 @@ feature -- Status report port: INTEGER -- Listening port. - --| 0: not launched + --| 0: not launched + + is_verbose: BOOLEAN + -- Is verbose? feature -- Callbacks - on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]]] -- Actions triggered when launched - on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] - -- Actions triggered when stopped - -feature -- Element change +feature -- Event on_launched (a_port: INTEGER) -- Server launched @@ -102,14 +114,6 @@ feature -- Element change on_launched_actions.call ([Current]) end - on_stopped - -- Server stopped - do - on_stopped_actions.call ([Current]) - launched := False - port := 0 - end - feature -- Element change set_base (b: like base) @@ -154,6 +158,7 @@ feature {NONE} -- Implementation set_is_verbose_on_configuration (b: BOOLEAN; cfg: like configuration) do + is_verbose := b cfg.set_is_verbose (b) end @@ -164,6 +169,29 @@ feature -- Server launched := False port := 0 launch_server (server) + on_server_started (observer) + end + + shutdown_server + do + if launched then + -- FIXME jfiat [2015/03/27] : prevent multiple calls (otherwise it hangs) + separate_shutdown_server_on_controller (controller) + end + end + + server_controller (a_server: like server): separate HTTPD_CONTROLLER + do + Result := a_server.controller + end + + on_server_started (obs: like observer) + require + obs.started + do + if obs.port > 0 then + on_launched (obs.port) + end end configure_server (a_configuration: like configuration) @@ -181,6 +209,19 @@ feature -- Server a_server.launch end +feature {NONE} -- Implementation + + separate_server_terminated (a_server: like server): BOOLEAN + do + Result := a_server.is_terminated + end + + separate_shutdown_server_on_controller (a_controller: separate HTTPD_CONTROLLER) + do + a_controller.shutdown + end + + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e similarity index 87% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e rename to library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e index 3cb84e31..8c48d2ab 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_error_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for WGI_HTTPD_ERROR_STREAM." + description: "Summary description for WGI_STANDALONE_ERROR_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - WGI_HTTPD_ERROR_STREAM + WGI_STANDALONE_ERROR_STREAM inherit WGI_ERROR_STREAM @@ -58,7 +58,7 @@ feature -- Error end note - copyright: "2011-2011, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e similarity index 92% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e rename to library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e index ce34a558..fbfa2b0b 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_input_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for {WGI_HTTPD_INPUT_STREAM}." + description: "Summary description for {WGI_STANDALONE_INPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - WGI_HTTPD_INPUT_STREAM + WGI_STANDALONE_INPUT_STREAM inherit WGI_INPUT_STREAM @@ -22,7 +22,7 @@ feature {NONE} -- Initialization set_source (a_source) end -feature {WGI_HTTPD_CONNECTOR, WGI_SERVICE} -- Nino +feature {WGI_STANDALONE_CONNECTOR, WGI_SERVICE} -- Nino set_source (i: like source) do diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e similarity index 92% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e rename to library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e index c581bc79..b5ca291e 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_output_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for {WGI_HTTPD_OUTPUT_STREAM}." + description: "Summary description for {WGI_STANDALONE_OUTPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - WGI_HTTPD_OUTPUT_STREAM + WGI_STANDALONE_OUTPUT_STREAM inherit WGI_OUTPUT_STREAM @@ -26,7 +26,7 @@ feature {NONE} -- Initialization set_target (a_target) end -feature {WGI_HTTPD_CONNECTOR, WGI_SERVICE} -- Nino +feature {WGI_STANDALONE_CONNECTOR, WGI_SERVICE} -- Nino set_target (o: like target) do diff --git a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e similarity index 72% rename from library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e rename to library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e index acc8a3cd..9c9ab699 100644 --- a/library/server/ewsgi/connectors/httpd/src/wgi_httpd_response_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e @@ -7,7 +7,7 @@ note revision: "$Revision$" class - WGI_HTTPD_RESPONSE_STREAM + WGI_STANDALONE_RESPONSE_STREAM inherit WGI_RESPONSE_STREAM @@ -27,9 +27,11 @@ feature -- Header output operation o := output o.put_string (a_text) - -- Nino does not support persistent connection for now - o.put_string ("Connection: close") - o.put_crlf + if not {HTTPD_SERVER}.is_persistent_connection_supported then + -- standalone does not support persistent connection for now + o.put_string ("Connection: close") + o.put_crlf + end -- end of headers o.put_crlf @@ -38,7 +40,7 @@ feature -- Header output operation end ;note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e similarity index 53% rename from library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e rename to library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e index e2c3c00f..b36d0fb7 100644 --- a/library/server/ewsgi/connectors/httpd/dev/app_wsf_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e @@ -1,28 +1,45 @@ note - description: "Summary description for {APP_WSF_HTTPD_REQUEST_HANDLER}." + description: "Summary description for {WGI_STANDALONE_SERVER_OBSERVER}." author: "" date: "$Date$" revision: "$Revision$" class - APP_WSF_HTTPD_REQUEST_HANDLER + WGI_STANDALONE_SERVER_OBSERVER inherit - WSF_HTTPD_REQUEST_HANDLER + HTTPD_SERVER_OBSERVER -create - make +feature -- Access -feature -- Execute + started: BOOLEAN - do_more (req: WGI_REQUEST; res: WGI_RESPONSE) - local - exec: WSF_EXECUTION + stopped: BOOLEAN + + terminated: BOOLEAN + + port: INTEGER + +feature -- Event + + on_launched (a_port: INTEGER) do - create {APP_WSF_EXECUTION} exec.make (req, res) - exec.execute + started := True + port := a_port end + on_stopped + do + stopped := True + end + + on_terminated + do + port := 0 + terminated := True + end + + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf b/library/server/ewsgi/connectors/standalone/standalone-safe.ecf similarity index 68% rename from library/server/ewsgi/connectors/httpd/httpd-safe.ecf rename to library/server/ewsgi/connectors/standalone/standalone-safe.ecf index 0213ebef..acf1c95f 100644 --- a/library/server/ewsgi/connectors/httpd/httpd-safe.ecf +++ b/library/server/ewsgi/connectors/standalone/standalone-safe.ecf @@ -1,13 +1,13 @@ - - + + /EIFGENs$ /\.git$ /\.svn$ - @@ -16,16 +16,14 @@ - - - - /httpd$ - + + + - + - @@ -33,10 +31,10 @@ - + - + diff --git a/library/server/ewsgi/connectors/standalone/standalone.ecf b/library/server/ewsgi/connectors/standalone/standalone.ecf new file mode 100644 index 00000000..3349c7ec --- /dev/null +++ b/library/server/ewsgi/connectors/standalone/standalone.ecf @@ -0,0 +1,23 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + diff --git a/library/server/ewsgi/examples/hello_world/src/hello_world.e b/library/server/ewsgi/examples/hello_world/src/hello_world.e index d66c934d..b48667eb 100644 --- a/library/server/ewsgi/examples/hello_world/src/hello_world.e +++ b/library/server/ewsgi/examples/hello_world/src/hello_world.e @@ -18,20 +18,13 @@ feature {NONE} -- Initialization make do print ("Example: start a Nino web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:8123/%N") - (create {NINO_SERVICE}.make_custom (Current, "")).listen (port_number) - end - - execute (req: WGI_REQUEST; res: WGI_RESPONSE) - do - res.set_status_code (200, Void) - res.put_header_text ("Content-Type: text/plain%R%N") - res.put_string ("Hello World!%N") + (create {NINO_SERVICE [HELLO_WORLD_EXECUTION]}.make_custom ("")).listen (port_number) end port_number: INTEGER = 8123 note - copyright: "2011-2012, Eiffel Software and others" + copyright: "2011-2015, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/examples/hello_world/src/hello_world_execution.e b/library/server/ewsgi/examples/hello_world/src/hello_world_execution.e new file mode 100644 index 00000000..5ecbc814 --- /dev/null +++ b/library/server/ewsgi/examples/hello_world/src/hello_world_execution.e @@ -0,0 +1,36 @@ +note + description: "Summary description for {HELLO_WORLD_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + HELLO_WORLD_EXECUTION + +inherit + WGI_EXECUTION + +create + make + +feature {NONE} -- Initialization + + execute + do + response.set_status_code (200, Void) + response.put_header_text ("Content-Type: text/plain%R%N") + response.put_string ("Hello World!%N") + end + +note + copyright: "2011-2015, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end + diff --git a/library/server/wsf/default/nino/wsf_default_response_service.e b/library/server/ewsgi/specification/connector/wgi_execution_factory.e similarity index 68% rename from library/server/wsf/default/nino/wsf_default_response_service.e rename to library/server/ewsgi/specification/connector/wgi_execution_factory.e index db3fddc6..d0df1af0 100644 --- a/library/server/wsf/default/nino/wsf_default_response_service.e +++ b/library/server/ewsgi/specification/connector/wgi_execution_factory.e @@ -1,15 +1,17 @@ note - description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." + description: "Summary description for {WGI_EXECUTION_FACTORY}." + author: "" date: "$Date$" revision: "$Revision$" deferred class - WSF_DEFAULT_RESPONSE_SERVICE [G -> WSF_EXECUTION create make end] + WGI_EXECUTION_FACTORY -inherit - WSF_DEFAULT_SERVICE [G] +feature -- Factory - WSF_RESPONSE_SERVICE [G] + execution (req: WGI_REQUEST; res: WGI_RESPONSE): WGI_EXECUTION + deferred + end note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" diff --git a/library/server/ewsgi/specification/request/wgi_request_cgi_variables.e b/library/server/ewsgi/specification/request/wgi_request_cgi_variables.e index a969dfad..cd588e35 100644 --- a/library/server/ewsgi/specification/request/wgi_request_cgi_variables.e +++ b/library/server/ewsgi/specification/request/wgi_request_cgi_variables.e @@ -22,13 +22,13 @@ feature {NONE} -- Initialization local utf: UTF_CONVERTER do - auth_type := req.auth_type content_length := req.content_length if attached req.content_type as ct then content_type := ct.string else content_type := Void end + auth_type := req.auth_type gateway_interface := req.gateway_interface path_info := req.path_info path_translated := req.path_translated diff --git a/library/server/wsf/connector/openshift/wsf_openshift_service_launcher.e b/library/server/wsf/connector/openshift/wsf_openshift_service_launcher.e index 5e262ae9..4fe7c19b 100644 --- a/library/server/wsf/connector/openshift/wsf_openshift_service_launcher.e +++ b/library/server/wsf/connector/openshift/wsf_openshift_service_launcher.e @@ -16,10 +16,10 @@ note revision: "$Revision$" class - WSF_OPENSHIFT_SERVICE_LAUNCHER + WSF_OPENSHIFT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_NINO_SERVICE_LAUNCHER + WSF_NINO_SERVICE_LAUNCHER [G] redefine initialize end @@ -31,9 +31,7 @@ inherit create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch feature {NONE} -- Initialization @@ -86,7 +84,7 @@ feature {NONE} -- Implementation ;note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/connector/httpd-safe.ecf b/library/server/wsf/connector/standalone-safe.ecf similarity index 77% rename from library/server/wsf/connector/httpd-safe.ecf rename to library/server/wsf/connector/standalone-safe.ecf index c5d577f6..7ad62d20 100644 --- a/library/server/wsf/connector/httpd-safe.ecf +++ b/library/server/wsf/connector/standalone-safe.ecf @@ -1,6 +1,6 @@ - - + + /EIFGENs$ @@ -10,13 +10,13 @@ - + - + diff --git a/library/server/wsf/connector/standalone.ecf b/library/server/wsf/connector/standalone.ecf new file mode 100644 index 00000000..63d5cd22 --- /dev/null +++ b/library/server/wsf/connector/standalone.ecf @@ -0,0 +1,22 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + diff --git a/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e b/library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e similarity index 85% rename from library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e rename to library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e index 6738c80f..006a23ee 100644 --- a/library/server/wsf/connector/httpd/wsf_httpd_service_launcher.e +++ b/library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e @@ -8,8 +8,8 @@ note The httpd default connector support options: port: numeric such as 8099 (or equivalent string as "8099") base: base_url (very specific to standalone server) - verbose: to display verbose output, useful for Nino - force_single_threaded: use only one thread, useful for Nino + verbose: to display verbose output, useful for standalone connector + force_single_threaded: use only one thread, useful for standalone connector check WSF_SERVICE_LAUNCHER for more documentation ]" @@ -17,7 +17,7 @@ note revision: "$Revision$" class - WSF_HTTPD_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] + WSF_STANDALONE_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit WSF_SERVICE_LAUNCHER [G] @@ -71,7 +71,6 @@ feature {NONE} -- Initialization create conn.make connector := conn conn.on_launched_actions.extend (agent on_launched) - conn.on_stopped_actions.extend (agent on_stopped) conn.set_base (base_url) update_configuration (conn.configuration) @@ -88,7 +87,6 @@ feature -- Execution if attached server_name as l_server_name then cfg.set_http_server_name (l_server_name) end --- conn.set_port_number (port_number) cfg.http_server_port := port_number end @@ -102,7 +100,7 @@ feature -- Execution conn.set_base (base_url) debug ("nino") if verbose then - io.error.put_string ("Launching Nino web server on port " + port_number.out) + io.error.put_string ("Launching standalone web server on port " + port_number.out) if attached server_name as l_name then io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N") else @@ -116,24 +114,19 @@ feature -- Execution feature -- Callback - on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [G]]] -- Actions triggered when launched - on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [G]]] -- Actions triggered when stopped feature {NONE} -- Implementation - on_launched (conn: WGI_CONNECTOR) + on_launched (conn: WGI_STANDALONE_CONNECTOR [G]) do on_launched_actions.call ([conn]) end - on_stopped (conn: WGI_CONNECTOR) - do - on_stopped_actions.call ([conn]) - end - port_number: INTEGER server_name: detachable READABLE_STRING_8 @@ -146,7 +139,7 @@ feature {NONE} -- Implementation feature -- Status report - connector: WGI_HTTPD_CONNECTOR [G] + connector: WGI_STANDALONE_CONNECTOR [G] -- Default connector launchable: BOOLEAN diff --git a/library/server/wsf/default/cgi/wsf_default_response_service.e b/library/server/wsf/default/cgi/wsf_default_response_service.e deleted file mode 100644 index 0cefc7da..00000000 --- a/library/server/wsf/default/cgi/wsf_default_response_service.e +++ /dev/null @@ -1,24 +0,0 @@ -note - description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_DEFAULT_RESPONSE_SERVICE - -inherit - WSF_DEFAULT_SERVICE - - WSF_RESPONSE_SERVICE - -note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/default/cgi/wsf_default_service.e b/library/server/wsf/default/cgi/wsf_default_service.e index dd76ca78..a19fb656 100644 --- a/library/server/wsf/default/cgi/wsf_default_service.e +++ b/library/server/wsf/default/cgi/wsf_default_service.e @@ -4,13 +4,13 @@ note revision: "$Revision$" deferred class - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [G -> WSF_EXECUTION create make end] inherit - WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER] + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER [G]] note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/httpd/wsf_default_response_service.e b/library/server/wsf/default/httpd/wsf_default_response_service.e deleted file mode 100644 index 0cefc7da..00000000 --- a/library/server/wsf/default/httpd/wsf_default_response_service.e +++ /dev/null @@ -1,24 +0,0 @@ -note - description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_DEFAULT_RESPONSE_SERVICE - -inherit - WSF_DEFAULT_SERVICE - - WSF_RESPONSE_SERVICE - -note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/default/libfcgi/wsf_default_response_service.e b/library/server/wsf/default/libfcgi/wsf_default_response_service.e deleted file mode 100644 index 0cefc7da..00000000 --- a/library/server/wsf/default/libfcgi/wsf_default_response_service.e +++ /dev/null @@ -1,24 +0,0 @@ -note - description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_DEFAULT_RESPONSE_SERVICE - -inherit - WSF_DEFAULT_SERVICE - - WSF_RESPONSE_SERVICE - -note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/default/libfcgi/wsf_default_service.e b/library/server/wsf/default/libfcgi/wsf_default_service.e index dd76ca78..a19fb656 100644 --- a/library/server/wsf/default/libfcgi/wsf_default_service.e +++ b/library/server/wsf/default/libfcgi/wsf_default_service.e @@ -4,13 +4,13 @@ note revision: "$Revision$" deferred class - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [G -> WSF_EXECUTION create make end] inherit - WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER] + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER [G]] note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e b/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e index 82189381..99f302ce 100644 --- a/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e +++ b/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e @@ -5,19 +5,17 @@ note revision: "$Revision$" class - WSF_DEFAULT_SERVICE_LAUNCHER + WSF_DEFAULT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_LIBFCGI_SERVICE_LAUNCHER + WSF_LIBFCGI_SERVICE_LAUNCHER [G] create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/openshift/wsf_default_response_service.e b/library/server/wsf/default/openshift/wsf_default_response_service.e deleted file mode 100644 index 0cefc7da..00000000 --- a/library/server/wsf/default/openshift/wsf_default_response_service.e +++ /dev/null @@ -1,24 +0,0 @@ -note - description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_DEFAULT_RESPONSE_SERVICE - -inherit - WSF_DEFAULT_SERVICE - - WSF_RESPONSE_SERVICE - -note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/default/openshift/wsf_default_service.e b/library/server/wsf/default/openshift/wsf_default_service.e index dd76ca78..a19fb656 100644 --- a/library/server/wsf/default/openshift/wsf_default_service.e +++ b/library/server/wsf/default/openshift/wsf_default_service.e @@ -4,13 +4,13 @@ note revision: "$Revision$" deferred class - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [G -> WSF_EXECUTION create make end] inherit - WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER] + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER [G]] note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/openshift/wsf_default_service_launcher.e b/library/server/wsf/default/openshift/wsf_default_service_launcher.e index a648940a..f0b14177 100644 --- a/library/server/wsf/default/openshift/wsf_default_service_launcher.e +++ b/library/server/wsf/default/openshift/wsf_default_service_launcher.e @@ -6,19 +6,17 @@ note revision: "$Revision$" class - WSF_DEFAULT_SERVICE_LAUNCHER + WSF_DEFAULT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_OPENSHIFT_SERVICE_LAUNCHER + WSF_OPENSHIFT_SERVICE_LAUNCHER [G] create make, - make_and_launch, - make_callback, - make_callback_and_launch + make_and_launch note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/default/httpd-safe.ecf b/library/server/wsf/default/standalone-safe.ecf similarity index 69% rename from library/server/wsf/default/httpd-safe.ecf rename to library/server/wsf/default/standalone-safe.ecf index c60d7c8e..9716756e 100644 --- a/library/server/wsf/default/httpd-safe.ecf +++ b/library/server/wsf/default/standalone-safe.ecf @@ -1,6 +1,6 @@ - - + + /EIFGENs$ @@ -11,7 +11,7 @@ - - + + diff --git a/library/server/wsf/default/standalone.ecf b/library/server/wsf/default/standalone.ecf new file mode 100644 index 00000000..918b7a99 --- /dev/null +++ b/library/server/wsf/default/standalone.ecf @@ -0,0 +1,17 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + diff --git a/library/server/wsf/default/httpd/wsf_default_service.e b/library/server/wsf/default/standalone/wsf_default_service.e similarity index 100% rename from library/server/wsf/default/httpd/wsf_default_service.e rename to library/server/wsf/default/standalone/wsf_default_service.e diff --git a/library/server/wsf/default/httpd/wsf_default_service_launcher.e b/library/server/wsf/default/standalone/wsf_default_service_launcher.e similarity index 82% rename from library/server/wsf/default/httpd/wsf_default_service_launcher.e rename to library/server/wsf/default/standalone/wsf_default_service_launcher.e index 3a91dafd..65c07c38 100644 --- a/library/server/wsf/default/httpd/wsf_default_service_launcher.e +++ b/library/server/wsf/default/standalone/wsf_default_service_launcher.e @@ -1,6 +1,6 @@ note description: "[ - Default launcher for WSF_SERVICE based on {WSF_HTTPD_SERVICE_LAUNCHER} + Default launcher for WSF_SERVICE based on {WSF_STANDALONE_SERVICE_LAUNCHER} ]" date: "$Date$" revision: "$Revision$" @@ -9,7 +9,7 @@ class WSF_DEFAULT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - WSF_HTTPD_SERVICE_LAUNCHER [G] + WSF_STANDALONE_SERVICE_LAUNCHER [G] create make, diff --git a/library/server/wsf/router/filter/wsf_filtered_execution.e b/library/server/wsf/router/filter/wsf_filtered_execution.e new file mode 100644 index 00000000..eb2bd534 --- /dev/null +++ b/library/server/wsf/router/filter/wsf_filtered_execution.e @@ -0,0 +1,92 @@ +note + description: "Summary description for {WSF_FILTERED_EXECUTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_FILTERED_EXECUTION + +inherit + WSF_EXECUTION + redefine + initialize + end + +feature {NONE} -- Initialization + + initialize + do + Precursor + initialize_filter + end + + initialize_filter + -- Initialize `filter' + do + create_filter + setup_filter + end + + create_filter + -- Create `filter' + deferred + ensure + filter_created: filter /= Void + end + + setup_filter + -- Setup `filter' + require + filter_created: filter /= Void + deferred + end + + append_filters (a_filters: ITERABLE [WSF_FILTER]) + -- Append collection `a_filters' of filters to the end of the `filter' chain. + local + f: like filter + l_next_filter: detachable like filter + do + from + f := filter + l_next_filter := f.next + until + l_next_filter = Void + loop + f := l_next_filter + l_next_filter := f.next + end + check f_attached_without_next: f /= Void and then f.next = Void end + across + a_filters as ic + loop + l_next_filter := ic.item + f.set_next (l_next_filter) + f := l_next_filter + end + end + +feature -- Access + + filter: WSF_FILTER + -- Filter + +feature -- Execution + + execute + do + filter.execute (request, response) + end + +;note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e b/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e index 7daacd25..8a0a4792 100644 --- a/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e +++ b/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e @@ -48,7 +48,7 @@ feature -- Execution create l_sess router.dispatch (req, res, l_sess) if not l_sess.dispatched then - execute_default + execute_default (req, res) end end end @@ -279,7 +279,7 @@ invariant unavailability_duration_xor_unavailable_until: unavailability_duration > 0 implies unavailable_until = Void ;note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/wsf_filtered_routed_execution.e b/library/server/wsf/router/wsf_filtered_routed_execution.e new file mode 100644 index 00000000..68129add --- /dev/null +++ b/library/server/wsf/router/wsf_filtered_routed_execution.e @@ -0,0 +1,68 @@ +note + description: "[ + Execution which is first filtered, and then pass to the router + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_FILTERED_ROUTED_EXECUTION + +inherit + WSF_FILTERED_EXECUTION + redefine + initialize + end + + WSF_ROUTED_EXECUTION + undefine + execute + redefine + initialize + end + + WSF_FILTER + rename + execute as filter_execute + end + +feature {NONE} -- Initialize + + initialize + local + f: like filter + do + Precursor {WSF_ROUTED_EXECUTION} + Precursor {WSF_FILTERED_EXECUTION} + -- Current is a WSF_FILTER as well in order to call the router + -- let's add Current at the end of the filter chain. + from + f := filter + until + not attached f.next as l_next + loop + f := l_next + end + f.set_next (Current) + end + +feature -- Execute Filter + + filter_execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter. + do + router_execute (req, res) + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/wsf/router/wsf_routed_execution.e b/library/server/wsf/router/wsf_routed_execution.e index 40581dcc..7b2d693a 100644 --- a/library/server/wsf/router/wsf_routed_execution.e +++ b/library/server/wsf/router/wsf_routed_execution.e @@ -7,6 +7,20 @@ note deferred class WSF_ROUTED_EXECUTION +inherit + WSF_EXECUTION + redefine + initialize + end + +feature {NONE} -- Initialize + + initialize + do + Precursor + initialize_router + end + feature -- Router initialize_router @@ -34,14 +48,6 @@ feature -- Router feature -- Access - request: WSF_REQUEST - deferred - end - - response: WSF_RESPONSE - deferred - end - router: WSF_ROUTER -- Router used to dispatch the request according to the WSF_REQUEST object -- and associated request methods @@ -51,19 +57,22 @@ feature -- Execution execute -- Dispatch the request -- and if handler is not found, execute the default procedure `execute_default'. + do + router_execute (request, response) + end + + router_execute (req: WSF_REQUEST; res: WSF_RESPONSE) local sess: WSF_ROUTER_SESSION do create sess - router.dispatch (request, response, sess) + router.dispatch (req, res, sess) if not sess.dispatched then - execute_default + execute_default (req, res) end - ensure - response_status_is_set: response.status_is_set end - execute_default + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) -- Dispatch requests without a matching handler. local msg: WSF_DEFAULT_ROUTER_RESPONSE @@ -73,4 +82,14 @@ feature -- Execution response.send (msg) end +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" end diff --git a/library/server/wsf/src/service/wsf_response_service.e b/library/server/wsf/src/wsf_execution_factory.e similarity index 50% rename from library/server/wsf/src/service/wsf_response_service.e rename to library/server/wsf/src/wsf_execution_factory.e index 5b375e19..04be7117 100644 --- a/library/server/wsf/src/service/wsf_response_service.e +++ b/library/server/wsf/src/wsf_execution_factory.e @@ -1,31 +1,22 @@ note - description: "[ - Inherit from this class to implement the main entry of your web service - You just need to implement `execute', get data from the request `req' - and return a response message - ]" + description: "Summary description for {WSF_EXECUTION_FACTORY}." + author: "" date: "$Date$" revision: "$Revision$" deferred class - WSF_RESPONSE_SERVICE [G -> WSF_EXECUTION create make end] + WSF_EXECUTION_FACTORY inherit - WSF_SERVICE - -feature -- Response - - response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE - deferred - ensure - Result_attached: Result /= Void + WGI_EXECUTION_FACTORY + redefine + execution end -feature -- Execution +feature -- Factory - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - do - res.send (response (req)) + execution (req: WGI_REQUEST; res: WGI_RESPONSE): WSF_EXECUTION + deferred end note diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e index d7964568..32922fa1 100644 --- a/library/server/wsf/src/wsf_response.e +++ b/library/server/wsf/src/wsf_response.e @@ -19,7 +19,7 @@ note class WSF_RESPONSE -create {WSF_TO_WGI_SERVICE, WSF_EXECUTION, WGI_EXPORTER} +create {WSF_EXECUTION, WGI_EXPORTER} make_from_wgi create {WSF_RESPONSE} diff --git a/library/server/wsf/tests/echo/src/echo_server.e b/library/server/wsf/tests/echo/src/echo_server.e index 0ff1a36b..efc71879 100644 --- a/library/server/wsf/tests/echo/src/echo_server.e +++ b/library/server/wsf/tests/echo/src/echo_server.e @@ -8,7 +8,7 @@ class ECHO_SERVER inherit - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [ECHO_SERVER_EXECUTION] create make @@ -23,53 +23,4 @@ feature {NONE} -- Initialization make_and_launch end -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - local - page: WSF_PAGE_RESPONSE - l_body: STRING_8 - do - create l_body.make (1024) - create page.make_with_body (l_body) - page.header.put_content_type_text_plain - - l_body.append ("REQUEST_METHOD=" + req.request_method + "%N") - l_body.append ("REQUEST_URI=" + req.request_uri + "%N") - l_body.append ("PATH_INFO=" + req.path_info + "%N") - l_body.append ("QUERY_STRING=" + req.query_string + "%N") - - l_body.append ("Query parameters:%N") - across - req.query_parameters as q - loop - l_body.append ("%T"+ q.item.name + "=" + q.item.string_representation +"%N") - end - - l_body.append ("Form parameters:%N") - across - req.form_parameters as q - loop - l_body.append ("%T"+ q.item.name + "=" + q.item.string_representation +"%N") - end - - l_body.append ("Meta variables:%N") - across - req.meta_variables as q - loop - l_body.append ("%T"+ q.item.name + "=" + q.item.string_representation +"%N") - end - - res.send (page) - end - -feature -- Access - -feature -- Change - -feature {NONE} -- Implementation - -invariant --- invariant_clause: True - end diff --git a/library/server/wsf/tests/echo/src/echo_server_execution.e b/library/server/wsf/tests/echo/src/echo_server_execution.e new file mode 100644 index 00000000..e4b73f46 --- /dev/null +++ b/library/server/wsf/tests/echo/src/echo_server_execution.e @@ -0,0 +1,59 @@ +note + description : "Objects that ..." + author : "$Author$" + date : "$Date$" + revision : "$Revision$" + +class + ECHO_SERVER_EXECUTION + +inherit + WSF_EXECUTION + +create + make + +feature -- Execution + + execute + local + req: WSF_REQUEST; res: WSF_RESPONSE + page: WSF_PAGE_RESPONSE + l_body: STRING_8 + do + req := request + res := response + create l_body.make (1024) + create page.make_with_body (l_body) + page.header.put_content_type_text_plain + + l_body.append ("REQUEST_METHOD=" + req.request_method + "%N") + l_body.append ("REQUEST_URI=" + req.request_uri + "%N") + l_body.append ("PATH_INFO=" + req.path_info + "%N") + l_body.append ("QUERY_STRING=" + req.query_string + "%N") + + l_body.append ("Query parameters:%N") + across + req.query_parameters as q + loop + l_body.append ("%T"+ q.item.name + "=" + q.item.string_representation +"%N") + end + + l_body.append ("Form parameters:%N") + across + req.form_parameters as q + loop + l_body.append ("%T"+ q.item.name + "=" + q.item.string_representation +"%N") + end + + l_body.append ("Meta variables:%N") + across + req.meta_variables as q + loop + l_body.append ("%T"+ q.item.name + "=" + q.item.string_representation +"%N") + end + + res.send (page) + end + +end diff --git a/library/server/wsf/tests/server/test.e b/library/server/wsf/tests/server/test.e index 5cd52363..f672cb23 100644 --- a/library/server/wsf/tests/server/test.e +++ b/library/server/wsf/tests/server/test.e @@ -2,9 +2,9 @@ class TEST inherit - WSF_DEFAULT_SERVICE + WSF_DEFAULT_SERVICE [TEST_EXECUTION] - TEST_SERVICE + TEST_SERVICE [TEST_EXECUTION] create make @@ -22,38 +22,6 @@ feature {NONE} -- Initialization make_and_launch end -feature -- Helper - server_log_path: STRING - local - fn: FILE_NAME - once - create fn.make_from_string ("server_test.log") - Result := fn.string - end - - server_log (m: STRING_8) - local - f: RAW_FILE - do - create f.make (server_log_path) - f.open_append - f.put_string (m) - f.put_character ('%N') - f.close - end - - base_url: detachable STRING - - test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8 - local - b: like base_url - do - b := base_url - if b = Void then - b := "" - end - Result := "/" + b + a_query_url - end end diff --git a/library/server/wsf/tests/server/test_execution.e b/library/server/wsf/tests/server/test_execution.e new file mode 100644 index 00000000..be73d987 --- /dev/null +++ b/library/server/wsf/tests/server/test_execution.e @@ -0,0 +1,51 @@ +note + description: "Summary description for {}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + TEST_EXECUTION + +inherit + TEST_EXECUTION_I + +create + make + +feature -- Helper + + server_log_path: STRING + local + fn: FILE_NAME + once + create fn.make_from_string ("server_test.log") + Result := fn.string + end + + server_log (m: STRING_8) + local + f: RAW_FILE + do + create f.make (server_log_path) + f.open_append + f.put_string (m) + f.put_character ('%N') + f.close + end + + base_url: detachable STRING + + test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8 + local + b: like base_url + do + b := base_url + if b = Void then + b := "" + end + Result := "/" + b + a_query_url + end + +end + diff --git a/library/server/wsf/tests/server/test_execution_i.e b/library/server/wsf/tests/server/test_execution_i.e new file mode 100644 index 00000000..56537b06 --- /dev/null +++ b/library/server/wsf/tests/server/test_execution_i.e @@ -0,0 +1,195 @@ +note + description: "Summary description for {}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + TEST_EXECUTION_I + +inherit + WSF_EXECUTION + +feature -- Execution + + execute + local + req: WSF_REQUEST + res: WSF_RESPONSE + q: detachable STRING_32 + n: NATURAL_64 + page: WSF_PAGE_RESPONSE + log_res: WSF_LOGGER_RESPONSE_WRAPPER + do + req := request + res := response + debug + server_log (req.request_uri) + if attached req.content_type as l_content_type then + server_log ("content_type:" + l_content_type.string) + end + end + if attached req.http_expect as l_expect and then l_expect.same_string ("100-continue") then + (create {EXECUTION_ENVIRONMENT}).sleep (900_000_000) -- 900 milliseconds + end + + create page.make + if attached req.request_uri as l_uri then + if l_uri.starts_with (test_url ("get/01")) then + page.set_status_code (200) + page.header.put_content_type_text_plain + page.put_string ("get-01") + create q.make_empty + + across + req.query_parameters as qcur + loop + if not q.is_empty then + q.append_character ('&') + end + q.append (qcur.item.name.as_string_32 + "=" + qcur.item.string_representation) + end + if not q.is_empty then + page.put_string ("(" + q + ")") + end + elseif l_uri.starts_with (test_url ("post/01")) then + page.put_header (200, <<["Content-Type", "text/plain"]>>) + page.put_string ("post-01") + create q.make_empty + + across + req.query_parameters as qcur + loop + if not q.is_empty then + q.append_character ('&') + end + q.append (qcur.item.name.as_string_32 + "=" + qcur.item.string_representation) + end + + if not q.is_empty then + page.put_string ("(" + q + ")") + end + + create q.make_empty +-- req.set_raw_input_data_recorded (True) + + across + req.form_parameters as fcur + loop + debug + server_log ("%Tform: " + fcur.item.name) + end + if not q.is_empty then + q.append_character ('&') + end + q.append (fcur.item.name.as_string_32 + "=" + fcur.item.string_representation) + end + +-- if attached req.raw_input_data as d then +-- server_log ("Raw data=" + d) +-- end + + if not q.is_empty then + page.put_string (" : " + q ) + end + elseif l_uri.starts_with (test_url ("post/file/01")) then + page.put_header (200, <<["Content-Type", "text/plain"]>>) + page.put_string ("post-file-01") + n := req.content_length_value + if n > 0 then + req.input.read_string (n.to_integer_32) + q := req.input.last_string + page.put_string ("%N" + q) + end + else + page.put_header (200, <<["Content-Type", "text/plain"]>>) + page.put_string ("Hello") + end + else + page.put_header (200, <<["Content-Type", "text/plain"]>>) + page.put_string ("Bye") + end + + if + attached new_file (req, "output.log") as l_out and + attached new_file (req, "error.log") as l_err + then + create log_res.make_from_response (res, l_out, l_err) + log_res.send (page) + + l_out.close + l_err.close + else + check False end + res.send (page) + end + end + + new_file (req: WSF_REQUEST; a_suffix: STRING): detachable FILE + local + dp, p, fp: FILE_NAME + d: DIRECTORY + i: INTEGER + f: detachable FILE + retried: INTEGER + do + if retried = 0 then + create dp.make_from_string ("logs") + create d.make (dp.string) + if not d.exists then + d.recursive_create_dir + end + if attached req.request_time_stamp as t then + create p.make_from_string (t.out) + else + create p.make_from_string ("") + end + + from + i := 0 + create fp.make_from_string (dp.string) + if p.is_empty then + fp.set_file_name (p.string + a_suffix) + else + fp.set_file_name (p.string + "-" + a_suffix) + end + create {PLAIN_TEXT_FILE} f.make (fp.string) + until + not f.exists + loop + i := i + 1 + create fp.make_from_string (dp.string) + if p.is_empty then + fp.set_file_name (p.string + i.out + "-" + a_suffix) + else + fp.set_file_name (p.string + "_" + i.out + "-" + a_suffix) + end + + f.make (fp.string) + end + f.open_write + elseif retried < 5 then + + -- Eventually another request created the file at the same time .. + f := new_file (req, a_suffix) + else + f := Void + end + Result := f + rescue + retried := retried + 1 + retry + end + +feature -- Helper + + server_log (s: STRING) + deferred + end + + test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8 + deferred + end + +end + diff --git a/library/server/wsf/tests/server/test_service.e b/library/server/wsf/tests/server/test_service.e index 716e0b51..f2ea7e1e 100644 --- a/library/server/wsf/tests/server/test_service.e +++ b/library/server/wsf/tests/server/test_service.e @@ -5,187 +5,11 @@ note revision: "$Revision$" deferred class - TEST_SERVICE + TEST_SERVICE [G -> TEST_EXECUTION_I create make end] inherit WSF_SERVICE -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - local - q: detachable STRING_32 - n: NATURAL_64 - page: WSF_PAGE_RESPONSE - log_res: WSF_LOGGER_RESPONSE_WRAPPER - do - debug - server_log (req.request_uri) - if attached req.content_type as l_content_type then - server_log ("content_type:" + l_content_type.string) - end - end - if attached req.http_expect as l_expect and then l_expect.same_string ("100-continue") then - (create {EXECUTION_ENVIRONMENT}).sleep (900_000_000) -- 900 milliseconds - end - - create page.make - if attached req.request_uri as l_uri then - if l_uri.starts_with (test_url ("get/01")) then - page.set_status_code (200) - page.header.put_content_type_text_plain - page.put_string ("get-01") - create q.make_empty - - across - req.query_parameters as qcur - loop - if not q.is_empty then - q.append_character ('&') - end - q.append (qcur.item.name.as_string_32 + "=" + qcur.item.string_representation) - end - if not q.is_empty then - page.put_string ("(" + q + ")") - end - elseif l_uri.starts_with (test_url ("post/01")) then - page.put_header (200, <<["Content-Type", "text/plain"]>>) - page.put_string ("post-01") - create q.make_empty - - across - req.query_parameters as qcur - loop - if not q.is_empty then - q.append_character ('&') - end - q.append (qcur.item.name.as_string_32 + "=" + qcur.item.string_representation) - end - - if not q.is_empty then - page.put_string ("(" + q + ")") - end - - create q.make_empty --- req.set_raw_input_data_recorded (True) - - across - req.form_parameters as fcur - loop - debug - server_log ("%Tform: " + fcur.item.name) - end - if not q.is_empty then - q.append_character ('&') - end - q.append (fcur.item.name.as_string_32 + "=" + fcur.item.string_representation) - end - --- if attached req.raw_input_data as d then --- server_log ("Raw data=" + d) --- end - - if not q.is_empty then - page.put_string (" : " + q ) - end - elseif l_uri.starts_with (test_url ("post/file/01")) then - page.put_header (200, <<["Content-Type", "text/plain"]>>) - page.put_string ("post-file-01") - n := req.content_length_value - if n > 0 then - req.input.read_string (n.to_integer_32) - q := req.input.last_string - page.put_string ("%N" + q) - end - else - page.put_header (200, <<["Content-Type", "text/plain"]>>) - page.put_string ("Hello") - end - else - page.put_header (200, <<["Content-Type", "text/plain"]>>) - page.put_string ("Bye") - end - - if - attached new_file (req, "output.log") as l_out and - attached new_file (req, "error.log") as l_err - then - create log_res.make_from_response (res, l_out, l_err) - log_res.send (page) - - l_out.close - l_err.close - else - check False end - res.send (page) - end - end - - new_file (req: WSF_REQUEST; a_suffix: STRING): detachable FILE - local - dp, p, fp: FILE_NAME - d: DIRECTORY - i: INTEGER - f: detachable FILE - retried: INTEGER - do - if retried = 0 then - create dp.make_from_string ("logs") - create d.make (dp.string) - if not d.exists then - d.recursive_create_dir - end - if attached req.request_time_stamp as t then - create p.make_from_string (t.out) - else - create p.make_from_string ("") - end - - from - i := 0 - create fp.make_from_string (dp.string) - if p.is_empty then - fp.set_file_name (p.string + a_suffix) - else - fp.set_file_name (p.string + "-" + a_suffix) - end - create {PLAIN_TEXT_FILE} f.make (fp.string) - until - not f.exists - loop - i := i + 1 - create fp.make_from_string (dp.string) - if p.is_empty then - fp.set_file_name (p.string + i.out + "-" + a_suffix) - else - fp.set_file_name (p.string + "_" + i.out + "-" + a_suffix) - end - - f.make (fp.string) - end - f.open_write - elseif retried < 5 then - - -- Eventually another request created the file at the same time .. - f := new_file (req, a_suffix) - else - f := Void - end - Result := f - rescue - retried := retried + 1 - retry - end - -feature -- Helper - - server_log (s: STRING) - deferred - end - - test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8 - deferred - end end diff --git a/library/server/wsf/tests/src/test_wsf_request.e b/library/server/wsf/tests/src/test_wsf_request.e index c011f03c..fadd050a 100644 --- a/library/server/wsf/tests/src/test_wsf_request.e +++ b/library/server/wsf/tests/src/test_wsf_request.e @@ -17,14 +17,9 @@ inherit on_clean end - TEST_SERVICE - undefine - default_create - end - feature {NONE} -- Events - web_app: detachable NINO_SERVICE + web_app: detachable NINO_SERVICE [TEST_EXECUTION] port_number: INTEGER base_url: detachable STRING @@ -32,7 +27,7 @@ feature {NONE} -- Events on_prepare -- local - app: NINO_SERVICE + app: NINO_SERVICE [TEST_EXECUTION] wt: WORKER_THREAD e: EXECUTION_ENVIRONMENT do @@ -43,7 +38,7 @@ feature {NONE} -- Events port_number := 0 base_url := "/test/" - create app.make_custom (to_wgi_service, base_url) + create app.make_custom (base_url) web_app := app create wt.make (agent app.listen (port_number)) diff --git a/library/server/wsf/tests/src/test_wsf_response_test_suite.e b/library/server/wsf/tests/src/test_wsf_response_test_suite.e index 2f6c0771..968ca0b2 100644 --- a/library/server/wsf/tests/src/test_wsf_response_test_suite.e +++ b/library/server/wsf/tests/src/test_wsf_response_test_suite.e @@ -7,15 +7,13 @@ class TEST_WSF_RESPONSE_TEST_SUITE inherit - WSF_TO_WGI_SERVICE - rename - default_create as df_wgi, - execute as execute_wgi - end EQA_TEST_SET redefine on_prepare - select + end + + WGI_EXPORTER + undefine default_create end @@ -23,7 +21,6 @@ feature {NONE} -- Events on_prepare do - make_from_service (create {WSF_SERVICE_NULL}) end feature -- Test Cases @@ -96,7 +93,7 @@ feature -- Test Cases end - test_add_multiple_cookie_with_similar_cookie_name_2 + test_add_multiple_cookie_with_similar_cookie_name_2 local w_res: WSF_RESPONSE l_cookie: WSF_COOKIE diff --git a/library/server/wsf/tests/src/wsf_service_null.e b/library/server/wsf/tests/src/wsf_service_null.e deleted file mode 100644 index 4f6cf001..00000000 --- a/library/server/wsf/tests/src/wsf_service_null.e +++ /dev/null @@ -1,26 +0,0 @@ -note - description: "[ - Mock implementation of the WGI_SERVICE interface. - - Used for testing the ewf core and also web applications - ]" - date: "$Date$" - revision: "$Revision$" - -class - WSF_SERVICE_NULL - -inherit - - WSF_SERVICE - - -feature -- Execute - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Execute the request - -- See `req.input' for input stream - -- `req.meta_variables' for the CGI meta variable - -- and `res' for output buffer - do - end -end diff --git a/tests/all-stable-safe.ecf b/tests/all-stable-safe.ecf index 80db1dc4..db1cc477 100644 --- a/tests/all-stable-safe.ecf +++ b/tests/all-stable-safe.ecf @@ -13,11 +13,13 @@ + + @@ -45,6 +47,7 @@ + diff --git a/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf b/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf index f30460a5..6562aee1 100644 --- a/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf +++ b/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf @@ -17,22 +17,28 @@ {if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}{/if} {if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}{/if} - {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{/if} + {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{/if} + {if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"}{/if} - - /default$ - + {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"} + + + + + + + + {/if} +{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"} - - - /any$ - + + {/if} @@ -40,10 +46,8 @@ - - - /any$ - + + {/if} @@ -51,10 +55,8 @@ - - - /any$ - + + {/if} diff --git a/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e b/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e index 58f5e2ba..ff7a5956 100644 --- a/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e +++ b/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e @@ -10,33 +10,38 @@ note revision: "$Revision: 36 $" deferred class - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end] + +inherit + SHARED_EXECUTION_ENVIRONMENT feature -- Execution - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) - -- Launch Web Server Application using `a_service' and optionals `opts'. + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + -- Launch Web Server Application using optionals `opts'. local - l_id: like launcher_id launcher: WSF_SERVICE_LAUNCHER do l_id := launcher_id - if l_id = Void then + if not attached launcher_id as l_id then {unless condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} io.error.put_string ("Application launcher not found!%N") (create {EXCEPTIONS}).die (-1){/literal}{/unless} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} -- Choose a default -> standalone - create {WSF_NINO_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts){/literal}{/if} -{if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}{literal} - elseif is_libfcgi_launcher_id (l_id) then - create {WSF_LIBFCGI_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts){/literal}{/if} -{if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}{literal} - elseif is_cgi_launcher_id (l_id) then - create {WSF_CGI_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts){/literal}{/if} + create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} elseif is_nino_launcher_id (l_id) then - create {WSF_NINO_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts){/literal}{/if} + create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} +{if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}{literal} + elseif is_libfcgi_launcher_id (l_id) then + create {WSF_LIBFCGI_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} +{if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}{literal} + elseif is_cgi_launcher_id (l_id) then + create {WSF_CGI_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} +{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"}{literal} + elseif is_nino_launcher_id (l_id) then + create {WSF_NINO_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} {literal} else io.error.put_string ("Application launcher not found!%N") @@ -48,11 +53,8 @@ feature -- Execution -- Launcher id based on the executable extension name if any. -- This can be redefine to customize for your application. --| ex: nino, cgi, libfcgi or Void. - local - sh_exec: SHARED_EXECUTION_ENVIRONMENT do - create sh_exec - if attached (create {PATH}.make_from_string (sh_exec.execution_environment.arguments.command_name)).extension as ext then + if attached (create {PATH}.make_from_string (execution_environment.arguments.command_name)).extension as ext then Result := ext end end @@ -60,10 +62,15 @@ feature -- Execution feature -- Status report {/literal} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"} + is_nino_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN + do + Result := a_id.is_case_insensitive ("standalone") + end{/if} + +{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"} is_nino_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN do Result := a_id.is_case_insensitive ("nino") - or a_id.is_case_insensitive ("standalone") end{/if} {if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"} @@ -79,6 +86,5 @@ feature -- Status report or a_id.is_case_insensitive ("fcgi") end{/if} - end diff --git a/tools/estudio_wizard/rootdir/resources/launcher/application_launcher.e b/tools/estudio_wizard/rootdir/resources/launcher/application_launcher.e index 7754546d..616dbd6f 100644 --- a/tools/estudio_wizard/rootdir/resources/launcher/application_launcher.e +++ b/tools/estudio_wizard/rootdir/resources/launcher/application_launcher.e @@ -8,10 +8,10 @@ note revision: "$Revision: 36 $" class - APPLICATION_LAUNCHER + APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G] feature -- Custom diff --git a/tools/estudio_wizard/rootdir/resources/launcher/default/application_launcher_i.e b/tools/estudio_wizard/rootdir/resources/launcher/default/application_launcher_i.e index 03bd497b..72fb1389 100644 --- a/tools/estudio_wizard/rootdir/resources/launcher/default/application_launcher_i.e +++ b/tools/estudio_wizard/rootdir/resources/launcher/default/application_launcher_i.e @@ -10,21 +10,21 @@ note revision: "$Revision: 36 $" deferred class - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end] feature -- Execution - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) -- Launch Web Server Application using `a_service' and optionals `opts'. local - launcher: WSF_SERVICE_LAUNCHER + launcher: WSF_SERVICE_LAUNCHER [G] do {literal} - create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts){/literal} + create {WSF_DEFAULT_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts){/literal} end launcher_id: detachable READABLE_STRING_GENERAL - do + once -- Not used for default connector selection. end diff --git a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e index 75792d57..0dab746f 100644 --- a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e +++ b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e @@ -16,8 +16,8 @@ inherit end {if condition="$WIZ.routers.use_router ~ $WIZ_YES"} WSF_ROUTED_SERVICE{/if} - - APPLICATION_LAUNCHER + {if isset="$APP_ROOT"}APPLICATION_LAUNCHER [{$APP_ROOT/}_EXECUTION]{/if} + {unless isset="$APP_ROOT"}APPLICATION_LAUNCHER [APPLICATION_EXECUTION]{/if} {literal}create make_and_launch @@ -29,27 +29,7 @@ feature {NONE} -- Initialization do Precursor set_service_option ("port", {$WIZ.standalone_connector.port/}) -{unless condition="$WIZ.routers.use_router ~ $WIZ_YES"} end -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - do - end{/unless} -{if condition="$WIZ.routers.use_router ~ $WIZ_YES"}{literal} - initialize_router - end - - setup_router - -- Setup `router' - local - fhdl: WSF_FILE_SYSTEM_HANDLER - do - router.handle_with_request_methods ("/doc", create {WSF_ROUTER_SELF_DOCUMENTATION_HANDLER}.make (router), router.methods_GET) - create fhdl.make_hidden ("www") - fhdl.set_directory_index (<<"index.html">>) - router.handle_with_request_methods ("", fhdl, router.methods_GET) - end{/literal}{/if} end diff --git a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e new file mode 100644 index 00000000..9baf8fe4 --- /dev/null +++ b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e @@ -0,0 +1,89 @@ +note + description: "[ + application execution + ]" + date: "$Date$" + revision: "$Revision$" + +class + {if isset="$APP_ROOT"}{$APP_ROOT/}_EXECUTION{/if} + {unless isset="$APP_ROOT"}APPLICATION_EXECUTION{/unless} + +inherit +{unless condition="$WIZ.routers.use_router ~ $WIZ_YES"} + {unless condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + WSF_EXECUTION{/unless} + {if condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + WSF_FILTERED_EXECUTION{/if} +{/unless} +{if condition="$WIZ.routers.use_router ~ $WIZ_YES"} + {unless condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + WSF_ROUTED_EXECUTION{/unless} + {if condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + WSF_FILTERED_ROUTED_EXECUTION{/if} +{/if} + +{literal}create + make + +feature {NONE} -- Initialization +{/literal} + +{unless condition="$WIZ.routers.use_router ~ $WIZ_YES"}{literal} +feature -- Execution + + execute + -- Use `request' to get data for the incoming http request + -- and `response' to send response back to the client + local + mesg: WSF_PAGE_RESPONSE + do + --| As example, you can use {WSF_PAGE_RESPONSE} + --| To send back easily a simple plaintext message. + create mesg.make_with_body ("Hello Eiffel Web") + response.send (mesg) + end{/unless} + +{if condition="$WIZ.routers.use_filter ~ $WIZ_YES"}{literal} +feature -- Filter + + create_filter + -- Create `filter' + do + --| Example using Maintenance filter. + create {WSF_MAINTENANCE_FILTER} filter + end + + setup_filter + -- Setup `filter' + do + append_filters (<< + create {WSF_CORS_FILTER}, + create {WSF_LOGGING_FILTER} + >>) + --| Chain more filters like {WSF_CUSTOM_HEADER_FILTER}, ... + --| and your owns filters. + end{/if} + +{if condition="$WIZ.routers.use_router ~ $WIZ_YES"}{literal} +feature -- Router + + setup_router + -- Setup `router' + local + fhdl: WSF_FILE_SYSTEM_HANDLER + do + --| As example: + --| /doc is dispatched to self documentated page + --| /* are dispatched to serve files/directories contained in "www" directory + + --| Self documentation + router.handle_with_request_methods ("/doc", create {WSF_ROUTER_SELF_DOCUMENTATION_HANDLER}.make (router), router.methods_GET) + + --| Files publisher + create fhdl.make_hidden ("www") + fhdl.set_directory_index (<<"index.html">>) + router.handle_with_request_methods ("", fhdl, router.methods_GET) + end{/literal}{/if} + +end diff --git a/tools/estudio_wizard/src/ewf_wizard.e b/tools/estudio_wizard/src/ewf_wizard.e index 670207b2..f98cea13 100644 --- a/tools/estudio_wizard/src/ewf_wizard.e +++ b/tools/estudio_wizard/src/ewf_wizard.e @@ -24,7 +24,7 @@ feature -- Factory create Result.make (Current) end -feature -- Pages +feature -- Pages first_page: WIZARD_PAGE once @@ -83,11 +83,13 @@ Web application runs on top of connectors Select connectors you want to support: ]") - Result.add_boolean_question ("Standalone", "use_standalone", "Using the Eiffel Web nino server") + Result.add_boolean_question ("Standalone", "use_standalone", "Using the standalone Eiffel Web server") + Result.add_boolean_question ("Nino", "use_nino", "Using the Eiffel Web nino server") Result.add_boolean_question ("CGI", "use_cgi", "Require a httpd server") Result.add_boolean_question ("libFCGI", "use_libfcgi", "Require a httpd server") Result.data.force ("yes", "use_standalone") + Result.data.force ("no", "use_nino") Result.data.force ("yes", "use_cgi") Result.data.force ("yes", "use_libfcgi") end @@ -95,7 +97,7 @@ Select connectors you want to support: standalone_connector_page: WIZARD_PAGE once Result := new_page ("standalone_connector") - Result.set_title ("Standalone (nino) connector") + Result.set_title ("Standalone (or nino) connector") Result.set_subtitle ("Set options .") Result.add_integer_question ("Port number", "port", "It happens port 80 is already taken, thus choose another one.") Result.add_boolean_question ("Verbose", "verbose", "Verbose output") @@ -117,6 +119,19 @@ Use the router component to easily map URL patterns to handlers: Result.data.force ("yes", "use_router") end + filters_page: WIZARD_PAGE + once + Result := new_page ("filters") + Result.set_title ("Use Filter (chain filter)") + Result.set_subtitle ("Use the filter component.") + Result.add_text ("[ +Use the filter component: + ]") + Result.add_boolean_question ("use the filter component", "use_filter", "Check generated code to see how to configure it.") + + Result.data.force ("yes", "use_filter") + end + final_page: WIZARD_PAGE local -- s,sv: STRING_32 @@ -160,6 +175,12 @@ Use the router component to easily map URL patterns to handlers: end sv.append ("standalone") end + if connectors_page.boolean_field_value ("use_nino") then + if not sv.is_empty then + sv.append (", ") + end + sv.append ("nino") + end if connectors_page.boolean_field_value ("use_cgi") then if not sv.is_empty then sv.append (", ") @@ -178,6 +199,9 @@ Use the router component to easily map URL patterns to handlers: if routers_page.boolean_field_value ("use_router") then l_settings.force (["Use Router", "yes"]) end + if routers_page.boolean_field_value ("use_filter") then + l_settings.force (["Use Filter", "yes"]) + end a_txt2.set_text (formatted_title_value_items (l_settings)) end(Result, txt1, txt2)) @@ -195,7 +219,10 @@ feature -- Events elseif a_current_page = project_page then Result := connectors_page elseif a_current_page = connectors_page then - if connectors_page.boolean_field_value ("use_standalone") then + if + connectors_page.boolean_field_value ("use_standalone") + or connectors_page.boolean_field_value ("use_nino") + then Result := standalone_connector_page else Result := routers_page @@ -203,6 +230,8 @@ feature -- Events elseif a_current_page = standalone_connector_page then Result := routers_page elseif a_current_page = routers_page then + Result := filters_page + elseif a_current_page = filters_page then Result := final_page end end From 9e1083eba8f4c65c9a3d93f80d103dc314d53e68 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 31 Mar 2015 16:07:48 +0200 Subject: [PATCH 10/33] Added migration note. --- MIGRATION.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 MIGRATION.md diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 00000000..6b34d0b1 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,121 @@ +Date: 2015-mar-31 + +# Goal: +======= +- support safe concurrency with EWF +- provide a concurrent standalone connector + +# Status: +========= +- The current version of EWF has mainly 3 connectors: CGI, libFCGI, and nino. + - CGI and libFCGI connectors does not need any concurrency support. + - But the nino connector had a pseudo concurrency support with Thread, however one could do write code that result in hasardeous concurrency execution. + +So, it was decided to provide an improved Eiffel web nino connector, and update EWF design to make it concurrency compliant. + +# Decisions: +============ +- instead of updating current nino library, we now have a new "standalone" connector which is inspired by nino, but have support for the 3 concurrency modes: none, thread and SCOOP. + + +# Overview +========== +Adding support for SCOOP concurrency mode add constraints to the design, but also helps ensuring the concurrency design of EWF is correct. + +As a consequence, we had to introduce a new interface WSF_EXECUTION which is instantiated for each incoming request. See its simplified interface : + + deferred class WSF_EXECUTION + + feature -- Initialization + + make (req: WGI_REQUEST; res: WGI_RESPONSE) + do + ... + īnitialize + end + + initialize + -- Initialize Current object. + --| To be redefined if needed. + do + end + + + feature -- Access + + request: WSF_REQUEST + -- Access to request data. + -- Header, Query, Post, Input data.. + + response: WSF_RESPONSE + -- Access to output stream, back to the client. + + feature -- Execution + + execute + -- Execute Current `request', + -- getting data from `request' + -- and response to client via `response'. + deferred + ensure + is_valid_end_of_execution: is_valid_end_of_execution + end + + end + + +And the related request execution routines are extracted from WSF_SERVICE which becomes almost useless. The "service" part is not mostly responsible of launching the expected connector and set optional options, and declare the type of "execution" interface. + +As a result, the well known WSF_DEFAULT_SERVICE has now a formal generic that should conform to WSF_EXECUTION with a `make' creation procedure. See update code: + + + class + APPLICATION + + inherit + WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION] + redefine + initialize + end + + create + make_and_launch + + feature {NONE} -- Initialization + + initialize + -- Initialize current service. + do + set_service_option ("port", 9090) + end + + end + + +Where APPLICATION_EXECUTION is an implementation of the WSF_EXECUTION interface (with the `make' creation procedure). + +In addition to add better and safer concurrency support, there are other advantages: +- we now have a clear separation between the service launcher, and the request execution itself. +- the WSF_EXECUTION is created per request, with two main attributes request: WSF_REQUEST and response: WSF_RESPONSE. + +# How to migrate to new design +- you can check the various example from the EWF repository, there should all be migrated to new design and comparing previous and new code, this will show you how the migration was done. +- a frequent process: + - identify the root class of your service, (the class implementing the WSF_SERVICE), let us name it APPLICATION_SERVICE + - copy the APPLICATION_SERVICE file to APPLICATION_EXECUTION file. + - change the class name to be APPLICATION_EXECUTION, and replace _SERVICE occurences by _EXECUTION (note the new WSF_ROUTED_EXECUTION and so on, which are mainly migration from previous WSF_ROUTED_SERVICE .., and also WSF_FILTERED_ROUTED_EXECUTION which is new. + - replace "make_and_launch" by "make", remove the initialize redefinition if any. + - in the APPLICATION_SERVICE class, remove most of the ROUTED, FILTERED ... inheritance, and keep WSF_DEFAULT_SERVICE, with a new formal generic i.e WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]. + - in the eventual redefined initialize, remove code related to routers, filters, ... + - remove all the execution related code. + - And you should be done. + - To be short, this is mostly creating a new _EXECUTION class, and move the execution related code into this class from the _SERVICE class. +- Then, you can replace the usage of nino connector by using the new "Standalone" connector, and switch to SCOOP concurrency mode, to ensure you are not messing up with concurrency. Your own code/libraris may not be SCOOP compliant, we recommend to migrate to SCOOP, but as an intermediate solutioņ, you can use the other concurrency mode (none or thread). + +Note: the new design impacts the _SERVICE classes, connectors, but WSF_REQUEST, WSF_RESPONSE , WSF_ROUTER are compatible, so the migration is really easy. + +We may take the opportunity to update the design deeper according to user feedback, and eventually "wsf" library will be renamed "wsf2". +This is work in progress, all comments , feedback, suggestions, bug report are welcome. +Hopefully before the final version of the new design is out. + + From 8246bc1444986da5a77a7e4b1bbfb50382e18f9b Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 31 Mar 2015 21:33:38 +0200 Subject: [PATCH 11/33] Updated various indexing notes. Removed a few obsolete classes. Cosmetics --- .../network/protocol/http/src/http_cookie.e | 106 +++---- .../http/src/http_date_time_utilities.e | 4 +- .../protocol/http/src/http_format_constants.e | 2 +- .../http/src/http_request_method_constants.e | 4 +- .../notification_chain_mailer.e | 5 +- .../openid/consumer/demo/application.e | 5 +- .../connectors/cgi/src/wgi_cgi_connector.e | 2 +- .../connectors/cgi/src/wgi_cgi_error_stream.e | 2 +- .../connectors/cgi/src/wgi_cgi_input_stream.e | 2 +- .../cgi/src/wgi_cgi_output_stream.e | 2 +- .../libfcgi/src/wgi_libfcgi_connector.e | 2 +- .../libfcgi/src/wgi_libfcgi_input_stream.e | 2 +- .../libfcgi/src/wgi_libfcgi_output_stream.e | 2 +- .../connectors/nino/src/wgi_nino_connector.e | 2 +- .../nino/src/wgi_nino_error_stream.e | 2 +- .../nino/src/wgi_nino_input_stream.e | 2 +- .../nino/src/wgi_nino_output_stream.e | 2 +- .../connectors/null/src/wgi_null_connector.e | 2 +- .../null/src/wgi_null_file_input_stream.e | 2 +- .../null/src/wgi_null_input_stream.e | 2 +- .../null/src/wgi_null_output_stream.e | 2 +- .../null/src/wgi_null_string_input_stream.e | 2 +- .../none/httpd_connection_handler.e | 7 +- .../none/httpd_request_handler_factory.e | 3 +- .../scoop/httpd_connection_handler.e | 23 +- .../scoop/httpd_request_handler_factory.e | 3 +- .../concurrency/scoop/pool/concurrent_pool.e | 4 +- .../scoop/pool/concurrent_pool_factory.e | 3 +- .../scoop/pool/concurrent_pool_item.e | 8 +- .../thread/httpd_connection_handler.e | 5 +- .../thread/httpd_request_handler_factory.e | 3 +- .../configuration/httpd_configuration_i.e | 3 +- .../src/httpd/httpd_connection_handler_i.e | 34 ++- .../standalone/src/httpd/httpd_controller.e | 10 +- .../src/httpd/httpd_debug_facilities.e | 3 +- .../standalone/src/httpd/httpd_logger.e | 3 +- .../src/httpd/httpd_server_observer.e | 5 +- .../src/httpd/no_ssl/httpd_configuration.e | 4 +- .../src/httpd/ssl/httpd_configuration.e | 4 +- .../src/httpd/ssl/ssl_tcp_stream_socket.e | 3 +- .../standalone/src/wgi_standalone_connector.e | 86 +++--- .../src/wgi_standalone_error_stream.e | 4 +- .../src/wgi_standalone_input_stream.e | 4 +- .../src/wgi_standalone_output_stream.e | 4 +- .../src/wgi_standalone_response_stream.e | 2 +- .../src/wgi_standalone_server_observer.e | 8 +- .../connectors/standalone/standalone-safe.ecf | 16 - .../standalone/test_standalone-safe.ecf | 24 ++ .../app_counter.e => tests/test_counter.e} | 5 +- .../test_execution.e} | 9 +- .../test_standalone_connector.e} | 6 +- .../examples/hello_world/src/hello_world.e | 3 - .../specification/connector/wgi_connector.e | 4 +- .../specification/connector/wgi_execution.e | 6 +- .../connector/wgi_execution_factory.e | 26 -- .../specification/connector/wgi_exporter.e | 3 +- .../specification/request/wgi_meta_names.e | 2 +- .../response/wgi_filter_response.e | 4 +- .../response/wgi_logger_response.e | 2 +- .../specification/response/wgi_response.e | 2 +- .../stream/wgi_chunked_input_stream.e | 2 +- library/server/ewsgi/src/wgi_agent_service.e | 48 --- .../wsf/default/cgi/wsf_default_service.e | 2 +- .../cgi/wsf_default_service_launcher.e | 3 +- .../wsf/default/libfcgi/wsf_default_service.e | 2 +- .../libfcgi/wsf_default_service_launcher.e | 3 +- .../wsf/default/nino/wsf_default_service.e | 2 +- .../default/openshift/wsf_default_service.e | 2 +- .../default/standalone/wsf_default_service.e | 2 +- .../wsf/extension/filter/wsf_debug_filter.e | 2 +- .../wsf/extension/handler/wsf_debug_handler.e | 4 +- .../wsf/extension/wsf_request_utility.e | 3 +- .../wsf/extension/wsf_request_utility_proxy.e | 6 +- .../server/wsf/extension/wsf_value_utility.e | 4 +- .../wsf/policy_driven/wsf_skeleton_handler.e | 12 +- .../wsf/router/filter/wsf_filtered_service.e | 55 ---- .../wsf_routed_skeleton_execution.e | 2 +- .../service/wsf_routed_skeleton_service.e | 287 ------------------ .../wsf_uri_helper_for_routed_service.e | 60 ---- ...f_uri_template_helper_for_routed_service.e | 73 ----- .../server/wsf/router/wsf_routed_execution.e | 3 +- .../server/wsf/router/wsf_routed_service.e | 84 ----- .../server/wsf/router/wsf_router_methods.e | 72 ----- .../wsf_starts_with_context_routed_service.e | 27 -- .../wsf_starts_with_context_router_helper.e | 3 +- .../helpers/wsf_uri_context_routed_service.e | 28 -- .../helpers/wsf_uri_context_router_helper.e | 3 +- .../wsf_uri_template_context_routed_service.e | 27 -- .../wsf_uri_template_context_router_helper.e | 3 +- library/server/wsf/src/support/wsf_cookie.e | 1 - library/server/wsf/src/wsf_execution.e | 3 +- .../server/wsf/src/wsf_execution_factory.e | 32 -- 92 files changed, 300 insertions(+), 1066 deletions(-) create mode 100644 library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf rename library/server/ewsgi/connectors/standalone/{dev/app_counter.e => tests/test_counter.e} (88%) rename library/server/ewsgi/connectors/standalone/{dev/app_wsf_execution.e => tests/test_execution.e} (85%) rename library/server/ewsgi/connectors/standalone/{dev/httpd_connector_dev.e => tests/test_standalone_connector.e} (87%) delete mode 100644 library/server/ewsgi/specification/connector/wgi_execution_factory.e delete mode 100644 library/server/ewsgi/src/wgi_agent_service.e delete mode 100644 library/server/wsf/router/filter/wsf_filtered_service.e rename library/server/wsf/router/policy/{service => execution}/wsf_routed_skeleton_execution.e (99%) delete mode 100644 library/server/wsf/router/policy/service/wsf_routed_skeleton_service.e delete mode 100644 library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_service.e delete mode 100644 library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_service.e delete mode 100644 library/server/wsf/router/wsf_routed_service.e delete mode 100644 library/server/wsf/router/wsf_router_methods.e delete mode 100644 library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_routed_service.e delete mode 100644 library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_routed_service.e delete mode 100644 library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_routed_service.e delete mode 100644 library/server/wsf/src/wsf_execution_factory.e diff --git a/library/network/protocol/http/src/http_cookie.e b/library/network/protocol/http/src/http_cookie.e index e46c07fa..17b3738a 100644 --- a/library/network/protocol/http/src/http_cookie.e +++ b/library/network/protocol/http/src/http_cookie.e @@ -1,23 +1,23 @@ note description: "[ - This class represents the value of a HTTP cookie, transferred in a request. - The class has features to build an HTTP cookie. - - Following a newer RFC standard for Cookies http://tools.ietf.org/html/rfc6265 - - Domain - * WARNING: Some existing user agents treat an absent Domain attribute as if the Domain attribute were present and contained the current host name. - * For example, if example.com returns a Set-Cookie header without a Domain attribute, these user agents will erroneously send the cookie to www.example.com as well. - - Max-Age, Expires - * If a cookie has both the Max-Age and the Expires attribute, the Max-Age attribute has precedence and controls the expiration date of the cookie. - * If a cookie has neither the Max-Age nor the Expires attribute, the user agent will retain the cookie until "the current session is over" (as defined by the user agent). - * You will need to call the feature - - HttpOnly, Secure - * Note that the HttpOnly attribute is independent of the Secure attribute: a cookie can have both the HttpOnly and the Secure attribute. + This class represents the value of a HTTP cookie, transferred in a request. + The class has features to build an HTTP cookie. + + Following a newer RFC standard for Cookies http://tools.ietf.org/html/rfc6265 + + Domain + * WARNING: Some existing user agents treat an absent Domain attribute as if the Domain attribute were present and contained the current host name. + * For example, if example.com returns a Set-Cookie header without a Domain attribute, these user agents will erroneously send the cookie to www.example.com as well. + + Max-Age, Expires + * If a cookie has both the Max-Age and the Expires attribute, the Max-Age attribute has precedence and controls the expiration date of the cookie. + * If a cookie has neither the Max-Age nor the Expires attribute, the user agent will retain the cookie until "the current session is over" (as defined by the user agent). + * You will need to call the feature + + HttpOnly, Secure + * Note that the HttpOnly attribute is independent of the Secure attribute: a cookie can have both the HttpOnly and the Secure attribute. -]" + ]" date: "$Date$" revision: "$Revision$" EIS: "name=HTTP Cookie specification", "src=http://tools.ietf.org/html/rfc6265", "protocol=uri" @@ -48,38 +48,38 @@ feature {NONE} -- Initialization feature -- Access name: STRING_8 - -- name of the cookie. + -- name of the cookie. value: STRING_8 - -- value of the cookie. + -- value of the cookie. expiration: detachable STRING_8 - -- Value of the Expires attribute. + -- Value of the Expires attribute. path: detachable STRING_8 - -- Value of the Path attribute. - -- Path to which the cookie applies. - --| The path "/", specify a cookie that apply to all URLs in your site. + -- Value of the Path attribute. + -- Path to which the cookie applies. + --| The path "/", specify a cookie that apply to all URLs in your site. domain: detachable STRING_8 - -- Value of the Domain attribute. - -- Domain to which the cookies apply. + -- Value of the Domain attribute. + -- Domain to which the cookies apply. secure: BOOLEAN - -- Value of the Secure attribute. - -- By default False. - --| Indicate if the cookie should only be sent over secured(encrypted connections, for example SSL). + -- Value of the Secure attribute. + -- By default False. + --| Indicate if the cookie should only be sent over secured(encrypted connections, for example SSL). http_only: BOOLEAN - -- Value of the http_only attribute. - -- By default false. - --| Limits the scope of the cookie to HTTP requests. + -- Value of the http_only attribute. + -- By default false. + --| Limits the scope of the cookie to HTTP requests. max_age: INTEGER - -- Value of the Max-Age attribute. - --| How much time in seconds should elapsed before the cookie expires. - --| By default max_age < 0 indicate a cookie will last only for the current user-agent (Browser, etc) session. - --| A value of 0 instructs the user-agent to delete the cookie. + -- Value of the Max-Age attribute. + --| How much time in seconds should elapsed before the cookie expires. + --| By default max_age < 0 indicate a cookie will last only for the current user-agent (Browser, etc) session. + --| A value of 0 instructs the user-agent to delete the cookie. has_valid_characters (a_name: READABLE_STRING_8):BOOLEAN -- Has `a_name' valid characters for cookies? @@ -102,12 +102,12 @@ feature -- Access end include_max_age: BOOLEAN - -- Does the Set-Cookie header include Max-Age attribute? - --|By default will include both. + -- Does the Set-Cookie header include Max-Age attribute? + --|By default will include both. include_expires: BOOLEAN - -- Does the Set-Cookie header include Expires attribute? - --|By default will include both. + -- Does the Set-Cookie header include Expires attribute? + --|By default will include both. is_valid_rfc1123_date (a_string: READABLE_STRING_8): BOOLEAN @@ -118,7 +118,7 @@ feature -- Access create d.make_from_string (a_string) Result := not d.has_error and then d.rfc1123_string.same_string (a_string) end - + feature -- Change Element set_name (a_name: READABLE_STRING_8) @@ -323,20 +323,20 @@ feature {NONE} -- Constants -- 0x2D-3A: -./0123456789: -- 0x3C-5B: <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[ -- 0x5D-7E: ]^_`abcdefghijklmnopqrstuvwxyz{|}~ - note - EIS: "name=valid-characters", "src=http://tools.ietf.org/html/rfc6265#section-4.1.1", "protocol=uri" - do - Result := True - inspect c - when 0x21 then - when 0x23 .. 0x2B then - when 0x2D .. 0x3A then - when 0x3C .. 0x5B then - when 0x5D .. 0x7E then - else - Result := False - end + note + EIS: "name=valid-characters", "src=http://tools.ietf.org/html/rfc6265#section-4.1.1", "protocol=uri" + do + Result := True + inspect c + when 0x21 then + when 0x23 .. 0x2B then + when 0x2D .. 0x3A then + when 0x3C .. 0x5B then + when 0x5D .. 0x7E then + else + Result := False end + end note copyright: "2011-2015, Jocelyn Fiat, Eiffel Software and others" diff --git a/library/network/protocol/http/src/http_date_time_utilities.e b/library/network/protocol/http/src/http_date_time_utilities.e index d24c6b09..d8f41fa2 100644 --- a/library/network/protocol/http/src/http_date_time_utilities.e +++ b/library/network/protocol/http/src/http_date_time_utilities.e @@ -1,5 +1,7 @@ note - description: "Summary description for {HTTP_DATE_TIME_UTILITIES}." + description: "[ + Utilities routines to manipulate date + ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/network/protocol/http/src/http_format_constants.e b/library/network/protocol/http/src/http_format_constants.e index b5d00397..67b6312c 100644 --- a/library/network/protocol/http/src/http_format_constants.e +++ b/library/network/protocol/http/src/http_format_constants.e @@ -1,5 +1,5 @@ note - description: "Summary description for {HTTP_FORMAT_CONSTANTS}." + description: "Various constants implied in http format." date: "$Date$" revision: "$Revision$" diff --git a/library/network/protocol/http/src/http_request_method_constants.e b/library/network/protocol/http/src/http_request_method_constants.e index 625a7a98..b378dc09 100644 --- a/library/network/protocol/http/src/http_request_method_constants.e +++ b/library/network/protocol/http/src/http_request_method_constants.e @@ -1,5 +1,7 @@ note - description: "Summary description for {HTTP_REQUEST_METHOD_CONSTANTS}." + description: "[ + Constants related to HTTP request method identification + ]" date: "$Date$" revision: "$Revision$" diff --git a/library/runtime/process/notification_email/notification_chain_mailer.e b/library/runtime/process/notification_email/notification_chain_mailer.e index 7c400683..844dc270 100644 --- a/library/runtime/process/notification_email/notification_chain_mailer.e +++ b/library/runtime/process/notification_email/notification_chain_mailer.e @@ -1,6 +1,7 @@ note - description: "Summary description for {NOTIFICATION_CHAIN_MAILER}." - author: "" + description: "[ + Node of a notification mailer chain + ]" date: "$Date$" revision: "$Revision$" diff --git a/library/security/openid/consumer/demo/application.e b/library/security/openid/consumer/demo/application.e index 819fa640..2f4de614 100644 --- a/library/security/openid/consumer/demo/application.e +++ b/library/security/openid/consumer/demo/application.e @@ -7,9 +7,8 @@ class APPLICATION inherit - - WSF_SERVICE - + ANY + SHARED_EXECUTION_ENVIRONMENT export {NONE} all diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e index c40b7a28..372a20a0 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_CGI_CONNECTOR}." + description: "CGI connector, see CGI interface, and CGI scripts." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_error_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_error_stream.e index 1fab40b2..88e84a4d 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_error_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_error_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_CGI_ERROR_STREAM." + description: "Error stream for CGI connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e index faa595d5..c23892e7 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_CGI_INPUT_STREAM." + description: "Input stream for CGI connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e index 323927d3..0a5dea0c 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_CGI_OUTPUT_STREAM." + description: "Output stream for CGI connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e index 2bd68609..ed8209e0 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_LIBFCGI_CONNECTOR}." + description: "libFCGI connector, see libfcgi and http://fastcgi.com" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e index ec757d63..590f6c73 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_LIBFCGI_INPUT_STREAM." + description: "Input stream for libFCGI connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e index d3b67676..cbe0f762 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_LIBFCGI_OUTPUT_STREAM}." + description: "Output stream for libFCGI connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 524659ac..b96f4bf3 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_NINO_CONNECTOR}." + description: "Standalone Eiffel Web nino server connector." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_error_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_error_stream.e index facbfb66..f65beaf3 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_error_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_error_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_CGI_ERROR_STREAM." + description: "Error stream for Nino connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e index 6cddecdd..de13091a 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_NINO_INPUT_STREAM}." + description: "Input stream for Nino connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e index 9e95b69e..3b595927 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_NINO_OUTPUT_STREAM}." + description: "Output stream for Nino connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_connector.e b/library/server/ewsgi/connectors/null/src/wgi_null_connector.e index 789c84e4..f08fbf4e 100644 --- a/library/server/ewsgi/connectors/null/src/wgi_null_connector.e +++ b/library/server/ewsgi/connectors/null/src/wgi_null_connector.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_NULL_CONNECTOR}." + description: "NULL connector, mainly used for void-safety purpose or testing" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e index 6e0282f0..9a28baee 100644 --- a/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e +++ b/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_NULL_FILE_INPUT_STREAM." + description: "Null Input stream based on FILE." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e index 93461b24..ee84dee5 100644 --- a/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e +++ b/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_NULL_INPUT_STREAM." + description: "Input stream for NULL connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e index 16fdbf73..21d95864 100644 --- a/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e +++ b/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_NULL_OUTPUT_STREAM." + description: "Output stream for NULL connector." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e index 09df2d2e..3c98c09b 100644 --- a/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e +++ b/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for WGI_NULL_STRING_INPUT_STREAM." + description: "Input stream for NULL connector based on string body (in memory)." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e index 54ca8b74..9b32f4a2 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e @@ -1,6 +1,7 @@ note - description: "Summary description for {HTTPD_CONNECTION_HANDLER}." - author: "" + description: "[ + Implementation of HTTPD_CONNECTION_HANDLER_I for concurrency mode: none + ]" date: "$Date$" revision: "$Revision$" @@ -29,7 +30,7 @@ feature -- Access Result := a_server.controller.shutdown_requested end -feature -- Execution +feature {HTTPD_SERVER_I} -- Execution accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) local diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler_factory.e index 8bff0870..1c93e9e3 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler_factory.e @@ -1,6 +1,5 @@ note - description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY}." - author: "" + description: "Implementation of request handler factory for concurrency mode: none" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e index e90c89d4..25b458ab 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -1,5 +1,7 @@ note - description: "Summary description for {HTTPD_CONNECTION_HANDLER}." + description: "[ + Implementation of HTTPD_CONNECTION_HANDLER_I for concurrency mode: SCOOP + ]" date: "$Date$" revision: "$Revision$" @@ -36,8 +38,10 @@ feature {NONE} -- Initialization feature -- Access is_shutdown_requested: BOOLEAN + -- max_concurrent_connections (a_server: like server): INTEGER + -- Max concurrent connection settings from server `a_server'. do Result := a_server.configuration.max_concurrent_connections end @@ -87,11 +91,6 @@ feature {HTTPD_SERVER_I} -- Execution end end - separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET - do - Result := hdl.client_socket - end - process_handler (hdl: separate HTTPD_REQUEST_HANDLER) require hdl.is_connected @@ -99,22 +98,28 @@ feature {HTTPD_SERVER_I} -- Execution hdl.safe_execute end + separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET + do + Result := hdl.client_socket + end + feature {HTTPD_SERVER_I} -- Status report wait_for_completion - -- Wait until Current is ready for shutdown + -- Wait until Current is ready for shutdown. do wait_for_pool_completion (pool) end wait_for_pool_completion (p: like pool) + -- Wait until concurrent pool is empty and terminated. require - p.is_empty + p.is_empty -- SCOOP wait condition. do p.terminate end -feature {NONE} -- Access +feature {NONE} -- Implementation pool: separate CONCURRENT_POOL [HTTPD_REQUEST_HANDLER] -- Pool of separate connection handlers. diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler_factory.e index 56fa78d6..e48a96a2 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler_factory.e @@ -1,6 +1,5 @@ note - description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY}." - author: "" + description: "Implementation of request handler factory for concurrency mode: SCOOP" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e index a26156da..90a75855 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e @@ -1,6 +1,5 @@ note - description: "Summary description for {CONCURRENT_POOL}." - author: "" + description: "Concurrent pool for SCOOP concurrency mode." date: "$Date$" revision: "$Revision$" @@ -19,7 +18,6 @@ feature {NONE} -- Initialization do capacity := n create items.make_empty (n) --- create busy_items.make_filled (False, n) create busy_items.make_empty (n) end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e index 51205fb3..92e0f2cb 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_factory.e @@ -1,6 +1,5 @@ note - description: "Summary description for {CONCURRENT_POOL_FACTORY}." - author: "" + description: "Factory in charge of creating new concurrent pool item." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e index c197fd88..f0af2268 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e @@ -1,6 +1,8 @@ note - description: "Summary description for {CONCURRENT_POOL_ITEM}." - author: "" + description: "[ + Item create by the CONCURRENT_POOL_FACTORY, and managed by the CONCURRENT_POOL + for SCOOP concurrency mode. + ]" date: "$Date$" revision: "$Revision$" @@ -10,10 +12,12 @@ deferred class feature {NONE} -- Access pool: detachable separate CONCURRENT_POOL [CONCURRENT_POOL_ITEM] + -- Associated concurrent pool component. feature {CONCURRENT_POOL} -- Change set_pool (p: like pool) + -- Set associated `pool' to `p'. do pool := p end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_connection_handler.e index d6bebdc1..45b85bd4 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_connection_handler.e @@ -1,6 +1,7 @@ note - description: "Summary description for {HTTPD_CONNECTION_HANDLER}." - author: "" + description: "[ + Implementation of HTTPD_CONNECTION_HANDLER_I for concurrency mode: Thread + ]" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler_factory.e index 8bff0870..cf692e55 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/thread/httpd_request_handler_factory.e @@ -1,6 +1,5 @@ note - description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY}." - author: "" + description: "Implementation of request handler factory for concurrency mode: Thread" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e index 7acf397b..79b82c83 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e @@ -1,5 +1,5 @@ note - description: "Summary description for {HTTPD_CONFIGURATION_I}." + description: "Configuration for the standalone HTTPd server." date: "$Date$" revision: "$Revision$" @@ -24,6 +24,7 @@ feature {NONE} -- Initialization feature -- Access Server_details: STRING_8 + -- Detail of the server. deferred end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e index 99d4acc0..017e2a69 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e @@ -1,6 +1,12 @@ note - description: "Summary description for {HTTPD_CONNECTION_HANDLER_I}." - author: "" + description: "[ + Interface for the incoming connection handler. + + Each incoming socket connection is processed by + an implementation of HTTPD_CONNECTION_HANDLER_I. + + Note there are 3 implementations, one for each concurrent mode: none, thread, scoop. + ]" date: "$Date$" revision: "$Revision$" @@ -23,41 +29,40 @@ feature {NONE} -- Initialization deferred end - separate_factory (a_server: like server): like factory - -- Separate factory from `a_server'. - --| required by SCOOP design. - do - Result := a_server.factory - end - feature {NONE} -- Access factory: separate HTTPD_REQUEST_HANDLER_FACTORY + -- Request handler factory. server: separate HTTPD_SERVER_I + -- Associated server. feature {HTTPD_SERVER_I} -- Execution accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) + -- Accept incoming connection from `a_listening_socket'. deferred end shutdown + -- Shutdown server. deferred end wait_for_completion - -- Wait until Current completed any pending task + -- Wait until Current completed any pending task. + --| Used for SCOOP synchronisation. deferred end feature {HTTPD_SERVER} -- Status report is_shutdown_requested: BOOLEAN + -- Any request to shutdown the server? deferred end -feature {NONE} -- Output +feature {NONE} -- Implementation log (a_message: separate READABLE_STRING_8) -- Log `a_message' @@ -66,6 +71,13 @@ feature {NONE} -- Output separate_server_log (server, a_message) end + separate_factory (a_server: like server): like factory + -- Separate factory from `a_server'. + --| required by SCOOP design. + do + Result := a_server.factory + end + separate_server_log (a_server: like server; a_message: separate READABLE_STRING_8) do a_server.log (a_message) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_controller.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_controller.e index 8693a71d..f9a66673 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_controller.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_controller.e @@ -1,6 +1,8 @@ note - description: "Summary description for {HTTPD_CONTROLLER}." - author: "" + description: "[ + Object used to control (i.e shutdown) the server. + Mostly needed in SCOOP concurrency mode. + ]" date: "$Date$" revision: "$Revision$" @@ -10,11 +12,15 @@ class feature -- Operation shutdown + -- Request the associated server to be shutdown. do shutdown_requested := True end +feature -- Status report. + shutdown_requested: BOOLEAN + -- Shutdown requested. ;note copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_debug_facilities.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_debug_facilities.e index 77704e5b..31823329 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_debug_facilities.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_debug_facilities.e @@ -1,6 +1,5 @@ note - description: "Summary description for {HTTPD_DEBUG_FACILITIES}." - author: "" + description: " Routines used for debug logging." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger.e index c9668af9..057f43a3 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger.e @@ -1,6 +1,5 @@ note - description: "Summary description for {HTTPD_LOGGER}." - author: "" + description: "Logging facilities component" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e index 3c64c812..18a59981 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_observer.e @@ -1,6 +1,5 @@ note description: "Summary description for {HTTPD_SERVER_OBSERVER}." - author: "" date: "$Date$" revision: "$Revision$" @@ -10,14 +9,18 @@ deferred class feature -- Event on_launched (a_port: INTEGER) + -- Associated server launched listening on port `a_port'. deferred end on_stopped + -- Associated server stopped. + --| the server may restart itself after being rescued. deferred end on_terminated + -- Associated server terminated. deferred end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_configuration.e b/library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_configuration.e index b62114ff..7af8bb74 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_configuration.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/no_ssl/httpd_configuration.e @@ -1,5 +1,5 @@ note - description: "Summary description for {HTTPD_CONFIGURATION}." + description: "Standalone server configuration (ssl NOT supported)." date: "$Date$" revision: "$Revision$" @@ -14,7 +14,7 @@ create feature -- Status - Server_details: STRING_8 = "Server : NINO Eiffel Server" + Server_details: STRING_8 = "Server: Standalone Eiffel Server" has_ssl_support: BOOLEAN = False -- Precursor diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e index 275fd5e4..d702bac5 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e @@ -1,5 +1,5 @@ note - description: "Summary description for {HTTPD_CONFIGURATION}." + description: "Standalone server configuration (ssl supported)." date: "$Date$" revision: "$Revision$" @@ -25,7 +25,7 @@ feature {NONE} -- Initialization feature -- Access - Server_details: STRING_8 = "Server : NINO Eiffel Server (https)" + Server_details: STRING_8 = "Server: Standalone Eiffel Server (https)" has_ssl_support: BOOLEAN = True -- Precursor diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e index c4f5e668..0ad0f7c7 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e @@ -1,6 +1,5 @@ note - description: "Summary description for {SSL_TCP_STREAM_SOCKET}." - author: "" + description: "SSL tcp stream socket." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e index 541b58a8..9c35e715 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e @@ -1,12 +1,7 @@ note - description: "Summary description for {WGI_STANDALONE_CONNECTOR}." - author: "" - todo: "[ - Check if server and configuration has to be 'separate' ? - currently yes, due to WGI_REQUEST.wgi_connector setting. - But we may get rid of this one... - See `{WGI_REQUEST}.wgi_connector' and `{WSF_REQUEST}.wgi_connector' ... - ]" + description: "[ + Standalone Web Server connector + ]" date: "$Date$" revision: "$Revision$" @@ -23,6 +18,7 @@ create feature {NONE} -- Initialization make + -- Create current standalone connector. local fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G] do @@ -40,6 +36,7 @@ feature {NONE} -- Initialization end make_with_base (a_base: like base) + -- Create current standalone connector with base url `a_base' require a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies a_base.starts_with ("/") do @@ -47,13 +44,13 @@ feature {NONE} -- Initialization set_base (a_base) end +feature {NONE} -- Separate helper + initialize_server (a_server: like server) do a_server.set_observer (observer) end -feature {NONE} -- Separate helper - set_factory_connector (conn: detachable separate WGI_STANDALONE_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) do fac.set_connector (conn) @@ -75,12 +72,16 @@ feature -- Access feature -- Access server: separate HTTPD_SERVER + -- HTTPd server object. controller: separate HTTPD_CONTROLLER + -- Controller used to shutdown server. observer: separate WGI_STANDALONE_SERVER_OBSERVER + -- Observer providing information related to port number, and server status. configuration: separate HTTPD_CONFIGURATION + -- Server configuration. feature -- Access @@ -116,16 +117,18 @@ feature -- Event feature -- Element change - set_base (b: like base) + set_base (v: like base) + -- Set base url `base' to `v'. require - b_starts_with_slash: (b /= Void and then not b.is_empty) implies b.starts_with ("/") + b_starts_with_slash: (v /= Void and then not v.is_empty) implies v.starts_with ("/") do - base := b + base := v ensure valid_base: (attached base as l_base and then not l_base.is_empty) implies l_base.starts_with ("/") end set_port_number (a_port_number: INTEGER) + -- Set port number to `a_port_number'. require a_port_number_positive_or_zero: a_port_number >= 0 do @@ -133,6 +136,7 @@ feature -- Element change end set_max_concurrent_connections (nb: INTEGER) + -- Set maximum concurrent connections to `nb'. require nb_positive_or_zero: nb >= 0 do @@ -140,31 +144,16 @@ feature -- Element change end set_is_verbose (b: BOOLEAN) + -- Set verbose mode. do set_is_verbose_on_configuration (b, configuration) end -feature {NONE} -- Implementation - - set_port_on_configuration (a_port_number: INTEGER; cfg: like configuration) - do - cfg.set_http_server_port (a_port_number) - end - - set_max_concurrent_connections_on_configuration (nb: INTEGER; cfg: like configuration) - do - cfg.set_max_concurrent_connections (nb) - end - - set_is_verbose_on_configuration (b: BOOLEAN; cfg: like configuration) - do - is_verbose := b - cfg.set_is_verbose (b) - end feature -- Server launch + -- Launch web server listening. do launched := False port := 0 @@ -173,6 +162,7 @@ feature -- Server end shutdown_server + -- Shutdown web server listening. do if launched then -- FIXME jfiat [2015/03/27] : prevent multiple calls (otherwise it hangs) @@ -180,20 +170,26 @@ feature -- Server end end - server_controller (a_server: like server): separate HTTPD_CONTROLLER - do - Result := a_server.controller - end +feature -- Events on_server_started (obs: like observer) + -- Server started and listeing on port `obs.port'. require - obs.started + obs.started -- SCOOP wait condition. do if obs.port > 0 then on_launched (obs.port) end end + +feature {NONE} -- Implementation + + server_controller (a_server: like server): separate HTTPD_CONTROLLER + do + Result := a_server.controller + end + configure_server (a_configuration: like configuration) do if a_configuration.is_verbose then @@ -209,8 +205,6 @@ feature -- Server a_server.launch end -feature {NONE} -- Implementation - separate_server_terminated (a_server: like server): BOOLEAN do Result := a_server.is_terminated @@ -221,6 +215,24 @@ feature {NONE} -- Implementation a_controller.shutdown end +feature {NONE} -- Implementation: element change + + set_port_on_configuration (a_port_number: INTEGER; cfg: like configuration) + do + cfg.set_http_server_port (a_port_number) + end + + set_max_concurrent_connections_on_configuration (nb: INTEGER; cfg: like configuration) + do + cfg.set_max_concurrent_connections (nb) + end + + set_is_verbose_on_configuration (b: BOOLEAN; cfg: like configuration) + do + is_verbose := b + cfg.set_is_verbose (b) + end + note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e index 8c48d2ab..f0267335 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_error_stream.e @@ -1,5 +1,7 @@ note - description: "Summary description for WGI_STANDALONE_ERROR_STREAM." + description: "[ + Error stream for the Standalone Web Server connector. + ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e index fbfa2b0b..b3ac4d84 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_input_stream.e @@ -1,5 +1,7 @@ note - description: "Summary description for {WGI_STANDALONE_INPUT_STREAM}." + description: "[ + Input stream for the Standalone Web Server connector. + ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e index b5ca291e..7f95ec22 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e @@ -1,5 +1,7 @@ note - description: "Summary description for {WGI_STANDALONE_OUTPUT_STREAM}." + description: "[ + Output stream for the Standalone Web Server connector + ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e index 9c9ab699..4510addb 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e @@ -1,7 +1,7 @@ note description: "[ WGI Response implemented using stream buffer - + for the standalone Eiffel web server connector. ]" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e index b36d0fb7..702b8ae8 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e @@ -1,6 +1,9 @@ note - description: "Summary description for {WGI_STANDALONE_SERVER_OBSERVER}." - author: "" + description: "[ + Server status observer for the Standalone Web Server connector. + This is used to get information related to the port number + and the status of the server. + ]" date: "$Date$" revision: "$Revision$" @@ -39,7 +42,6 @@ feature -- Event terminated := True end - note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/standalone/standalone-safe.ecf b/library/server/ewsgi/connectors/standalone/standalone-safe.ecf index acf1c95f..1d21728c 100644 --- a/library/server/ewsgi/connectors/standalone/standalone-safe.ecf +++ b/library/server/ewsgi/connectors/standalone/standalone-safe.ecf @@ -21,20 +21,4 @@ - - - - - - - - - - - - - diff --git a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf new file mode 100644 index 00000000..cdc30795 --- /dev/null +++ b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/library/server/ewsgi/connectors/standalone/dev/app_counter.e b/library/server/ewsgi/connectors/standalone/tests/test_counter.e similarity index 88% rename from library/server/ewsgi/connectors/standalone/dev/app_counter.e rename to library/server/ewsgi/connectors/standalone/tests/test_counter.e index 1e4a6489..8999b4df 100644 --- a/library/server/ewsgi/connectors/standalone/dev/app_counter.e +++ b/library/server/ewsgi/connectors/standalone/tests/test_counter.e @@ -1,11 +1,10 @@ note - description: "Summary description for {APP_COUNTER}." - author: "" + description: "Simple counter component." date: "$Date$" revision: "$Revision$" class - APP_COUNTER + TEST_COUNTER create put diff --git a/library/server/ewsgi/connectors/standalone/dev/app_wsf_execution.e b/library/server/ewsgi/connectors/standalone/tests/test_execution.e similarity index 85% rename from library/server/ewsgi/connectors/standalone/dev/app_wsf_execution.e rename to library/server/ewsgi/connectors/standalone/tests/test_execution.e index 2a87ee9c..c02a3c65 100644 --- a/library/server/ewsgi/connectors/standalone/dev/app_wsf_execution.e +++ b/library/server/ewsgi/connectors/standalone/tests/test_execution.e @@ -1,11 +1,11 @@ note - description: "Summary description for {APP_WSF_EXECUTION}." + description: "Summary description for {TEST_EXECUTION}." author: "" date: "$Date$" revision: "$Revision$" class - APP_WSF_EXECUTION + TEST_EXECUTION inherit WSF_EXECUTION @@ -22,6 +22,7 @@ feature -- Execution s: STRING i64: INTEGER_64 do + i64 := {INTEGER_64} 1_000_000_000 s := "Hello Concurrent EWF" s.append (" (counter=") s.append_integer (next_cell_counter_item (counter_cell)) @@ -30,7 +31,7 @@ feature -- Execution if attached {WSF_STRING} request.query_parameter ("sleep") as p_sleep then if attached p_sleep.value.is_integer then s.append ("sleep for ") - i64 := p_sleep.value.to_integer_64 * {INTEGER_64} 1_000_000_000 + i64 := p_sleep.value.to_integer_64 * ({INTEGER_64} 1_000_000_000) s.append_integer_64 (i64) execution_environment.sleep (i64) end @@ -49,7 +50,7 @@ feature -- Execution Result := cl.next_item end - counter_cell: separate APP_COUNTER + counter_cell: separate TEST_COUNTER once ("PROCESS") create Result.put (0) end diff --git a/library/server/ewsgi/connectors/standalone/dev/httpd_connector_dev.e b/library/server/ewsgi/connectors/standalone/tests/test_standalone_connector.e similarity index 87% rename from library/server/ewsgi/connectors/standalone/dev/httpd_connector_dev.e rename to library/server/ewsgi/connectors/standalone/tests/test_standalone_connector.e index d299ec48..ddb3bce8 100644 --- a/library/server/ewsgi/connectors/standalone/dev/httpd_connector_dev.e +++ b/library/server/ewsgi/connectors/standalone/tests/test_standalone_connector.e @@ -1,13 +1,13 @@ note description: "[ - Objects that ... + Testing+developping the standalone connector, no need to review. ]" author: "$Author$" date: "$Date$" revision: "$Revision$" class - HTTPD_CONNECTOR_DEV + TEST_STANDALONE_CONNECTOR create make @@ -17,7 +17,7 @@ feature {NONE} -- Initialization make -- Initialize `Current'. local - conn: WGI_STANDALONE_CONNECTOR [APP_WSF_EXECUTION] + conn: WGI_STANDALONE_CONNECTOR [TEST_EXECUTION] do print ("Starting httpd server ...%N") diff --git a/library/server/ewsgi/examples/hello_world/src/hello_world.e b/library/server/ewsgi/examples/hello_world/src/hello_world.e index b48667eb..260aa393 100644 --- a/library/server/ewsgi/examples/hello_world/src/hello_world.e +++ b/library/server/ewsgi/examples/hello_world/src/hello_world.e @@ -7,9 +7,6 @@ note class HELLO_WORLD -inherit - WGI_SERVICE - create make diff --git a/library/server/ewsgi/specification/connector/wgi_connector.e b/library/server/ewsgi/specification/connector/wgi_connector.e index 07614609..d0c45d41 100644 --- a/library/server/ewsgi/specification/connector/wgi_connector.e +++ b/library/server/ewsgi/specification/connector/wgi_connector.e @@ -1,6 +1,6 @@ note - description: "Summary description for {WGI_CONNECTOR}." - specification: "Eiffel WGI/connector specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/WGI-specification" + description: "Common interface for all EWSGI connectors." + specification: "Eiffel WGI/connector specification https://github.com/EiffelWebFramework/EWF/wiki/WGI-specification" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/specification/connector/wgi_execution.e b/library/server/ewsgi/specification/connector/wgi_execution.e index deb0734c..ad18a6ac 100644 --- a/library/server/ewsgi/specification/connector/wgi_execution.e +++ b/library/server/ewsgi/specification/connector/wgi_execution.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WGI_EXECUTION}." - author: "" + description: "Common interface for any request execution." date: "$Date$" revision: "$Revision$" @@ -13,6 +12,7 @@ deferred class feature {NONE} -- Initialization make (req: WGI_REQUEST; res: WGI_RESPONSE) + -- Create current execution with request `req' and response `res'. do request := req response := res @@ -21,8 +21,10 @@ feature {NONE} -- Initialization feature {NONE} -- Access request: WGI_REQUEST + -- Request data. response: WGI_RESPONSE + -- Response interface. feature -- Execution diff --git a/library/server/ewsgi/specification/connector/wgi_execution_factory.e b/library/server/ewsgi/specification/connector/wgi_execution_factory.e deleted file mode 100644 index d0df1af0..00000000 --- a/library/server/ewsgi/specification/connector/wgi_execution_factory.e +++ /dev/null @@ -1,26 +0,0 @@ -note - description: "Summary description for {WGI_EXECUTION_FACTORY}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WGI_EXECUTION_FACTORY - -feature -- Factory - - execution (req: WGI_REQUEST; res: WGI_RESPONSE): WGI_EXECUTION - deferred - end - -note - copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/specification/connector/wgi_exporter.e b/library/server/ewsgi/specification/connector/wgi_exporter.e index 7fd4e349..386b23f5 100644 --- a/library/server/ewsgi/specification/connector/wgi_exporter.e +++ b/library/server/ewsgi/specification/connector/wgi_exporter.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WGI_EXPORTER}." - author: "" +description: "Interface giving access to restricting features of EWSGI components." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/specification/request/wgi_meta_names.e b/library/server/ewsgi/specification/request/wgi_meta_names.e index 5c2ed931..6e4f2db9 100644 --- a/library/server/ewsgi/specification/request/wgi_meta_names.e +++ b/library/server/ewsgi/specification/request/wgi_meta_names.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_META_NAMES}." + description: "Common CGI and meta variable names." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" diff --git a/library/server/ewsgi/specification/response/wgi_filter_response.e b/library/server/ewsgi/specification/response/wgi_filter_response.e index 02485387..81d1b28a 100644 --- a/library/server/ewsgi/specification/response/wgi_filter_response.e +++ b/library/server/ewsgi/specification/response/wgi_filter_response.e @@ -1,5 +1,7 @@ note - description: "Summary description for {WGI_FILTER_RESPONSE}." + description: "[ + WGI response acting as a filter. + ]" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/specification/response/wgi_logger_response.e b/library/server/ewsgi/specification/response/wgi_logger_response.e index 39f6195a..f715d90a 100644 --- a/library/server/ewsgi/specification/response/wgi_logger_response.e +++ b/library/server/ewsgi/specification/response/wgi_logger_response.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_LOGGER_RESPONSE}." + description: "Filter response used to log response sending." date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/specification/response/wgi_response.e b/library/server/ewsgi/specification/response/wgi_response.e index d0192a5a..53838af0 100644 --- a/library/server/ewsgi/specification/response/wgi_response.e +++ b/library/server/ewsgi/specification/response/wgi_response.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_RESPONSE}." + description: "Interface to send response back to the client" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/specification/stream/wgi_chunked_input_stream.e b/library/server/ewsgi/specification/stream/wgi_chunked_input_stream.e index 4722591d..12d3fc00 100644 --- a/library/server/ewsgi/specification/stream/wgi_chunked_input_stream.e +++ b/library/server/ewsgi/specification/stream/wgi_chunked_input_stream.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_CHUNKED_INPUT_STREAM}." + description: "Input stream for chunked encoding request." date: "$Date$" revision: "$Revision$" EIS: "name=Chunked Transfer Coding", "protocol=URI", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1" diff --git a/library/server/ewsgi/src/wgi_agent_service.e b/library/server/ewsgi/src/wgi_agent_service.e deleted file mode 100644 index 579e5bcf..00000000 --- a/library/server/ewsgi/src/wgi_agent_service.e +++ /dev/null @@ -1,48 +0,0 @@ -note - description: "Summary description for {WGI_AGENT_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - WGI_AGENT_SERVICE - -inherit - WGI_SERVICE - -create - make - -feature {NONE} -- Implementation - - make (a_callback: like callback) - -- Initialize `Current'. - do - callback := a_callback - end - -feature {NONE} -- Implementation - - callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]] - -- Procedure called on `execute' - - execute (req: WGI_REQUEST; res: WGI_RESPONSE) - -- Execute the request - do - callback.call ([req, res]) - end - -invariant - callback_attached: callback /= Void - -note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/default/cgi/wsf_default_service.e b/library/server/wsf/default/cgi/wsf_default_service.e index a19fb656..bf0f21d5 100644 --- a/library/server/wsf/default/cgi/wsf_default_service.e +++ b/library/server/wsf/default/cgi/wsf_default_service.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE}." + description: "Service using default connector launcher: CGI" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/default/cgi/wsf_default_service_launcher.e b/library/server/wsf/default/cgi/wsf_default_service_launcher.e index a6ba4e6c..524a820a 100644 --- a/library/server/wsf/default/cgi/wsf_default_service_launcher.e +++ b/library/server/wsf/default/cgi/wsf_default_service_launcher.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE_LAUNCHER}." - author: "" + description: "Launcher for default connector: CGI" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/default/libfcgi/wsf_default_service.e b/library/server/wsf/default/libfcgi/wsf_default_service.e index a19fb656..bf8d350b 100644 --- a/library/server/wsf/default/libfcgi/wsf_default_service.e +++ b/library/server/wsf/default/libfcgi/wsf_default_service.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE}." + description: "Service using default connector launcher: libFCGI" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e b/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e index 99f302ce..ca37b590 100644 --- a/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e +++ b/library/server/wsf/default/libfcgi/wsf_default_service_launcher.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE_LAUNCHER}." - author: "" + description: "Launcher for default connector: libFCGI" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/default/nino/wsf_default_service.e b/library/server/wsf/default/nino/wsf_default_service.e index c29c7047..87173559 100644 --- a/library/server/wsf/default/nino/wsf_default_service.e +++ b/library/server/wsf/default/nino/wsf_default_service.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE}." + description: "Service using default connector launcher: Nino" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/default/openshift/wsf_default_service.e b/library/server/wsf/default/openshift/wsf_default_service.e index a19fb656..8ffe9150 100644 --- a/library/server/wsf/default/openshift/wsf_default_service.e +++ b/library/server/wsf/default/openshift/wsf_default_service.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE}." + description: "Service using default connector launcher: openshift" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/default/standalone/wsf_default_service.e b/library/server/wsf/default/standalone/wsf_default_service.e index a19fb656..df754d51 100644 --- a/library/server/wsf/default/standalone/wsf_default_service.e +++ b/library/server/wsf/default/standalone/wsf_default_service.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_DEFAULT_SERVICE}." + description: "Service using default connector launcher: Standalone" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/extension/filter/wsf_debug_filter.e b/library/server/wsf/extension/filter/wsf_debug_filter.e index a9354ddb..abe403eb 100644 --- a/library/server/wsf/extension/filter/wsf_debug_filter.e +++ b/library/server/wsf/extension/filter/wsf_debug_filter.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_DEBUG_FILTER}." + description: "Filter implementing debug output in error stream, or `output' file." date: "$Date: 2013-05-23 21:54:29 +0200 (jeu., 23 mai 2013) $" revision: "$Revision: 92585 $" diff --git a/library/server/wsf/extension/handler/wsf_debug_handler.e b/library/server/wsf/extension/handler/wsf_debug_handler.e index d4b7d954..7ae7a266 100644 --- a/library/server/wsf/extension/handler/wsf_debug_handler.e +++ b/library/server/wsf/extension/handler/wsf_debug_handler.e @@ -1,6 +1,6 @@ note - description: "Summary description for {WSF_DEBUG_HANDLER}." - author: "" + description: "Handler returning debug information." + date: "$Date: 2013-06-28 16:14:02 +0200 (ven., 28 juin 2013) $" revision: "$Revision: 92754 $" diff --git a/library/server/wsf/extension/wsf_request_utility.e b/library/server/wsf/extension/wsf_request_utility.e index 88566954..be6c7a08 100644 --- a/library/server/wsf/extension/wsf_request_utility.e +++ b/library/server/wsf/extension/wsf_request_utility.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_REQUEST_UTILITY}." - author: "" + description: "Collection of utilities routines for WSF_REQUEST." date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/extension/wsf_request_utility_proxy.e b/library/server/wsf/extension/wsf_request_utility_proxy.e index eb8a3afd..850fd7e0 100644 --- a/library/server/wsf/extension/wsf_request_utility_proxy.e +++ b/library/server/wsf/extension/wsf_request_utility_proxy.e @@ -1,6 +1,8 @@ note - description: "Summary description for {WSF_REQUES_UTILITY_PROXY}." - author: "" + description: "[ + Proxy interface on WSF_REQUEST_UTILITY interface. + Used to factorize code. + ]" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/extension/wsf_value_utility.e b/library/server/wsf/extension/wsf_value_utility.e index 19623e20..229db9be 100644 --- a/library/server/wsf/extension/wsf_value_utility.e +++ b/library/server/wsf/extension/wsf_value_utility.e @@ -1,5 +1,7 @@ note - description: "Summary description for {WSF_VALUE_UTILITY}." + description: "[ + Collection of utilities routines to factorize code related to WSF_VALUE manipulation. + ]" author: "" date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/policy_driven/wsf_skeleton_handler.e b/library/server/wsf/policy_driven/wsf_skeleton_handler.e index ee6f5b2e..07993264 100644 --- a/library/server/wsf/policy_driven/wsf_skeleton_handler.e +++ b/library/server/wsf/policy_driven/wsf_skeleton_handler.e @@ -146,7 +146,7 @@ feature -- Access Result := True -- redefine to return `False', so as to induce a Vary: * header end - + allowed_cross_origins (req: WSF_REQUEST): detachable STRING -- Value for Access-Control-Allow-Origin header; -- If supplied, should be a single URI, or the values "*" or "null". @@ -177,7 +177,7 @@ feature -- Access req_attached: req /= Void deferred end - + last_modified (req: WSF_REQUEST): detachable DATE_TIME -- When representation of resource selected in `req' was last modified; -- SHOULD be set whenever it can reasonably be determined. @@ -503,7 +503,7 @@ feature -- Execution a_helper_attached: a_helper /= Void do a_helper.handle_content_negotiation (req, res, Current) - if not res.status_is_set or else res.status_code /= {HTTP_STATUS_CODE}.Not_acceptable then + if res.status_code /= {HTTP_STATUS_CODE}.Not_acceptable then check_resource_exists (req, a_helper) if a_helper.resource_exists then a_helper.execute_existing_resource (req, res, Current) @@ -538,7 +538,7 @@ feature -- Execution end feature {NONE} -- Implementation - + handle_invalid_content_range (res: WSF_RESPONSE) -- Write "Bad Request" response to `res' for Content-Range header present in PUT request. require @@ -560,7 +560,7 @@ feature {NONE} -- Implementation status_is_service_unavailable: res.status_code = {HTTP_STATUS_CODE}.internal_server_error body_sent: res.message_committed and then res.transfered_content_length > 0 end - + handle_internal_server_error (res: WSF_RESPONSE) -- Write "Internal Server Error" response to `res'. require @@ -584,7 +584,7 @@ feature {NONE} -- Implementation end note - copyright: "2011-2013, Colin Adams, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2014, Colin Adams, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/filter/wsf_filtered_service.e b/library/server/wsf/router/filter/wsf_filtered_service.e deleted file mode 100644 index f7cb826d..00000000 --- a/library/server/wsf/router/filter/wsf_filtered_service.e +++ /dev/null @@ -1,55 +0,0 @@ -note - description: "Summary description for {WSF_FILTERED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_FILTERED_SERVICE - -feature {NONE} -- Initialization - - initialize_filter - -- Initialize `filter' - do - create_filter - setup_filter - end - - create_filter - -- Create `filter' - deferred - ensure - filter_created: filter /= Void - end - - setup_filter - -- Setup `filter' - require - filter_created: filter /= Void - deferred - end - -feature -- Access - - filter: WSF_FILTER - -- Filter - -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - do - filter.execute (req, res) - end - -;note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e b/library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e similarity index 99% rename from library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e rename to library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e index 8a0a4792..859adaff 100644 --- a/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e +++ b/library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WSF_ROUTED_SKELETON_EXECUTION}." + description: "Skeleton execution based on router." date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/router/policy/service/wsf_routed_skeleton_service.e b/library/server/wsf/router/policy/service/wsf_routed_skeleton_service.e deleted file mode 100644 index df05e4ea..00000000 --- a/library/server/wsf/router/policy/service/wsf_routed_skeleton_service.e +++ /dev/null @@ -1,287 +0,0 @@ -note - description: "Summary description for {WSF_ROUTED_SKELETON_SERVICE}." - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_ROUTED_SKELETON_SERVICE - -inherit - WSF_ROUTED_SERVICE - redefine - execute - end - - WSF_SYSTEM_OPTIONS_ACCESS_POLICY - - WSF_PROXY_USE_POLICY - -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- If the service is available, and request URI is not too long, dispatch the request - -- and if handler is not found, execute the default procedure `execute_default'. - local - l_sess: WSF_ROUTER_SESSION - do - --| When we reach here, the request has already passed check for 400 (Bad request), - --| which is implemented in WSF_REQUEST.make_from_wgi (when it calls `analyze'). - if unavailable then - handle_unavailable (res) - elseif requires_proxy (req) then - handle_use_proxy (req, res) - elseif - maximum_uri_length > 0 and then - req.request_uri.count.to_natural_32 > maximum_uri_length - then - handle_request_uri_too_long (res) - elseif - req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) and then - req.request_uri.same_string ("*") - then - handle_server_options (req, res) - else - create l_sess - router.dispatch (req, res, l_sess) - if not l_sess.dispatched then - execute_default (req, res) - end - end - end - -feature -- Measurement - - maximum_uri_length: NATURAL - -- Maximum length in characters (or zero for no limit) permitted - -- for {WSF_REQUEST}.request_uri - -feature -- Status report - - unavailable: BOOLEAN - -- Is service currently unavailable? - - unavailablity_message: detachable READABLE_STRING_8 - -- Message to be included as text of response body for {HTTP_STATUS_CODE}.service_unavailable - - unavailability_duration: NATURAL - -- Delta seconds for service unavailability (0 if not known) - - unavailable_until: detachable DATE_TIME - -- Time at which service becomes available again (if known) - -feature -- Status setting - - set_available - -- Set `unavailable' to `False'. - do - unavailable := False - unavailablity_message := Void - unavailable_until := Void - ensure - available: unavailable = False - unavailablity_message_detached: unavailablity_message = Void - unavailable_until_detached: unavailable_until = Void - end - - set_unavailable (a_message: READABLE_STRING_8; a_duration: NATURAL; a_until: detachable DATE_TIME) - -- Set `unavailable' to `True'. - require - a_message_attached: a_message /= Void - a_duration_xor_a_until: a_duration > 0 implies a_until = Void - do - unavailable := True - unavailablity_message := a_message - unavailability_duration := a_duration - ensure - unavailable: unavailable = True - unavailablity_message_aliased: unavailablity_message = a_message - unavailability_duration_set: unavailability_duration = a_duration - unavailable_until_aliased: unavailable_until = a_until - end - - set_maximum_uri_length (a_len: NATURAL) - -- Set `maximum_uri_length' to `a_len'. - -- Can pass zero to mean no restrictions. - do - maximum_uri_length := a_len - ensure - maximum_uri_length_set: maximum_uri_length = a_len - end - -feature {NONE} -- Implementation - - handle_unavailable (res: WSF_RESPONSE) - -- Write "Service unavailable" response to `res'. - require - unavailable: unavailable - res_attached: res /= Void - local - h: HTTP_HEADER - do - create h.make - h.put_content_type_text_plain - check attached unavailablity_message as m then - -- invariant `unavailability_message_attached' plus precondition `unavailable' - h.put_content_length (m.count) - h.put_current_date - res.set_status_code ({HTTP_STATUS_CODE}.service_unavailable) - if unavailability_duration > 0 then - h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, unavailability_duration.out) - elseif attached unavailable_until as u then - h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, - h.date_to_rfc1123_http_date_format (u)) - end - res.put_header_text (h.string) - res.put_string (m) - end - ensure - response_status_is_set: res.status_is_set - status_is_service_unavailable: res.status_code = {HTTP_STATUS_CODE}.service_unavailable - body_sent: res.message_committed and then res.transfered_content_length > 0 - body_content_was_unavailablity_message: True -- doesn't seem to be any way to check - end - - handle_request_uri_too_long (res: WSF_RESPONSE) - -- Write "Request URI too long" response into `res'. - require - res_attached: res /= Void - local - h: HTTP_HEADER - m: READABLE_STRING_8 - do - create h.make - h.put_content_type_text_plain - h.put_current_date - m := "Maximum permitted length for request URI is " + maximum_uri_length.out + " characters" - h.put_content_length (m.count) - res.set_status_code ({HTTP_STATUS_CODE}.request_uri_too_long) - res.put_header_text (h.string) - res.put_string (m) - ensure - response_status_is_set: res.status_is_set - status_is_request_uri_too_long: res.status_code = {HTTP_STATUS_CODE}.request_uri_too_long - body_sent: res.message_committed and then res.transfered_content_length > 0 - end - - frozen handle_server_options (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Write response to OPTIONS * into `res'. - require - req_attached: req /= Void - res_attached: res /= Void - method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) - server_options_requested: req.request_uri.same_string ("*") - do - --| First check if forbidden. - --| (N.B. authentication requires an absoluteURI (RFC3617 page 3), and so cannot be used for OPTIONS *. - --| Otherwise construct an Allow response automatically from the router. - if is_system_options_forbidden (req) then - handle_system_options_forbidden (req, res) - else - handle_system_options (req, res) - end - ensure - response_status_is_set: res.status_is_set - valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or - res.status_code = {HTTP_STATUS_CODE}.not_found or res.status_code = {HTTP_STATUS_CODE}.ok - header_sent: res.header_committed and res.message_committed - end - - frozen handle_system_options_forbidden (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Write a 403 Forbidden or a 404 Not found response into `res'. - require - req_attached: req /= Void - res_attached: res /= Void - method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) - server_options_requested: req.request_uri.same_string ("*") - local - m: detachable READABLE_STRING_8 - h: HTTP_HEADER - do - m := system_options_forbidden_text (req) - if attached {READABLE_STRING_8} m as l_msg then - create h.make - h.put_content_type_text_plain - h.put_current_date - h.put_content_length (l_msg.count) - res.set_status_code ({HTTP_STATUS_CODE}.forbidden) - res.put_header_text (h.string) - res.put_string (l_msg) - else - create h.make - h.put_content_type_text_plain - h.put_current_date - h.put_content_length (0) - res.set_status_code ({HTTP_STATUS_CODE}.not_found) - res.put_header_text (h.string) - end - ensure - response_status_is_set: res.status_is_set - valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or - res.status_code = {HTTP_STATUS_CODE}.not_found - header_sent: res.header_committed - message_sent: res.message_committed - end - - handle_system_options (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Write response to OPTIONS * into `res'. - -- This may be redefined by the user, but normally this will not be necessary. - require - req_attached: req /= Void - res_attached: res /= Void - method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) - server_options_requested: req.request_uri.same_string ("*") - local - h: HTTP_HEADER - do - create h.make - h.put_content_type_text_plain - h.put_current_date - h.put_allow (router.all_allowed_methods) - h.put_content_length (0) - res.set_status_code ({HTTP_STATUS_CODE}.ok) - res.put_header_text (h.string) - ensure - response_status_is_set: res.status_is_set - response_code_ok: res.status_code = {HTTP_STATUS_CODE}.ok - header_sent: res.header_committed and res.message_committed - empty_body: res.transfered_content_length = 0 - end - - frozen handle_use_proxy (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Write Use Proxy response `res'. - require - res_attached: res /= Void - req_attached: req /= Void - proxy_required: requires_proxy (req) - local - h: HTTP_HEADER - do - create h.make - h.put_content_type_text_plain - h.put_current_date - h.put_location (proxy_server (req).string) - h.put_content_length (0) - res.put_header_lines (h) - res.set_status_code ({HTTP_STATUS_CODE}.use_proxy) - ensure - response_status_is_set: res.status_is_set - response_code_use_proxy: res.status_code = {HTTP_STATUS_CODE}.use_proxy - end - -invariant - - unavailability_message_attached: unavailable implies attached unavailablity_message as m and then - m.count > 0 - unavailability_duration_xor_unavailable_until: unavailability_duration > 0 implies unavailable_until = Void - -;note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_service.e b/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_service.e deleted file mode 100644 index 287fcbfd..00000000 --- a/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_service.e +++ /dev/null @@ -1,60 +0,0 @@ -note - description: "Facilities inheritance to add URI base routing to a routed service" - - date: "$Date$" - revision: "$Revision$" - -deferred class WSF_URI_HELPER_FOR_ROUTED_SERVICE - -feature -- Access - - router: WSF_ROUTER - -- Router used to dispatch the request according to the WSF_REQUEST object - -- and associated request methods; - -- This should not be implemented by descendants. Instead, you gain an effective - -- version by also inheriting from WSF_ROUTED_SERVICE, or one of it's descendants. - deferred - ensure - router_not_void: Result /= Void - end - -feature -- Mapping helper: uri - - map_uri (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER) - -- Map `h' as handler for `a_uri' - do - map_uri_with_request_methods (a_uri, h, Void) - end - - map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) - -- Map `h' as handler for `a_uri' for request methods `rqst_methods'. - do - router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, h), rqst_methods) - end - -feature -- Mapping helper: uri agent - - map_uri_agent (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) - -- Map `proc' as handler for `a_uri' - do - map_uri_agent_with_request_methods (a_uri, proc, Void) - end - - map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) - -- Map `proc' as handler for `a_uri' for request methods `rqst_methods'. - do - map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_HANDLER}.make (proc), rqst_methods) - end - -note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" - -end diff --git a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_service.e b/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_service.e deleted file mode 100644 index d61a6a4e..00000000 --- a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_service.e +++ /dev/null @@ -1,73 +0,0 @@ -note - - description: "Facilities inheritance to add URI template-base routing to a routed service" - - date: "$Date$" - revision: "$Revision$" - -deferred class WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE - -feature -- Access - - router: WSF_ROUTER - -- Router used to dispatch the request according to the WSF_REQUEST object - -- and associated request methods; - -- This should not be implemented by descendants. Instead, you gain an effective - -- version by also inheriting from WSF_ROUTED_SERVICE, or one of it's descendants. - deferred - ensure - router_not_void: Result /= Void - end - -feature -- Mapping helper: uri template - - map_uri_template (a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER) - -- Map `h' as handler for `a_tpl' - require - a_tpl_attached: a_tpl /= Void - h_attached: h /= Void - do - map_uri_template_with_request_methods (a_tpl, h, Void) - end - - map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) - -- Map `h' as handler for `a_tpl' for request methods `rqst_methods'. - require - a_tpl_attached: a_tpl /= Void - h_attached: h /= Void - do - router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods) - end - -feature -- Mapping helper: uri template agent - - map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) - -- Map `proc' as handler for `a_tpl' - require - a_tpl_attached: a_tpl /= Void - proc_attached: proc /= Void - do - map_uri_template_agent_with_request_methods (a_tpl, proc, Void) - end - - map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) - -- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'. - require - a_tpl_attached: a_tpl /= Void - proc_attached: proc /= Void - do - map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods) - end - -note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" - -end diff --git a/library/server/wsf/router/wsf_routed_execution.e b/library/server/wsf/router/wsf_routed_execution.e index 7b2d693a..a5bb8f12 100644 --- a/library/server/wsf/router/wsf_routed_execution.e +++ b/library/server/wsf/router/wsf_routed_execution.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_ROUTED_EXECUTION}." - author: "" + description: "Execution based on router." date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/router/wsf_routed_service.e b/library/server/wsf/router/wsf_routed_service.e deleted file mode 100644 index d205f770..00000000 --- a/library/server/wsf/router/wsf_routed_service.e +++ /dev/null @@ -1,84 +0,0 @@ -note - description: "Summary description for {WSF_ROUTED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_ROUTED_SERVICE - -feature -- Initialization - - initialize_router - -- Initialize router - do - create_router - setup_router - end - - create_router - -- Create `router' - --| could be redefine to initialize with proper capacity - do - create router.make (10) - ensure - router_created: router /= Void - end - - setup_router - -- Setup `router' - require - router_created: router /= Void - deferred - end - -feature -- Execution - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Dispatch the request - -- and if handler is not found, execute the default procedure `execute_default'. - require - req_attached: req /= Void - res_attached: res /= Void - local - sess: WSF_ROUTER_SESSION - do - create sess - router.dispatch (req, res, sess) - if not sess.dispatched then - execute_default (req, res) - end - ensure - response_status_is_set: res.status_is_set - end - - execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Dispatch requests without a matching handler. - require - req_attached: req /= Void - res_attached: res /= Void - local - msg: WSF_DEFAULT_ROUTER_RESPONSE - do - create msg.make_with_router (req, router) - msg.set_documentation_included (True) - res.send (msg) - end - -feature -- Access - - router: WSF_ROUTER - -- Router used to dispatch the request according to the WSF_REQUEST object - -- and associated request methods - -;note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router/wsf_router_methods.e b/library/server/wsf/router/wsf_router_methods.e deleted file mode 100644 index d89dd1ca..00000000 --- a/library/server/wsf/router/wsf_router_methods.e +++ /dev/null @@ -1,72 +0,0 @@ -note - description: "[ - Object that is use in relation with WSF_ROUTER, to precise which request methods is accepted. - For convenience, `make_from_iterable' is available, so that you can use <<"GET", "POST">> for instance - but remember manifest string are evil ... - Since in HTTP you can use your own custom request method, this is not possible to catch any typo - ( for instance if you write "POST" instead of "P0ST" this is hard to find the error, - but in one case it uses upper "o" and in the other case this is zero "0" - ) - - The recommanded way to use is for instance - create {WSF_ROUTER_METHODS}.make_get_post - create methods; methods.enable_get; methods.enable_post - - This sounds heavy, but this is much safer. - - ( note: in addition internally this first checks using reference comparison - and then compare string value, so it brings optimization for accepted request methods. - ) - ]" - date: "$Date$" - revision: "$Revision$" - -class - WSF_ROUTER_METHODS - -obsolete - "Use WSF_REQUEST_METHODS" - -inherit - WSF_REQUEST_METHODS - redefine - plus - end - -create - default_create, - make, - make_from_iterable, - make_from_string - -convert - to_array: {ARRAY [READABLE_STRING_8]}, - make_from_iterable ({ITERABLE [READABLE_STRING_8], ITERABLE [STRING_8], ARRAY [READABLE_STRING_8], ARRAY [STRING_8]}), - make_from_string ({READABLE_STRING_8, STRING_8}) - -feature -- Basic operations - - add (a_other: like plus): like plus - obsolete "Use `plus' or `alias +'" - do - Result := plus (a_other) - end - - plus alias "+" (a_other: WSF_ROUTER_METHODS): WSF_ROUTER_METHODS - -- Merge Current and a_other into Result - do - create Result.make_from_iterable (Current) - Result.add_methods (a_other) - end - -;note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_routed_service.e b/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_routed_service.e deleted file mode 100644 index c7b8245e..00000000 --- a/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_routed_service.e +++ /dev/null @@ -1,27 +0,0 @@ -note - description: "Summary description for {WSF_STARTS_WITH_CONTEXT_ROUTED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_STARTS_WITH_CONTEXT_ROUTED_SERVICE [C -> WSF_HANDLER_CONTEXT create make end] - -obsolete "Inherit from WSF_ROUTED_SERVICE and WSF_STARTS_WITH_CONTEXT_ROUTER_HELPER [2013-mar-19]" - -inherit - WSF_ROUTED_SERVICE - - WSF_STARTS_WITH_CONTEXT_ROUTER_HELPER [C] - -note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_router_helper.e b/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_router_helper.e index 330ceb49..77f53f32 100644 --- a/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_router_helper.e +++ b/library/server/wsf/router_context/support/starts_with/helpers/wsf_starts_with_context_router_helper.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_STARTS_WITH_CONTEXT_ROUTED_SERVICE}." - author: "" + description: "Helper for routed execution with context." date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_routed_service.e b/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_routed_service.e deleted file mode 100644 index 46be558a..00000000 --- a/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_routed_service.e +++ /dev/null @@ -1,28 +0,0 @@ -note - description: "Summary description for {WSF_URI_CONTEXT_ROUTED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_URI_CONTEXT_ROUTED_SERVICE [C -> WSF_HANDLER_CONTEXT create make end] - -obsolete "Inherit from WSF_ROUTED_SERVICE and WSF_URI_CONTEXT_ROUTER_HELPER [2013-mar-19]" - -inherit - WSF_ROUTED_SERVICE - - WSF_URI_CONTEXT_ROUTER_HELPER [C] - - -note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_router_helper.e b/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_router_helper.e index b52d8096..8d5baa5b 100644 --- a/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_router_helper.e +++ b/library/server/wsf/router_context/support/uri/helpers/wsf_uri_context_router_helper.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_URI_CONTEXT_ROUTER_HELPER}." - author: "" + description: "Helper for exection based on router, and uri mapping context." date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_routed_service.e b/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_routed_service.e deleted file mode 100644 index e6ef848b..00000000 --- a/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_routed_service.e +++ /dev/null @@ -1,27 +0,0 @@ -note - description: "Summary description for {WSF_URI_TEMPLATE_CONTEXT_ROUTED_SERVICE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_URI_TEMPLATE_CONTEXT_ROUTED_SERVICE [C -> WSF_HANDLER_CONTEXT create make end] - -obsolete "Inherit from WSF_ROUTED_SERVICE and WSF_URI_TEMPLATE_CONTEXT_ROUTER_HELPER [2013-mar-19]" - -inherit - WSF_ROUTED_SERVICE - - WSF_URI_TEMPLATE_CONTEXT_ROUTER_HELPER [C] - -note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_router_helper.e b/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_router_helper.e index a744719e..e3969420 100644 --- a/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_router_helper.e +++ b/library/server/wsf/router_context/support/uri_template/helpers/wsf_uri_template_context_router_helper.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_URI_TEMPLATE_CONTEXT_ROUTER_HELPER}." - author: "" + description: "Helper for execution based on router and uri template mapping context." date: "$Date$" revision: "$Revision$" diff --git a/library/server/wsf/src/support/wsf_cookie.e b/library/server/wsf/src/support/wsf_cookie.e index 9a011a86..2b9f57c2 100644 --- a/library/server/wsf/src/support/wsf_cookie.e +++ b/library/server/wsf/src/support/wsf_cookie.e @@ -7,7 +7,6 @@ class WSF_COOKIE inherit - HTTP_COOKIE create diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e index ea559543..79c69336 100644 --- a/library/server/wsf/src/wsf_execution.e +++ b/library/server/wsf/src/wsf_execution.e @@ -25,6 +25,7 @@ inherit feature {NONE} -- Initialization make (req: WGI_REQUEST; res: WGI_RESPONSE) + -- Create Current execution with request `req' and response `res'. do Precursor (req, res) create request.make_from_wgi (wgi_request) @@ -39,7 +40,7 @@ feature {NONE} -- Initialization end -feature {NONE} -- Access +feature -- Access request: WSF_REQUEST -- Access to request data. diff --git a/library/server/wsf/src/wsf_execution_factory.e b/library/server/wsf/src/wsf_execution_factory.e deleted file mode 100644 index 04be7117..00000000 --- a/library/server/wsf/src/wsf_execution_factory.e +++ /dev/null @@ -1,32 +0,0 @@ -note - description: "Summary description for {WSF_EXECUTION_FACTORY}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WSF_EXECUTION_FACTORY - -inherit - WGI_EXECUTION_FACTORY - redefine - execution - end - -feature -- Factory - - execution (req: WGI_REQUEST; res: WGI_RESPONSE): WSF_EXECUTION - deferred - end - -note - copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end From 48cb99498c90e9ff9f827e3e54206ec160a2595c Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 15:09:04 +0200 Subject: [PATCH 12/33] Cleaned simple example, and made the standalone target with SCOOP concurrency. --- examples/simple/application_execution.e | 2 +- examples/simple/simple.ecf | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/simple/application_execution.e b/examples/simple/application_execution.e index decbde71..b02bdf55 100644 --- a/examples/simple/application_execution.e +++ b/examples/simple/application_execution.e @@ -20,7 +20,7 @@ feature -- Basic operations do -- To send a response we need to setup, the status code and -- the response headers. - s := "Hello World!" + s := "Hello World!" response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", s.count.out]>>) response.set_status_code ({HTTP_STATUS_CODE}.ok) response.header.put_content_type_text_html diff --git a/examples/simple/simple.ecf b/examples/simple/simple.ecf index 1f7ea4c9..cfbf36fd 100644 --- a/examples/simple/simple.ecf +++ b/examples/simple/simple.ecf @@ -1,12 +1,12 @@ - + /EIFGENs$ /CVS$ /.svn$ - @@ -15,15 +15,16 @@ - + - @@ -31,7 +32,7 @@ - @@ -39,7 +40,7 @@ - From 9d20e85c0394c1d12d42204630355cef47935d2d Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 15:33:47 +0200 Subject: [PATCH 13/33] Improved the simple_file example with image, and not found message. Use standalone connector in SCOOP concurrency mode. --- examples/simple_file/404.html | 12 +++++++++++ examples/simple_file/ewf.png | Bin 0 -> 12314 bytes examples/simple_file/home.html | 4 +++- examples/simple_file/service_file.ecf | 7 ++++--- examples/simple_file/service_file_execution.e | 19 +++++++++++++----- 5 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 examples/simple_file/404.html create mode 100644 examples/simple_file/ewf.png diff --git a/examples/simple_file/404.html b/examples/simple_file/404.html new file mode 100644 index 00000000..2c11720c --- /dev/null +++ b/examples/simple_file/404.html @@ -0,0 +1,12 @@ + + + 404 not found! + + + +

    404 not found!

    + This is a static html file served by EWF. + + + + diff --git a/examples/simple_file/ewf.png b/examples/simple_file/ewf.png new file mode 100644 index 0000000000000000000000000000000000000000..5a825a4f38669edeef2fbea03810f57dbcd9c2de GIT binary patch literal 12314 zcmXw91yq#p(_LCxkWK+9>5`W2?k;Kg(cLH@Eg~)5-6GxH-3`*+4d286oX>MsmgVg3 z`_40S=gz$oswgjkibQ|}fk05DBt@0M&pz-_d;<^u*R|oP06$=zgr!v9fPda^OhUl# zi1w0NP7nzE;p+p6#D$9kyom2Crs=F=XXfl?7M1@q{Q;t$Syk%z}dRN`3l3}%ecH?|8_(hdlkd^6c6`5ON<4}4pGZA*~8Z_qMo&X=)=^^31|B3fyeL={|?{I67P=F zDEBD$4tH3HV#F7$PQL%roT1X7Eg%LNdwSdm-bnvG_X}fh?)je!%zfj6k*kvk=@BgS zcDROW{;CpHYtik#aM~*PlVFKLL?wgqyLvWr4os(iIjP=w*x8@W*2wp0f+DhrO2?%8 zj~Kh?AD%_{yKiwfR^@-5C;nR3YMap&ZPp*HH13^ibYsG0(*JiLaiN>gM$M(Ijh5l zXlPg%CPp+<%dIfPa;hLYh0lZ4&lN#5=UL^HK5UDn?;TT{&j1QW^k4$h;BO9Vlc@rw zi6##xTBR&eDB*u`e{B{AwgwZrLkbFLXjSqe*zHzyMNwdjH7m1FNcc2GMZXvuPydmZ zm#;ExhwcyNC1+I?jm=+6!WyKArPlX<_(?$ii<11j9f4GnQgmg27$2Wje5t`jX2pFI zmBV{$AdZ~8%Ja$!D#!Qfo}4^u_Mm%scvw`U_Xja08JW=eIxfbUH&U8hB_FxR1{_V1 ziHS)Gr)#t`Pbw@NoED|TWS-pCRH4e3u6PEWoG;yBR_=G_Ta?t)5~8BeFfed$#gzW_ zL=uvdPn7D^Lh~#yFH`dHXrHft4}s<1+fkv95>Io73Zp3%czJXhx2ib@#}gJJsjdC{ z_Td4ypv%?OmDS_iqNEXYjNbe;E$l&&*BFq8TyJ!T_e#for1a}NZmD`Daf3Sc4 zn#cctc3(z|&jU_Dij`=KgcBT$Xsv29>^GAZ>>uwuuMf2fFbw;Ck~v=Ot6@ZY zD70UEj1Q()XoAd$=1&e=E!9+{a5AL)xfm$Czr)=H-i?V+EV}W{coWo{MAwx(=d)0KM zu|)Adh{@STH@JPvNvd#%@93nA7VM4cXp^{;_0JHO6WOOk#QOOwuh71M7y48 z-Oakse|DP`N=4PX^+1)nBb}}f&bJ7Cby+IYZ?i3emw4}T6 z$5O<~>Z4rpr>)cVPBWKyT9xlI35@G&Yl0vucXvDK!#!Tt^X8!7p)$Z(gRBgWrjVFu zaIxkXG4Olp9!g@5CiWsI8a+Arlu@rLwIJRX>x_ixpUR#=q?8{Ad`QC>vXu-9)|XOxHV&Y+N5%cv<)DSc@v^mdOInG&si4s>+%PyfxeJ>Fe_gxP5O3d3$O<_`{>j65eN zXRJ_#8uQ(|LhYK5AWgbQMn+W2)dw?#0w5tFA%f+z$-}FwtLfe0xSRj}!QyGBUS2wP zbasOL#sS%_)(pI3{J3*BN+H0_{wpmp zXiZbjl|H+gHMrP}5>Wp8pVr3aCL#*T2X=NxCK>pZmv*Vy!M+z4^^^vs&J8s5&IwsI()KVDz* zW~uYM)EIfJ4`K6TBtPm&65ccj302-S&lULn^q)f9>EC87(gr6ezCi9&hZymt3dhF#UK;EFE_fAg6kcoU}wqFx; z@s3VP>c3g_8$Fz_o}Qtlr;iwjqr2D$XR0zA{tfNXeAW9+A-{u7Nc9w1IGdv}|G9g7#zUx9mK-iS- z^%NbuS4bua#~F0XZ*VcAW5?ooX~9l_%4xS^(&i6UqStuc;v7lD{Y$&XYW%N_j(Uk^ z<_~;Ey@oDOPJ8p!`8?uMl9KPq$-njWN!l*e8D*J2Tpzt2;Gh5IC+LN=YY#dyb#59o z5UKx0dp_lKJL)}pVe4Nlj$bZgcYo*)j>tj&$bCqpXMbH}&EdOI|MK3G7{ZACR8h%v zCpmC6^)|=ONk@9?Z)a~Wf`23-=lOBti6cPohnd{Tz1`(TPS94}y}TwfMGzn#)k`GP zKl?zq+)v+En+Xm;?H4?XM)$5ABTXoGGIE{cI@pR_{PN}+7#UU*pkxA#zLfB00i zkZ*rRN4NJyQzQxawanKsGBScJ`;E=S#B}8~Uu8OOA^T#FVYJy3IrN(&9CSY%?J}Fi zzfg*`wt7p;%k{ob4FuaKC!^gZVgBs|d9zzT@mdv7Z#4XXYPjh`F23a3#YeRKXfFOyC4r3NesSI=K$3WQ!w z=?9?(J5qDp4J*z0|M{jay=`VBgbRxAtaT)#3JWxDjZSim{ABzL{r;%O60MX}Vx!(? zNvZ|fKg;5@Xf@5eK{n5%e&6E-R^AqU=ka;#g8_HMu1lq4NeLdtt>)JsdVUE8G=pJdRYD98hYg0Kr7Nk~YzxVW&g##yn%$S5g;0uaz~ zXnnoC`F2Lrdlwgz+u8)Pva+Ts&{7-hANToH&Pu~8cdOVU@Rj~*t8g4%n@&FJe!L~P zJkc9iEtV+Qljibrpxz?z)I;03VW8OB$IyUGO}`F=D1u}#w6t0fmhj=1`;=8K=GIagC5V^s#n^icJTO8S!pOIT~j{bBwz|=sqdB3&b zpifdw8X3vokivVYcaEchww#)e6D(ZlOp7^|j~A*_v=2y(V9g0P6I{~CBp zPI;$;38(>8%dXH>v!Z`AT4g+=&6WPFY6Re&LcYni?}KJWFlMEp)L&w9E?B_HLD@T( z_Eqz5uc_BV&Hk`6T6KGxI;To|K*xS+TvJ}rkV|&GNV$JH{f=mohu3ggqZ7rReDaP` zk`^K8IP$+bpNCI7BdOJzdy(mYQmS78q7hl%a*xEx$q9P%_`www!w8sK-eLg4*ALFe zV>6NykIVl3+1VM6i|yiHIm!?W(5yD&ZHNW)^&1_o^-ZPgT~jzHbjNpo|F9vF_L}%| z3eT?1`(-vlw45!m_}~v}Zb?*TH|>!UVFFT%Rq@X>3wPrLn$+O;T9y!^7aMpGb_bA) zvkFHL6xe?0W}!!Ym^f3YiUjHT*;spJu5k&j?>mo}zio8vSvKw$C4XUDR1fd@;owIo!OHmg*4B+podpn~)MFE)%}y!WGA&Njqt~ zLf98~=3Ax+^L#+f0B20{ zJ{0iCpXeH1Yc24^<^{^Yb@Hb+YKTWIl*&@zj%BJxp0jdTVj@W1#|K4mlDd2>x<9^SN9)KnR z4vqBn>(|HAPISJ>5;j7{WwsM418(7wRFf;W&CfCw4C@iuGH}v$s$C=F-J<5w9a1$e z;}$k@+QCDy)+S3wJJ~c`tHk91Y_lpWCDN0{Y}I)rKFJ9u#7J#@FW)>=!$mM>ny^iw zI_jYvInqP&mw^*#B5Wz!whXM+&?C5H*RwPXjP#Mhii}@OK#z8!hGYIC{G$w8Zetlh zw0s`f(wrE(d5to=cFIx{cePWdXKAb#Y7AE%b_?yy&-A*Uc-;4AOZtx0sIU$+M^gQK zADkIa1|uhVF`9pf9P~yzuNWFuOx3V%gbwF$I`DSfo*8*xMjQEa_&&N@fdOB#$ZO1k zJ@EVYDz6(`tC^C1K!orwQv=v};Ahqk=~#;u2I=24Ozk2>;FzR9ILT7#KJP zq=6qK{L&z|LqbE>t4BX~0`mQV$(U}U%2bArkFU?g#so9%2Ay$BKVSgWb4~5WG-Ys> zNe~S}*yv?ld)YvwTt>|K_;y|Kk_-F-DdIRN*N%lqFV$GQ-ut6pi^%w#V)>J%$lNl^ zz`WjSfyvbYpAxZiJpE4gzEq1RmRNSKY@B#eox1n;#RRk>oQhjP7Z_me?WGAw2`q{#sU-r=jw0=i5P|wMtK0blm`KRU$zMk> zFhbF5|9O-9=K27PdzCH+>UpwB-%3jvS|87mTUuKFo2!8GUupK*+}IEXaRmB`gy>vl z=a>XK3JUvp4TwB6G;|`f5j1(nT%~bnczCu}wO3q+#j(wN6=f=~8`XBx-a>KHr^gO@ zX2VmpgwoK}8-7UclJ&-{$1f?KO+mecn9yApRiBoq1voa$u3Px4 zf~Q|nwFM?xq)XOII`&Oh;W&WMCAP++Z$yR2m%QW}*1y%D#$r#uE)6*&&TK@q#}J( z|LT|L8?^eGn43>#i6O6eo$wd$8TeeOp@F+>hV=)Ud7M z@ZSirNGqouS@~u6={^q*K)!;Qgp|@ zr}D8#-$C|!6DAx}+p0q6wh%d)^7tgPZLS2}6XLqZH!`+%^ z6`O4)4M9;Yo@Dr%1yMxHLas9!NI1WZ$=;UneKNjsjhNyab`uhz!hfca0>iVa<3JzZhe*gyQ&(F8Upcur!1=V?8eFU?d>Fw#dS-(q=5NUMP*Nx0)Ja?pi+y5nVC^1UJDKm zPL7OmJIe%5`rAGWqwEzxUea^4+S(d| zryKh*j2!facwi@lV$9FapTBBeT+P>4SJ)UHCsHq3-RHMkO6F@UhHd`;$;8!o-VI-2tAO|R@TB<}8iCU|!(eeYCS@~=uwefUeWqTj zO-T-qo8Ck5_B<>(IT>hjAt93Bn@fLnwzmtxqm$6{q{>G~%F6@sG%uvFv9a5k*X@|^ zG3TY=iwEmDO&kKydXx?31RpQ=CMQ4zhR02Ic8XlBkYHday?+cq|NIss`W>}A7T1Sf znx0LJ2pDGy--jbkV0KhW7lAGu8sdEpK8%|3NLcu=5sgG;yZL6N+DDQ2>t^qwGcjMD ztl{bzn!>&Bu?ERJ%NP*RcqUr?{NBxCK|w*$8?>Y>)L6q*IPWQcN5NMv-~|%UeT7Ls zW@jfF%D*UqX9&umuzdPwIWXYhfBFyam7h!PY;TK8O1=S@3!Dp7|71?PDnQsldj3!J zbsFV2=Qw%Q;@pmP{nq^JPcxuMr*R^EGt?+wAOx{?vtsh09Jn*4_7*CsX(Zbnim`(S z6nTm1aW&sE+Ktmha&X7cPNC1smP4X`Bx+B44|wh3@%2b#?|NlvG-N8m*~3K?D^`yy zQFyjbA;)t(vN;p5H(<~-hhcIKS9c*Sc689&ih6!{5W>X7^psEGQlbpbqS+@w<>lr5 z6%&KcZt+&&@l+)G(&yo*_HutZ{FBW>1;~uY$H%^*p&XEAs-@a-fBvw?(`#k*++1Fo zbcJA`5U_{*qC`D5EYq#;h`?vltg|P(zP@e((kv`2?Aqa>tfOO9P)a6v_iQC#e%<0l z?@{O`BKh8kUPGH9X1(iHQ0fw1afHyY3Vr(~vIynmzmG#f8(Wc=y}35-!k$GxCCDaP zFM+5sXUP#YV;Y_{J|#xapWq!rja4D}Q$k7cVZPd20uL7v6kXbIGAA2Qbq@~@=bF7Z zpP!$_sDd$o6+^POw+Fax0OC6;$c_3D$dg(iT(2D+$+^38ff?5r{4thZ>(}kAJ3J~u zU{n-3Q2NOE`BQUpJ^&8luU@Qn6Py?j9*$fJRPNok2dyZn2*GGDzC8roNYgA0x#F>{ z{vEZj&*7(Ih`_yRK?M2W02N@c4CJ3z+25ImINkT2mO=YZMFYYT=196gxosH%x8ny8 zm#wV?198#0DpTZeT&8W{6#z304*>z;2dMx^FrNaYZ1{_vQKkx4x)UlInccBW7!Y8A zWjCW2v0c6oe}di^81DHPz&hje{rweEg>+kfvGG)axWNIiDjI@}L%-Hb>i3FKDFS|J zKz-`y=l~obXs;sV^wi$&*UbblZ2=(hanFKVL zX#qR^xy41`U?dwrU8GgLAdk7U1y4f;?cTsRw{ZuyiqWhoX|wzXb)*t_SVsOB*>R@( zhdW5Z&z^>ylevWU5#9dp&t3JiG59@hZf;a3N5_TZ`Dz4^>k|_bZx9h#@cDEC#IrMj zQK(w3uNMcV>caG%3m!0VqYIeaUp}zSeW0cWewj=FJn9=16#6xSr|s zLa`ybi6*eM80_w{2BJ6u z1!ckFZ*_DQ=bJsRl-un2w7?9DoRV*3Y#dNqTPwB285R|#0A-FS4tybpyK~czss)Ch zya!@wRSOiqDtx}nktA7*ocn7-h)TfDe2~)Mv@_yqXdE4fjVd)Bt&+dpI_Gk0kE<8| zPyPa%T0IVEh9%p7Up}3D~QvsIeE#n`TArSQN*IfV#4vsh=bU55!T8^Y}8=r$p zv>e}$OHP&n4qE4T)Xg{zeX9+c&0#~<4wXkC( zmDh5n1RrP$czBX8&rh$i79`}y4>MqB!d*A-NC3@1Qd+vBrw1M=?9(woq7)cCUT&0t zVk`N`93b4FNu5QJH#6c_xwZI?NSfE|`)`?yNo#exkdz$TrW1A==f7E4rYmCHq{J+_ z((UJwX-EUR9h1plnW=aj_op(}#`Og6&Y)aM!hfVJbSv9OVNgh$m@Pz#WuglEoTuO> zB3L3x(`Q9!;c|N>z{T=@zS{xTW+D!Q_E@8vUCYz84mkw{A`(&-Ag~dH zoIkjowl)8xs# z`q?F5<#2~RVqo!kHgwAMIw&a_MRg^fE0k(t`;X1dX#y$+jKnPAAf%?-jqs+65#Cpo z2CNkT*fn^s3?Lb^2X~i~3YNdF)(JOB$ez`m|eR_(^4IhNRNwvWtefRRqZ<*=%djfWl>|Bh-77A{zR7Mb^JmKQoK zDor-qpxLqAqFvx(HqD}dmC*C;W>g;#in!rmVHL~u`NMZ&aIt$RX=A7rdS+(g0m&Z+ zF#?n@EH#xF1|9{XcvD)g-~1b&&1`LFMof?tnS<0#f}QdMg&I5Bvw<+R$uLK<)zt znCEC3;Pe;R$8jd04Zk)cTL0;U%bwpv0qn6FYXf`VgszB(0 z(W(Sp|5Sf4o&gsxN~KJvmJt|&z}9(7K%i~HbOc%#i*XOLQ3vcFZH8AJ7CiQOXekId zZA;KbV4$Hx!W%g`)$1Kifx@VS1xHFs3P8o2r4=m0II!n4 z2=);`nqS=zL~hH4OCt%9sh4D}35;W?Bx8}3GKa@{(5dS?lkk}}#UT#-+YKp%;oa~x4rdFJHAFA5ZcDGCGhzdP6d3x$^zfRf9njXjg7po$`zp3qQ%oy9v5bh zPfy4{VUBA^0B&%QA!weMZS{i0F3>0^N%wo^2809*Zvm~(_u-e$ojFd)pKO4Z5LM)* z7UBIi@{7%uot3Nl%;C3C=i<`6q4C`VP2^UCrJMIYpaHM}I;p%iv<$9h0{E@3UJe*j zEXFdR@bU4@T)@Uj7*KQ9_x3{N^NpA48~~Gnb1F^B&!+}n#7BEO`!rG|C8bvk0~pL^ z{Qash900j^6v;67m{&Rq1kE0>fq<8S`e>yl#6m&<+ig&3GOE^BQC;&uWue%zM(f)aQdb+h(Ygb#xeh*9n z6e6yl03rcF?E-sD(`>v02~49v@R>%H2Jzk~tzFsJmKz*=Wxse_V-?9RfYsqF#}hPa zfe37aHfwZ!_>G~O8_1Txa2EohkJR5Jb-CG>cJBH!OX@)Kg5-=svRPEm+y1DS8C`|0 zrl&-q-{fBTx~@|C(2fAeUG8tA*1K&&AnsZ${(U8hulW6MdmEF0KpM#ECBI-Y!071i z?p`oMV_ji3%!&ZaA}YDxUEp-5D6rils&`%v?5FxE&Y;Ueuo`?1eHEv0L=n-^4a|mx zV{t{kqhyMO;{fZu8eovOx3?lz5Fo|p_Xp+GAoDunz;U;LY=EW0XE@V6Obah`fij&rt&$%*$L@szc4vhLueZZ!f!M=JXf%^s@G$OiA%qB#g zO_8T9PYVp54`y*ocZ|!Dx4>AXsfh=Cw$}~~oHr-Ht~_s!Bh%AKL6gb_ zeCsr)QGZC1$iYk;}z{W24ZT zkdUC=-wI?K@)KiD?P{Ph3W4Om`xm1S5*20sczXuc+?>`s;DCswkjmo%f}7O9PzyGH zLff9nO_d{p;hXzBE2?ZYqN4)7Nhln#yr1IsQ>+!rUgAYZBaYX)9zlc){WHz|`$~?g z-f>DBUsOq32f3CfCM_vRD;Fe-Iq3KXG|?bgH0vF68ysE1*IypYMuFAjhp!8n zpoGdH2l>I;g1zn82Nsvo=2zc36j9J-hlGN^c?v&|xo-=2EC!7cw@tt5BBAdnCPb3Wkg~NCqbEgmZ{p0d)b&?@qg&L+tqn zrFJe3F88SPh{cp*ykZms2H5+b4@AOhck36y?+pwa3EXqg{bxl>Y7z=V_un9z5^>Pj*emT1e# zJPZ<&vNYFZ(w9G8xzlu`Asw+<;u5FsV@(ie3mw|9rDc6fQ>OH_OqwcGL5yXdwu&&# zVw=48V)KXpOk~l2%6mfIBK*{6T$ZEzZ377^RaFkOQ$mTp4J6n`npkph!}nfFBcc{m##M> zY5aq+v?>5Q)H(^+E!se-GXVGk1NnTLU67e-gv7T3IF%R-(_IlIs)2$Z?Z&zn2I`8w zzKU`2Z?Z(i#Tjd^ufd8SkJt5~Qlo6o7UkWnG(HR1vtrb(^9Kek7}_}r5spzu6jHd1 zu2Y0wYYC6fo!NXOWj&m!rEPgR70kzP!4U)@!`GJ2c7g7*F1jOq zeRbzxDl@x0UQPyTO*sBC*icF1_uAgQ0yx@ozkfx-?}>F9f41Z_x&_wym@y=O1HE|O z(g`ewg7H7uXQL~03iO^>&|LCAeE5)qM)--o5$tM#o2~+4ApQGhAZx}epumCGa@`yq zKTg#su#oW2h{+>MC@qKxt?Gz<>%d7B-+ax)wt)>BBcuBIPfb6*sfEXLClUt$acK~j zdB;Zw-TN7A*Nq@3Vs*pZ5)>H34jp@nJ*tYffK6q`o{9q5tA)RQFVE=y(_vY2kO%)q zpGpBoCnsup{ifTY0nm#m<*7=gV{{VO!e?19TzW&1J zDLR^5RWA{R=)yK=f+DJP4;_>`>n#@;7bdQS!*3U+M)$9Wdy?@Ak1x|R&!j0J3#GFo zkwRbyQ&jZ(mjY*XGIB)0-i{3|$z+s7eqU8l$FIV(L*bHW6{ls1$fNKi`x`Znee{Jo zCy8b%yU`Hzut)tjDy%Y(|8^5?`=!lrT(7yUWPV#ana5-~)sw-u1cdDC$D^F zPs&js^4Il2JXCeOEL;eQliViG9?rjUVb4Ud(6Pod`{2ZS;n;O6T0M@PRaI4^8%^Cx z?VYg1k``Uo5Voo+oo1~Z2luWBl-LtfcfCw@0

    EWF simple_file example

    - This is a static html file served by EWF. +

    This is a static html file served by EWF.

    +

    Try to get lost.

    + diff --git a/examples/simple_file/service_file.ecf b/examples/simple_file/service_file.ecf index 2a023343..9674713e 100644 --- a/examples/simple_file/service_file.ecf +++ b/examples/simple_file/service_file.ecf @@ -1,14 +1,15 @@ - + - + - + diff --git a/examples/simple_file/service_file_execution.e b/examples/simple_file/service_file_execution.e index 4fc0aacf..1fc98f91 100644 --- a/examples/simple_file/service_file_execution.e +++ b/examples/simple_file/service_file_execution.e @@ -1,6 +1,5 @@ note - description: "Summary description for {SERVICE_FILE_EXECUTION}." - author: "" + description: "Simple file execution, serving home.html, ewf.png and 404.html" date: "$Date$" revision: "$Revision$" @@ -17,10 +16,20 @@ feature {NONE} -- Initialization execute local - f: WSF_FILE_RESPONSE + mesg: WSF_RESPONSE_MESSAGE + not_found: WSF_NOT_FOUND_RESPONSE do - create f.make_html ("home.html") - response.send (f) + if request.path_info.is_case_insensitive_equal_general ("/") then + create {WSF_FILE_RESPONSE} mesg.make_html ("home.html") + elseif request.path_info.is_case_insensitive_equal_general ("/ewf.png") then + create {WSF_FILE_RESPONSE} mesg.make_with_content_type ({HTTP_MIME_TYPES}.image_png ,"ewf.png") + else + create not_found.make (request) + not_found.add_suggested_location (request.absolute_script_url (""), "Home", "Back to home page") + + mesg := not_found + end + response.send (mesg) end end From 89e26519e4336f24fb5dcf2b5909bd1645d73119 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 17:29:53 +0200 Subject: [PATCH 14/33] First step to improve a bit error handling related to socket disconnection. Mainly in standalone connector for now. --- .../connectors/cgi/src/wgi_cgi_output_stream.e | 7 ++++++- .../libfcgi/src/wgi_libfcgi_output_stream.e | 7 ++++++- .../nino/src/wgi_nino_output_stream.e | 11 ++++++++++- .../null/src/wgi_null_output_stream.e | 7 ++++++- .../src/httpd/httpd_request_handler_i.e | 7 +++++-- .../src/httpd/network/httpd_stream_socket.e | 17 ++++++++++++++++- .../implementation/wgi_httpd_request_handler.e | 7 +++++-- .../src/wgi_standalone_output_stream.e | 17 +++++++++++++++++ .../standalone/test_standalone-safe.ecf | 1 + .../response/wgi_filter_response.e | 4 ++-- .../specification/stream/wgi_output_stream.e | 8 +++++++- .../src/implementation/wgi_response_stream.e | 2 +- 12 files changed, 82 insertions(+), 13 deletions(-) diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e index 0a5dea0c..a0abbb22 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e @@ -70,8 +70,13 @@ feature -- Status writing end end +feature -- Status report + + is_available: BOOLEAN = True + -- + note - copyright: "2011-2011, Eiffel Software and others" + copyright: "2011-2015, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e index cbe0f762..33987d68 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e @@ -38,6 +38,11 @@ feature -- Status report Result := True end +feature -- Status report + + is_available: BOOLEAN = True + -- + feature -- Status writing put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8) @@ -100,7 +105,7 @@ invariant fcgi_attached: fcgi /= Void note - copyright: "2011-2011, Eiffel Software and others" + copyright: "2011-2015, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e index 3b595927..f45f9cdd 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e @@ -79,6 +79,15 @@ feature -- Status report Result := target.is_open_write end +feature -- Status report + + is_available: BOOLEAN + -- + -- FIXME: see how "standalone" connection is doing that. + do + Result := target.is_open_read + end + feature -- Basic operations flush @@ -86,7 +95,7 @@ feature -- Basic operations end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e index 21d95864..1d3be84b 100644 --- a/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e +++ b/library/server/ewsgi/connectors/null/src/wgi_null_output_stream.e @@ -70,8 +70,13 @@ feature -- Status writing end end +feature -- Status report + + is_available: BOOLEAN = True + -- + note - copyright: "2011-2011, Eiffel Software and others" + copyright: "2011-2015, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index b27bb173..c2f4e589 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -176,6 +176,7 @@ feature -- Execution l_remote_info: detachable like remote_info l_continue: BOOLEAN l_socket: like client_socket + l_ready_for_reading: BOOLEAN do l_socket := client_socket check @@ -190,9 +191,11 @@ feature -- Execution debug ("dbglog") dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER") end + l_socket.set_timeout (5) -- 5 seconds! from until l_continue loop - if l_socket.try_ready_for_reading then --- ready_for_reading then + -- Use timeout from l_socket! + l_ready_for_reading := l_socket.ready_for_reading + if l_ready_for_reading then l_continue := True create l_remote_info if attached l_socket.peer_address as l_addr then diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/network/httpd_stream_socket.e index e9221910..4f4f1154 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/network/httpd_stream_socket.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/network/httpd_stream_socket.e @@ -46,12 +46,27 @@ feature {NONE} -- Initialization do Result := s.socket.descriptor end + feature -- Change + set_timeout (n: INTEGER) + do + if attached {NETWORK_STREAM_SOCKET} socket as l_socket then + l_socket.set_timeout (n) + end + end + + set_connect_timeout (n: INTEGER) + do + if attached {NETWORK_STREAM_SOCKET} socket as l_socket then + l_socket.set_connect_timeout (n) + end + end + set_accept_timeout (n: INTEGER) do if attached {NETWORK_STREAM_SOCKET} socket as l_socket then - l_socket.set_accept_timeout (500_000) + l_socket.set_accept_timeout (n) end end diff --git a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e index c709ec8d..e00743a3 100644 --- a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e @@ -62,7 +62,7 @@ feature -- Request processing -- Process request ... local l_input: WGI_INPUT_STREAM - l_output: WGI_OUTPUT_STREAM + l_output: detachable WGI_OUTPUT_STREAM l_error: WGI_ERROR_STREAM req: WGI_REQUEST_FROM_TABLE res: detachable WGI_STANDALONE_RESPONSE_STREAM @@ -84,12 +84,15 @@ feature -- Request processing res.push exec.clean else - process_rescue (res) + if not has_error then + process_rescue (res) + end if exec /= Void then exec.clean end end rescue + has_error := l_output = Void or else not l_output.is_available if not retried then retried := True retry diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e index 7f95ec22..8fbeb459 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e @@ -26,6 +26,7 @@ feature {NONE} -- Initialization make (a_target: like target) do set_target (a_target) + last_target_call_succeed := True end feature {WGI_STANDALONE_CONNECTOR, WGI_SERVICE} -- Nino @@ -37,6 +38,9 @@ feature {WGI_STANDALONE_CONNECTOR, WGI_SERVICE} -- Nino target: HTTPD_STREAM_SOCKET + last_target_call_succeed: BOOLEAN + -- Last target call succeed? + feature -- Status writing put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8) @@ -65,22 +69,35 @@ feature -- Output put_readable_string_8 (s: READABLE_STRING_8) -- Send `s' to http client do + last_target_call_succeed := False target.put_readable_string_8 (s) + last_target_call_succeed := True end put_string (s: READABLE_STRING_8) -- Send `s' to http client do + last_target_call_succeed := False target.put_readable_string_8 (s) + last_target_call_succeed := True end put_character (c: CHARACTER_8) do + last_target_call_succeed := False target.put_character (c) + last_target_call_succeed := True end feature -- Status report + is_available: BOOLEAN + -- + -- for instance IO failure due to socket disconnection. + do + Result := not last_target_call_succeed + end + is_open_write: BOOLEAN -- Can items be written to output stream? do diff --git a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf index cdc30795..f56141dd 100644 --- a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf +++ b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/specification/response/wgi_filter_response.e b/library/server/ewsgi/specification/response/wgi_filter_response.e index 81d1b28a..f9b14d70 100644 --- a/library/server/ewsgi/specification/response/wgi_filter_response.e +++ b/library/server/ewsgi/specification/response/wgi_filter_response.e @@ -1,6 +1,6 @@ note description: "[ - WGI response acting as a filter. + WGI response acting as a filter. ]" date: "$Date$" revision: "$Revision$" @@ -147,7 +147,7 @@ feature -- Error reporting end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/specification/stream/wgi_output_stream.e b/library/server/ewsgi/specification/stream/wgi_output_stream.e index 39d8dcd7..aa731ece 100644 --- a/library/server/ewsgi/specification/stream/wgi_output_stream.e +++ b/library/server/ewsgi/specification/stream/wgi_output_stream.e @@ -74,6 +74,12 @@ feature -- Status writing feature -- Status report + is_available: BOOLEAN + -- Is output available? + --| i.e: no issue with associated output stream, like closed socket, or related? + deferred + end + is_open_write: BOOLEAN -- Can items be written to output stream? deferred @@ -93,7 +99,7 @@ feature -- Constant crlf: STRING = "%R%N" note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/src/implementation/wgi_response_stream.e b/library/server/ewsgi/src/implementation/wgi_response_stream.e index a7610d42..73edf89a 100644 --- a/library/server/ewsgi/src/implementation/wgi_response_stream.e +++ b/library/server/ewsgi/src/implementation/wgi_response_stream.e @@ -128,7 +128,7 @@ feature {NONE} -- Implementation: Access -- Server output channel ;note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software From 3165c1e5c6f631f0de8a5176d7c806fbca98605b Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 19:31:27 +0200 Subject: [PATCH 15/33] Enable support for persistent connections. (test: works fine with curl -k , but weird behavior with ab -k ...) --- .../src/httpd/httpd_request_handler_i.e | 44 ++++++++----------- .../standalone/src/httpd/httpd_server_i.e | 2 +- .../standalone/test_standalone-safe.ecf | 5 ++- .../standalone/tests/test_execution.e | 7 +-- 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index c2f4e589..1f987381 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -174,7 +174,6 @@ feature -- Execution is_connected: is_connected local l_remote_info: detachable like remote_info - l_continue: BOOLEAN l_socket: like client_socket l_ready_for_reading: BOOLEAN do @@ -192,25 +191,20 @@ feature -- Execution dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER") end l_socket.set_timeout (5) -- 5 seconds! - from until l_continue loop - -- Use timeout from l_socket! - l_ready_for_reading := l_socket.ready_for_reading - if l_ready_for_reading then - l_continue := True - create l_remote_info - if attached l_socket.peer_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 - remote_info := l_remote_info - end - analyze_request_message (l_socket) - else - has_error := True - l_continue := True - debug ("dbglog") - dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + "} WAITING") - end + l_ready_for_reading := l_socket.ready_for_reading + if l_ready_for_reading then + create l_remote_info + if attached l_socket.peer_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 + remote_info := l_remote_info + end + analyze_request_message (l_socket) + else + has_error := True + debug ("dbglog") + dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + "} timeout!") end end @@ -310,11 +304,11 @@ feature -- Parsing l_connection.is_case_insensitive_equal_general ("keep-alive") else -- By default HTTP:1/1 support persistent connection. - if - attached request_header_map.item ("Connection") as l_connection and then - l_connection.is_case_insensitive_equal_general ("close") - then - keep_alive_enabled := False + if attached request_header_map.item ("Connection") as l_connection then + print ("Connection -> " + l_connection + "%N") + if l_connection.is_case_insensitive_equal_general ("close") then + keep_alive_enabled := False + end else keep_alive_enabled := True end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e index 2c3d9c6c..15caf568 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e @@ -58,7 +58,7 @@ feature -- Access factory: separate HTTPD_REQUEST_HANDLER_FACTORY - is_persistent_connection_supported: BOOLEAN = False + is_persistent_connection_supported: BOOLEAN = True -- Is persistent connection supported? --| For now, disabled during dev. diff --git a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf index f56141dd..4bb190b4 100644 --- a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf +++ b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf @@ -1,4 +1,4 @@ - + @@ -10,7 +10,8 @@ - + + diff --git a/library/server/ewsgi/connectors/standalone/tests/test_execution.e b/library/server/ewsgi/connectors/standalone/tests/test_execution.e index c02a3c65..cb99663c 100644 --- a/library/server/ewsgi/connectors/standalone/tests/test_execution.e +++ b/library/server/ewsgi/connectors/standalone/tests/test_execution.e @@ -22,9 +22,10 @@ feature -- Execution s: STRING i64: INTEGER_64 do - i64 := {INTEGER_64} 1_000_000_000 - s := "Hello Concurrent EWF" - s.append (" (counter=") + i64 := {INTEGER_64} 1_000_000_000 + s := "Test Concurrent EWF [" + s.append (request.percent_encoded_path_info) + s.append ("] (counter=") s.append_integer (next_cell_counter_item (counter_cell)) s.append (")%N") From 7e057b20b15fe8b674618ab92ece5f50859381a0 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 20:11:30 +0200 Subject: [PATCH 16/33] Improved support for HTTP/1.0 persistent connection. --- .../src/wgi_standalone_response_stream.e | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e index 4510addb..1823bcaa 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e @@ -18,23 +18,47 @@ inherit create make -feature -- Header output operation +feature -- Header output operation put_header_text (a_text: READABLE_STRING_8) local o: like output + l_connection: detachable STRING + s: STRING + i,j: INTEGER do o := output - o.put_string (a_text) + create s.make_from_string (a_text) - if not {HTTPD_SERVER}.is_persistent_connection_supported then + -- FIXME: check if HTTP versions 1.0 or else. + + i := s.substring_index ("%NConnection:", 1) + if i > 0 then + j := s.index_of ('%R', i + 12) + end + if {HTTPD_SERVER}.is_persistent_connection_supported then + if i = 0 then + s.append ("Connection: Keep-Alive") + s.append (o.crlf) + end + else -- standalone does not support persistent connection for now - o.put_string ("Connection: close") - o.put_crlf + if j > 0 then + l_connection := s.substring (i + 12, j - 1) + l_connection.adjust + if not l_connection.is_case_insensitive_equal_general ("close") then + s.replace_substring ("Connection: close", i + 1, j - 1) + end + else + s.append ("Connection: close") + s.append (o.crlf) + end end - -- end of headers - o.put_crlf + -- end of headers + s.append (o.crlf) + + o.put_string (s) header_committed := True end From d9cbc720585e531f4e86d043b745f9b2d98a7065 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 22:41:43 +0200 Subject: [PATCH 17/33] Better support for HTTP/1.0 and also related to persistent connection. --- .../src/httpd/httpd_request_handler_i.e | 26 +++--- .../wgi_httpd_request_handler.e | 7 ++ .../src/wgi_standalone_output_stream.e | 7 +- .../src/wgi_standalone_response_stream.e | 92 +++++++++++++++---- .../specification/stream/wgi_output_stream.e | 13 +++ 5 files changed, 116 insertions(+), 29 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index 1f987381..8e701145 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -39,7 +39,7 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) - keep_alive_enabled := False + keep_alive_requested := False end feature -- Status report @@ -85,8 +85,10 @@ feature -- Access remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER] -- Information related to remote client - keep_alive_enabled: BOOLEAN - -- Inside a persistent connection? + keep_alive_requested: BOOLEAN + -- Persistent connection requested? + -- either has "Connection: Keep-Alive" header, + -- or is HTTP/1.1 and no header "Connection: close". is_http_version_1_0: BOOLEAN do @@ -117,7 +119,6 @@ feature -- Change set_is_verbose (b: BOOLEAN) do is_verbose := b - print ("set_is_verbose " + b.out + "%N") end feature -- Execution @@ -164,7 +165,9 @@ feature -- Execution n := n + 1 -- FIXME: it seems to be called one more time, mostly to see this is done. execute_request - l_exit := has_error or l_socket.is_closed or not l_socket.is_open_read or not keep_alive_enabled + l_exit := not {HTTPD_SERVER}.is_persistent_connection_supported + or has_error or l_socket.is_closed or not l_socket.is_open_read + or not keep_alive_requested reset_request end end @@ -297,20 +300,19 @@ feature -- Parsing line := next_line (a_socket) end end - if not {HTTPD_SERVER}.is_persistent_connection_supported then - keep_alive_enabled := False - elseif is_http_version_1_0 then - keep_alive_enabled := attached request_header_map.item ("Connection") as l_connection and then + -- Except for HTTP/1.0, persistent connection is the default. + keep_alive_requested := True + if is_http_version_1_0 then + keep_alive_requested := attached request_header_map.item ("Connection") as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") else -- By default HTTP:1/1 support persistent connection. if attached request_header_map.item ("Connection") as l_connection then - print ("Connection -> " + l_connection + "%N") if l_connection.is_case_insensitive_equal_general ("close") then - keep_alive_enabled := False + keep_alive_requested := False end else - keep_alive_enabled := True + keep_alive_requested := True end end end diff --git a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e index e00743a3..0f4ad723 100644 --- a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e @@ -76,6 +76,13 @@ feature -- Request processing create req.make (httpd_environment (a_socket), l_input, connector) create res.make (l_output, l_error) + if is_http_version_1_0 then + l_output.set_http_version ({HTTP_CONSTANTS}.http_version_1_0) + res.set_http_version_1_0 + else + l_output.set_http_version (version) + end + res.set_is_persistent_connection_requested (keep_alive_requested) req.set_meta_string_variable ("RAW_HEADER_DATA", request_header) diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e index 8fbeb459..29c38300 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_output_stream.e @@ -50,7 +50,12 @@ feature -- Status writing m: detachable READABLE_STRING_8 do create s.make (16) - s.append ({HTTP_CONSTANTS}.http_version_1_1) + if attached http_version as v then + s.append (v) + else + -- Default to 1.1 + s.append ({HTTP_CONSTANTS}.http_version_1_1) + end s.append_character (' ') s.append_integer (a_code) m := a_reason_phrase diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e index 1823bcaa..b9ccf59a 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e @@ -18,6 +18,28 @@ inherit create make +feature -- Settings + + is_http_version_1_0: BOOLEAN + -- Is associated request using HTTP/1.0 ? + + is_persistent_connection_requested: BOOLEAN + -- Is persistent connection requested? + +feature -- Settings change + + set_http_version_1_0 + -- Set associated request is using HTTP/1.0. + do + is_http_version_1_0 := True + end + + set_is_persistent_connection_requested (b: BOOLEAN) + -- Set `is_persistent_connection_requested' to `b'. + do + is_persistent_connection_requested := b + end + feature -- Header output operation put_header_text (a_text: READABLE_STRING_8) @@ -30,26 +52,64 @@ feature -- Header output operation o := output create s.make_from_string (a_text) - -- FIXME: check if HTTP versions 1.0 or else. - i := s.substring_index ("%NConnection:", 1) - if i > 0 then - j := s.index_of ('%R', i + 12) - end if {HTTPD_SERVER}.is_persistent_connection_supported then - if i = 0 then - s.append ("Connection: Keep-Alive") - s.append (o.crlf) - end - else - -- standalone does not support persistent connection for now - if j > 0 then - l_connection := s.substring (i + 12, j - 1) - l_connection.adjust - if not l_connection.is_case_insensitive_equal_general ("close") then - s.replace_substring ("Connection: close", i + 1, j - 1) + -- Current standalone support persistent connection. + -- If HTTP/1.1: + -- by default all connection are persistent + -- then no need to return "Connection:" header + -- unless header has "Connection: close" + -- then return "Connection: close" + -- If HTTP/1.0: + -- by default, connection is not persistent + -- unless header has "Connection: Keep-Alive" + -- then return "Connection: Keep-Alive" + -- if header has "Connection: Close" + -- then return "Connection: close" + if is_persistent_connection_requested then + if is_http_version_1_0 then + if i = 0 then + -- Existing response header does not has "Connection: " header. + s.append ("Connection: Keep-Alive") + s.append (o.crlf) + else + -- Do not override the application decision. + end end else + -- If HTTP/1.1 and persistent connection is not requested, + -- then return "close" + if i = 0 and not is_http_version_1_0 then + -- Existing response header does not has "Connection: " header. + s.append ("Connection: close") + s.append (o.crlf) + else + -- Do not override the application decision. + end + end + else + -- persistent connection support is disabled. + -- Return "Connection: close" in any case. + -- Except for HTTP/1.0 since not required. + if i > 0 then + j := s.index_of ('%R', i + 12) + end + if j > 0 then + -- Replace existing "Connection:" header with "Connection: close" + l_connection := s.substring (i + 12, j - 1) + l_connection.adjust + if + not is_http_version_1_0 and + not l_connection.is_case_insensitive_equal_general ("close") + then + s.replace_substring ("Connection: close", i + 1, j - 1) + end + elseif not is_http_version_1_0 then + -- HTTP/1.1: always return "close" since persistent connection is not supported. + s.append ("Connection: close") + s.append (o.crlf) + elseif is_persistent_connection_requested then + -- For HTTP/1.0, return "Connection: close", only if client sent a "Connection: Keep-Alive" s.append ("Connection: close") s.append (o.crlf) end diff --git a/library/server/ewsgi/specification/stream/wgi_output_stream.e b/library/server/ewsgi/specification/stream/wgi_output_stream.e index aa731ece..8d02bdea 100644 --- a/library/server/ewsgi/specification/stream/wgi_output_stream.e +++ b/library/server/ewsgi/specification/stream/wgi_output_stream.e @@ -74,6 +74,9 @@ feature -- Status writing feature -- Status report + http_version: detachable READABLE_STRING_8 + -- Optional HTTP version. + is_available: BOOLEAN -- Is output available? --| i.e: no issue with associated output stream, like closed socket, or related? @@ -85,6 +88,16 @@ feature -- Status report deferred end +feature -- Element change + + set_http_version (v: like http_version) + -- Set `http_version' to `v'. + require + valid_version: v /= Void implies v.starts_with ("HTTP/") + do + http_version := v + end + feature -- Basic operations flush From c42af5b2deef08f57ab4d98639bc4c58aa9b142e Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 22:44:24 +0200 Subject: [PATCH 18/33] Following the spec, use "keep-alive" and "close" in lowercase for Connection header. --- .../standalone/src/wgi_standalone_response_stream.e | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e index b9ccf59a..d4863bde 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_response_stream.e @@ -62,15 +62,15 @@ feature -- Header output operation -- then return "Connection: close" -- If HTTP/1.0: -- by default, connection is not persistent - -- unless header has "Connection: Keep-Alive" - -- then return "Connection: Keep-Alive" + -- unless header has "Connection: keep-alive" + -- then return "Connection: keep-alive" -- if header has "Connection: Close" -- then return "Connection: close" if is_persistent_connection_requested then if is_http_version_1_0 then if i = 0 then -- Existing response header does not has "Connection: " header. - s.append ("Connection: Keep-Alive") + s.append ("Connection: keep-alive") s.append (o.crlf) else -- Do not override the application decision. @@ -109,7 +109,7 @@ feature -- Header output operation s.append ("Connection: close") s.append (o.crlf) elseif is_persistent_connection_requested then - -- For HTTP/1.0, return "Connection: close", only if client sent a "Connection: Keep-Alive" + -- For HTTP/1.0, return "Connection: close", only if client sent a "Connection: keep-alive" s.append ("Connection: close") s.append (o.crlf) end From d8ea9ba63cd08a3c60837fd3bf0a39a0c056b747 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 1 Apr 2015 22:51:20 +0200 Subject: [PATCH 19/33] renamed keep_alive_requested as is_persistent_connection_requested. --- .../src/httpd/httpd_request_handler_i.e | 16 ++++++++-------- .../implementation/wgi_httpd_request_handler.e | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index 8e701145..bf526b93 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -39,7 +39,7 @@ feature {NONE} -- Initialization create request_header.make_empty create request_header_map.make (10) - keep_alive_requested := False + is_persistent_connection_requested := False end feature -- Status report @@ -85,9 +85,9 @@ feature -- Access remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER] -- Information related to remote client - keep_alive_requested: BOOLEAN + is_persistent_connection_requested: BOOLEAN -- Persistent connection requested? - -- either has "Connection: Keep-Alive" header, + -- either has "Connection: keep-alive" header, -- or is HTTP/1.1 and no header "Connection: close". is_http_version_1_0: BOOLEAN @@ -167,7 +167,7 @@ feature -- Execution execute_request l_exit := not {HTTPD_SERVER}.is_persistent_connection_supported or has_error or l_socket.is_closed or not l_socket.is_open_read - or not keep_alive_requested + or not is_persistent_connection_requested reset_request end end @@ -301,18 +301,18 @@ feature -- Parsing end end -- Except for HTTP/1.0, persistent connection is the default. - keep_alive_requested := True + is_persistent_connection_requested := True if is_http_version_1_0 then - keep_alive_requested := attached request_header_map.item ("Connection") as l_connection and then + is_persistent_connection_requested := attached request_header_map.item ("Connection") as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") else -- By default HTTP:1/1 support persistent connection. if attached request_header_map.item ("Connection") as l_connection then if l_connection.is_case_insensitive_equal_general ("close") then - keep_alive_requested := False + is_persistent_connection_requested := False end else - keep_alive_requested := True + is_persistent_connection_requested := True end end end diff --git a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e index 0f4ad723..c9644fec 100644 --- a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e @@ -82,7 +82,7 @@ feature -- Request processing else l_output.set_http_version (version) end - res.set_is_persistent_connection_requested (keep_alive_requested) + res.set_is_persistent_connection_requested (is_persistent_connection_requested) req.set_meta_string_variable ("RAW_HEADER_DATA", request_header) From a1a620a9c365d038bbbba82278142cd39ac47ec9 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Thu, 2 Apr 2015 18:23:58 +0200 Subject: [PATCH 20/33] Export request and response from WGI_EXECUTION to itself. Added WSF_FILTERED_ROUTED_SKELETON_EXECUTION --- .../specification/connector/wgi_execution.e | 2 +- .../wsf_filtered_routed_skeleton_execution.e | 68 +++++++++++++++++++ .../execution/wsf_routed_skeleton_execution.e | 14 ++-- 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 library/server/wsf/router/policy/execution/wsf_filtered_routed_skeleton_execution.e diff --git a/library/server/ewsgi/specification/connector/wgi_execution.e b/library/server/ewsgi/specification/connector/wgi_execution.e index ad18a6ac..07070ea0 100644 --- a/library/server/ewsgi/specification/connector/wgi_execution.e +++ b/library/server/ewsgi/specification/connector/wgi_execution.e @@ -18,7 +18,7 @@ feature {NONE} -- Initialization response := res end -feature {NONE} -- Access +feature {WGI_EXECUTION} -- Access request: WGI_REQUEST -- Request data. diff --git a/library/server/wsf/router/policy/execution/wsf_filtered_routed_skeleton_execution.e b/library/server/wsf/router/policy/execution/wsf_filtered_routed_skeleton_execution.e new file mode 100644 index 00000000..b860b3dc --- /dev/null +++ b/library/server/wsf/router/policy/execution/wsf_filtered_routed_skeleton_execution.e @@ -0,0 +1,68 @@ +note + description: "[ + Skeleton execution based on filtered routed execution. + ]" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_FILTERED_ROUTED_SKELETON_EXECUTION + +inherit + WSF_ROUTED_SKELETON_EXECUTION + undefine + execute + redefine + initialize + end + + WSF_FILTERED_EXECUTION + redefine + initialize + end + + WSF_FILTER + rename + execute as filter_execute + end + +feature {NONE} -- Initialize + + initialize + local + f: like filter + do + Precursor {WSF_ROUTED_SKELETON_EXECUTION} + Precursor {WSF_FILTERED_EXECUTION} + -- Current is a WSF_FILTER as well in order to call the router + -- let's add Current at the end of the filter chain. + from + f := filter + until + not attached f.next as l_next + loop + f := l_next + end + f.set_next (Current) + end + +feature -- Execute Filter + + filter_execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter. + do + execute_skeleton (req, res) + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e b/library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e index 859adaff..e59a4312 100644 --- a/library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e +++ b/library/server/wsf/router/policy/execution/wsf_routed_skeleton_execution.e @@ -19,17 +19,19 @@ inherit feature -- Execution execute + -- + do + execute_skeleton (request, response) + end + + execute_skeleton (req: WSF_REQUEST; res: WSF_RESPONSE) -- If the service is available, and request URI is not too long, dispatch the request -- and if handler is not found, execute the default procedure `execute_default'. local l_sess: WSF_ROUTER_SESSION - req: WSF_REQUEST; res: WSF_RESPONSE do - req := request - res := response - - --| When we reach here, the request has already passed check for 400 (Bad request), - --| which is implemented in WSF_REQUEST.make_from_wgi (when it calls `analyze'). + --| When we reach here, the request has already passed check for 400 (Bad request), + --| which is implemented in WSF_REQUEST.make_from_wgi (when it calls `analyze'). if unavailable then handle_unavailable (res) elseif requires_proxy (req) then From dc35925eb0aa9a499986403788b893697e44fd98 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Mon, 6 Apr 2015 12:24:47 -0300 Subject: [PATCH 21/33] Added Missing Class and feature descriptions. Removed author entry. --- .../examples/demo/application_execution.e | 1 - .../demo/autocompletion/contact_autocompletion.e | 1 - .../demo/autocompletion/flag_autocompletion.e | 1 - .../demo/autocompletion/google_autocompletion.e | 1 - .../server/wsf_js_widget/examples/demo/base_page.e | 1 - .../wsf_js_widget/examples/demo/codeview_page.e | 1 - .../examples/demo/googlenews/google_news.e | 1 - .../demo/googlenews/google_news_datasource.e | 1 - .../examples/demo/googlenews/google_news_repeater.e | 1 - .../server/wsf_js_widget/examples/demo/grid_page.e | 1 - .../wsf_js_widget/examples/demo/own_validator.e | 1 - .../demo/progress/increasing_progresssource.e | 1 - .../wsf_js_widget/examples/demo/repeater_page.e | 1 - .../wsf_js_widget/examples/demo/sample_page.e | 1 - .../wsf_js_widget/examples/demo/slider_page.e | 1 - .../wsf_js_widget/examples/demo/upload_page.e | 1 - .../concurrency/scoop/httpd_connection_handler.e | 7 +++++++ .../src/httpd/httpd_connection_handler_i.e | 1 + .../standalone/src/httpd/httpd_request_handler_i.e | 13 +++++++++++-- .../connectors/standalone/test_standalone-safe.ecf | 8 ++++++-- library/server/wsf/src/wsf_execution.e | 6 ++++-- 21 files changed, 29 insertions(+), 22 deletions(-) diff --git a/draft/library/server/wsf_js_widget/examples/demo/application_execution.e b/draft/library/server/wsf_js_widget/examples/demo/application_execution.e index b0582128..564f5c85 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/application_execution.e +++ b/draft/library/server/wsf_js_widget/examples/demo/application_execution.e @@ -1,6 +1,5 @@ note description: "Summary description for {APPLICATION_EXECUTION}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/autocompletion/contact_autocompletion.e b/draft/library/server/wsf_js_widget/examples/demo/autocompletion/contact_autocompletion.e index 20382b1a..2bf5fc7f 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/autocompletion/contact_autocompletion.e +++ b/draft/library/server/wsf_js_widget/examples/demo/autocompletion/contact_autocompletion.e @@ -1,6 +1,5 @@ note description: "Summary description for {CONTACT_AUTOCOMPLETION}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/autocompletion/flag_autocompletion.e b/draft/library/server/wsf_js_widget/examples/demo/autocompletion/flag_autocompletion.e index f7ff00a3..18fb6d74 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/autocompletion/flag_autocompletion.e +++ b/draft/library/server/wsf_js_widget/examples/demo/autocompletion/flag_autocompletion.e @@ -1,6 +1,5 @@ note description: "Summary description for {FLAG_AUTOCOMPLETION}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/autocompletion/google_autocompletion.e b/draft/library/server/wsf_js_widget/examples/demo/autocompletion/google_autocompletion.e index 8ff832a9..95403ae2 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/autocompletion/google_autocompletion.e +++ b/draft/library/server/wsf_js_widget/examples/demo/autocompletion/google_autocompletion.e @@ -1,6 +1,5 @@ note description: "Summary description for {GOOGLE_AUTOCOMPLETION}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/base_page.e b/draft/library/server/wsf_js_widget/examples/demo/base_page.e index 672df4f1..33ea23ff 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/base_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/base_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {BASE_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/codeview_page.e b/draft/library/server/wsf_js_widget/examples/demo/codeview_page.e index 68b51521..b2ef9849 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/codeview_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/codeview_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {CODEVIEW_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news.e b/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news.e index 11386b42..18cc5ce6 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news.e +++ b/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news.e @@ -1,6 +1,5 @@ note description: "Summary description for {GOOGLE_NEWS}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_datasource.e b/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_datasource.e index 8c4b0de1..07019133 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_datasource.e +++ b/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_datasource.e @@ -1,6 +1,5 @@ note description: "Summary description for {GOOGLE_NEWS_DATASOURCE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_repeater.e b/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_repeater.e index b5631025..c3b4813c 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_repeater.e +++ b/draft/library/server/wsf_js_widget/examples/demo/googlenews/google_news_repeater.e @@ -1,6 +1,5 @@ note description: "Summary description for {GOOGLE_NEWS_REPEATER}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/grid_page.e b/draft/library/server/wsf_js_widget/examples/demo/grid_page.e index 124f31ff..09119d67 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/grid_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/grid_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {GRID_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/own_validator.e b/draft/library/server/wsf_js_widget/examples/demo/own_validator.e index b0a0b3b9..bb0dda47 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/own_validator.e +++ b/draft/library/server/wsf_js_widget/examples/demo/own_validator.e @@ -1,6 +1,5 @@ note description: "Summary description for {OWN_VALIDATOR}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/progress/increasing_progresssource.e b/draft/library/server/wsf_js_widget/examples/demo/progress/increasing_progresssource.e index 1881abe0..f7ed2011 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/progress/increasing_progresssource.e +++ b/draft/library/server/wsf_js_widget/examples/demo/progress/increasing_progresssource.e @@ -1,6 +1,5 @@ note description: "Summary description for {INCREASING_PROGRESSSOURCE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/repeater_page.e b/draft/library/server/wsf_js_widget/examples/demo/repeater_page.e index 3af98551..02e88c36 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/repeater_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/repeater_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {REPEATER_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/sample_page.e b/draft/library/server/wsf_js_widget/examples/demo/sample_page.e index 1febf1fe..4797b42c 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/sample_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/sample_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {SAMPLE_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/slider_page.e b/draft/library/server/wsf_js_widget/examples/demo/slider_page.e index aa3abff5..448aca56 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/slider_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/slider_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {SLIDER_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/draft/library/server/wsf_js_widget/examples/demo/upload_page.e b/draft/library/server/wsf_js_widget/examples/demo/upload_page.e index 6c125136..454fdd15 100644 --- a/draft/library/server/wsf_js_widget/examples/demo/upload_page.e +++ b/draft/library/server/wsf_js_widget/examples/demo/upload_page.e @@ -1,6 +1,5 @@ note description: "Summary description for {UPLOAD_PAGE}." - author: "" date: "$Date$" revision: "$Revision$" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e index 25b458ab..0b28c038 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -31,6 +31,8 @@ feature {NONE} -- Initialization end initialize_pool (p: like pool; n: INTEGER) + -- Initialize pool of separate connection handlers. + --| set the pool capacity to n. do p.set_count (n) end @@ -49,6 +51,7 @@ feature -- Access feature {HTTPD_SERVER_I} -- Execution shutdown + -- do if not is_shutdown_requested then is_shutdown_requested := True @@ -57,11 +60,13 @@ feature {HTTPD_SERVER_I} -- Execution end pool_gracefull_stop (p: like pool) + -- Graceful stop pool of separate connection handlers. do p.gracefull_stop end accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) + -- do accept_connection_on_pool (pool, a_listening_socket) -- Wait on not pool.is_full or is_stop_requested end @@ -92,6 +97,7 @@ feature {HTTPD_SERVER_I} -- Execution end process_handler (hdl: separate HTTPD_REQUEST_HANDLER) + -- Process request handler `hdl' with exclusive access. require hdl.is_connected do @@ -99,6 +105,7 @@ feature {HTTPD_SERVER_I} -- Execution end separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET + -- Separate client socket from a request handler `hdl'. do Result := hdl.client_socket end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e index 017e2a69..fa89d1fa 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e @@ -79,6 +79,7 @@ feature {NONE} -- Implementation end separate_server_log (a_server: like server; a_message: separate READABLE_STRING_8) + -- Separete log from a server `a_server' with message `a_message'. do a_server.log (a_message) end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index bf526b93..67b327cd 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -1,6 +1,5 @@ note - description: "Summary description for {HTTPD_REQUEST_HANDLER_I}." - author: "" + description: "Represent a handler interface for components that process HTTP requests." date: "$Date$" revision: "$Revision$" @@ -117,13 +116,17 @@ feature -- Status report feature -- Change set_is_verbose (b: BOOLEAN) + -- Set `is_verbose' with `b'. do is_verbose := b + ensure + is_verbose_set: is_verbose = b end feature -- Execution safe_execute + -- Execute incoming request. local retried: BOOLEAN do @@ -194,6 +197,8 @@ feature -- Execution dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER") end l_socket.set_timeout (5) -- 5 seconds! + --| TODO: add configuration options for socket timeout. + --| set by default 5 seconds. l_ready_for_reading := l_socket.ready_for_reading if l_ready_for_reading then create l_remote_info @@ -364,11 +369,15 @@ feature -- Output logger: detachable HTTPD_LOGGER set_logger (a_logger: like logger) + -- Set `logger' with `a_logger'. do logger := a_logger + ensure + logger_set: logger = a_logger end log (m: STRING) + -- Log message `m'. do if attached logger as l_logger then l_logger.log (m) diff --git a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf index 4bb190b4..d6c14438 100644 --- a/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf +++ b/library/server/ewsgi/connectors/standalone/test_standalone-safe.ecf @@ -10,8 +10,12 @@ - - + + + +
    diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e index 79c69336..36d5d7d4 100644 --- a/library/server/wsf/src/wsf_execution.e +++ b/library/server/wsf/src/wsf_execution.e @@ -1,6 +1,5 @@ note - description: "Summary description for {WSF_EXECUTION}." - author: "" + description: "Object that represent a request execution with request and response. " date: "$Date$" revision: "$Revision$" @@ -75,6 +74,7 @@ feature -- Status report feature -- Helpers put_character (c: CHARACTER_8) + -- Send the character `c'. require message_writable: message_writable do @@ -82,6 +82,7 @@ feature -- Helpers end put_string (s: READABLE_STRING_8) + -- Send the string `s'. require message_writable: message_writable do @@ -89,6 +90,7 @@ feature -- Helpers end put_error (err: READABLE_STRING_8) + -- Report error described by `a_message'. require message_writable: message_writable do From dd9aff03d398f4fbbd06ddb1f69882a8dffb578c Mon Sep 17 00:00:00 2001 From: jvelilla Date: Mon, 6 Apr 2015 16:42:45 -0300 Subject: [PATCH 22/33] Added features comments. --- .../configuration/httpd_configuration_i.e | 31 +++++++++++++++++++ .../src/httpd/httpd_request_handler_i.e | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e index 79b82c83..8d2b9a7b 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e @@ -57,8 +57,10 @@ feature -- Access: SSL -- Is SSL/TLS session?. ca_crt: STRING + -- the signed certificate. ca_key: STRING + -- private key to the sertificate. ssl_protocol: NATURAL -- By default protocol is tls 1.2. @@ -78,31 +80,49 @@ feature -- Element change unset_http_server_name do http_server_name := Void + --| Missing postcondition + --| ensure + --| unser_http_server_name: http_server_name = Void. end set_http_server_port (v: like http_server_port) + -- Set `http_server_port' with `v'. do http_server_port := v + ensure + http_server_port_set: http_server_port = v end set_max_tcp_clients (v: like max_tcp_clients) + -- Set `max_tcp_clients' with `v'. do max_tcp_clients := v + ensure + max_tcp_clients_set: max_tcp_clients = v end set_max_concurrent_connections (v: like max_concurrent_connections) + -- Set `max_concurrent_connections' with `v'. do max_concurrent_connections := v + ensure + max_concurrent_connections_set : max_concurrent_connections = v end set_socket_accept_timeout (v: like socket_accept_timeout) + -- Set `socket_accept_timeout' with `v' do socket_accept_timeout := v + ensure + socket_accept_timeout_set: socket_accept_timeout = v end set_socket_connect_timeout (v: like socket_connect_timeout) + -- Set `socket_connect_timeout' with `v' do socket_connect_timeout := v + ensure + socket_connect_timeout_set: socket_connect_timeout = v end set_force_single_threaded (v: like force_single_threaded) @@ -110,12 +130,17 @@ feature -- Element change if v then set_max_concurrent_connections (0) end + --|Missing postcondition + --| force_single_thread_set: v implies max_concurrent_connections = 0 + --| not_single_thread: not v implies max_concurrent_connections > 0 end set_is_verbose (b: BOOLEAN) -- Set `is_verbose' to `b' do is_verbose := b + ensure + is_verbose_set: is_verbose = b end set_keep_alive_timeout (a_seconds: like keep_alive_timeout) @@ -137,6 +162,12 @@ feature -- Element change else is_secure := False end + --| Missing postcondition + --| ensure + -- is_secure_set : has_ssl_support implies is_secure + -- http_server_port_set: has_ssl_support implies http_server_port = 443 + -- is_not_secure: not has_ssl_support implies not is_secure + -- default_port: not has_ssl_support implies http_server_port = 80 end feature -- Element change diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index 67b327cd..de42e66f 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -1,5 +1,5 @@ note - description: "Represent a handler interface for components that process HTTP requests." + description: "Represent a handler interface that process HTTP requests." date: "$Date$" revision: "$Revision$" From a0e9a41e2145b5b1a311f972565aceefe84748a5 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Mon, 6 Apr 2015 17:05:35 -0300 Subject: [PATCH 23/33] Added descriptions and feature comments. --- .../src/implementation/wgi_httpd_request_handler.e | 9 +++++++-- .../implementation/wgi_httpd_request_handler_factory.e | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e index c9644fec..0ddecd18 100644 --- a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler.e @@ -1,6 +1,8 @@ note - description: "Summary description for {WGI_HTTPD_REQUEST_HANDLER}." - author: "" + description: "[ + WGI implementation of HTTPD_REQUEST_HANDLER, will process the incoming connection + and extract information on the request and the server + ]" date: "$Date$" revision: "$Revision$" @@ -34,8 +36,10 @@ feature {NONE} -- Initialization feature -- Access connector: detachable separate WGI_STANDALONE_CONNECTOR [G] + -- httpd solution. base: detachable IMMUTABLE_STRING_8 + -- Root url base. do if attached connector as conn then if attached connector_base (conn) as l_base then @@ -47,6 +51,7 @@ feature -- Access feature -- SCOOP helpers connector_base (conn: separate WGI_STANDALONE_CONNECTOR [G]): detachable separate READABLE_STRING_8 + -- Rool url based from a connector `conn'. do Result := conn.base end diff --git a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e index 2570bc00..b853eb10 100644 --- a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e @@ -1,6 +1,5 @@ note description: "Summary description for {WGI_HTTPD_REQUEST_HANDLER_FACTORY}." - author: "" date: "$Date$" revision: "$Revision$" @@ -13,10 +12,12 @@ inherit feature -- Access connector: detachable separate WGI_STANDALONE_CONNECTOR [G] + -- httpd solution. feature -- Element change set_connector (conn: like connector) + -- Set `connector' with `conn'. do connector := conn end From 9c7e29b8361cadde235fc73b41335a47b822a99b Mon Sep 17 00:00:00 2001 From: jvelilla Date: Mon, 6 Apr 2015 17:46:59 -0300 Subject: [PATCH 24/33] Added descriptions and comments --- .../httpd/configuration/httpd_configuration_i.e | 15 ++++++++++++++- .../standalone/src/httpd/httpd_server_i.e | 7 +++++-- .../src/httpd/ssl/httpd_configuration.e | 5 ++++- .../wgi_httpd_request_handler_factory.e | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e index 8d2b9a7b..e9f669db 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e @@ -60,7 +60,7 @@ feature -- Access: SSL -- the signed certificate. ca_key: STRING - -- private key to the sertificate. + -- private key to the certificate. ssl_protocol: NATURAL -- By default protocol is tls 1.2. @@ -75,6 +75,7 @@ feature -- Element change else create {IMMUTABLE_STRING_8} http_server_name.make_from_separate (v) end + --| Missing postcondition. end unset_http_server_name @@ -201,31 +202,43 @@ feature -- SSL Helpers set_ssl_protocol_to_ssl_2_or_3 -- Set `ssl_protocol' with `Ssl_23'. deferred + ensure + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.Ssl_23 end set_ssl_protocol_to_ssl_3 -- Set `ssl_protocol' with `Ssl_3'. deferred + ensure + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.Ssl_3 end set_ssl_protocol_to_tls_1_0 -- Set `ssl_protocol' with `Tls_1_0'. deferred + ensure + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.Tls_1_0 end set_ssl_protocol_to_tls_1_1 -- Set `ssl_protocol' with `Tls_1_1'. deferred + ensure + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.Tls_1_1 end set_ssl_protocol_to_tls_1_2 -- Set `ssl_protocol' with `Tls_1_2'. deferred + ensure + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.Tls_1_2 end set_ssl_protocol_to_dtls_1_0 -- Set `ssl_protocol' with `Dtls_1_0'. deferred + ensure + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.Dtls_1_0 end note diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e index 15caf568..39a7c894 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e @@ -1,5 +1,5 @@ note - description: "Summary description for {HTTPD_SERVER_I}." + description: "HTTPD server interface" date: "$Date$" revision: "$Revision$" @@ -14,7 +14,6 @@ inherit feature {NONE} -- Initialization make (a_factory: like factory) - -- `a_cfg': server configuration -- `a_factory': connection handler builder require fac_is_separated: {PLATFORM}.is_scoop_capable implies not attached {HTTPD_REQUEST_HANDLER_FACTORY} a_factory @@ -67,6 +66,7 @@ feature -- Callbacks observer: detachable separate HTTPD_SERVER_OBSERVER set_observer (obs: like observer) + -- Set `observer' with `obs' do observer := obs end @@ -320,8 +320,11 @@ feature -- Output output: detachable FILE set_log_output (f: FILE) + -- Set `output' with `f'. do output := f + ensure + output_set: output = f end log (a_message: separate READABLE_STRING_8) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e index d702bac5..eb6d656e 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/httpd_configuration.e @@ -18,9 +18,12 @@ create feature {NONE} -- Initialization make + -- Create a new instance and set ssl protocol to tls_1_2. do Precursor - ssl_protocol := {SSL_PROTOCOL}.tls_1_2 + set_ssl_protocol_to_tls_1_2 + ensure then + ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.tls_1_2 end feature -- Access diff --git a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e index b853eb10..48ea569c 100644 --- a/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e +++ b/library/server/ewsgi/connectors/standalone/src/implementation/wgi_httpd_request_handler_factory.e @@ -1,5 +1,5 @@ note - description: "Summary description for {WGI_HTTPD_REQUEST_HANDLER_FACTORY}." + description: "Implementation of WGI request handler factory for WGI_STANDALOE_CONNECTOR." date: "$Date$" revision: "$Revision$" From 24620b228c6fb4bb470bac2c5599ae72223329d2 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Mon, 6 Apr 2015 18:07:35 -0300 Subject: [PATCH 25/33] Added feature comments. Added missing postconditions. --- .../standalone/src/wgi_standalone_server_observer.e | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e index 702b8ae8..8684943a 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_server_observer.e @@ -16,12 +16,16 @@ inherit feature -- Access started: BOOLEAN + -- is the server started? stopped: BOOLEAN + -- is the server stoped? terminated: BOOLEAN + -- is the server terminated? port: INTEGER + -- Server listening on port. feature -- Event @@ -29,17 +33,24 @@ feature -- Event do started := True port := a_port + ensure then + started_set: started = True + port_set: port = a_port end on_stopped do stopped := True + ensure then + stopped_set: stopped = True end on_terminated do port := 0 terminated := True + ensure then + terminated_set: terminated = True end note From 20ed000879f759b4a5616262e653989e7e73660b Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 7 Apr 2015 14:13:41 +0200 Subject: [PATCH 26/33] Added a few descriptions and comments. --- examples/filter/src/database/database_api.e | 2 -- .../connectors/cgi/src/wgi_cgi_connector.e | 2 ++ .../libfcgi/src/wgi_libfcgi_connector.e | 8 ++++++-- .../none/httpd_connection_handler.e | 1 + .../scoop/httpd_connection_handler.e | 14 +++++++------- .../concurrency/scoop/httpd_request_handler.e | 1 + .../concurrency/scoop/pool/concurrent_pool.e | 18 ++++++++++++++++-- .../scoop/pool/concurrent_pool_item.e | 1 + .../wsf_html/widget/wsf_widget_agent_table.e | 2 +- tests/all-safe.ecf | 11 ++++++++--- 10 files changed, 43 insertions(+), 17 deletions(-) diff --git a/examples/filter/src/database/database_api.e b/examples/filter/src/database/database_api.e index 669ef656..d57f3dda 100644 --- a/examples/filter/src/database/database_api.e +++ b/examples/filter/src/database/database_api.e @@ -46,8 +46,6 @@ feature -- Access -- User with id `a_id' or name `a_name'. require a_id > 0 xor a_name /= Void - local - n: like {USER}.name do if a_id > 0 then Result := user_by_id (a_id) diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e index 372a20a0..e4a23692 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e @@ -24,6 +24,7 @@ feature -- Access feature -- Execution launch + -- Launch execution of CGI application. local req: WGI_REQUEST_FROM_TABLE res: detachable WGI_RESPONSE_STREAM @@ -51,6 +52,7 @@ feature -- Execution end process_rescue (res: detachable WGI_RESPONSE) + -- Handle rescued execution of current request. do if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then if res /= Void then diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e index ed8209e0..88c74ecc 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e @@ -22,6 +22,7 @@ inherit feature {NONE} -- Initialization default_create + -- Create libFCGI connector. do Precursor {WGI_CONNECTOR} create fcgi.make @@ -40,6 +41,7 @@ feature -- Access feature -- Server launch + -- Launch libFCGI server. local res: INTEGER do @@ -56,6 +58,7 @@ feature -- Server feature -- Execution process_fcgi_request (vars: STRING_TABLE [READABLE_STRING_8]; a_input: like input; a_output: like output) + -- Process the request with variables `vars', input `a_input' and output `a_output'. local req: WGI_REQUEST_FROM_TABLE res: detachable WGI_RESPONSE_STREAM @@ -82,8 +85,9 @@ feature -- Execution retry end end - + process_rescue (res: detachable WGI_RESPONSE) + -- Handle rescued execution of current request. do if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then if res /= Void then @@ -116,7 +120,7 @@ invariant fcgi_attached: fcgi /= Void note - copyright: "2011-2013, Eiffel Software and others" + copyright: "2011-2015, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e index 9b32f4a2..5bc857c4 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_connection_handler.e @@ -23,6 +23,7 @@ feature {NONE} -- Initialization feature -- Access is_shutdown_requested: BOOLEAN + -- shutdown_requested (a_server: like server): BOOLEAN do diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e index 0b28c038..757d46bd 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -97,19 +97,13 @@ feature {HTTPD_SERVER_I} -- Execution end process_handler (hdl: separate HTTPD_REQUEST_HANDLER) - -- Process request handler `hdl' with exclusive access. + -- Process request handler `hdl' concurrently. require hdl.is_connected do hdl.safe_execute end - separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET - -- Separate client socket from a request handler `hdl'. - do - Result := hdl.client_socket - end - feature {HTTPD_SERVER_I} -- Status report wait_for_completion @@ -128,6 +122,12 @@ feature {HTTPD_SERVER_I} -- Status report feature {NONE} -- Implementation + separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET + -- Client socket for handler `hdl'. + do + Result := hdl.client_socket + end + pool: separate CONCURRENT_POOL [HTTPD_REQUEST_HANDLER] -- Pool of separate connection handlers. diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler.e index 4055f7e2..9335e76f 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -23,6 +23,7 @@ inherit feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation release + -- local d: STRING do diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e index 90a75855..070f2710 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool.e @@ -24,24 +24,32 @@ feature {NONE} -- Initialization feature -- Access count: INTEGER + -- Number of concurrent items managed by Current pool. + + capacity: INTEGER + -- Maximum number of concurrent items managed by Current pool. + +feature -- Status report is_full: BOOLEAN + -- Pool is full? do Result := count >= capacity end is_empty: BOOLEAN + -- No concurrent item waiting in current pool. do Result := count = 0 end - capacity: INTEGER - stop_requested: BOOLEAN + -- Current pool received a request to terminate. feature -- Access separate_item (a_factory: separate CONCURRENT_POOL_FACTORY [G]): detachable separate G + -- Reused, or new separate item of type {G} created by `a_factory'. require is_not_full: not is_full local @@ -94,6 +102,7 @@ feature -- Access feature -- Basic operation gracefull_stop + -- Request the Current pool to terminate. do stop_requested := True end @@ -101,8 +110,10 @@ feature -- Basic operation feature {NONE} -- Internal items: SPECIAL [detachable separate G] + -- List of concurrent items. busy_items: SPECIAL [BOOLEAN] + -- Map of items being proceed. feature {CONCURRENT_POOL_ITEM} -- Change @@ -140,6 +151,7 @@ feature {CONCURRENT_POOL_ITEM} -- Change feature -- Change set_count (n: INTEGER) + -- Set capacity of Current pool to `n'. local g: detachable separate G do @@ -149,6 +161,7 @@ feature -- Change end terminate + -- Terminate current pool. local l_items: like items do @@ -159,6 +172,7 @@ feature -- Change feature {NONE} -- Implementation register_item (a_item: separate G) + -- Adopt `a_item' in current pool. do a_item.set_pool (Current) end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e index f0af2268..2b5d1c6b 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/pool/concurrent_pool_item.e @@ -25,6 +25,7 @@ feature {CONCURRENT_POOL} -- Change feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation release + -- Release Current pool item from associated pool. do if attached pool as p then pool_release (p) diff --git a/library/server/wsf_html/widget/wsf_widget_agent_table.e b/library/server/wsf_html/widget/wsf_widget_agent_table.e index 3d8fc16b..c9f42c52 100644 --- a/library/server/wsf_html/widget/wsf_widget_agent_table.e +++ b/library/server/wsf_html/widget/wsf_widget_agent_table.e @@ -5,7 +5,7 @@ note revision: "$Revision$" class - WSF_WIDGET_AGENT_TABLE [G] + WSF_WIDGET_AGENT_TABLE [G -> detachable ANY] inherit WSF_WIDGET diff --git a/tests/all-safe.ecf b/tests/all-safe.ecf index de7fb826..84a9e075 100644 --- a/tests/all-safe.ecf +++ b/tests/all-safe.ecf @@ -1,5 +1,5 @@ - + Integration project including many lib @@ -51,14 +51,19 @@ + + - - + + + Compiling with SCOOP concurrency + + Compiling as Windows , on other platforms than Windows From da8028f8b30c9daaf3fb244921bdb605696daa5f Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 7 Apr 2015 14:47:38 +0200 Subject: [PATCH 27/33] Fixed a typo. --- .../src/httpd/configuration/httpd_configuration_i.e | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e index e9f669db..6046dc2e 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e @@ -81,9 +81,8 @@ feature -- Element change unset_http_server_name do http_server_name := Void - --| Missing postcondition - --| ensure - --| unser_http_server_name: http_server_name = Void. + ensure + unset_http_server_name: http_server_name = Void end set_http_server_port (v: like http_server_port) From 019393fdb1d2f61b0ff01343443aa53545015d13 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 7 Apr 2015 15:02:44 +0200 Subject: [PATCH 28/33] Fixed typo. --- .../src/httpd/concurrency/none/httpd_request_handler.e | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e index 535255c4..5055af02 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e @@ -1,6 +1,5 @@ note - description : "Concurrent specific feature to implemente HTTPD_REQUEST_HANDLER" - author : "$Author$" + description : "Concurrent specific feature to implement HTTPD_REQUEST_HANDLER" date : "$Date$" revision : "$Revision$" @@ -10,8 +9,6 @@ deferred class inherit HTTPD_REQUEST_HANDLER_I - - note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" From 8ea443c1158e7aeed8904bf725c91eaa43ddc16f Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 6 May 2015 19:32:05 +0200 Subject: [PATCH 29/33] Added abstraction WSF_ROUTED, and WSF_FILTERED. Added under library/server/obsolete/v0 the previous non concurrent friendly version of EWF/WSF, for backward compatiblity. Removed WSF_CALLBACK_SERVICE and WSF_TO_WGI_SERVICE which are not need with new EWF. --- .../src/restbucks_server_execution.e | 2 +- .../src/image_uploader_execution.e | 2 +- .../consumer/demo/application_execution.e | 2 +- .../ewsgi/connectors/libfcgi/libfcgi-safe.ecf | 23 ++ .../v0/ewsgi/connectors/libfcgi/libfcgi.ecf | 18 ++ .../v0/ewsgi/connectors/libfcgi/license.lic | 10 + .../libfcgi/src/wgi_libfcgi_connector.e | 118 +++++++ .../v0/ewsgi/connectors/nino/license.lic | 10 + .../v0/ewsgi/connectors/nino/nino-safe.ecf | 28 ++ .../v0/ewsgi/connectors/nino/nino.ecf | 28 ++ .../ewsgi/connectors/nino/src/nino_service.e | 116 +++++++ .../connectors/nino/src/wgi_nino_connector.e | 160 ++++++++++ .../connectors/nino/src/wgi_nino_handler.e | 260 ++++++++++++++++ .../server/obsolete/v0/ewsgi/ewsgi-safe.ecf | 26 ++ library/server/obsolete/v0/ewsgi/ewsgi.ecf | 26 ++ .../ewsgi/specification/service/wgi_service.e | 39 +++ .../obsolete/v0/ewsgi/src/wgi_agent_service.e | 48 +++ .../v0/wsf/connector/libfcgi-safe.ecf | 22 ++ .../obsolete/v0/wsf/connector/libfcgi.ecf | 22 ++ .../libfcgi/wsf_libfcgi_service_launcher.e | 64 ++++ .../obsolete/v0/wsf/connector/license.lic | 10 + .../obsolete/v0/wsf/connector/nino-safe.ecf | 25 ++ .../server/obsolete/v0/wsf/connector/nino.ecf | 25 ++ .../nino/wsf_nino_service_launcher.e | 164 ++++++++++ .../obsolete/v0/wsf/default/libfcgi-safe.ecf | 17 ++ .../obsolete/v0/wsf/default/libfcgi.ecf | 17 ++ .../libfcgi/wsf_default_response_service.e | 24 ++ .../wsf/default/libfcgi/wsf_default_service.e | 22 ++ .../libfcgi/wsf_default_service_launcher.e | 30 ++ .../obsolete/v0/wsf/default/nino-safe.ecf | 17 ++ .../server/obsolete/v0/wsf/default/nino.ecf | 17 ++ .../nino/wsf_default_response_service.e | 24 ++ .../v0/wsf/default/nino/wsf_default_service.e | 22 ++ .../nino/wsf_default_service_launcher.e} | 17 +- .../service/wsf_routed_skeleton_service.e | 287 ++++++++++++++++++ .../v0/wsf/router/wsf_filtered_service.e | 29 ++ .../v0/wsf/router/wsf_routed_service.e | 87 ++++++ .../wsf/src/service/wsf_callback_service.e | 0 .../wsf/src/service/wsf_default_service_i.e | 31 ++ .../wsf/src/service/wsf_launchable_service.e | 59 ++++ .../v0/wsf/src/service/wsf_response_service.e | 41 +++ .../obsolete/v0/wsf/src/service/wsf_service.e | 41 +++ .../v0/wsf/src/service/wsf_service_launcher.e | 132 ++++++++ .../service/wsf_service_launcher_options.e | 124 ++++++++ .../wsf_service_launcher_options_from_ini.e | 84 +++++ .../v0/wsf/src/service/wsf_to_wgi_service.e | 67 ++++ library/server/obsolete/v0/wsf/wsf-safe.ecf | 37 +++ library/server/obsolete/v0/wsf/wsf.ecf | 37 +++ .../obsolete/v0/wsf/wsf_extension-safe.ecf | 20 ++ .../server/obsolete/v0/wsf/wsf_extension.ecf | 20 ++ .../v0/wsf/wsf_policy_driven-safe.ecf | 22 ++ .../obsolete/v0/wsf/wsf_policy_driven.ecf | 22 ++ .../v0/wsf/wsf_router_context-safe.ecf | 16 + .../obsolete/v0/wsf/wsf_router_context.ecf | 16 + .../obsolete/v0/wsf/wsf_session-safe.ecf | 3 + .../server/obsolete/v0/wsf/wsf_session.ecf | 3 + .../server/wsf/router/filter/wsf_filtered.e | 63 ++++ .../router/filter/wsf_filtered_execution.e | 53 +--- ...ed_execution.e => wsf_routed_uri_helper.e} | 19 +- ...ion.e => wsf_routed_uri_template_helper.e} | 20 +- library/server/wsf/router/wsf_routed.e | 31 ++ .../server/wsf/router/wsf_routed_execution.e | 2 + .../wsf/src/service/wsf_launchable_service.e | 6 + library/server/wsf/wsf-safe.ecf | 4 +- 64 files changed, 2741 insertions(+), 90 deletions(-) create mode 100644 library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf create mode 100644 library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf create mode 100644 library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic create mode 100644 library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e create mode 100644 library/server/obsolete/v0/ewsgi/connectors/nino/license.lic create mode 100644 library/server/obsolete/v0/ewsgi/connectors/nino/nino-safe.ecf create mode 100644 library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf create mode 100644 library/server/obsolete/v0/ewsgi/connectors/nino/src/nino_service.e create mode 100644 library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_connector.e create mode 100644 library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_handler.e create mode 100644 library/server/obsolete/v0/ewsgi/ewsgi-safe.ecf create mode 100644 library/server/obsolete/v0/ewsgi/ewsgi.ecf create mode 100644 library/server/obsolete/v0/ewsgi/specification/service/wgi_service.e create mode 100644 library/server/obsolete/v0/ewsgi/src/wgi_agent_service.e create mode 100644 library/server/obsolete/v0/wsf/connector/libfcgi-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/connector/libfcgi.ecf create mode 100644 library/server/obsolete/v0/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e create mode 100644 library/server/obsolete/v0/wsf/connector/license.lic create mode 100644 library/server/obsolete/v0/wsf/connector/nino-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/connector/nino.ecf create mode 100644 library/server/obsolete/v0/wsf/connector/nino/wsf_nino_service_launcher.e create mode 100644 library/server/obsolete/v0/wsf/default/libfcgi-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/default/libfcgi.ecf create mode 100644 library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_response_service.e create mode 100644 library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service.e create mode 100644 library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service_launcher.e create mode 100644 library/server/obsolete/v0/wsf/default/nino-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/default/nino.ecf create mode 100644 library/server/obsolete/v0/wsf/default/nino/wsf_default_response_service.e create mode 100644 library/server/obsolete/v0/wsf/default/nino/wsf_default_service.e rename library/server/{wsf/src/service/wsf_to_wgi_service.e => obsolete/v0/wsf/default/nino/wsf_default_service_launcher.e} (57%) create mode 100644 library/server/obsolete/v0/wsf/router/policy/service/wsf_routed_skeleton_service.e create mode 100644 library/server/obsolete/v0/wsf/router/wsf_filtered_service.e create mode 100644 library/server/obsolete/v0/wsf/router/wsf_routed_service.e rename library/server/{ => obsolete/v0}/wsf/src/service/wsf_callback_service.e (100%) create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_default_service_i.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_launchable_service.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_response_service.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_service.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_service_launcher.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options_from_ini.e create mode 100644 library/server/obsolete/v0/wsf/src/service/wsf_to_wgi_service.e create mode 100644 library/server/obsolete/v0/wsf/wsf-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_extension-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_extension.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_policy_driven-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_policy_driven.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_router_context-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_router_context.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_session-safe.ecf create mode 100644 library/server/obsolete/v0/wsf/wsf_session.ecf create mode 100644 library/server/wsf/router/filter/wsf_filtered.e rename library/server/wsf/router/support/uri/helpers/{wsf_uri_helper_for_routed_execution.e => wsf_routed_uri_helper.e} (73%) rename library/server/wsf/router/support/uri_template/helpers/{wsf_uri_template_helper_for_routed_execution.e => wsf_routed_uri_template_helper.e} (77%) create mode 100644 library/server/wsf/router/wsf_routed.e diff --git a/examples/restbucksCRUD/src/restbucks_server_execution.e b/examples/restbucksCRUD/src/restbucks_server_execution.e index 1637d1c7..6a7af74d 100644 --- a/examples/restbucksCRUD/src/restbucks_server_execution.e +++ b/examples/restbucksCRUD/src/restbucks_server_execution.e @@ -14,7 +14,7 @@ inherit initialize end - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + WSF_ROUTED_URI_TEMPLATE_HELPER WSF_HANDLER_HELPER diff --git a/examples/upload_image/src/image_uploader_execution.e b/examples/upload_image/src/image_uploader_execution.e index 68f1d22b..6cfe5184 100644 --- a/examples/upload_image/src/image_uploader_execution.e +++ b/examples/upload_image/src/image_uploader_execution.e @@ -17,7 +17,7 @@ inherit WSF_NO_PROXY_POLICY - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + WSF_ROUTED_URI_TEMPLATE_HELPER SHARED_EXECUTION_ENVIRONMENT diff --git a/library/security/openid/consumer/demo/application_execution.e b/library/security/openid/consumer/demo/application_execution.e index bfac0f31..15e9396b 100644 --- a/library/security/openid/consumer/demo/application_execution.e +++ b/library/security/openid/consumer/demo/application_execution.e @@ -13,7 +13,7 @@ inherit requires_proxy end - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + WSF_ROUTED_URI_TEMPLATE_HELPER WSF_NO_PROXY_POLICY diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf new file mode 100644 index 00000000..0178aae0 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf @@ -0,0 +1,23 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + /wgi_.*_connector.e$ + + + + + diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf new file mode 100644 index 00000000..b99fe98b --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf @@ -0,0 +1,18 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic new file mode 100644 index 00000000..cf2d1ed9 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e new file mode 100644 index 00000000..2bb63746 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e @@ -0,0 +1,118 @@ +note + description: "Summary description for {WGI_LIBFCGI_CONNECTOR}." + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + WGI_LIBFCGI_CONNECTOR + +inherit + WGI_CONNECTOR + +create + make + +feature {NONE} -- Initialization + + make (a_service: like service) + do + service := a_service + create fcgi.make + create input.make (fcgi) + create output.make (fcgi) + end + +feature -- Access + + Name: STRING_8 = "libFCGI" + -- Name of Current connector + + Version: STRING_8 = "0.1" + -- Version of Current connector + +feature {NONE} -- Access + + service: WGI_SERVICE + -- Gateway Service + +feature -- Server + + launch + local + res: INTEGER + do + from + res := fcgi.fcgi_listen + until + res < 0 + loop + process_fcgi_request (fcgi.updated_environ_variables, input, output) + res := fcgi.fcgi_listen + end + end + +feature -- Execution + + process_fcgi_request (vars: STRING_TABLE [READABLE_STRING_8]; a_input: like input; a_output: like output) + local + req: WGI_REQUEST_FROM_TABLE + res: detachable WGI_RESPONSE_STREAM + rescued: BOOLEAN + do + if not rescued then + a_input.reset + create req.make (vars, a_input, Current) + create res.make (a_output, a_output) + service.execute (req, res) + res.push + else + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.put_string ("
    ")
    +							res.put_string (l_trace)
    +							res.put_string ("
    ") + end + res.push + end + end + end + rescue + if not rescued then + rescued := True + retry + end + end + +feature -- Input/Output + + input: WGI_LIBFCGI_INPUT_STREAM + -- Input from client (from httpd server via FCGI) + + output: WGI_LIBFCGI_OUTPUT_STREAM + -- Output to client (via httpd server/fcgi) + +feature {NONE} -- Implementation + + fcgi: FCGI + +invariant + fcgi_attached: fcgi /= Void + +note + copyright: "2011-2013, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/license.lic b/library/server/obsolete/v0/ewsgi/connectors/nino/license.lic new file mode 100644 index 00000000..d4d72876 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/nino-safe.ecf b/library/server/obsolete/v0/ewsgi/connectors/nino/nino-safe.ecf new file mode 100644 index 00000000..bfcccf72 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/nino-safe.ecf @@ -0,0 +1,28 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + /wgi_.*_handler.e$ + /wgi_.*_connector.e$ + /.*_service.e$ + + + + + diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf b/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf new file mode 100644 index 00000000..feee5fa9 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf @@ -0,0 +1,28 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + /wgi_.*_handler.e$ + /wgi_.*_connector.e$ + /.*_service.e$ + + + + + diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/src/nino_service.e b/library/server/obsolete/v0/ewsgi/connectors/nino/src/nino_service.e new file mode 100644 index 00000000..fd020b39 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/src/nino_service.e @@ -0,0 +1,116 @@ +note + description: "Summary description for {NINO_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +class + NINO_SERVICE + +create + make, + make_custom, + make_with_callback, + make_custom_with_callback + +feature {NONE} -- Implementation + + make (a_service: WGI_SERVICE) + -- Initialize `Current'. + do + make_custom (a_service, Void) + end + + make_custom (a_service: WGI_SERVICE; a_base_url: detachable STRING) + -- Initialize `Current'. + require + base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/") + do + create connector.make_with_base (a_service, a_base_url) + end + + make_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]) + -- Initialize `Current'. + do + make_custom_with_callback (a_callback, Void) + end + + make_custom_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]; a_base_url: detachable STRING) + -- Initialize `Current'. + require + base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/") + local + app: WGI_AGENT_SERVICE + do + create app.make (a_callback) + make_custom (app, a_base_url) + end + +feature -- Access + + connector: WGI_NINO_CONNECTOR + -- Web server connector + +feature -- Status report + + launched: BOOLEAN + -- Server launched? + do + Result := connector.launched + end + + port: INTEGER + -- Port listened + do + Result := connector.port + end + +feature -- Status settings + + configuration: HTTP_SERVER_CONFIGURATION + do + Result := connector.configuration + end + + force_single_threaded + -- Force single threaded behavior + do + configuration.force_single_threaded := True + end + + set_is_verbose (b: BOOLEAN) + -- Set verbose message behavior to `b' + do + configuration.set_is_verbose (b) + end + + set_base_url (s: detachable READABLE_STRING_8) + -- Set base_url to `s' + do + connector.set_base (s) + end + +feature -- Server + + listen (a_port: INTEGER) + do + configuration.http_server_port := a_port + connector.launch + end + + shutdown + -- Shutdown the server + do + connector.server.shutdown_server + end + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_connector.e new file mode 100644 index 00000000..431001af --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -0,0 +1,160 @@ +note + description: "Summary description for {WGI_NINO_CONNECTOR}." + date: "$Date$" + revision: "$Revision$" + +class + WGI_NINO_CONNECTOR + +inherit + WGI_CONNECTOR + +create + make, + make_with_base + +feature {NONE} -- Initialization + + make (a_service: like service) + local + cfg: HTTP_SERVER_CONFIGURATION + do + service := a_service + + create cfg.make + create server.make (cfg) + + -- Callbacks + create on_launched_actions + create on_stopped_actions + end + + make_with_base (a_service: like service; a_base: like base) + require + a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies a_base.starts_with ("/") + do + make (a_service) + set_base (a_base) + end + +feature -- Access + + name: STRING_8 = "Nino" + -- Name of Current connector + + version: STRING_8 = "0.1" + -- Version of Current connector + +feature {NONE} -- Access + + service: WGI_SERVICE + -- Gateway Service + +feature -- Access + + server: HTTP_SERVER + + configuration: HTTP_SERVER_CONFIGURATION + do + Result := server.configuration + end + +feature -- Access + + base: detachable READABLE_STRING_8 + -- Root url base + +feature -- Status report + + launched: BOOLEAN + -- Server launched and listening on `port' + + port: INTEGER + -- Listening port. + --| 0: not launched + +feature -- Callbacks + + on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when launched + + on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when stopped + +feature -- Element change + + on_launched (a_port: INTEGER) + -- Server launched + do + launched := True + port := a_port + on_launched_actions.call ([Current]) + end + + on_stopped + -- Server stopped + do + on_stopped_actions.call ([Current]) + launched := False + port := 0 + end + +feature -- Element change + + set_base (b: like base) + require + b_starts_with_slash: (b /= Void and then not b.is_empty) implies b.starts_with ("/") + do + base := b + ensure + valid_base: (attached base as l_base and then not l_base.is_empty) implies l_base.starts_with ("/") + end + +feature -- Server + + launch + local + l_http_handler : HTTP_HANDLER + do + launched := False + port := 0 + create {WGI_NINO_HANDLER} l_http_handler.make_with_callback (server, Current) + if configuration.is_verbose then + if attached base as l_base then + io.error.put_string ("Base=" + l_base + "%N") + end + end + server.setup (l_http_handler) + end + + process_request (env: STRING_TABLE [READABLE_STRING_8]; a_headers_text: STRING; a_socket: TCP_STREAM_SOCKET) + local + req: WGI_REQUEST_FROM_TABLE + res: detachable WGI_NINO_RESPONSE_STREAM + retried: BOOLEAN + do + if not retried then + create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current) + create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), create {WGI_NINO_ERROR_STREAM}.make_stderr (a_socket.descriptor.out)) + req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) + service.execute (req, res) + res.push + end + rescue + if not retried then + retried := True + retry + end + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_handler.e b/library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_handler.e new file mode 100644 index 00000000..528a48c1 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/src/wgi_nino_handler.e @@ -0,0 +1,260 @@ +note + description : "Objects that ..." + author : "$Author$" + date : "$Date$" + revision : "$Revision$" + +class + WGI_NINO_HANDLER + +inherit + HTTP_CONNECTION_HANDLER + redefine + on_launched, + on_stopped + end + +create + make_with_callback + +feature {NONE} -- Initialization + + make_with_callback (a_server: like server; a_callback: like callback) + -- Initialize `Current'. + do + base := a_callback.base + make (a_server) + callback := a_callback + end + + callback: WGI_NINO_CONNECTOR + +feature -- Access + + base: detachable READABLE_STRING_8 + -- Root url base + +feature -- Element change + + on_launched (a_port: INTEGER) + do + Precursor (a_port) + callback.on_launched (a_port) + end + + on_stopped + do + Precursor + callback.on_stopped + end + +feature -- Element change + + set_base (a_uri: like base) + -- Set `base' to `a_uri' + do + base := a_uri + end + +feature -- Request processing + + process_request (a_handler: HTTP_CONNECTION_HANDLER; a_socket: TCP_STREAM_SOCKET) + -- Process request ... + local + env: STRING_TABLE [READABLE_STRING_8] + p: INTEGER + l_request_uri, l_script_name, l_query_string, l_path_info: STRING + l_server_name, l_server_port: detachable STRING + l_headers_map: HASH_TABLE [STRING, STRING] + vn: STRING + + e: EXECUTION_ENVIRONMENT + enc: URL_ENCODER + utf: UTF_CONVERTER + do + l_request_uri := a_handler.uri + l_headers_map := a_handler.request_header_map + create e + create enc + if attached e.starting_environment as vars then + create env.make_equal (vars.count) + across + vars as c + loop + env.force (utf.utf_32_string_to_utf_8_string_8 (c.item), utf.utf_32_string_to_utf_8_string_8 (c.key)) + end + else + create env.make (0) + end + + --| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `env' + from + l_headers_map.start + until + l_headers_map.after + loop + create vn.make_from_string (l_headers_map.key_for_iteration.as_upper) + vn.replace_substring_all ("-", "_") + if + vn.starts_with ("CONTENT_") and then + (vn.same_string_general ({WGI_META_NAMES}.content_type) or vn.same_string_general ({WGI_META_NAMES}.content_length)) + then + --| Keep this name + else + vn.prepend ("HTTP_") + end + add_environment_variable (l_headers_map.item_for_iteration, vn, env) + l_headers_map.forth + end + + --| Specific cases + + p := l_request_uri.index_of ('?', 1) + if p > 0 then + l_script_name := l_request_uri.substring (1, p - 1) + l_query_string := l_request_uri.substring (p + 1, l_request_uri.count) + else + l_script_name := l_request_uri.string + l_query_string := "" + end + if attached l_headers_map.item ("Host") as l_host then + check has_host: env.has ("HTTP_HOST") end +-- set_environment_variable (l_host, "HTTP_HOST", env) + p := l_host.index_of (':', 1) + if p > 0 then + l_server_name := l_host.substring (1, p - 1) + l_server_port := l_host.substring (p+1, l_host.count) + else + l_server_name := l_host + l_server_port := "80" -- Default + end + else + check host_available: False end + end + + if attached l_headers_map.item ("Authorization") as l_authorization then + check has_authorization: env.has ("HTTP_AUTHORIZATION") end +-- set_environment_variable (l_authorization, "HTTP_AUTHORIZATION", env) + p := l_authorization.index_of (' ', 1) + if p > 0 then + set_environment_variable (l_authorization.substring (1, p - 1), "AUTH_TYPE", env) + end + end + + set_environment_variable ("CGI/1.1", "GATEWAY_INTERFACE", env) + set_environment_variable (l_query_string, "QUERY_STRING", env) + + if attached a_handler.remote_info as l_remote_info then + set_environment_variable (l_remote_info.addr, "REMOTE_ADDR", env) + set_environment_variable (l_remote_info.hostname, "REMOTE_HOST", env) + set_environment_variable (l_remote_info.port.out, "REMOTE_PORT", env) +-- set_environment_variable (Void, "REMOTE_IDENT", env) +-- set_environment_variable (Void, "REMOTE_USER", env) + end + + set_environment_variable (l_request_uri, "REQUEST_URI", env) + set_environment_variable (a_handler.method, "REQUEST_METHOD", env) + + set_environment_variable (l_script_name, "SCRIPT_NAME", env) + set_environment_variable (l_server_name, "SERVER_NAME", env) + set_environment_variable (l_server_port, "SERVER_PORT", env) + set_environment_variable (a_handler.version, "SERVER_PROTOCOL", env) + set_environment_variable ({HTTP_SERVER_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", env) + + --| Apply `base' value + if attached base as l_base and then l_request_uri /= Void then + if l_request_uri.starts_with (l_base) then + l_path_info := l_request_uri.substring (l_base.count + 1, l_request_uri.count) + p := l_path_info.index_of ('?', 1) + if p > 0 then + l_path_info.keep_head (p - 1) + end + env.force (l_base, "SCRIPT_NAME") + else + -- This should not happen, this means the `base' is not correctly set. + -- It is better to consider base as empty, rather than having empty PATH_INFO + check valid_base_value: False end + + l_path_info := l_request_uri + p := l_request_uri.index_of ('?', 1) + if p > 0 then + l_path_info := l_request_uri.substring (1, p - 1) + else + l_path_info := l_request_uri.string + end + env.force ("", "SCRIPT_NAME") + end + --| In order to have same path value for PATH_INFO on various connectors and servers + --| the multiple slashes must be stripped to single slash. + --| tested with: CGI+apache, libfcgi+apache on Windows and Linux + --| + --| For example: "////abc/def///end////" to "/abc/def/end/" ? + convert_multiple_slashes_to_single (l_path_info) + env.force (enc.decoded_utf_8_string (l_path_info), "PATH_INFO") + end + + callback.process_request (env, a_handler.request_header, a_socket) + end + + add_environment_variable (a_value: detachable STRING; a_var_name: READABLE_STRING_GENERAL; env: STRING_TABLE [READABLE_STRING_8]) + -- Add variable `a_var_name => a_value' to `env' + do + if a_value /= Void then + if env.has_key (a_var_name) and then attached env.found_item as l_existing_value then + --| Check http://www.ietf.org/rfc/rfc3875 4.1.18 + check find_proper_rewrite_for_same_header: False end + env.force (l_existing_value + " " + a_value, a_var_name) + else + env.force (a_value, a_var_name) + end + end + end + + set_environment_variable (a_value: detachable STRING; a_var_name: READABLE_STRING_GENERAL; env: STRING_TABLE [READABLE_STRING_8]) + -- Add variable `a_var_name => a_value' to `env' + do + if a_value /= Void then + env.force (a_value, a_var_name) + end + end + +feature {NONE} -- Implementation + + convert_multiple_slashes_to_single (s: STRING_8) + -- Replace multiple slashes sequence by a single slash character. + local + i,n: INTEGER + do + from + i := 1 + n := s.count + until + i > n + loop + if s[i] = '/' then + -- Remove following slashes '/'. + from + i := i + 1 + until + i > n or s[i] /= '/' + loop + s.remove (i) + n := n - 1 + end + else + i := i + 1 + end + end + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/ewsgi/ewsgi-safe.ecf b/library/server/obsolete/v0/ewsgi/ewsgi-safe.ecf new file mode 100644 index 00000000..e1401dba --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/ewsgi-safe.ecf @@ -0,0 +1,26 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/ewsgi/ewsgi.ecf b/library/server/obsolete/v0/ewsgi/ewsgi.ecf new file mode 100644 index 00000000..3894be85 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/ewsgi.ecf @@ -0,0 +1,26 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/ewsgi/specification/service/wgi_service.e b/library/server/obsolete/v0/ewsgi/specification/service/wgi_service.e new file mode 100644 index 00000000..910bbc42 --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/specification/service/wgi_service.e @@ -0,0 +1,39 @@ +note + description: "[ + WGI_SERVICE + ]" + specification: "EWSGI specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification" + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +deferred class + WGI_SERVICE + +feature {WGI_CONNECTOR} -- Execution + + execute (req: WGI_REQUEST; res: WGI_RESPONSE) + -- Execute the request + -- See `req.input' for input stream + -- `req.meta_variables' for the CGI meta variable + -- and `res' for output buffer + require + res_status_unset: not res.status_is_set + deferred + ensure + res_status_set: res.status_is_set + end + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/obsolete/v0/ewsgi/src/wgi_agent_service.e b/library/server/obsolete/v0/ewsgi/src/wgi_agent_service.e new file mode 100644 index 00000000..579e5bcf --- /dev/null +++ b/library/server/obsolete/v0/ewsgi/src/wgi_agent_service.e @@ -0,0 +1,48 @@ +note + description: "Summary description for {WGI_AGENT_SERVICE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WGI_AGENT_SERVICE + +inherit + WGI_SERVICE + +create + make + +feature {NONE} -- Implementation + + make (a_callback: like callback) + -- Initialize `Current'. + do + callback := a_callback + end + +feature {NONE} -- Implementation + + callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]] + -- Procedure called on `execute' + + execute (req: WGI_REQUEST; res: WGI_RESPONSE) + -- Execute the request + do + callback.call ([req, res]) + end + +invariant + callback_attached: callback /= Void + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/connector/libfcgi-safe.ecf b/library/server/obsolete/v0/wsf/connector/libfcgi-safe.ecf new file mode 100644 index 00000000..68612d66 --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/libfcgi-safe.ecf @@ -0,0 +1,22 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/connector/libfcgi.ecf b/library/server/obsolete/v0/wsf/connector/libfcgi.ecf new file mode 100644 index 00000000..664ecbd6 --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/libfcgi.ecf @@ -0,0 +1,22 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e b/library/server/obsolete/v0/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e new file mode 100644 index 00000000..5eca65f0 --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/libfcgi/wsf_libfcgi_service_launcher.e @@ -0,0 +1,64 @@ +note + description: "[ + Component to launch the service using the default connector + + libFCGI for this class + + How-to: + + s: WSF_DEFAULT_SERVICE_LAUNCHER + create s.make_and_launch (agent execute) + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + do + -- ... + end + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_LIBFCGI_SERVICE_LAUNCHER + +inherit + WSF_SERVICE_LAUNCHER + +create + make, + make_and_launch, + make_callback, + make_callback_and_launch + +feature {NONE} -- Initialization + + initialize + do + create connector.make (Current) + end + +feature -- Execution + + launch + do + if attached connector as conn then + conn.launch + end + end + +feature -- Status report + + connector: detachable WGI_LIBFCGI_CONNECTOR + -- Default service name + +;note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/obsolete/v0/wsf/connector/license.lic b/library/server/obsolete/v0/wsf/connector/license.lic new file mode 100644 index 00000000..d4d72876 --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" diff --git a/library/server/obsolete/v0/wsf/connector/nino-safe.ecf b/library/server/obsolete/v0/wsf/connector/nino-safe.ecf new file mode 100644 index 00000000..359d8833 --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/nino-safe.ecf @@ -0,0 +1,25 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/connector/nino.ecf b/library/server/obsolete/v0/wsf/connector/nino.ecf new file mode 100644 index 00000000..40913165 --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/nino.ecf @@ -0,0 +1,25 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/connector/nino/wsf_nino_service_launcher.e b/library/server/obsolete/v0/wsf/connector/nino/wsf_nino_service_launcher.e new file mode 100644 index 00000000..7fa62a9e --- /dev/null +++ b/library/server/obsolete/v0/wsf/connector/nino/wsf_nino_service_launcher.e @@ -0,0 +1,164 @@ +note + description: "[ + Component to launch the service using the default connector + + Eiffel Web Nino for this class + + + The Nino default connector support options: + port: numeric such as 8099 (or equivalent string as "8099") + base: base_url (very specific to standalone server) + verbose: to display verbose output, useful for Nino + force_single_threaded: use only one thread, useful for Nino + + check WSF_SERVICE_LAUNCHER for more documentation + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_NINO_SERVICE_LAUNCHER + +inherit + WSF_SERVICE_LAUNCHER + redefine + launchable + end + +create + make, + make_and_launch, + make_callback, + make_callback_and_launch + +feature {NONE} -- Initialization + + initialize + local + conn: like connector + do + create on_launched_actions + create on_stopped_actions + + port_number := 80 --| Default, but quite often, this port is already used ... + base_url := "" + + if attached options as opts then + if attached {READABLE_STRING_GENERAL} opts.option ("server_name") as l_server_name then + server_name := l_server_name.to_string_8 + end + if attached {INTEGER} opts.option ("port") as l_port then + port_number := l_port + elseif + attached {READABLE_STRING_GENERAL} opts.option ("port") as l_port_str and then + l_port_str.is_integer + then + port_number := l_port_str.as_string_8.to_integer + end + if attached {READABLE_STRING_GENERAL} opts.option ("base") as l_base_str then + base_url := l_base_str.as_string_8 + end + if attached {BOOLEAN} opts.option ("force_single_threaded") as l_single_threaded then + single_threaded := l_single_threaded + elseif attached {READABLE_STRING_GENERAL} opts.option ("force_single_threaded") as l_single_threaded_str then + single_threaded := l_single_threaded_str.as_lower.same_string ("true") + end + if attached {BOOLEAN} opts.option ("verbose") as l_verbose then + verbose := l_verbose + elseif attached {READABLE_STRING_GENERAL} opts.option ("verbose") as l_verbose_str then + verbose := l_verbose_str.as_lower.same_string ("true") + end + end + create conn.make (Current) + conn.on_launched_actions.extend (agent on_launched) + conn.on_stopped_actions.extend (agent on_stopped) + connector := conn + conn.set_base (base_url) + if single_threaded then + conn.configuration.set_force_single_threaded (True) + end + conn.configuration.set_is_verbose (verbose) + end + +feature -- Execution + + launch + -- + -- using `port_number', `base_url', `verbose' and `single_threaded' + do + if attached connector as conn then + conn.set_base (base_url) + if single_threaded then + conn.configuration.set_force_single_threaded (True) + end + conn.configuration.set_is_verbose (verbose) + debug ("nino") + if verbose then + io.error.put_string ("Launching Nino web server on port " + port_number.out) + if attached server_name as l_name then + io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N") + else + io.error.put_string ("%N http://localhost:" + port_number.out + "/" + base_url + "%N") + end + end + end + if attached server_name as l_server_name then + conn.configuration.set_http_server_name (l_server_name) + end + conn.configuration.http_server_port := port_number + conn.launch + end + end + +feature -- Callback + + on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when launched + + on_stopped_actions: ACTION_SEQUENCE [TUPLE [WGI_CONNECTOR]] + -- Actions triggered when stopped + +feature {NONE} -- Implementation + + on_launched (conn: WGI_CONNECTOR) + do + on_launched_actions.call ([conn]) + end + + on_stopped (conn: WGI_CONNECTOR) + do + on_stopped_actions.call ([conn]) + end + + port_number: INTEGER + + server_name: detachable READABLE_STRING_8 + + base_url: READABLE_STRING_8 + + verbose: BOOLEAN + + single_threaded: BOOLEAN + +feature -- Status report + + connector: detachable WGI_NINO_CONNECTOR + -- Default connector + + launchable: BOOLEAN + do + Result := Precursor and port_number >= 0 + end + +;note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/obsolete/v0/wsf/default/libfcgi-safe.ecf b/library/server/obsolete/v0/wsf/default/libfcgi-safe.ecf new file mode 100644 index 00000000..24a3a7fe --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/libfcgi-safe.ecf @@ -0,0 +1,17 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/default/libfcgi.ecf b/library/server/obsolete/v0/wsf/default/libfcgi.ecf new file mode 100644 index 00000000..c35cd504 --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/libfcgi.ecf @@ -0,0 +1,17 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_response_service.e b/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_response_service.e new file mode 100644 index 00000000..0cefc7da --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_response_service.e @@ -0,0 +1,24 @@ +note + description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_RESPONSE_SERVICE + +inherit + WSF_DEFAULT_SERVICE + + WSF_RESPONSE_SERVICE + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service.e b/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service.e new file mode 100644 index 00000000..dd76ca78 --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service.e @@ -0,0 +1,22 @@ +note + description: "Summary description for {WSF_DEFAULT_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_SERVICE + +inherit + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER] + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service_launcher.e b/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service_launcher.e new file mode 100644 index 00000000..82189381 --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/libfcgi/wsf_default_service_launcher.e @@ -0,0 +1,30 @@ +note + description: "Summary description for {WSF_DEFAULT_SERVICE_LAUNCHER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_DEFAULT_SERVICE_LAUNCHER + +inherit + WSF_LIBFCGI_SERVICE_LAUNCHER + +create + make, + make_and_launch, + make_callback, + make_callback_and_launch + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/obsolete/v0/wsf/default/nino-safe.ecf b/library/server/obsolete/v0/wsf/default/nino-safe.ecf new file mode 100644 index 00000000..f9f0aa19 --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/nino-safe.ecf @@ -0,0 +1,17 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/default/nino.ecf b/library/server/obsolete/v0/wsf/default/nino.ecf new file mode 100644 index 00000000..0157a5a6 --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/nino.ecf @@ -0,0 +1,17 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/default/nino/wsf_default_response_service.e b/library/server/obsolete/v0/wsf/default/nino/wsf_default_response_service.e new file mode 100644 index 00000000..0cefc7da --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/nino/wsf_default_response_service.e @@ -0,0 +1,24 @@ +note + description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_RESPONSE_SERVICE + +inherit + WSF_DEFAULT_SERVICE + + WSF_RESPONSE_SERVICE + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/default/nino/wsf_default_service.e b/library/server/obsolete/v0/wsf/default/nino/wsf_default_service.e new file mode 100644 index 00000000..dd76ca78 --- /dev/null +++ b/library/server/obsolete/v0/wsf/default/nino/wsf_default_service.e @@ -0,0 +1,22 @@ +note + description: "Summary description for {WSF_DEFAULT_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_SERVICE + +inherit + WSF_DEFAULT_SERVICE_I [WSF_DEFAULT_SERVICE_LAUNCHER] + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/service/wsf_to_wgi_service.e b/library/server/obsolete/v0/wsf/default/nino/wsf_default_service_launcher.e similarity index 57% rename from library/server/wsf/src/service/wsf_to_wgi_service.e rename to library/server/obsolete/v0/wsf/default/nino/wsf_default_service_launcher.e index 10d6d841..aab44c4f 100644 --- a/library/server/wsf/src/service/wsf_to_wgi_service.e +++ b/library/server/obsolete/v0/wsf/default/nino/wsf_default_service_launcher.e @@ -1,20 +1,24 @@ note description: "[ - This class is the link between WGI_SERVICE and WSF_SERVICE - It makes a WSF_SERVICE callable from the WGI_ world. - + Default launcher for WSF_SERVICE based on {WSF_NINO_SERVICE_LAUNCHER} ]" date: "$Date$" revision: "$Revision$" class - WSF_TO_WGI_SERVICE + WSF_DEFAULT_SERVICE_LAUNCHER inherit - WGI_SERVICE + WSF_NINO_SERVICE_LAUNCHER + +create + make, + make_and_launch, + make_callback, + make_callback_and_launch note - copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software @@ -23,4 +27,5 @@ note Website http://www.eiffel.com Customer support http://support.eiffel.com ]" + end diff --git a/library/server/obsolete/v0/wsf/router/policy/service/wsf_routed_skeleton_service.e b/library/server/obsolete/v0/wsf/router/policy/service/wsf_routed_skeleton_service.e new file mode 100644 index 00000000..df05e4ea --- /dev/null +++ b/library/server/obsolete/v0/wsf/router/policy/service/wsf_routed_skeleton_service.e @@ -0,0 +1,287 @@ +note + description: "Summary description for {WSF_ROUTED_SKELETON_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_ROUTED_SKELETON_SERVICE + +inherit + WSF_ROUTED_SERVICE + redefine + execute + end + + WSF_SYSTEM_OPTIONS_ACCESS_POLICY + + WSF_PROXY_USE_POLICY + +feature -- Execution + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- If the service is available, and request URI is not too long, dispatch the request + -- and if handler is not found, execute the default procedure `execute_default'. + local + l_sess: WSF_ROUTER_SESSION + do + --| When we reach here, the request has already passed check for 400 (Bad request), + --| which is implemented in WSF_REQUEST.make_from_wgi (when it calls `analyze'). + if unavailable then + handle_unavailable (res) + elseif requires_proxy (req) then + handle_use_proxy (req, res) + elseif + maximum_uri_length > 0 and then + req.request_uri.count.to_natural_32 > maximum_uri_length + then + handle_request_uri_too_long (res) + elseif + req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) and then + req.request_uri.same_string ("*") + then + handle_server_options (req, res) + else + create l_sess + router.dispatch (req, res, l_sess) + if not l_sess.dispatched then + execute_default (req, res) + end + end + end + +feature -- Measurement + + maximum_uri_length: NATURAL + -- Maximum length in characters (or zero for no limit) permitted + -- for {WSF_REQUEST}.request_uri + +feature -- Status report + + unavailable: BOOLEAN + -- Is service currently unavailable? + + unavailablity_message: detachable READABLE_STRING_8 + -- Message to be included as text of response body for {HTTP_STATUS_CODE}.service_unavailable + + unavailability_duration: NATURAL + -- Delta seconds for service unavailability (0 if not known) + + unavailable_until: detachable DATE_TIME + -- Time at which service becomes available again (if known) + +feature -- Status setting + + set_available + -- Set `unavailable' to `False'. + do + unavailable := False + unavailablity_message := Void + unavailable_until := Void + ensure + available: unavailable = False + unavailablity_message_detached: unavailablity_message = Void + unavailable_until_detached: unavailable_until = Void + end + + set_unavailable (a_message: READABLE_STRING_8; a_duration: NATURAL; a_until: detachable DATE_TIME) + -- Set `unavailable' to `True'. + require + a_message_attached: a_message /= Void + a_duration_xor_a_until: a_duration > 0 implies a_until = Void + do + unavailable := True + unavailablity_message := a_message + unavailability_duration := a_duration + ensure + unavailable: unavailable = True + unavailablity_message_aliased: unavailablity_message = a_message + unavailability_duration_set: unavailability_duration = a_duration + unavailable_until_aliased: unavailable_until = a_until + end + + set_maximum_uri_length (a_len: NATURAL) + -- Set `maximum_uri_length' to `a_len'. + -- Can pass zero to mean no restrictions. + do + maximum_uri_length := a_len + ensure + maximum_uri_length_set: maximum_uri_length = a_len + end + +feature {NONE} -- Implementation + + handle_unavailable (res: WSF_RESPONSE) + -- Write "Service unavailable" response to `res'. + require + unavailable: unavailable + res_attached: res /= Void + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + check attached unavailablity_message as m then + -- invariant `unavailability_message_attached' plus precondition `unavailable' + h.put_content_length (m.count) + h.put_current_date + res.set_status_code ({HTTP_STATUS_CODE}.service_unavailable) + if unavailability_duration > 0 then + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, unavailability_duration.out) + elseif attached unavailable_until as u then + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, + h.date_to_rfc1123_http_date_format (u)) + end + res.put_header_text (h.string) + res.put_string (m) + end + ensure + response_status_is_set: res.status_is_set + status_is_service_unavailable: res.status_code = {HTTP_STATUS_CODE}.service_unavailable + body_sent: res.message_committed and then res.transfered_content_length > 0 + body_content_was_unavailablity_message: True -- doesn't seem to be any way to check + end + + handle_request_uri_too_long (res: WSF_RESPONSE) + -- Write "Request URI too long" response into `res'. + require + res_attached: res /= Void + local + h: HTTP_HEADER + m: READABLE_STRING_8 + do + create h.make + h.put_content_type_text_plain + h.put_current_date + m := "Maximum permitted length for request URI is " + maximum_uri_length.out + " characters" + h.put_content_length (m.count) + res.set_status_code ({HTTP_STATUS_CODE}.request_uri_too_long) + res.put_header_text (h.string) + res.put_string (m) + ensure + response_status_is_set: res.status_is_set + status_is_request_uri_too_long: res.status_code = {HTTP_STATUS_CODE}.request_uri_too_long + body_sent: res.message_committed and then res.transfered_content_length > 0 + end + + frozen handle_server_options (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write response to OPTIONS * into `res'. + require + req_attached: req /= Void + res_attached: res /= Void + method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) + server_options_requested: req.request_uri.same_string ("*") + do + --| First check if forbidden. + --| (N.B. authentication requires an absoluteURI (RFC3617 page 3), and so cannot be used for OPTIONS *. + --| Otherwise construct an Allow response automatically from the router. + if is_system_options_forbidden (req) then + handle_system_options_forbidden (req, res) + else + handle_system_options (req, res) + end + ensure + response_status_is_set: res.status_is_set + valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or + res.status_code = {HTTP_STATUS_CODE}.not_found or res.status_code = {HTTP_STATUS_CODE}.ok + header_sent: res.header_committed and res.message_committed + end + + frozen handle_system_options_forbidden (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write a 403 Forbidden or a 404 Not found response into `res'. + require + req_attached: req /= Void + res_attached: res /= Void + method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) + server_options_requested: req.request_uri.same_string ("*") + local + m: detachable READABLE_STRING_8 + h: HTTP_HEADER + do + m := system_options_forbidden_text (req) + if attached {READABLE_STRING_8} m as l_msg then + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_content_length (l_msg.count) + res.set_status_code ({HTTP_STATUS_CODE}.forbidden) + res.put_header_text (h.string) + res.put_string (l_msg) + else + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_content_length (0) + res.set_status_code ({HTTP_STATUS_CODE}.not_found) + res.put_header_text (h.string) + end + ensure + response_status_is_set: res.status_is_set + valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or + res.status_code = {HTTP_STATUS_CODE}.not_found + header_sent: res.header_committed + message_sent: res.message_committed + end + + handle_system_options (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write response to OPTIONS * into `res'. + -- This may be redefined by the user, but normally this will not be necessary. + require + req_attached: req /= Void + res_attached: res /= Void + method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) + server_options_requested: req.request_uri.same_string ("*") + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_allow (router.all_allowed_methods) + h.put_content_length (0) + res.set_status_code ({HTTP_STATUS_CODE}.ok) + res.put_header_text (h.string) + ensure + response_status_is_set: res.status_is_set + response_code_ok: res.status_code = {HTTP_STATUS_CODE}.ok + header_sent: res.header_committed and res.message_committed + empty_body: res.transfered_content_length = 0 + end + + frozen handle_use_proxy (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Write Use Proxy response `res'. + require + res_attached: res /= Void + req_attached: req /= Void + proxy_required: requires_proxy (req) + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + h.put_current_date + h.put_location (proxy_server (req).string) + h.put_content_length (0) + res.put_header_lines (h) + res.set_status_code ({HTTP_STATUS_CODE}.use_proxy) + ensure + response_status_is_set: res.status_is_set + response_code_use_proxy: res.status_code = {HTTP_STATUS_CODE}.use_proxy + end + +invariant + + unavailability_message_attached: unavailable implies attached unavailablity_message as m and then + m.count > 0 + unavailability_duration_xor_unavailable_until: unavailability_duration > 0 implies unavailable_until = Void + +;note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/router/wsf_filtered_service.e b/library/server/obsolete/v0/wsf/router/wsf_filtered_service.e new file mode 100644 index 00000000..c4103aaf --- /dev/null +++ b/library/server/obsolete/v0/wsf/router/wsf_filtered_service.e @@ -0,0 +1,29 @@ +note + description: "Summary description for {WSF_FILTERED_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_FILTERED_SERVICE + +inherit + WSF_FILTERED + +feature -- Execution + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + do + filter.execute (req, res) + end + +;note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/router/wsf_routed_service.e b/library/server/obsolete/v0/wsf/router/wsf_routed_service.e new file mode 100644 index 00000000..2ed6524d --- /dev/null +++ b/library/server/obsolete/v0/wsf/router/wsf_routed_service.e @@ -0,0 +1,87 @@ +note + description: "Summary description for {WSF_ROUTED_SERVICE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_ROUTED_SERVICE + +inherit + WSF_ROUTED + +feature -- Initialization + + initialize_router + -- Initialize router + do + create_router + setup_router + end + + create_router + -- Create `router' + --| could be redefine to initialize with proper capacity + do + create router.make (10) + ensure + router_created: router /= Void + end + + setup_router + -- Setup `router' + require + router_created: router /= Void + deferred + end + +feature -- Execution + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Dispatch the request + -- and if handler is not found, execute the default procedure `execute_default'. + require + req_attached: req /= Void + res_attached: res /= Void + local + sess: WSF_ROUTER_SESSION + do + create sess + router.dispatch (req, res, sess) + if not sess.dispatched then + execute_default (req, res) + end + ensure + response_status_is_set: res.status_is_set + end + + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Dispatch requests without a matching handler. + require + req_attached: req /= Void + res_attached: res /= Void + local + msg: WSF_DEFAULT_ROUTER_RESPONSE + do + create msg.make_with_router (req, router) + msg.set_documentation_included (True) + res.send (msg) + end + +feature -- Access + + router: WSF_ROUTER + -- Router used to dispatch the request according to the WSF_REQUEST object + -- and associated request methods + +;note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/service/wsf_callback_service.e b/library/server/obsolete/v0/wsf/src/service/wsf_callback_service.e similarity index 100% rename from library/server/wsf/src/service/wsf_callback_service.e rename to library/server/obsolete/v0/wsf/src/service/wsf_callback_service.e diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_default_service_i.e b/library/server/obsolete/v0/wsf/src/service/wsf_default_service_i.e new file mode 100644 index 00000000..b54b86d6 --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_default_service_i.e @@ -0,0 +1,31 @@ +note + description: "Summary description for {WSF_DEFAULT_SERVICE_I}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_DEFAULT_SERVICE_I [G -> WSF_SERVICE_LAUNCHER create make_and_launch end] + +inherit + WSF_LAUNCHABLE_SERVICE + +feature {NONE} -- Initialization + + launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + local + l_launcher: G + do + create l_launcher.make_and_launch (a_service, opts) + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_launchable_service.e b/library/server/obsolete/v0/wsf/src/service/wsf_launchable_service.e new file mode 100644 index 00000000..fa8aa1d4 --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_launchable_service.e @@ -0,0 +1,59 @@ +note + description: "Summary description for {WSF_LAUNCHABLE_SERVICE}." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_LAUNCHABLE_SERVICE + +inherit + WSF_SERVICE + +feature {NONE} -- Initialization + + frozen make_and_launch + do + initialize + launch (Current, service_options) + end + + initialize + -- Initialize current service + --| Could be redefine to set custom service option(s) + do + end + + service_options: detachable WSF_SERVICE_LAUNCHER_OPTIONS + + launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + deferred + end + +feature -- Default service options + + set_service_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY) + -- Set options related to WSF_SERVICE_LAUNCHER + local + opts: like service_options + do + opts := service_options + if opts = Void then + create opts.make + service_options := opts + end + opts.set_option (a_name, a_value) + ensure + attached service_options as l_options and then l_options.option (a_name) = a_value + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_response_service.e b/library/server/obsolete/v0/wsf/src/service/wsf_response_service.e new file mode 100644 index 00000000..383d9cdd --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_response_service.e @@ -0,0 +1,41 @@ +note + description: "[ + Inherit from this class to implement the main entry of your web service + You just need to implement `execute', get data from the request `req' + and return a response message + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_RESPONSE_SERVICE + +inherit + WSF_SERVICE + +feature -- Response + + response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE + deferred + ensure + Result_attached: Result /= Void + end + +feature -- Execution + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + do + res.send (response (req)) + end + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_service.e b/library/server/obsolete/v0/wsf/src/service/wsf_service.e new file mode 100644 index 00000000..38aef9ac --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_service.e @@ -0,0 +1,41 @@ +note + description: "[ + Inherit from this class to implement the main entry of your web service + You just need to implement `execute', get data from the request `req' + and write the response in `res' + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_SERVICE + +feature -- Execution + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the request + -- See `req.input' for input stream + -- `req.meta_variables' for the CGI meta variable + -- and `res' for output buffer + deferred + end + +feature -- Conversion + + to_wgi_service: WGI_SERVICE + -- Adapt Current WSF Service to plug into WGI component + do + create {WSF_TO_WGI_SERVICE} Result.make_from_service (Current) + end + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher.e b/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher.e new file mode 100644 index 00000000..bf60ab56 --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher.e @@ -0,0 +1,132 @@ +note + description: "[ + Component to launch the service using the default connector + + How-to: + + s: WSF_SERVICE_LAUNCHER + create s.make_and_launch (service) + + `service' can be Current if inherit from WSF_SERVICE + or also `create {WSF_CALLBACK_SERVICE}.make (agent execute)' + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + do + -- ... + end + + You can also provide specific options that might be relevant + only for specific connectors such as + + + For instance, you can use + create s.make_and_launch_and_options (agent execute, <<["port", 8099]>>) + + And if Nino is the default connector it will support: + port: numeric such as 8099 (or equivalent string as "8099") + base: base_url (very specific to standalone server) + force_single_threaded: use only one thread, useful for Nino + verbose: to display verbose output, useful for Nino + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_SERVICE_LAUNCHER + +inherit + WSF_TO_WGI_SERVICE + +feature {NONE} -- Initialization + + frozen make (a_service: like service; a_options: like options) + do + make_from_service (a_service) + options := a_options + initialize + ensure + service_set: service = a_service + options_set: options = a_options + launchable: launchable + end + + frozen make_and_launch (a_service: like service; a_options: like options) + do + make (a_service, a_options) + launch + end + + frozen make_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; a_options: like options) + do + make (create {WSF_CALLBACK_SERVICE}.make (a_callback), a_options) + end + + frozen make_callback_and_launch (a_callback: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; a_options: like options) + do + make (create {WSF_CALLBACK_SERVICE}.make (a_callback), a_options) + end + + initialize + -- Initialize Current using `options' if attached + -- and build the connector + require + service_set: service /= Void + deferred + ensure + connector_attached: connector /= Void + end + +feature -- Status report + + launchable: BOOLEAN + -- Is default service launchable? + do + Result := connector /= Void + end + + connector: detachable WGI_CONNECTOR + -- Connector associated to current default service + deferred + end + + connector_name: READABLE_STRING_8 + -- Connector's name associated to current default service + do + if attached connector as conn then + Result := conn.name + else + check + connector_attached: False + end + Result := "" + end + end + +feature -- Execution + + launch + -- Launch default service + require + launchable: launchable + deferred + end + +feature {NONE} -- Implementation + + options: detachable WSF_SERVICE_LAUNCHER_OPTIONS + -- Custom options which might be support (or not) by the default service + +invariant + connector_attached: connector /= Void + +note + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options.e b/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options.e new file mode 100644 index 00000000..fd690f88 --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options.e @@ -0,0 +1,124 @@ +note + description: "[ + Options used by WSF_SERVICE_LAUNCHER + + For instance options supported by Nino as default connector:: + port: numeric such as 8099 (or equivalent string as "8099") + base: base_url (very specific to standalone server) + force_single_threaded: use only one thread, useful for Nino + verbose: to display verbose output, useful for Nino + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_SERVICE_LAUNCHER_OPTIONS + +inherit + TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL] + redefine + default_create + end + +create + default_create, + make, + make_from_array, + make_from_iterable + +convert + make_from_array ({ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]]}) + +feature {NONE} -- Initialization + + default_create + do + Precursor + create options.make (0) + end + + make + do + default_create + end + + make_from_array (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]]) + do + make + append_array_of_options (a_options) + end + + make_from_iterable (a_options: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]) + do + make + append_options (a_options) + end + +feature -- Merging + + append_array_of_options (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]]) + do + across + a_options as opt + loop + if attached opt.item as o then + set_option (o.name, o.value) + end + end + end + + append_options (a_options: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]) + do + across + a_options as o + loop + set_option (o.key, o.item) + end + end + +feature -- Access + + option (a_name: READABLE_STRING_GENERAL): detachable ANY + do + Result := options.item (a_name) + end + +feature -- Access + + new_cursor: TABLE_ITERATION_CURSOR [detachable ANY, READABLE_STRING_GENERAL] + -- Fresh cursor associated with current structure + do + Result := options.new_cursor + end + +feature -- Element change + + set_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY) + do + options.force (a_value, a_name) + end + + set_verbose (b: BOOLEAN) + -- Set option "verbose" to `b' + do + set_option ("verbose", b) + end + +feature {NONE} -- Implementation + + options: STRING_TABLE [detachable ANY] + -- Custom options which might be support (or not) by the default service + +invariant + options_attached: options /= Void +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options_from_ini.e b/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options_from_ini.e new file mode 100644 index 00000000..4b2658c5 --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_service_launcher_options_from_ini.e @@ -0,0 +1,84 @@ +note + description: "[ + Options used by WSF_SERVICE_LAUNCHER + Built from ini configuration file + ]" + +class + WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI + +inherit + WSF_SERVICE_LAUNCHER_OPTIONS + +create + make_from_file, + make_from_file_and_defaults + +feature {NONE} -- Initialization + + make_from_file (a_filename: READABLE_STRING_GENERAL) + -- Initialize `Current'. + do + make + import (a_filename) + end + + make_from_file_and_defaults (a_filename: READABLE_STRING_GENERAL; dft: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + -- Initialize `Current'. + do + make + + if dft /= Void then + append_options (dft) + end + + import (a_filename) + end + +feature {NONE} -- Implementation + + import (a_filename: READABLE_STRING_GENERAL) + -- Import ini file content + local + f: PLAIN_TEXT_FILE + l,v: STRING_8 + p: INTEGER + do + create f.make_with_name (a_filename) + if f.exists and f.is_readable then + f.open_read + from + f.read_line + until + f.exhausted + loop + l := f.last_string + l.left_adjust + if not l.is_empty and then l[1] /= '#' then + p := l.index_of ('=', 1) + if p > 1 then + v := l.substring (p + 1, l.count) + l.keep_head (p - 1) + v.left_adjust + v.right_adjust + l.right_adjust + set_option (l.as_lower, v) + end + end + f.read_line + end + f.close + end + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/src/service/wsf_to_wgi_service.e b/library/server/obsolete/v0/wsf/src/service/wsf_to_wgi_service.e new file mode 100644 index 00000000..9bec25fd --- /dev/null +++ b/library/server/obsolete/v0/wsf/src/service/wsf_to_wgi_service.e @@ -0,0 +1,67 @@ +note + description: "[ + This class is the link between WGI_SERVICE and WSF_SERVICE + It makes a WSF_SERVICE callable from the WGI_ world. + + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_TO_WGI_SERVICE + +inherit + WGI_SERVICE + + WGI_EXPORTER + +create + make_from_service + +feature {NONE} -- Make + + make_from_service (a_service: like service) + -- Make from WSF_SERVICE `a_service' + do + service := a_service + end + + service: WSF_SERVICE + -- Associated WSF_SERVICE + +feature {WGI_CONNECTOR} -- Implementation: Execution + + execute (req: WGI_REQUEST; res: WGI_RESPONSE) + -- Delegate the WGI processing to the WSF_SERVICE object + -- + local + w_res: detachable WSF_RESPONSE + w_req: detachable WSF_REQUEST + do + create w_res.make_from_wgi (res) + create w_req.make_from_wgi (req) + service.execute (w_req, w_res) + w_req.destroy + rescue + if w_res /= Void then + if not (w_res.status_committed or w_res.header_committed) then + w_res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error) + end + w_res.flush + end + if w_req /= Void then + w_req.destroy + end + end + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/obsolete/v0/wsf/wsf-safe.ecf b/library/server/obsolete/v0/wsf/wsf-safe.ecf new file mode 100644 index 00000000..edd519f2 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf-safe.ecf @@ -0,0 +1,37 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + + + + + + + /policy_driven$ + + + + + + /service$ + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf.ecf b/library/server/obsolete/v0/wsf/wsf.ecf new file mode 100644 index 00000000..3b84f417 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf.ecf @@ -0,0 +1,37 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + + + + + + + /policy_driven$ + + + + + + /service$ + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_extension-safe.ecf b/library/server/obsolete/v0/wsf/wsf_extension-safe.ecf new file mode 100644 index 00000000..433868dc --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_extension-safe.ecf @@ -0,0 +1,20 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_extension.ecf b/library/server/obsolete/v0/wsf/wsf_extension.ecf new file mode 100644 index 00000000..65fe0016 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_extension.ecf @@ -0,0 +1,20 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_policy_driven-safe.ecf b/library/server/obsolete/v0/wsf/wsf_policy_driven-safe.ecf new file mode 100644 index 00000000..d42de944 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_policy_driven-safe.ecf @@ -0,0 +1,22 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_policy_driven.ecf b/library/server/obsolete/v0/wsf/wsf_policy_driven.ecf new file mode 100644 index 00000000..ae8e48d8 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_policy_driven.ecf @@ -0,0 +1,22 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_router_context-safe.ecf b/library/server/obsolete/v0/wsf/wsf_router_context-safe.ecf new file mode 100644 index 00000000..f55c41ed --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_router_context-safe.ecf @@ -0,0 +1,16 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_router_context.ecf b/library/server/obsolete/v0/wsf/wsf_router_context.ecf new file mode 100644 index 00000000..ba8138f4 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_router_context.ecf @@ -0,0 +1,16 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + diff --git a/library/server/obsolete/v0/wsf/wsf_session-safe.ecf b/library/server/obsolete/v0/wsf/wsf_session-safe.ecf new file mode 100644 index 00000000..0e713330 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_session-safe.ecf @@ -0,0 +1,3 @@ + + + diff --git a/library/server/obsolete/v0/wsf/wsf_session.ecf b/library/server/obsolete/v0/wsf/wsf_session.ecf new file mode 100644 index 00000000..a138e7a6 --- /dev/null +++ b/library/server/obsolete/v0/wsf/wsf_session.ecf @@ -0,0 +1,3 @@ + + + diff --git a/library/server/wsf/router/filter/wsf_filtered.e b/library/server/wsf/router/filter/wsf_filtered.e new file mode 100644 index 00000000..0ac3c60d --- /dev/null +++ b/library/server/wsf/router/filter/wsf_filtered.e @@ -0,0 +1,63 @@ +note + description: "Object with a `filter: WSF_FILTER' feature." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_FILTERED + +feature {NONE} -- Initialization + + initialize_filter + -- Initialize `filter' + do + create_filter + setup_filter + end + + create_filter + -- Create `filter' + deferred + ensure + filter_created: filter /= Void + end + + setup_filter + -- Setup `filter' + require + filter_created: filter /= Void + deferred + end + + append_filters (a_filters: ITERABLE [WSF_FILTER]) + -- Append collection `a_filters' of filters to the end of the `filter' chain. + local + f: like filter + l_next_filter: detachable like filter + do + from + f := filter + l_next_filter := f.next + until + l_next_filter = Void + loop + f := l_next_filter + l_next_filter := f.next + end + check f_attached_without_next: f /= Void and then f.next = Void end + across + a_filters as ic + loop + l_next_filter := ic.item + f.set_next (l_next_filter) + f := l_next_filter + end + end + +feature -- Access + + filter: WSF_FILTER + -- Filter + + +end diff --git a/library/server/wsf/router/filter/wsf_filtered_execution.e b/library/server/wsf/router/filter/wsf_filtered_execution.e index eb2bd534..3de16a50 100644 --- a/library/server/wsf/router/filter/wsf_filtered_execution.e +++ b/library/server/wsf/router/filter/wsf_filtered_execution.e @@ -13,6 +13,8 @@ inherit initialize end + WSF_FILTERED + feature {NONE} -- Initialization initialize @@ -21,57 +23,6 @@ feature {NONE} -- Initialization initialize_filter end - initialize_filter - -- Initialize `filter' - do - create_filter - setup_filter - end - - create_filter - -- Create `filter' - deferred - ensure - filter_created: filter /= Void - end - - setup_filter - -- Setup `filter' - require - filter_created: filter /= Void - deferred - end - - append_filters (a_filters: ITERABLE [WSF_FILTER]) - -- Append collection `a_filters' of filters to the end of the `filter' chain. - local - f: like filter - l_next_filter: detachable like filter - do - from - f := filter - l_next_filter := f.next - until - l_next_filter = Void - loop - f := l_next_filter - l_next_filter := f.next - end - check f_attached_without_next: f /= Void and then f.next = Void end - across - a_filters as ic - loop - l_next_filter := ic.item - f.set_next (l_next_filter) - f := l_next_filter - end - end - -feature -- Access - - filter: WSF_FILTER - -- Filter - feature -- Execution execute diff --git a/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e b/library/server/wsf/router/support/uri/helpers/wsf_routed_uri_helper.e similarity index 73% rename from library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e rename to library/server/wsf/router/support/uri/helpers/wsf_routed_uri_helper.e index ee087582..0e1cfd84 100644 --- a/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e +++ b/library/server/wsf/router/support/uri/helpers/wsf_routed_uri_helper.e @@ -1,22 +1,13 @@ note - description: "Facilities inheritance to add URI base routing to a routed execution" + description: "Facilities inheritance to add URI base routing to a routed object." date: "$Date$" revision: "$Revision$" -deferred class WSF_URI_HELPER_FOR_ROUTED_EXECUTION +deferred class WSF_ROUTED_URI_HELPER -feature -- Access - - router: WSF_ROUTER - -- Router used to dispatch the request according to the WSF_REQUEST object - -- and associated request methods; - -- This should not be implemented by descendants. Instead, you gain an effective - -- version by also inheriting from WSF_ROUTED_EXECUTION, or one of it's descendants. - deferred - ensure - router_not_void: Result /= Void - end +inherit + WSF_ROUTED feature -- Mapping helper: uri @@ -47,7 +38,7 @@ feature -- Mapping helper: uri agent end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e b/library/server/wsf/router/support/uri_template/helpers/wsf_routed_uri_template_helper.e similarity index 77% rename from library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e rename to library/server/wsf/router/support/uri_template/helpers/wsf_routed_uri_template_helper.e index 223b8292..7ed42435 100644 --- a/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e +++ b/library/server/wsf/router/support/uri_template/helpers/wsf_routed_uri_template_helper.e @@ -1,23 +1,13 @@ note - description: "Facilities inheritance to add URI template-base routing to a routed execution" - author: "" + description: "Facilities inheritance to add URI template-base routing to a routed object." date: "$Date$" revision: "$Revision$" deferred class - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + WSF_ROUTED_URI_TEMPLATE_HELPER -feature -- Access - - router: WSF_ROUTER - -- Router used to dispatch the request according to the WSF_REQUEST object - -- and associated request methods; - -- This should not be implemented by descendants. Instead, you gain an effective - -- version by also inheriting from WSF_ROUTED_SERVICE, or one of it's descendants. - deferred - ensure - router_not_void: Result /= Void - end +inherit + WSF_ROUTED feature -- Mapping helper: uri template @@ -60,7 +50,7 @@ feature -- Mapping helper: uri template agent end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/wsf_routed.e b/library/server/wsf/router/wsf_routed.e new file mode 100644 index 00000000..8d92d738 --- /dev/null +++ b/library/server/wsf/router/wsf_routed.e @@ -0,0 +1,31 @@ +note + description: "Object with a `router' feature, used to dispatch url." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_ROUTED + +feature -- Access + + router: WSF_ROUTER + -- Router used to dispatch the request according to the WSF_REQUEST object + -- and associated request methods; + -- This should not be implemented by descendants. Instead, you gain an effective + -- version by also inheriting from WSF_ROUTED_EXECUTION, or one of it's descendants. + deferred + ensure + router_not_void: Result /= Void + end + +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/router/wsf_routed_execution.e b/library/server/wsf/router/wsf_routed_execution.e index a5bb8f12..cd67f53f 100644 --- a/library/server/wsf/router/wsf_routed_execution.e +++ b/library/server/wsf/router/wsf_routed_execution.e @@ -12,6 +12,8 @@ inherit initialize end + WSF_ROUTED + feature {NONE} -- Initialize initialize diff --git a/library/server/wsf/src/service/wsf_launchable_service.e b/library/server/wsf/src/service/wsf_launchable_service.e index cdc8550e..385ee1fa 100644 --- a/library/server/wsf/src/service/wsf_launchable_service.e +++ b/library/server/wsf/src/service/wsf_launchable_service.e @@ -23,9 +23,15 @@ feature {NONE} -- Initialization do end +feature -- Access + service_options: detachable WSF_SERVICE_LAUNCHER_OPTIONS + -- Optional service options used to configure associated WSF_SERVICE_LAUNCHER. + +feature -- Basic operation launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + -- Launch service with optional options `opts'. deferred end diff --git a/library/server/wsf/wsf-safe.ecf b/library/server/wsf/wsf-safe.ecf index 9fd98569..d09d33af 100644 --- a/library/server/wsf/wsf-safe.ecf +++ b/library/server/wsf/wsf-safe.ecf @@ -1,5 +1,5 @@ - + @@ -9,6 +9,8 @@ + + From d015c065f689687f45dd49dc1b4ae913e3aedb2d Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 6 May 2015 21:35:09 +0200 Subject: [PATCH 30/33] Updated readme. --- ChangeLog | 3138 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 2522 insertions(+), 616 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3a2496cd..b8786d1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,2024 @@ -2012-05-14 Jocelyn Fiat +2015-05-06 Jocelyn Fiat + + Added abstraction WSF_ROUTED, and WSF_FILTERED. Added under + library/server/obsolete/v0 the previous non concurrent friendly version of + EWF/WSF, for backward compatiblity. Removed WSF_CALLBACK_SERVICE and + WSF_TO_WGI_SERVICE which are not need with new EWF. + +2015-04-07 Jocelyn Fiat + + Updated code to remove obsolete call on recent version of json library. + Updated upload_image example to use PATH instead of DIRECTORY_NAME or + similar. Removed unused local variables. + + Added a few descriptions and comments. + +2015-04-06 jvelilla + + Added descriptions and comments + + Added descriptions and feature comments. + + Added features comments. + + Added Missing Class and feature descriptions. Removed author entry. + +2015-04-02 Jocelyn Fiat + + Export request and response from WGI_EXECUTION to itself. Added + WSF_FILTERED_ROUTED_SKELETON_EXECUTION + +2015-04-01 Jocelyn Fiat + + renamed keep_alive_requested as is_persistent_connection_requested. + + Better support for HTTP/1.0 and also related to persistent connection. + + Enable support for persistent connections. (test: works fine with curl -k , + but weird behavior with ab -k ...) + + First step to improve a bit error handling related to socket disconnection. + Mainly in standalone connector for now. + + Improved the simple_file example with image, and not found message. Use + standalone connector in SCOOP concurrency mode. + + Cleaned simple example, and made the standalone target with SCOOP + concurrency. + +2015-03-31 Jocelyn Fiat + + Updated various indexing notes. Removed a few obsolete classes. Cosmetics + + Migrated most of the example and library to new design. + +2015-03-25 Jocelyn Fiat + + Implemented support for base url in httpd connector. + + Migrated simple, simple_file and upload_image example. Adapted EWF + accordingly. + +2015-03-24 Jocelyn Fiat + + Added SCOOP support for WSF. WSF_SERVICE is deeply changed, and addition of + WSF_EXECUTION. Todo: code cleaning, removing useless things. + +2015-03-20 Jocelyn Fiat + + Support for concurrencies: none, thread and SCOOP + + Finally SCOOP supported. + +2015-03-19 jvelilla + + Updated HTTP_COOKIE, enable to add a cookie with empty value. Added feature + to check if a date is valid rcf1123 is_valid_rfc1123_date. Added test cases + related to valid cookie dates. Updated wsf_response add_cookie basedo on + review comments. + + Updated is_valid_character, using NATURAL_32 as an argument to avoid multiple + conversions. Updated add_cookie, added features has_cookie_name and is_cookie + line to avoid the use of STRING.split and STRING.start_with. + +2015-03-17 jvelilla + + Updated HTTP_COOKIE class based on comments. Added missing descriptions in + test classes + + Added the add_cookie feature Added test cases to check cookies in + WSF_RESPONSE- Added mock classes use for test cases. + +2015-03-17 Jocelyn Fiat + + Experiment to avoid pseudo sequential execution + + First attempt to use `{NETWORK_STREAM_SOCKET}.accept_to' + +2015-03-13 jvelilla + + Updated code based on Jocelyn's comments. + + Added HTTP_COOKIE and test cases. Added WSF_COOKIE class, inherit from + HTTP_COOKIE. + +2015-03-13 Jocelyn Fiat + + First steps to provide a concurrent compliant EWF connector. + +2015-03-11 Jocelyn Fiat + + fixed location of before_15_01 folder. + +2015-03-05 Jocelyn Fiat + + Removed the -safe since now new project should be void-safe + + moved wizard under tools/estudio_wizard + + moved wizard from tools to helpers + + Updated script to install wizard in current EiffelStudio installation. + + Updated the ewf estudio wizard to have a console and a graphical wizard. + Usage: wizard -callback file.cb path-to-rootdir folder. + +2015-02-18 Jocelyn Fiat + + Prepare nino ecf to be compilable with upcoming changes in EiffelNet / + NETWORK_STREAM_SOCKET interface. (see rev#96640 from eiffelstudio subversion + repository) + +2014-12-02 Jocelyn Fiat + + Updated install_ewf.bat to use the new "ecf_tool" from + https://svn.eiffel.com/eiffelstudio/trunk/Src/tools/ecf_tool . + + Completed change on debug handler and filter, to use WSF_DEBUG_INFORMATION. + +2014-12-01 Jocelyn Fiat + + Added assertions on router helpers, and also agent handler. Closes issue #159 + +2014-11-24 Jocelyn Fiat + + Fixed issue#157 (WSF_REQUEST.cookies_table does not terminate on cookies + without a value, or ending with semi-colon) Added related autotest. + +2014-11-19 Colin Adams + + Added {WSF_REQUEST}.http_content_encoding + +2014-11-18 Colin Adams + + issue #149 (Simple CORS support for GET requests in policy-driven framework) + + Issue #144 (Add last_modified to WSF_SKELETON_HANDLER) + +2014-11-17 Colin Adams + + Issue #143 + +2014-11-17 Jocelyn Fiat + + Converted ecf file to complete void-safe. Improved JSON_PRETTY_STRING_VISITOR + to support STRING_8 or STRING_32 output. Added examples. Added doc in the + folder "doc". Updated Readme and other files. Added package.iron file. + +2014-10-10 Jocelyn Fiat + + Fixed compilation issue for wsf_js_widget package. + +2014-09-30 Jocelyn Fiat + + Marked converters classes as obsolete. + + Updated license and copyright. Updated classes with bottom indexing notes + related to copyright and license. + +2014-09-24 Jocelyn Fiat + + Fixed various issue with parsing string (such as \t and related), Implemented + escaping of slash '/' only in case of ' Many feature renaming to match Eiffel style and + naming convention, kept previous feature as obsolete. Restructured the + library to make easy extraction of "converter" classes if needed in the + future. Updated part of the code to use new feature names. + +2014-07-07 Jocelyn Fiat + + Added custom-template in examples, as a base template to integrate easily + other JS widgets. Added custom example (based on custom-template project) + that demonstrates how to integrate a thirdparty JS component such as d3 + within the application using wsf_js_widget. Removed various unecessary ecf + dependencies. + + Fixed compilation issue related to old usage of modified JSON library. + + Move wsf_js_widget library under draft/library/server/wsf_js_widget + +2014-07-04 Conaclos + + Apply pretty print tool. Apply on each class in test suite and library. + +2014-07-02 Jocelyn Fiat + + Replace any multiple slash sequence by a single slash character for + PATH_INFO. + +2014-07-01 Jocelyn Fiat + + Various changes related to new WSF_DEBUG_INFORMATION and WSF_DEBUG_HANDLER. + + Fixed various issues related to unicode and CGI variables (assuming that CGI + variables are utf-8 encoded, and sometime percent encoded). Delayed + computation of `value' and `name' from WSF_STRING. Fixed computation of + REQUEST_URI when the server does not provide it (this is rare, but possible). + compute it as SERVER_NAME + encoded-PATH_INFO + {? + QUERY_STRING} + +2014-06-30 Conaclos + + Add documentation and contracts for domain types. + + Improve converters. Replace old syntax with new one and improve + implementation. + + Syntax update. Replace assigment attempt with object test. + +2014-06-30 Jocelyn Fiat + + Improved the debug example, so that it outputs more information. + + Ensure that PATH_INFO and REQUEST_URI are following the CGI specifications: - + PATH_INFO is percent decoded but still utf-8 encoded, this is available via + WGI.path_info and WSF_REQUEST.utf_8_path_info. - Added + WSF_REQUEST.percent_encoded_path_info - and WSF_REQUEST.path_info remains the + unicode value for PATH_INFO Added cgi_variables: WGI_REQUEST_CGI_VARIABLES + to have a simple and quick view on CGI variables Added execution_variables to + be able to iterate on execution variables. Added + PERCENT_ENCODER.percent_decoded_utf_8_string Improved the WSF_DEBUG_HANDLER + to provide more information thanks to WSF_DEBUG_INFORMATION object. + +2014-06-23 Jocelyn Fiat + + Raised the void-safety level to "complete" Added comments. + +2014-06-12 Jocelyn Fiat + + Added example to help debugging EWF This is mainly a kind of echo server .. + that return the request information. + +2014-06-11 Jocelyn Fiat + + Improved the uploading of file in regard to temporary filename. Avoid to + overwrite the same file for concurrent requests uploading the same filename. + +2014-05-14 Jocelyn Fiat + + Make sure to be able to compile in complete void-safe for 14.05 and still + compile with 13.11 + + Support for unicode error message for the + ERROR_HANDLER.as_string_representation: STRING_32 and as well for + debug_output, this avoid unecessary unicode string truncation. + + debug_output can return a string 32, so avoid truncated unicode value by + returning a string 32 value for `debug_output' . + + Replaced notion of session uuid by session id which is more generic (could be + a uuid, or something else). Use STRING_TABLE for the implementation of + session data container. Added a few missing comments. + + renamed HTTP_HEADER_BUILDER as HTTP_HEADER_MODIFIER + +2014-04-22 Jocelyn Fiat + + Updated ecf files toward complete void-safety Added iron package files. Added + libfcgi files to compile .lib and .dll on Windows + + Fixed various Unicode text handling. Moved example folder inside the library, + and renamed it "demo" Improved example code. + + Added support for UTF-8 during decoding. The JSON specification does not + require it, but some json encoders are using utf-8 encoding for json + encoding. Added related autotest case. + +2014-04-10 Jocelyn Fiat + + Added an example to embed EWF nino service into a Vision2 desktop + application. This is locally consumed via the embedded web browser component. + +2014-04-09 Jocelyn Fiat + + Updated encoder library, especially URL encoders to reuse implementation of + percent_encoder.e Fixed JSON_ENCODER for %T and related. Updated related + autotest cases. + + Moved implementation of WSF_PERCENT_ENCODER into "encoder" library, and added + the *partial* variant. + + Improved BASE64 to update has_error when decoding. Added manual tests. + +2014-04-08 Jocelyn Fiat + + Fixed issue with URL_ENCODER encoding (and small optimization) + +2014-03-26 Jocelyn Fiat + + Code improvement Cosmetic (comments, names, formatting) + +2014-03-19 hassany + + Fix STRING_32 issues + +2014-03-19 severin + + Added more comments and assertions to all classes; clean up + +2014-03-18 Jocelyn Fiat + + Added alias "[]" to `item', to get header value for a header name. Added + assigner for `item' to make it easier to add header item without confusing + key and value. Better parameter names (more explicit) + +2014-03-17 Jocelyn Fiat + + Added comments, used better parameter names. + + Extracting HTTP_HEADER_BUILDER from HTTP_HEADER to provide useful interface + on WSF_RESPONSE, and make WSF_SESSION easier to use. + +2014-03-12 hassany + + Extend documentation + +2014-03-12 severin + + Updated comments and added contracts for core controls in webcontrol + +2014-03-05 severin + + Added assets to library + +2014-03-05 YNH Webdev + + Rename WSF_FILE to WSF_FILE_DEFINITION + + Change STRING TO STRING_32 + +2014-03-03 Jocelyn Fiat + + Added a demo application server for basic http autorization + +2014-02-28 Jocelyn Fiat + + Removed usage of remote anchor types. + +2014-02-24 Jocelyn Fiat + + Fixed the ecf to test global compilation of EWF. + +2014-02-23 YNH Webdev + + Add class description to validators Rename Wsf_progresssource + +2014-02-21 severin + + Began with class documentation + +2014-02-03 Jocelyn Fiat + + Udated to highest level of void-safety. Fixed obsolete calls. + +2014-01-26 YNH Webdev + + Finalize WSF_DYNAMIC_MULTI_CONTROL + + Add dynamic multicontrol + +2014-01-25 YNH Webdev + + Image preview + + Fix upload state + +2014-01-24 Jocelyn Fiat + + Update restbucksCRUD example to use "crypto" library rather than "eel". + Updated readme.md to add curl command to test the server. + +2014-01-11 YNH Webdev + + Add set value to value controls + +2014-01-11 severin + + Included time library to set current date in date picker + +2014-01-08 severin + + Small change on date picker control, removed date input + +2014-01-07 jvelilla + + Fixed error with identity encoding. + +2014-01-06 severin + + Modified datepicker control + +2014-01-05 severin + + Removed country chooser widget + + fixed js + + modified country and date/time chooser + +2014-01-04 severin + + Included bootstrap datetimepicker + + Added date chooser widget + + Removed add_dropdown methods from navbar, some cleanup in different controls + + ATTENTION: ugly append_attributes added to stateless control, replaces + set_attributes -> maybe improve + + Moved set_attributes from BASIC_CONTROL to STATELESS_CONTROL + +2014-01-02 YNH Webdev + + Add disable option + + Allow remove + +2014-01-01 YNH Webdev + + Add serverside file id to file structure + + Demo upload + + Workin file upload + +2013-12-31 YNH Webdev + + Change parameter type + + File upload implementation part1 + + Fix dropdown list, clean up actions + +2013-12-03 Jocelyn Fiat + + Fixed various issues with libfcgi on Linux, mainly related to + stdout,stderr,stdin, feof and related. Added `reset' to the libfcgi input + stream so that it is possible to reset previous errors. + +2013-12-02 Jocelyn Fiat + + For Nino connector, ensured that environment variables are percent-encoded in + meta variables. + +2013-11-19 Jocelyn Fiat + + http_client: changed some default settings `connect_timeout' and `timeout' to + 0 (never timeout) Updated comments + +2013-11-18 Jocelyn Fiat + + removed CRLF eol in many files + +2013-11-12 Jocelyn Fiat + + Fixed wrong assertion related to upload_data and upload_filename in + HTTP_CLIENT_REQUEST_CONTEXT . Fixed issue #124 Enable all assertion for the + related autotest cases. + +2013-11-11 YNH Webdev + + Rename files + +2013-11-10 YNH Webdev + + Rename validators, Make forms resizable + + Validate all fields and make regexp stricter + + Fix event handler + + Fix email validation and min and max validator + +2013-11-09 YNH Webdev + + Fix slider + +2013-11-08 YNH Webdev + + Fix rendering issue. Add active class + +2013-11-08 Jocelyn Fiat + + Fixed issue with unicode login:password Added EIS info Added testing cases. + + Updated gewf source code to allow custom settings, and in particular the + location of the templates. Fixed compilation of application launcher, and + make it more flexible. + +2013-11-08 YNH Webdev + + Adjust layout control and fix navlist + + Fix autocomplete + + Redesign states and implement generated control_name + +2013-11-07 jvelilla + + Updated comments, add DEBUG_OUPUT to JSON_ARRAY. + + Fixed normalized line endings + + Normalize line endings + +2013-11-06 YNH Webdev + + Add stateless widgets + +2013-11-05 severin + + Fix Layout Control + + Added navlist widget + + Added WSF_LAYOUT_CONTROL + +2013-11-03 YNH Webdev + + Add item alias + +2013-11-02 severin + + Fixed js + + Added dropdown control + + Fixed creation procedures (make) + +2013-10-30 YNH Webdev + + Fix slider code + +2013-10-29 YNH Webdev + + Fix path + +2013-10-29 severin + + Fixed WSF_MULTI_CONTROL (wrong order of subcontrols), completed navbar, + improved slider + +2013-10-25 Jocelyn Fiat + + Added content_negotiation to official EWF release. + +2013-10-23 Jocelyn Fiat + + Removed trimmed_string function and callers, and for now, use + (left_|right_)adjust + +2013-10-22 jvelilla + + Reuse trimmed_string from HTTP_HEADER_UTILITIES. Added description to + FITNESS_AND_QUALITY. + +2013-10-18 Jocelyn Fiat + + Added content_negotiation in "wsf" library + + Minor changes in wsf test cases. + + Fixed an issue with one short chunk and empty trailer issue#81 + + Class renaming for content_negotiation Splitted SERVER_CONTENT_NEGOTIATION in + 4 differents classes for each kind of negotiation Changed to use ITERABLE + over LIST for supported variants arguments Factorized some code for http + parameter parsing such as q=1.0;note="blabla" and so on Integrated within + EWF + +2013-10-15 Jocelyn Fiat + + Updated content_negotiation with better class names and feature names. Minor + semantic changes in VARIANTS classes Factorized some code in + HTTP_ACCEPT_LANGUAGE + +2013-10-14 Jocelyn Fiat + + Enabled assertion on content_negotiation during autotests The tests project + is now void-safe Using force instead of put_left seems to work fine and is + better for performance, and no need to check for precondition "not before" + +2013-09-29 Severin + + Test + +2013-09-28 YNH Webdev + + Add codeview + + Fix load state error + + Implement lazy js load wraper + + Load needed libraries dynamically + +2013-09-27 Severin Münger + + Fixed slider + +2013-09-27 YNH Webdev + + Create new JSON_OBJECT + +2013-09-25 jvelilla + + Fixed Issue #75 CONNEG doesn't handle accept encodings correcty + +2013-09-24 Jocelyn Fiat + + Reused string constants from HTTP_HEADER_NAMES + + Added WSF_SELF_DOCUMENTED_AGENT_HANDLER and variants for uri, uri_template, + starts_with, ... to provide a way to documentate easily wsf agent handler. + +2013-09-24 Severin Münger + + Moved to draft + + Removed WSF_STATELESS_MULTI_CONTROL + + Added slider demo + +2013-09-24 YNH Webdev + + Add table title + + Implement remove + +2013-09-23 YNH Webdev + + Stop interval if deleted + + Introduce actions First working modal + +2013-09-22 YNH Webdev + + Set url within page class + + Implement control isolation + + Restructure callbacks + +2013-09-22 Severin Münger + + Improved Navbar, changed attribute handling + +2013-09-22 YNH Webdev + + Add comments to grid controls + +2013-09-21 Severin Münger + + Added comments to autocompletion, input, navbar, progressbar, validator, + webcontrol. Some more little changes. + +2013-09-20 YNH Webdev + + Fix tuple + + Make recommended changes - Implicit casting - Use same_string + +2013-09-20 jvelilla + + Added description to results classes. Removed unnecessary class Clean code: + removed feature out, updated corresponding test cases. + +2013-09-20 YNH Webdev + + Rename clusters to singular names + + Move project to wsf_js_widget + +2013-09-20 Jocelyn Fiat + + Renamed `content_negotation' as `content_negotiation' (fixed typo) Updated + .ecf and Eiffel code depending on previous CONNEG + + Minor changes - using http_client library instead of libcurl directly - using + implicit conversion to JSON_STRING to improve code readability - use + ARRAYED_LIST instead of LINKED_LIST .. for performance. - cosmetic .. but + still a lot of feature clauses are missing, comments, assertions ... + +2013-09-19 jvelilla + + Removed http classes related to http expectations. Updated code based on the + code review. Still work in progress + +2013-09-17 jvelilla + + New directory structure (variants, results, parsers) Refactor STRING to + READABLE_STRING_8. Clean code, added documentation and EIS references. + +2013-09-16 jvelilla + + Renamed CONNEG to content_negotiation. Update MIME_PARSER to use + HTTP_MEDIA_TYPE. + +2013-09-16 Jocelyn Fiat + + Accepts "*" as valid media type (interpreted as */* to be flexible) + + Fixed type having a semicolon in a parameter value such as "text/plain; + param1=%"something;foo=bar%"; param2=%"another-thing%" + + Added autotests to http library in relation with mime type and content type. + Fixed an issue with more than one parameter. + +2013-09-16 YNH Webdev + + Slow down fetching + +2013-09-15 Severin Münger + + Fixed progressbar + + Added progress callback + +2013-09-15 YNH Webdev + + Make js files local + + Add all countries to flag list Set encoding (Must be changed to UTF-8 in + future) + + Rearrange demo Add contact autocompletion + + Create basepage + +2013-09-15 Severin Münger + + Small changes + + Added Progress Control + + Included navbar example + +2013-09-14 YNH Webdev + + Fix change event + + Style demo pages + + Implement repeater + + Google news example + + - Add event paramenter - Implement Paging control + +2013-09-13 Severin Münger + + Fixed rendering, added navbar + +2013-09-13 Jocelyn Fiat + + Added PATCH support in http_client, and provided custom_with_upload_data and + custom_with_upload_file. + + forget about older version of Eiffel cURL + +2013-09-13 Severin Münger + + Small changes/fixes + + Small fix removed DOCTYPE + + New Control structure + +2013-09-13 YNH Webdev + + Add Grid Widget + +2013-09-12 Severin Münger + + Extended autocompletion with customized templates + + Autocompletion + + Changed structure + +2013-09-09 Jocelyn Fiat + + Fixing handling of query parameter without value Issue#70 + https://github.com/EiffelWebFramework/EWF/issues/70 + +2013-09-08 jvelilla + + Moved Selenium web driver to WebDriver-Eiffel repository + +2013-09-06 YNH Webdev + + Min/Max validator + +2013-09-06 Severin Münger + + Some small changes + +2013-09-06 YNH Webdev + + Add HTML control + +2013-09-06 Jocelyn Fiat + + fixed compilation of wsf_extension + +2013-09-06 YNH Webdev + + Implement serverside and client side validatation + +2013-09-06 Jocelyn Fiat + + Added WSF_CUSTOM_HEADER_FILTER which provide a convenient way to add a custom + header from a filter. Added to wsf_extension WSF_DEBUG_FILTER and + WSF_DEBUG_HANDLER that could be convenient to test specific requests + Restructured wsf_extension + + added policy driven license .lic files + + Added WSF_WIDGET_RAW_TEXT to render text via html encoding. Added + WSF_WIDGET_COMPOSITE.extend_html_text (READABLE_STRING_8) that should replace + the now obsolete "extend_text" Added WSF_WIDGET_COMPOSITE.extend_raw_text + (READABLE_STRING_GENERAL), for text that need to be html encoded during html + rendering. Made WSF_FORM_RAW_TEXT obsolete. + + Used res.put_header_lines (h) rather than res.put_header_text (h.string) + +2013-09-06 YNH Webdev + + First working checkbox list + +2013-09-06 Severin Münger + + Added checkbox list, modified form validation + +2013-09-05 Severin Münger + + Added validators for decimals and mails + + Added Regexp validation (later used for mail, numbers...) + +2013-09-05 YNH Webdev + + Fix form and textarea bug + + Test the new controls + +2013-09-05 Severin Münger + + Implemented WSF_CHECKBOX_CONTROL, added id attribute to rendering of + WSF_CONTROL + +2013-09-05 YNH Webdev + + Fix render function + +2013-09-05 Severin Münger + + Restructured validators, fixed form element rendering + +2013-09-05 YNH Webdev + + Fix render function + +2013-09-05 Severin Münger + + Implemented WSF_FORM_ELEMENT_CONTROL + + Began with implementation of form handling + +2013-09-05 YNH Webdev + + Use render tag + +2013-09-05 Severin Münger + + Adapted rendering of multi control + + Changed creation procedures + +2013-09-05 YNH Webdev + + Change wsf control + +2013-09-04 Olivier Ligot + + Contribute page + +2013-09-03 Severin Münger + + Added TextArea + +2013-09-02 Severin Münger + + forgot to add new files + + Added generalized input control similiar to text + +2013-08-29 YNH Webdev + + Only send changes back to client + +2013-08-28 YNH Webdev + + Add comments Use Precursor + + Clean up code Simplify event + + Only callback if there is an event attached + + Remove ugly do nothing hack + + Communication in both directions (Text control) Code regrouping + + Fix multi control Use multi control in example + + First working callback + +2013-08-27 Severin Münger + + Added WSF_MULTI_CONTROL to support controls that consist of multiple separate + controls. + + Created first working sample page application. + +2013-08-27 YNH Webdev + + Pretty Print + + Add a json state to each control + + Page structure + +2013-08-27 Severin Münger + + Created widget-project testapp project. + +2013-08-21 Jocelyn Fiat + + Updated copyright for policy-driven classes, which is a contribution from + Colin Adams. + +2013-08-20 Jocelyn Fiat + + Extracted the policy driven classes into their own library for now + "wsf_policy_driven.ecf" Updated the restbucksCRUD example to demonstrate both + approaches. + + Moved recent policy-driven classes into "policy" sub folder + + Removed WSF_ROUTING_HANDLER.make_with_router (a_router) It was not used in + existing code, and potentially dangerous, if coder reuses router by accident. + +2013-08-16 Colin Adams + + Changed age to max_age + +2013-08-14 Colin Adams + + Further use of constants for execution variables + +2013-08-13 Colin Adams + + Gave symbolic names to execution variables used by the framework + +2013-08-12 Colin Adams + + Added some checks for custom erros being set. + + refactored to allow etags to work properly when multiple representations are + available + +2013-08-08 Colin Adams + + Implemented remaining error response calls + + made deleted into an effective routine + +2013-08-07 Colin Adams + + Fixes as picked up by code review + +2013-08-06 Colin Adams + + restbucksCRUD example changed to use policy-driven framework + + Policy-driven URI template handlers + + Add CONNEG to wsf*.ecf to support ploicy-driven framework + +2013-08-05 Jocelyn Fiat + + Enhanced interface of JSON_ARRAY and JSON_OBJECT Added JSON_ITERATOR + +2013-07-19 Olivier Ligot + + Fix C compilation when using libfcgi connector on OS X (#65) + +2013-07-11 Olivier Ligot + + Tests compile again (fixes #63) + +2013-07-05 Jocelyn Fiat + + Moved gewf under draft/src/gewf + + licensing and copyright + + First working (but limited) tool + + Added first attempt to provide a application builder. For now only trying to + have a generic template. Do not expect anything working for now, this is + just the start of a draft + +2013-07-02 Jocelyn Fiat + + Moved the cms component to https://github.com/EiffelWebFramework/cms This is + now out of EWF repository. + +2013-06-28 Jocelyn Fiat + + Improved Unicode support. + + Ensured that EWF compiles with 7.2 (note about ecf version 1-10-0 + void_safety="all" <--> 1-11-0 void_safety="transitional" 1-10-0 + void_safety="all" <--- 1-11-1 void_safety="all" ) + +2013-06-18 Jocelyn Fiat + + Removed wsf_support, which is useless and unused + +2013-06-17 Jocelyn Fiat + + Updated ecf file as workaround to make autotest works fine. + +2013-06-13 Jocelyn Fiat + + Added notification_email library as official EWF lib. + + Unicode support for notification_email library + +2013-06-12 Jocelyn Fiat + + Removed a few obsolete usages, and benefit from new classes from EiffelStudio + >= 7.2 + + Updated WGI specification to ease future migration to unicode support. Use + STRING_TABLE, and better interface of READABLE_STRING_GENERAL, this way the + signature are more flexible for unicode keys. Note that for now, unicode + environment variables are not correctly supported in WGI especially the value + of the variables. Any layer on top of EWGSI suffers from the same issues. + Better exception handling + code cleaning + + minor optimization avoiding to create temporary string that might be big + + Updated CMS support for unicode. + + Better support for unicode path and values. Added + WSF_REQUEST.percent_encoded_path_info: READABLE_STRING_8 to keep url encoded + path info, as it is useful for specific component The router is now using + WSF_REQUEST.percent_encoded_path_info since URI_TEMPLATE are handling URI + (and not IRI) this fixes an issue with unicode path parameters. This should + not break existing code, and this fixes various unicode related issues + related to PATH parameter and path info but also any component using file + names. (required EiffelStudio >= 7.2) + +2013-06-12 Olivier Ligot + + Rename notification to notification_email + + Extract notification library from the CMS draft application The new library + is located in library/runtime/process/notification. This allows to use it + apart from the CMS. + +2013-06-11 jvelilla + + merge + +2013-06-07 Jocelyn Fiat + + Fixed various void-safety issue with recent compilers. Note that EWF does + now require EiffelStudio 7.2, and is compiling with 7.3 + +2013-05-29 jvelilla + + Added command POST /session/:sessionId/modifier Initial implementation of + KeyBoard. Added Mouse class, but not implemented. + +2013-05-28 Jocelyn Fiat + + Added WSF_REQUEST.read_input_data_into_file (FILE) + +2013-05-22 jvelilla + + Updated command_executor Added more examples. + +2013-05-20 jvelilla + + Update find element examples. Improved command executor + +2013-05-18 jvelilla + + Added new selenium locator examples. Fixed find_elements in WEB_DRIVER. + +2013-05-14 jvelilla + + Move expectation classed under a expectation cluster, added a new expectation + class for header. + + Added examples find by id, name and class. + +2013-05-13 jvelilla + + Updated selenium WEB_DRIVER_WAIT, the feature until_when now use a predicate. + Updated the related example. + +2013-05-10 jvelilla + + Initial implementation of HTTP RESPONSE EXPECTATIONS. Added a class to test + http client with httpbin.org and expectations + +2013-05-08 jvelilla + + Updated WEB_DRIVER_WAIT class, still need to be improved. Updated Readme and + the example + +2013-05-03 jvelilla + + Improve the example, Added a new class WEB_DRIVER_WAIT, still under + development. Update web driver, to define time outs. + +2013-04-30 jvelilla + + Added a simple search example. Updated web_driver, use the API as delegation + instead of inheritance. Updated web_element class. + +2013-04-29 jvelilla + + Created new classes to represent a web driver. Added Examples, clean code + +2013-04-24 jvelilla + + Completed low level methods, clean code. + + Implemented more commands from REST API JSONWireProtocol Refactor + COMMAND_EXECUTOR. + +2013-04-23 jvelilla + + Added more command from JSONWireProtol. + + Added more commands from the JSONWireProtocol. + +2013-04-22 Jocelyn Fiat + + added header helper feature in the context interface added + HTTP_CLIENT_SESSION.custom (...) to support any kind of request methods + +2013-04-22 jvelilla + + Added new classes, implemented more methods from JSONWireProtol API. Added + test cases + +2013-04-17 Colin Adams + + Made changes requested in review + +2013-04-17 jvelilla + + Fixed errors in navigate_to_url command, Fixed url templates in + json_wire_protocol_command. Added test cases to AutoTest + +2013-04-16 jvelilla + + Fixed feature typo, improved commands, added AutoTest + +2013-04-15 jvelilla + + Updated RestAPI commands + +2013-04-13 Colin Adams + + If-Match implemented in skeleton handler + + If-Match implemented in skeleton handler + +2013-04-12 jvelilla + + Fixed configurations paths + + Initial import Selenium binding + +2013-04-11 Jocelyn Fiat + + Fixed HTTP_CLIENT_RESPONSE when dealing with redirection before it was + storing some header in the body. now we added redirections: .. which is a + list of redirection informations: - status line - header - and eventual + redirection body (but at least by default, libcurl does not cache body) + Enhanced the http_client library to be able to write directly the downloaded + data into a file (or as convenient thanks to agent). + +2013-04-11 Colin Adams + + Fixed bug in 32/8 bit string existance + + Handle Precondition Failed for If-Match: * where there is no handler for the + resource + +2013-04-10 Jocelyn Fiat + + Fixed HEAD request related issue see + https://github.com/EiffelWebFramework/EWF/issues/53 + +2013-04-05 Jocelyn Fiat + + Cosmetic fixed various indentations Removed useless dependencies for + ewf_ise_wizard project. + +2013-03-30 Jocelyn Fiat + + fixed name of file with class name + +2013-03-29 Jocelyn Fiat + + reuse implementation from WSF_REQUEST to get input data for MIME handlers. + + Fixed MIME multipart form data handler And use content-length value if + provided. + + be sure we got the full content same as content length + +2013-03-27 Colin Adams + + First attempt at WSF_HTTP_PROTOCOL_VERSION + +2013-03-27 Jocelyn Fiat + + Removed WSF_URI_*_ROUTER_HELPER and use instead the + WSF_URI_*_HELPER_FOR_ROUTED_SERVICE (the removed class were not in latest + release, so this is safe to use the new name) Cosmetic + +2013-03-27 Colin Adams + + Further changes in response to review comments by Jocelyn + + now all-safe.ecf compiles again + +2013-03-27 Jocelyn Fiat + + added wsf_html for (un)installation + + Updated all-safe.ecf (add all-stable-safe.ecf that includes only the library, + examples and specific draft lib) + +2013-03-27 Colin Adams + + openid demo fixed + +2013-03-26 Colin Adams + + merging from upstream - stage 4 + + Use class URI + +2013-03-26 Jocelyn Fiat + + Moved more components from CMS to wsf_html. This includes WSF_PAGER, and + feature in WSF_THEME .. including WSF_API_OPTIONS used to compute url and + link. + +2013-03-25 Jocelyn Fiat + + Added self doc to the wsf file system handler Allow to hide the wsf file + system handler from self documentation Better description format handling for + the self doc + +2013-03-22 Jocelyn Fiat + + added wsf_html-safe.ecf to all-safe.ecf + + Extracted the WIDGET and FORM classes out of "cms" component and build the + wsf_html library which also include the previous css lib. + + Fixed default status code for redirection response message object. + + Fixed assertion that were broken with recent delayed header response. Changed + semantic of put_header_lines and add_header_lines, Now the arguments are + iterable of string (i.e the header line) The previous features were not + used, and were not well named. So we removed them, and reused the names for + adpated implementation. + + Fixed self documentation when querying documentation related to a specific + resource (uri, uri-template, ..) Before it was showing only the first found + so if we had "/foo" GET -> FOO_GET_HANDLER "/foo" POST -> FOO_POST_HANDLER It + was showing only the first, now this is working as expected. + + Moved the *_CSS_* class in their own (draft) library, since they are not CMS + specific. + +2013-03-21 Jocelyn Fiat + + Fixing feature comments + + Removed WSF_AGENT_HANDLER since it was an artificial notion, as we have no + common ancestor for WSF_HANDLER having execute (req: WSF_REQUEST; res: + WSF_RESPONSE) + + Now WSF_FILTER_HANDLER is a handler and has formal generic G constrained to + WSF_HANDLER This eases implementation of potential descendants. + + Introduced WSF_ROUTER_SESSION This fixes CQS violation from + WSF_ROUTER.dispatch_and_return_handler (...): ? WSF_HANDLER and related code, + and this is more compliant with concurrency. In addition, the + WSF_ROUTER_SESSION can be enhanced in the future to answer more advanced + needs. + + Fixed WSF_FILE_RESPONSE and WSF_DOWNLOAD_RESPONSE and set the status code to + be Ok by default + +2013-03-19 Jocelyn Fiat + + mimic design of WSF_ROUTED_SERVICE for WSF_FILTERED_SERVICE and update the + filter example to make it simpler and reuse code. + + updated install and uninstall scripts + + added WSF_..._ROUTER_HELPER and made the previous WSF_..._ROUTED_SERVICE + obsolete + + WSF_CORS_OPTIONS_FILTER should not inherit from WSF_URI_TEMPLATE_HANDLER + + Moved all *_CONTEXT_* router related classes into wsf_router_context.ecf + library This makes wsf simpler to discover. And advanced context enabled + handler, mapping, ... are still available for now in wsf_router_context.ecf + library + +2013-03-18 Jocelyn Fiat + + Added deferred WSF_AGENT_HANDLER Added WSF_NOT_IMPLEMENTED_RESPONSE + +2013-03-18 Colin Adams + + refactored for WSF_ROUTED_SKELETON_SERVICE + + prior to refactoring for WSF_ROUTED_SKELETON_SERVICE + +2013-03-17 Colin Adams + + implemented OPTIONS * except for Allow header + +2013-03-16 Colin Adams + + Implemented 414 and 503 responses on WSF_ROUTED_SERVICE + + Implemented 503 and 414 responses in WSF_ROUTED_SERVICE + +2013-03-15 Colin Adams + + Sixth round of contracts for non-Void-safe users + + Fifth round of contracts for non-Void-safe users + +2013-03-15 Olivier Ligot + + Use new upstrem method put_header_key_values + +2013-03-15 Colin Adams + + Third iteration of contracts for non-Void-safe users + +2013-03-14 Colin Adams + + Further contracts for non-Void-safe users + + Response to comments from review "Contracts for non-Void-safe users (take 1)" + + Added non-Void contracts for classes previously flagged by AutoTest + +2013-03-08 Jocelyn Fiat + + Made it compilable with 7.1 + + Factorized code for checkbox and radio input. Renamed `text' and similar to + `title' and similar + + adding back missing uri template library + + Added support for OpenID identity Added user roles management Improvement + CMS_HOOK_FORM_ALTER design. Factorized code into CMS_WIDGET_COMPOSITE Use + general notion of CMS_WIDGET (and CMS_FORM allows CMS_WIDGET, and not just + CMS_FORM_ITEM) Fixed various CMS_WIDGET traversal, and fixed related issue + for CMS forms Fixed CMS_FORM_CHECKBOX_INPUT when no value was set. Added + CMS_FORM_DATA.cached_value .. to pass computed values during validation to + submit actions (mainly for optimization) Added support for @include=filename + in CMS_CONFIGURATION Added CMS_WIDGET_TABLE as filled version of + CMS_WIDGET_AGENT_TABLE (renamed from previous CMS_WIDGET_TABLE) Many + improvements to the CMS_FORM design Some improvements to CMS_MODULE ... + + Use the advanced SED storable to store data on disk (rather than the runtime + storable) + +2013-03-05 Jocelyn Fiat + + Added WITH_HTML_ATTRIBUTE + +2013-03-01 Jocelyn Fiat + + added the notion of site identifier "site.id" (typically this could be a + UUID) + + Also take into account sublink's permission + +2013-02-28 Jocelyn Fiat + + added CMS widgets demonstration in DEMO_MODULE + + add CMS_WIDGET_... to ease html page development. + + improved CMS_CSS_STYLE and WITH_CSS_STYLE + + Move draft\library\security\openid under library\security\openid + + Made it also compilable with compiler < 7.2 + + Added a version of ISE Library URI modified to be compilable with compiler < + 7.2 Fixed openid when redirection is involved Fixed Openid Attribute Exchange + implementation (AX) Added WSF_REQUEST.items_as_string_items: ... for + convenience, and ease integration with other components (such as the new + openid) + + updated relative path + +2013-02-27 Jocelyn Fiat + + OpenID consumer implementation REQUIRES EiffelStudio 7.2 + + First version of OpenID consumer (light implementation) + + Added a way to call a callback on launched and stopped for Nino connector + + Provided a way to report cURL error code back to http_client, via + HTTP_CLIENT_RESPONSE + + Provided `url_encoded_name' on the WSF_VALUE interface + +2013-02-26 Jocelyn Fiat + + Use append_to_html rather than function to_html: STRING this is mainly to + avoid creating useless intermediary strings. + +2013-02-21 Jocelyn Fiat + + Added functionalities to CMS_FORM_.. classes + +2013-02-20 Jocelyn Fiat + + Fixing various form urls, that was not taking into account base url + +2013-02-19 Jocelyn Fiat + + Fixed absolute url computing for CMS + + Code cleaning and use HTTP_DATE instead of duplicating code. + +2013-02-15 Jocelyn Fiat + + Now the cms.ini resolves variable ${abc} ... and key is case insensitive + + keep compilable with EiffelStudio <= 7.1 + + Refactorying the CMS component, to have an effective CMS_SERVICE, and setup + as CMS_SETUP. This way the application is much simpler, no need to implement + deferred feature of CMS_SERVICE. + +2013-02-14 Jocelyn Fiat + + Now also display sublinks if link is expanded. Updated theme + + Fixed register and new password link when the CMS's base dir is not the root + / + + Improve CMS_LINK to easily add children + +2013-02-05 Jocelyn Fiat + + added CMS_FORM_SELECT.select_value_by_text + + remove unwanted console output + +2013-02-04 Jocelyn Fiat + + Reviewed initialization and usage of various CMS_SERVICE urls + + more flexible permission control system ... + + Updated CMS experimental component Fixed various issues with fieldset or + similar not traversed + +2013-01-31 Jocelyn Fiat + + Fixing global EWF compilation + + Updated CMS code. Separated code to have a lib and an example. Improved + design, fixed a few issues related to folder location. This is still + experimental and require more work to be really friendly to use. + + Added ANSI C date time string format support in HTTP_DATE. + + Fixed HTTP_DATE for GMT+ offset (integer value) + + Added HTTP_DATE to ease http date manipulation and optimize code rather than + using EiffelTime's code facilities. Added autotests to `http' lib. + +2013-01-23 Jocelyn Fiat + + Removed eel and eapml contrib/library from EWF Since there are available from + $ISE_LIBRARY + +2013-01-23 Olivier Ligot + + Use execution_variable instead of context This is mainly to be compatibe + with other classes API. In a lot of classes, we define methods like this: + ```Eiffel method (req: WSF_REQUEST; res: WSF_RESPONSE) do ... end ``` With + the context, the signature becomes: ```Eiffel method (ctx: C; req: + WSF_REQUEST; res: WSF_RESPONSE) do ... end ``` So, I can't build a filter + chain where one filter is with context and one is without context (I can't + call WSF_FILTER.set_next (a_next: WSF_FILTER) with a filter that is a + descendant of WSF_CONTEXT_HANDLER). Moreover, having to play with generic + types just to pass some data from one filter to another is a bit overkill + imho. Because this is really what I use contexts for: to pass data from one + filter to the next one. Regarding execution_variable and strong typing, if + we want to achieve these, I realize we could write a class with one getter + and one setter like this: ```Eiffel class TYPED_DATA feature -- Access + user (req: WSF_REQUEST): detachable USER do if attached {USER} + req.execution_variable ("user") as l_user then Result := l_user end end + feature -- Element change set_user (req: WSF_REQUEST; a_user: USER) do + req.set_execution_variable ("user", a_user) end ``` Now, I realize this is a + major change since the last time we talked about this, but at the end, after + having played with both, I prefer the one with execution_variable. + +2013-01-09 Olivier Ligot + + Cross-Origin Resource Sharing initial support Initial support for the + Cross-Origin Resource Sharing specification. This allows JavaScript to make + requests across domain boundaries. Also reviewed the filter example to get + rid of the context and the generic classes (we can actually use + {WSF_REQUEST}.execution_variable and {WSF_REQUEST}.set_execution_variable). + Links: * How to enable server-side: http://enable-cors.org/server.html * + Specification: http://www.w3.org/TR/cors/ * Github: + http://developer.github.com/v3/#cross-origin-resource-sharing + +2012-12-22 Jocelyn Fiat + + Added http_authorization which is now needed by example filter. + + minor changes + +2012-12-20 Jocelyn Fiat + + added WSF_SUPPORT.environment_item + + Added is_available on HTTP_CLIENT_SESSION mainly to check if libcurl is + available. + + Avoid calling ANY.print, prefer io.error.put_string Fixed obsolete calls. + + Added support for server_name in nino, and openshift + + Added support for server name + + updated conneg .ecf + + Added openshift connector classes (for experimentation) + + Added comment to self documentation features + +2012-12-19 Jocelyn Fiat + + Added a few library_target to .ecf to be able to build the tests/all-safe.ecf + that enables us to check quickly the compilation state of EWF, and also + perform refactorying over many projects. + + Breaking changes: added `a_request_methods' argument to + WSF_ROUTER_SELF_DOCUMENTATION_HANDLER.mapping_documentation added similar + argument to WSF_ROUTER_SELF_DOCUMENTATION_ROUTER_MAPPING.documentation + Renamed WSF_ROUTER_METHODS as WSF_REQUEST_METHODS Enhanced + WSF_REQUEST_METHODS with new has_... function Added WSF_ROUTER_VISITOR and + WSF_ROUTER_ITERATOR that may be useful to iterate inside the router. we may + improve the implementation of the router using those visitors in the future. + Improved the WSF_DEFAULT_RESPONSE to embedded suggested items (typically + based on pseudo self documented router) + + Fixed issue in WSF_REQUEST.read_input_data_into when the content is zero + Cleaned the WGI_CHUNKED_INPUT_STREAM and provides access to last extension, + last trailer, ... Improved WSF_TRACE_RESPONSE to support tracing chunked + input back to the client. + + Fixed WSF_RESPONSE chunk transfer implementation and also the optional + extension `a_ext' should now include the ';' Now HTTP_HEADER is an ITERABLE + [READABLE_STRING_8] + + Fixed various assertions. Improved autotests Added target 'server' to be able + to run the server outside the test process. + +2012-12-18 Jocelyn Fiat + + Fixed reading chunked input data When retrieving data block by block, use + 8_192 instead of 1_024 (since 1_024 is too small most of the time) + + Added logger response wrapper, this is mainly to be able to save any response + message to a file. (debugging purpose) + + Added basic support for "Expect" http header i.e: WSF_REQUEST.http_expect: + detachable READABLE_STRING_8 Added WSF_REQUEST.request_time_stamp: + INTEGER_64 + +2012-12-14 Jocelyn Fiat + + Added WSF_DEFAULT_*_RESPONSE Fixed the method not allowed by setting the + Allow: header + +2012-12-13 Jocelyn Fiat + + removed unused local variables + + added code that may be used to avoid breaking compatibility with new Eiffel + Studio 7.2 This is experimental for now. + + Added to WSF_REQUEST - raw_header_data: like meta_string_variable - + read_input_data_into (buf: STRING) - is_content_type_accepted + (a_content_type: READABLE_STRING_GENERAL): BOOLEAN Changed raw_input_data to + return IMMUTABLE_STRING_8 Added WSF_METHOD_NOT_ALLOWED_RESPONSE Added + WSF_TRACE_RESPONSE to respond TRACE request Now Not_found response return + html content if the client accepts, other text/plain Implemented TRACE + response, and Method not allowed as implementation of + WSF_ROUTED_SERVICE.execute_default + + Added missing "context" classes for uri and starts_with mapping+handler (and + helper classes). So that it is address more needs. Factorized code between + "context" and non context classes. + +2012-12-11 Colin Adams + + Actioned Jocelyns comments re. a_req and a_res + +2012-12-10 Olivier Ligot + + Fix {JSON_OBJECT}.hash_code implementation Don't call + {HASH_TABLE}.item_for_iteration when {HASH_TABLE}.off Use {HASH_TABLE}.out + instead + +2012-12-10 Jocelyn Fiat + + Get rid of obsolete scripts (we do not use git submodule anymore, so this is + much easier .. for the users) + +2012-12-07 Jocelyn Fiat + + make it compiles with EiffelStudio 7.1 and 7.2 + +2012-12-06 Colin Adams + + Revert do_get_head patch + +2012-12-05 Jocelyn Fiat + + corrected null connector ecf files + + added tests\all-safe.ecf to compile most of EWF's lib, to quickly check the + compilation state + + use libfcgi(-safe).ecf rather than fcgi(-safe).ecf + + Prepare upcoming support for unicode environment variables + + removed fcgi(-safe).ecf files ... since there renamed libfcgi(-safe).ecf + +2012-12-04 Olivier Ligot + + ise_wizard Unix shell scripts + +2012-12-03 Olivier Ligot + + Fix ise_wizard * ewf.ini was used instead of template.ecf as configuration + file * remove initialize_router otherwise the compilation failed * remove + unused variables + + Logging filter The logging filter is now part of EWF core (before it was + only available in the filter example) and can therefore be reused by others + needing it. Note that this is a first implementation. It can certainly be + improved in the future to support more fine grained logging. + +2012-12-05 Jocelyn Fiat + + added tests\all-safe.ecf to compile most of EWF's lib, to quickly check the + compilation state + + use libfcgi(-safe).ecf rather than fcgi(-safe).ecf + + Prepare upcoming support for unicode environment variables + + removed fcgi(-safe).ecf files ... since there renamed libfcgi(-safe).ecf + +2012-12-04 Olivier Ligot + + ise_wizard Unix shell scripts + +2012-12-03 Olivier Ligot + + Fix ise_wizard * ewf.ini was used instead of template.ecf as configuration + file * remove initialize_router otherwise the compilation failed * remove + unused variables + + Logging filter The logging filter is now part of EWF core (before it was + only available in the filter example) and can therefore be reused by others + needing it. Note that this is a first implementation. It can certainly be + improved in the future to support more fine grained logging. + +2012-12-03 Jocelyn Fiat + + Fixed various compilation issue with new self documentation Improved the self + documentation handler to provide a make_hidden creation procedure + + updated ecf path + +2012-11-26 Jocelyn Fiat + + Added debug clause to detect in WSF_ROUTER.map_with_request_methods the + existing conflicts with similar mapping. Added smart handling of HEAD + request. Exported some internal features of WSF_REQUEST and WSF_RESPONSE to + respectively WSF_REQUEST_EXPORTER and WSF_RESPONSE_EXPORTER + + added debug_output to WSF_ROUTER_MAPPING + +2012-11-25 Jocelyn Fiat + + Included the library base(-safe).ecf which was forgotten by mistake. + +2012-11-24 Colin Adams + + Completed first pass for HTTP 1.1 conformace contracts + + Added framework for HTTP-conforming contracts + +2012-11-23 Jocelyn Fiat + + New design for self documented router. The documentation is built only on + demand. A mapping entry can be hidden for the documentation One can change + the status code when building itself the + WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE + + Made encoder and error library compilable with 6.8 + + Added SHARED_... classes for encoders (html, url, xml, json, ...) + + Updated signatures for the self documentated message + + Added WSF_ROUTER.has_item_associated_with_resource and + item_associated_with_resource Added WSF_ROUTER_MAPPING.associated_resource + Added WSF_ROUTER_SELF_DOCUMENTATION_HANDLER and + WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE to provide a self documentation for + WSF_ROUTER (for now, only HTML) + +2012-11-21 Jocelyn Fiat + + Include the `url' in the http client response. This way, we can get the real + url used by the lib, especially when there are query parameters. + +2012-11-20 Jocelyn Fiat + + Added WSF_ROUTER_ITEM to replace a structure represented with named TUPLE + Added debug_output to ease debugging + + Removed pseudo rest library from draft libraries. + +2012-10-22 Jocelyn Fiat + + Added WSF_REQUEST_UTILITY_PROXY, that provides the WSF_REQUEST_UTILITY + features to a class that implement request: WSF_REQUEST + + Added WSF_ROUTING_CONTEXT_HANDLER + +2012-10-08 Jocelyn Fiat + + Removed generic parameter in WSF_FILTER_HANDLER, since it is useless and make + code heavy + + Updated "filter" example + +2012-10-04 Jocelyn Fiat + + Updated Copyright + + updated copyright + + Added notion of mapping factory, so one can implement a handler without + having to implement new_mapping Added filter context handler Added + WSF_STARTS_WITH_ROUTING_HANDLER and WSF_URI_ROUTING_HANDLER (in addition to + the uri template version) + +2012-10-02 jvelilla + + Fixed wsf_extension.ecf path, in the example RestBucksCRUD. Replace the + assigment attempt with attached syntax + +2012-10-01 Jocelyn Fiat + + Fixed some configuration files (ecf) Fixed various compilation issue Fixed + draft rest library (still experimental and should be removed in the future) + +2012-09-28 Jocelyn Fiat + + Added initial experimentation of a CMS built with Eiffel + + moved wsf_extension inside wsf/extension as wsf/wsf_extension.ecf added + wsf/session as wsf/wsf_session.ecf In descendants of WSF_HANDLER , we can + keep the result of new_mapping as WSF_ROUTER_MAPPING + +2012-09-27 Jocelyn Fiat + + Reviewed the semantic of the handler context. Adapted existing code to fit + the new router design. + +2012-09-25 Jocelyn Fiat + + Applied new ROUTER design to the whole EWF project. + +2012-09-11 Jocelyn Fiat + + Minor implementation changes (feature renaming, ... ) + +2012-09-10 Jocelyn Fiat + + New ROUTER design, much simpler, less generic, easier to extend, and now one + can mix uri map, uri_template map and so on. Update the "tutorial" example. + +2012-09-12 Olivier Ligot + + [FIX] Convertion from HASH_TABLE keys to JSON + +2012-09-11 Jocelyn Fiat + + Added general_encoded_string (..) that accepts READABLE_STRING_GENERAL + +2012-09-10 Jocelyn Fiat + + added WSF_VALUE.is_empty: BOOLEAN + + Added put_expires_string (s: STRING) and put_expires_date (dt: DATE_TIME) + Better implementation for WSF_FILE_RESPONSE (added last modified, and other + caching related info) + +2012-08-28 Jocelyn Fiat + + Fixed source code for building and installing the ISE Wizard + +2012-08-13 jocelyn + + Updated Projects Suggestions (markdown) + + Updated Projects Suggestions (markdown) + + Updated Project suggestions (markdown) + +2012-08-10 Olivier Ligot + + [ADD] Filter: pre-process incoming data and post-process outgoing data + Filters are part of a filter chain, thus following the chain of + responsability design pattern. More information are available in + library/server/wsf/src/filter/README.md + +2012-08-08 Jocelyn Fiat + + removed "getest" since it is duplication with autotest (and we use mainly the + later for regression testing) + + Added JSON_PRETTY_STRING_VISITOR Added converter for ARRAYED_LIST Fixed + STRING_32 to JSON_VALUE issue in ejson.e Added missing new line character at + the end of some files. Cosmetic + +2012-06-29 Jocelyn Fiat + + updated to use WSF_STRING.value instead of obsolete WSF_STRING.string + + Better code for tutorial example. + +2012-06-28 jocelyn + + Updated EWSGI specification: difference in main proposals (markdown) + +2012-06-27 Jocelyn Fiat + + use svn export instead of svn checkout + +2012-06-26 Jocelyn Fiat + + If library/cURL exists, do not copy cURL to contrib/library/network/cURL + +2012-06-22 Jocelyn Fiat + + Added simple console wizard for Eiffel Studio. (It is not very user friendly, + this is a first draft) It should be improved in the future (with GUI, ...) + +2012-06-20 Jocelyn Fiat + + When installing, remove the folder "fonts" from the nino's example + +2012-06-19 Jocelyn Fiat + + Put examples under examples/web/ewf/... + +2012-06-19 Jocelyn Fiat + + IfECF_PATH_UPDATER is defined, let's use it to find ecf_updater executable + +2012-06-18 Jocelyn Fiat + + put everything under contrib for now, eventually svn checkout missing parts + +2012-06-18 Jocelyn Fiat + + Final version of the install scripts. + + Fixed typo and path separators usage in dos batch scripts + + Install script does the same on Windows and Linux + + improved install_ewf.sh , and removed usage of deleted router.ecf + +2012-06-15 Jocelyn Fiat + + Updated install_ewf.sh + + Updated draft library (consider it as draft quality) + + updated eel and eapml from more recent versions. + + Moved eel and eapml under the contrib folder. + + Fixing wrong path for ewsgi connector nino (this was introduced recently when + we moved folder location) + +2012-06-14 Jocelyn Fiat + + Updated structure of EWF, applied Now "nino" is under + contrib/library/network/server/nino (as git merge subtree, and not anymore + as submodule) + +2012-06-13 Jocelyn Fiat + + Change structure of EWF, to follow better categorization + + Better script, do not use default folder without asking. + + Added temporary scripts to install EWF on Windows + +2012-06-11 Jocelyn Fiat + + Adopted convention name and value or values for WSF_VALUE and descendant + (WSF_STRING ...) kept `key' as redirection, and also string as obsolete + redirection. Router: provide a way to pass the request methods without using + manifest string, thanks to WSF_ROUTER_METHODS so instead of using manifest + array or manifest strings, just create an instance of WSF_ROUTER_METHODS for + convenience, WSF_ROUTER provides a few `methods_...' returning prebuilt + WSF_ROUTER_METHODS objects Improved code related to unicode handling in URL, + and parameters (before the framework was doing too much) + +2012-05-30 Jocelyn Fiat + + Added html encoding facility to WSF_STRING Added WSF_STRING.is_empty Improved + HTML_ENCODER to be able to decode a STRING_8 or STRING_32 using + general_decoded_string (s) Improved tutorial example Added precompilation for + WSF library Cosmetic (removed unused locals) + +2012-05-28 Jocelyn Fiat + + Applied recent changes made on EWF Updated copyright + + Now inherit create_router ; but it is still possible to redefine it. Added + some wsf_reponse_message for redirection Use "found" for the redirec_now ... + Added content to the tutorial + +2012-05-25 Jocelyn Fiat + + Added descriptions to WSF_RESPONSE about .send (mesg) Fixed minor issues in + other classes + + Added more content to the tutorial + + Protected export of WSF_RESPONSE_MESSAGE.send_to Added + WSF_DEFAULT_RESPONSE_SERVICE Added simple + WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI class to load launch option from ini + file. Removed a few obsolete features + + added skeleton for tutorial_i text + + Updated indexing notes started tutorial Sync + +2012-05-15 Jocelyn Fiat + + added some git tips in doc + +2012-05-14 Jocelyn Fiat Rather use (READABLE_)STRING_GENERAL for argument instead of _8 or _32 variant Better design to set the WSF_REQUEST.path_parameters especially @@ -7,7 +2027,7 @@ Updated URI Template to follow official RFC6570 -2012-05-07 Jocelyn Fiat +2012-05-07 Jocelyn Fiat Reviewed WSF_REQUEST.item (..) and items to look into Form, Query, and Path (cookie are excluded for security) Added WSF_REQUEST.path_parameter (a_name): @@ -16,10 +2036,7 @@ value with reset_path_parameters (..), just in case the request is executed via severals routes. -2012-05-04 Jocelyn Fiat - - Reverted back to export upload_data and upload_filename to ANY (and related - features) +2012-05-04 Jocelyn Fiat Removed HTTP_CLIENT_SESSION.post_multipart .. because it was not doing what the name might evoque Restrict export of @@ -31,7 +2048,7 @@ possible (instead of multipart form data) Note for now, the library does not support sending file and form parameters at the same time. -2012-05-03 Jocelyn Fiat +2012-05-03 Jocelyn Fiat Fixed typo in .ecf .. curl instead of cURL @@ -44,11 +2061,7 @@ also ease extension of the class if needed. Updated cURL library with addition of {CURL_EXTERNALS}.slist_free_all (..) -2012-05-02 Jocelyn Fiat - - do not use implicit conversion from HTTP_CONTENT_TYPE - - Fixed wrong signature should be READABLE_STRING_32 instead of _8 +2012-05-02 Jocelyn Fiat Also removing the implicit conversion from STRING to HTTP_*_TYPE @@ -56,27 +2069,15 @@ could be a source of bug due to hidden conversion (and parameters) Applied changes to autotest cases Cosmetic -2012-04-30 Jocelyn Fiat - - Added comments Added `url' to compute the url from base_url, path and query - parameters - - Fixed error in URL encoding, according to the RFC3986, space should not be - encoded with '+' but with percent encoding. +2012-04-30 Jocelyn Fiat Fixed signature issue, the argument `name' should be READABLE_STRING_32 - Code cleaning - - Added specific helper function related to `charset' parameter - -2012-04-27 Jocelyn Fiat - - added postcondition status_reason_phrase_unset to `set_status' +2012-04-27 Jocelyn Fiat cosmetic -2012-04-13 Jocelyn Fiat +2012-04-13 Jocelyn Fiat Fixed a last minute regression due to removal REQUEST.chunked_input @@ -90,7 +2091,7 @@ REQUEST.is_chunked_input since it matters that Content-Length is 0 even if there are input (chunked) data. -2012-04-12 Jocelyn Fiat +2012-04-12 Jocelyn Fiat Fixed compilation of samples @@ -107,51 +2108,17 @@ to provide such user friendly features Now this is available directly on WSF_RESPONSE -2012-04-06 Jocelyn Fiat - - updated to EiffelWebFramework/EWF - - sync with json lib. - - Sync with wiki - - Use https://github.com/EiffelWebFramework/EWF.git as master - -2012-04-05 Jocelyn Fiat - - Added `transfered_content_length' to WSF_RESPONSE to provide the information - to application This can be used to build logs for instance. - - Relaxed WSF_REDIRECTION_RESPONSE.set_content (.., ..) to allow Void for - content type in order to use the one set in header or the default one. +2012-04-05 Jocelyn Fiat Removed default handler for WSF_ROUTER Added WSF_ROUTE to replace a TUPLE [H, C] WSF_ROUTER.route (req): detachable WSF_ROUTE WSF_ROUTER.execute_route (a_route, req, res) To help usage of Routers Remove WSF_HANDLER_CONTEXT obsolete features. Added comments -2012-03-27 Olivier Ligot - - [REM] Remove unneeded precondition - - [IMP] Ignore *.swp files - -2012-04-02 Jocelyn Fiat - - removed obsolete message. - -2012-03-27 Olivier Ligot - - [REM] Remove unneeded precondition - - [IMP] Ignore *.swp files - -2012-03-23 Jocelyn Fiat +2012-03-23 Jocelyn Fiat Renamed same_media_type as same_simple_type Added comments - updated tests.ecf - Added HTTP_MEDIA_TYPE (maybe it will just replace the HTTP_CONTENT_TYPE later) renamed .media_type as .simple_type for now allow more than one parameters @@ -163,23 +2130,12 @@ WSF_REQUEST return a HTTP_CONTENT_TYPE if available Adapted WSF_MIME_HANDLER to use this new class Added one manual autotest to test MIME handler -2012-03-21 Jocelyn Fiat +2012-03-21 Jocelyn Fiat in WSF_RESPONSE, `put_header' now call `put_header_text' Removed unused local variable - Fixed very bad mistake where no Result was ever set for WSF_REQUEST.item (..) - -2012-03-20 Jocelyn Fiat - - fixed compilation issue (typo) - - Do not try to compile_all in "dev" folder - - Reverted a previous change, we should not truncated Content-Type after ; In - the case of multipart/form-data the parameter "boundary=" is essential - - Use WSF_DEFAULT_SERVICE for the test echo server +2012-03-20 Jocelyn Fiat Fixing compilation of specific example using the WGI connector directly @@ -189,17 +2145,6 @@ Relaxed access to `send_to', now it is exported again to avoid breaking existing code. - remove unused local variable - - WSF_REQUEST.content_type should keep only the relevant part of the content - type and forget about the eventual parameters (charset, name) ... note: it - is possible to query meta_string_variable ("CONTENT_TYPE") to get the - complete Content-Type header - - Added HTTP_HEADER.(put|add)_content_type_with_parameters (...) - - removed obsolete - Implemented WSF_RESPONSE.put_error (...) and related Added WSF_RESPONSE.put_character Renamed WGI_OUTPUT_STREAM.put_character_8 as put_character to follow style of put_string (and not put_string_8) @@ -210,9 +2155,7 @@ Moved mime handler classes under wsf/src/mime/ -2012-03-19 Jocelyn Fiat - - removed unwanted rescue clause +2012-03-19 Jocelyn Fiat Updating EWSGI specification classes @@ -222,21 +2165,12 @@ WSF_RESPONSE.put_response (a_message) as `send (a_message)' WSF_RESPONSE_MESSAGE.send_to (res) is now exported only to WSF_RESPONSE -2012-03-19 Berend de Boer - - Avoid another indirection. - - status must be set, else WGI_SERVICE.execute will report the postcondition - violation. Conflicts: library/server/wsf/router/wsf_handler.e - - Minor code cleanup/typo fix. - -2012-03-17 Berend de Boer +2012-03-17 Berend de Boer Move wgi_service spec to its own directory else I get a class conflicts with compile_ise.ecf generated by gexace. -2012-03-19 Jocelyn Fiat +2012-03-19 Jocelyn Fiat Improved comment in WSF_RESPONSE.put_response (..) Added WSF_REDIRECTION_RESPONSE class @@ -251,32 +2185,29 @@ confusion, remove URI_TEMPLATE specific `path_parameter' and provide a way to use ctx.item (..) to also include meta variable, query, form, ... items - Use local variable to speed up access to `input' - -2012-03-16 Jocelyn Fiat +2012-03-16 Jocelyn Fiat Applied wsf_extension creation, and classes moved from wsf to wsf_extension Created wsf_extension, and moved some classes from wsf to wsf_extension WSF_HANDLER_HELPER WSF_RESOURCE_HANDLER_HELPER WSF_HANDLER_ROUTES_RECORDER - applied removal of HTTP_HEADER.put_status (..) - - Removed HTTP_HEADER.put_status (...) It is not recommended to send the status - code as part of the HTTP Header, so let's remove this ambiguity and do not - encourage EWF user to use it - Major renaming, adopt the WSF_ prefix for all classes under "wsf", and simplify some class names Removed in WGI_INPUT_STREAM, the assertion "same_last_string_reference" Copyright updates -2012-03-13 Jocelyn Fiat +2012-03-13 Jocelyn Fiat Fixed compilation of draft/library/server/request/rest/tests/.. Note the "rest" library will not be maintained since this is not REST. - precise that library/server/request/router is now part of "wsf" library and - not anymore independant library. +2012-03-13 jfiat + + Better use C_STRING.substring (1, size) instead of C_STRING.string since we + know the exact size and this way, no risk with \0 character inside the string + itself (for binary data..) Added comments + +2012-03-13 Jocelyn Fiat Nino connector: - fixed issue related to `ready_for_reading' now use the `try_...' variant - for now Nino does not support persistent connection, then @@ -293,33 +2224,22 @@ user WSF_REPONSE.redirect_... now use "temp_redirect" as default instead of "moved_permanently" which is specific usage Removed many obsolete features. -2012-02-29 Jocelyn Fiat - - use https:// url for git submodules +2012-02-29 Jocelyn Fiat Added assertions to catch if route mapping does not already exists -2012-02-28 Jocelyn Fiat +2012-02-28 Jocelyn Fiat Synchronized with nino and json library -2012-02-17 jvelilla +2012-02-17 jvelilla Refactor REQUEST_RESOURCE_HANDLER_HELPER to figure out the transfer encoding: Chunked. Added a new method to retrieve_data independently if the transfer is chunked or not. Updated ORDER_HANLDER to use this new feature. Sync with Jocelyn repo -2012-02-16 Jocelyn Fiat - - Minor correction, to avoid returning 200 as status code, when the client can - not connect - -2012-02-15 Jocelyn Fiat - - fixed compilation - - sync with cURL library +2012-02-15 Jocelyn Fiat Fixed error visitor due to recent signature changes @@ -332,36 +2252,26 @@ ERROR_HANDLER.remove_synchronized_handler Added comments Added associated autotests -2012-02-14 Jocelyn Fiat +2012-02-14 Jocelyn Fiat Better signature for encoders Split library .ecf and the autotest .ecf - added postcondition to ensure the body string set to the response, is the - same reference this is important, since sometime we just do rep.set_body (s) - s.append_string ("..") - - Added DEBUG_OUTPUT to ERROR, since this is convenient during debugging - Added notion of synchronization between error handler this is convenient to integrate two components using their own ERROR_HANDLER (not sharing the same object) - use WSF_PAGE_RESPONSE, instead of reimplementing it ourself +2012-02-14 larryl -2012-02-13 Jocelyn Fiat + Added cURL multi interface support (most APIs) issue#7305157 The multi + interface offers several abilities that the easy interface doesn't. They are + mainly: 1. Enable a "pull" interface. The application that uses libcurl + decides where and when to ask libcurl to get/send data. 2. Enable multiple + simultaneous transfers in the same thread without making it complicated for + the application. 3. Enable the application to wait for action on its own file + descriptors and curl's file descriptors simultaneous easily. More info: + http://curl.haxx.se/libcurl/c/libcurl-multi.html - added a JSON encoder test case - -2012-02-10 Olivier Ligot - - [FIX] libfcgi.so location On Ubuntu 10.04 LTS, libfcgi.so is in /usr/lib - instead of /usr/local/lib - -2012-02-08 Jocelyn Fiat - - added a case in test_json_encoder - -2012-02-08 unknown +2012-02-08 unknown libcurl: Applied a workaround to avoid issue on Win32 (see LIBCURL_HTTP_CLIENT_REQUEST.apply_workaround) Separated the @@ -369,15 +2279,7 @@ HTTP_CLIENT_SESSION.set_max_redirects Fixed broken test due to formatting trouble. -2012-02-08 Jocelyn Fiat - - fixed http_client tests - -2012-02-08 jvelilla - - Updated content - -2012-02-07 Jocelyn Fiat +2012-02-07 Jocelyn Fiat Better code to test similar functions but with chunked input @@ -386,16 +2288,10 @@ Added support for chunked input data (see Transfer-Encoding: chunked) - Added HTTP_HEADER.append_header_object and append_array. This is helpful to - "merge" two HTTP_HEADER and provide user friendly features - Added proxy, at least to make it is possible to use http://fiddler2.com/ to inspect the traffic. -2012-02-01 Jocelyn Fiat - - Fixed wrong code for postcondition on HTTP_HEADER.string Patch provided by - Paul-G.Crismer +2012-02-01 Jocelyn Fiat removed unwanted set_status_code, since we already use put_header to set the status code. @@ -406,7 +2302,7 @@ Improved redirect_now_custom to allow custom status code, custom header, and custom content -2012-01-31 Jocelyn Fiat +2012-01-31 Jocelyn Fiat Fixed usage of lst[] in web form, now we are url-decoding the name because the [] could escaped... Fixed bad code for assertion related to variable @@ -416,85 +2312,72 @@ handling list/array parameters fixed postcondition WSF_REQUEST.set_meta_string_variable ... -2012-01-25 Jocelyn Fiat +2012-01-25 Jocelyn Fiat Make sure to return a response Added precondition to check URI_TEMPLATE is valid -2012-01-23 Jocelyn Fiat - - Fixed issue with WSF_FILE_RESPONSE not setting the status code Added - Last-Modified - - Fixed wrong code for postcondition in unset_orig_path_info - - added "conversion" to ease the use of HTTP_HEADER - -2012-01-20 Jocelyn Fiat - - fixed compilation (was not up to date with tests.ecf) +2012-01-20 Jocelyn Fiat Corrected remaining issue related to recent addition of REQUEST_ROUTER.make_with_base_url And applied removal of format_name and format_id, and replaced by accepted_format_name, ... - Do not add again ctx.headers, since it is already "imported" during the - creation of Current request (see HTTP_CLIENT_REQUEST.make) +2012-01-20 manus + + Removed the ECF bounds license file and replaced them with `license.lic' + files. Made sure all license are the Eiffel Forum License 2. + +2012-01-20 Jocelyn Fiat Removed any "format" related query from router lib, this is too application specific to be there. Better handling of base_url for REQUEST_ROUTER -2012-01-19 Jocelyn Fiat +2012-01-19 Jocelyn Fiat separate library .ecf and tests .ecf merged tests .ecf for draft 05 and current implementation Fixed WSF_REQUEST.script_url (..) for clean path Added related autotests -2012-01-17 Jocelyn Fiat - - Don't forget to put Content-Length: 0 for redirect without any content +2012-01-17 Jocelyn Fiat export handler from REQUEST_ROUTER +2012-01-17 Jocelyn Fiat + REQUEST_ROUTER now inherit from ITERABLE [..] - Send the Status code, as an header line Status: code reason - - use READABLE_STRING_8 instead of STRING_8 - - According to http://www.fastcgi.com/docs/faq.html#httpstatus send the Status - code, as an header line Status: code reason - -2012-01-16 Jocelyn Fiat - - Do not send any Status line back to the FastCGI client - -2012-01-13 Jocelyn Fiat +2012-01-13 Jocelyn Fiat Synchronized with ejson library Cleaned JSON_ENCODER -2012-01-12 Jocelyn Fiat +2012-01-13 jfiat + + Renamed JSON_STRING.unescaped_string as unescaped_string_8 + code cleaning + + Better support for special character and unicode (\n \r \" ... and \uXXXX + where XXXX is an hexadecimal value) Added features to JSON_STRING - + make_json_from_string_32 (READABLE_STRING_32) - escaped_string_8: STRING_8 - + escaped_string_32: STRING_32 Added associated autotests + +2012-01-12 Jocelyn Fiat Added JSON_ENCODER -2012-01-09 Jocelyn Fiat +2012-01-09 Jocelyn Fiat removed obsolete call on `WSF_RESPONSE.write_..' by using the up-to-date `WSF_RESPONSE.put_..' -2012-01-06 Jocelyn Fiat +2012-01-06 Jocelyn Fiat HTTP_HEADER: - added put_last_modified - added RFC1123 http date format helper - added put_cookie_with_expiration_date as DATE_TIME REQUEST: added `execution_variable' to provide a way to keep object attached to the request and indexed by a string. A typical usage is a SESSION object -2011-12-21 jvelilla - - Update examples/restbucksCRUD/readme.md - -2011-12-18 Jocelyn Fiat +2011-12-18 Jocelyn Fiat added REQUEST.execution_variables ... to provide a solution to store data during request execution could be used for SESSION, or any "shared" data @@ -502,9 +2385,7 @@ applied write_ as put_ renaming to examples -2011-12-15 Jocelyn Fiat - - Use put_ instead of write_ +2011-12-15 Jocelyn Fiat various minor changes @@ -514,8 +2395,6 @@ Renamed write_ feature as put_ - Fixed stupid mistake in {WGI_NINO_INPUT_SREEAM}.end_of_input - Fixed typo and missing uri_template reference for draft rest library Now the 'router' library is part of 'wsf' Move hello_routed_world under @@ -523,14 +2402,7 @@ Made DEFAULT_SERVICE_LAUNCHER more flexible for the user. -2011-12-15 jvelilla - - Update read_trailer feature. - - Initial implementation of wgi_chunked_input_stream as a wrapper of - wgi_input_stream - -2011-12-14 Jocelyn Fiat +2011-12-14 Jocelyn Fiat Use port 9090 for restbuck server mainly to avoid using 80 or 8080 which are often already used (by current webserver, or even skype, or jenkins, or ...) @@ -541,25 +2413,10 @@ WSF_RESPONSE.redirect_now_with_content (...) Updated hello_routed_world .. mainly example use to test/develop... not really a nice example -2011-12-13 Jocelyn Fiat - - Updated readme on how to get source code - - added head and bottom value in WSF_FILE_RESPONSE, to enable the user to set a - head and bottom part easily - -2011-12-12 Jocelyn Fiat - - avoid infinite rescue due to internal error or user code not dealing well - with socket disconnection +2011-12-12 Jocelyn Fiat Removed dotnet target for now - Fixed http_client autotest code - - Break inheritance from WGI_RESPONSE, since it is not flexible for future - improvement. - Fixed HTTP client callers Renamed DEFAULT_SERVICE as DEFAULT_SERVICE_LAUNCHER @@ -575,126 +2432,72 @@ WSF_RESPONSE_MESSAGE, and WSF_RESPONSE.put_response (a_response_message) Now WSF_RESPONSE inherit from WGI_RESPONSE -2011-12-10 jvelilla + Handling bad incoming request (keep a check assertion to help during + debugging period) + +2011-12-10 jvelilla Update restbuck client, create and read an order. Update JSON converter, the id is not important, applied the DRY principle. Update the ORDER_HANDLER to use the meta_string_variable instead of meta_variable from req. Fix, the key in meta_variable_table, use c.key instead of c.item - Update examples/restbucksCRUD/readme.md - -2011-12-09 jvelilla +2011-12-09 jvelilla Update the restbuck_client, still work in progress. Update restbuck_server, remove unused class in inherit. Update libcurl_http_client_request, to parse context headers before the execution. Update wgi_input_stream, commented precondition. - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - - Update examples/restbucksCRUD/readme.md - -2011-12-08 jvelilla - - Update examples/restbucksCRUD/readme.md - - Updated documentation +2011-12-08 jvelilla Updated restbucksCRUD documentation Added basic two basic examples, refactor rename restbucks to restbucksCRUD -2011-12-07 jvelilla +2011-12-07 jvelilla Sync Jocelyn repo -2011-12-03 Jocelyn Fiat - - Update README.md - - Update README.md - - Update README.md - - fixed markdown syntax - -2011-12-02 Jocelyn Fiat - - Remove any useless library include from this .ecf we just need - default_"connector", router, wsf and http +2011-12-02 Jocelyn Fiat Fixed compilation issue for CGI and libFCGI connector due to recent changes in interface (use READABLE_STRING_8) -2011-12-01 Jocelyn Fiat +2011-12-01 Jocelyn Fiat Integrated new system to handle form_parameter, input_data in relation with MIME handling This is not yet clear how to let the user precise its own MIME handler but it is in progress - fixed remaining issue or useless code to set http environment variable - - Fixed stupid error where we were concatenating ... value by error - Added WSF_RESPONSE.write_chunk (s: ?READABLE_STRING_8) to help user sending chunk with "Transfer-Encoding: chunked" Synchronized with Nino - Fixed WSF_RESPONSE.redirect* features + various renaming and preparation to merge Thread and SCOOP implementation of + Eiffel Web Nino sync with Nino, call to put_readable_string_8 - Synchronized with EiffelWebNino - - relative path for README link - -2011-12-01 jvelilla - - Update library/protocol/CONNEG/README.md - - Update library/protocol/CONNEG/README.md +2011-12-01 jvelilla Updated Conneg library, added test cases -2011-11-30 jvelilla +2011-11-30 Jocelyn Fiat + + Removed initial Thread for the HTTP_HANDLER, this is not needed here Removed + HTTP_SERVER_SHARED_CONFIGURATION from the library ... not needed by the + library. Added HTTP_SERVER_SHARED_CONFIGURATION to the example to show how + to share the configuration, if needed + +2011-11-30 jvelilla Fixed minor issue, added test cases to check language negotiation. Update conneg library and test cases -2011-11-25 Jocelyn Fiat - - Fixed example due to recent interface changes +2011-11-25 Jocelyn Fiat - (WGI|WSF)_RESPONSE(*) renamed write_headers_string as write_header_text - HTTP_HEADER.string does not have the ending CRLFCRLF .. but just CRLF - @@ -707,12 +2510,6 @@ Applied recent renaming from WGI_RESPONSE_BUFFER as WGI_RESPONSE - updated WGI specification - - Added missing wgi_connector - - added "redirect" helper feature to WSF_RESPONSE - Added `{WGI_REQUEST}.wgi_*' function to WSF_REQUEST rename `application' as `service' @@ -720,8 +2517,6 @@ Use HTTP_HEADER instead of WSF_HEADER (WSF_HEADER is kept for convenience and existing code) - better script to check compilation and tests - Moved implementation of WSF_HEADER to HTTP_HEADER in the http library Simplified EWSGI interfaces Renamed WGI_RESPONSE_BUFFER as WGI_RESPONSE to @@ -736,24 +2531,16 @@ recommended due to portability issue on other connector) Removed useless connector.ecf since now EWF/WGI library provides the helper classes -2011-11-23 Jocelyn Fiat +2011-11-23 Jocelyn Fiat Fixed sample example config file after recent location change for "rest" lib - Improved run_CI_tests.py and include the compile_all call directly in the - python script. If compile_all tool supports -keep ... let's use it. (recent - addition) - fixed rest(-safe).ecf due to recent location change - Updated README.md in relation with "rest" lib relocation - Move "rest" library under "draft/..." since it is more an experiment rather than a real REST library -2011-11-21 Jocelyn Fiat - - Update draft/README.md +2011-11-21 Jocelyn Fiat updated Eiffel libfcgi README file @@ -764,28 +2551,33 @@ Added scripts to help building the libfcgi.dll and .lib from modified source of libfcgi - updated README to apply 'ext' renamed as 'contrib' +2011-11-21 jfiat -2011-11-18 Jocelyn Fiat + Removing autotest dotnet target, since Autotest does not support .Net + platform for now + + Fixed code from autotest tests to remove warnings Fixed getest ejson_test.ecf + configuration file Added script to allow using getest from Windows. Note: I + did not fixed warning from getest tests, we should apply same change already + made for autotest. it seems autotest and getests are doing the same checking, + I would suggest to either remove getest files or find a way to share test + code between getest and autotest tests. + +2011-11-18 Jocelyn Fiat fixed compilation for tests.ecf - fixed typo - Updated "draft" folder which contain potential future addition to EWF Added "draft" folder to contain potential future addition to EWF restructured CONNEG library fixed various issue in .ecf files -2011-11-17 jvelilla +2011-11-17 jvelilla Initial import CONNEG library, support server side content negotiation. -2011-11-17 Jocelyn Fiat - - Rename "ext" as "contrib" in compile_all.ini as well no need to test the code - coming from other projects. +2011-11-17 Jocelyn Fiat Renamed "ext" folder as "contrib" folder and reorganized a little bit Renamed any *_APPLICATION as *_SERVICE mainly because those components such as @@ -793,80 +2585,52 @@ entry, and "service" describe them better Minor implementation change in WSF_REQUEST Cosmetics -2011-11-16 Jocelyn Fiat - - handle last run failure +2011-11-16 Jocelyn Fiat Added request method PATCH even if not really used for now, it might in the future - Do not print command during script execution - - fixed indentation in python script - - Added information output to run_CI_tests.py - - updated run_CI_tests.py - - updated run_CI_tests.py - - updated run_CI_tests.py - - updated run_CI_tests.py - - removed unused local variables - - added a python script to be use inside jenkins CI server (experimental for - now) - -2011-11-14 Jocelyn Fiat - - cosmetic - - cosmetics +2011-11-14 Jocelyn Fiat Added various README.md (using the markdown syntax) - updated README with links to sub READM.md - - sync with Eiffel Web Nino + Applied the removal of HTTP_INPUT_STREAM and HTTP_OUTPUT_STREAM to the + example. Added default WSF_APPLICATION for libfcgi connector - code removal - Updated libfcgi source code for Windows AND Linux. Cleaning some code and feature clauses. Changed the WGI_INPUT_STREAM and WGI_OUTPUT_STREAM interfaces main changes for existing code `read_stream' is renamed `read_string' -2011-11-09 Jocelyn Fiat +2011-11-10 Jocelyn Fiat - Added is_request_method (STRING): BOOLEAN to help users + Removed HTTP_(INPUT,OUTPUT)_STREAM, since it is unlikely that we use + something else than TCP_STREAM_SOCKET This way, we remove one indirection for + users, and get smaller code. -2011-11-07 Jocelyn Fiat - - updated readme with better way to get the source code recursively - - added script to build archive for download area - -2011-11-04 Jocelyn Fiat - - sync with Eiffel Web Nino +2011-11-04 Jocelyn Fiat sync with nino and applied changes to connector + removed useless "a_name" argument Fixed typo in on_launched + Use recent changes from Nino, to get access to the launched and port information. Quite useful when launching using port=0 to use a random free port. This is great for testing, this way we can run many tests in the same time without any port blocking. -2011-11-03 Jocelyn Fiat +2011-11-03 Jocelyn Fiat applied recent changes from Nino -2011-11-02 Jocelyn Fiat + added access to the effective port that the server is listening to (useful + when we set port to 0 it use a random free port) added verbose , so that we + write message to the console only if desired. + +2011-11-02 Jocelyn Fiat removed compliance on ewsgi, since now we target WSF applied recent changes related to WSF_VALUE @@ -877,15 +2641,10 @@ renamed WSF_(.*)_VALUE as WSF_$1 -2011-10-31 Jocelyn Fiat - - Fixed obsolete calls, and compilation error. +2011-10-31 Jocelyn Fiat fixed path to cURL.ecf file, using the correct uppercase - Fixed missing syntax="provisional" , this was preventing compiling with - "across" statements - Better implementation to get http header for http_client, and to get list of header entries by key,value @@ -893,26 +2652,10 @@ Fixed remaining 6.8 vs 7.0 compilation issue related to UTF8_(URL_)ENCODER - removed unused local variable - - Added convenient features to BASE64 - decode_string_to_buffer (v: STRING; - a_buffer: STRING) - decode_string_to_output_medium (v: STRING; a_output: - IO_MEDIUM) - - removed unused local variable - Fixed code to be compilable with EiffelStudio 6.8 and 7.0 (due to recent change in UNICODE_CONVERSION) UNICODE_CONVERSION -2011-10-28 jvelilla - - Added headers to response in HTTP_CLIENT_RESPONSE - -2011-10-27 Jocelyn Fiat - - use '%/123/' syntax, to make sure no editor replace the accentued characters - - removed unwanted .rc +2011-10-27 Jocelyn Fiat Fixed a previously character changes in WSF_REQUEST (related to safe_filename), and modified the implementation to use inspect Fixed the @@ -920,35 +2663,26 @@ added script to update current git working copy and submodules recursively +2011-10-27 Jocelyn Fiat + cosmetic, or minor changes -2011-10-27 jvelilla +2011-10-27 jvelilla Added eel and eapml in EWF libraries. Removed them from gitmodule -2011-10-26 jvelilla - - Updated request resource handler. TODO: implement Content-Negotiation - -2011-10-24 Jocelyn Fiat - - Start index for list[]=a&list[]=b ... from 1 instead of 0 Stick to Eiffel - spirit +2011-10-24 Jocelyn Fiat Added visitor patterns to WSF_VALUE Handling UTF-8 unencoding for WSF_VALUE ... Added WSF_TABLE_VALUE to handle list[]=a&list[]=b ... Library encoder: added UTF8 facilities - missing implementation (forgot to uncomment) - -2011-10-23 jvelilla - - Added eel and eapml modules +2011-10-23 jvelilla Update delete method to hanlde method not allowed. Added method not allowed to request resource handler helper class. Update gitmodules -2011-10-21 Jocelyn Fiat +2011-10-21 Jocelyn Fiat Applied recent changes on WGI_ and WSF_ Moved classes away from ewsgi, restructured, cleaned @@ -958,108 +2692,95 @@ to avoid potential nasty issues in user's code URI-template is working only with STRING_8, then changed any _GENERAL or _STRING_32 to _STRING_8 -2011-10-19 Jocelyn Fiat +2011-10-19 Jocelyn Fiat First try to get a limited WGI_ and use WSF_ as default framework -2011-10-21 jvelilla +2011-10-21 jvelilla Update Restbucks example: Conditional GET, PUT. Added a response method to support resource not modified. Added a ETAG_UTILS class to calcule md5_digest. Added ext libs eel and eapml. -2011-10-19 Jocelyn Fiat - - Used object test - - removed useless local variable - -2011-10-14 Jocelyn Fiat +2011-10-14 Jocelyn Fiat fixed cgi and libfcgi connectors due to recent changes from WGI_APPLICATION Removed handling of internal error from WGI_APPLICATION And for now added it into nino connector - Fixed issue with index in uri template matcher - Added HTTP_FILE_EXTENSION_MIME_MAPPING Added REQUEST_FILE_SYSTEM_HANDLER to the router library Added file system handler in "hello_routed_world" example -2011-10-13 jvelilla +2011-10-13 jvelilla Added handle_resource_conflict_response feature to handle 409 reponse, Cosmetic. -2011-10-12 Jocelyn Fiat +2011-10-12 Jocelyn Fiat Added data and file for post and put request methods +2011-10-12 Jocelyn Fiat + Using Transfer-Encoding: chunked in example to send response progressively sync with submodules - removed unwanted code - - applied recent changes on HTTP_REQUEST_METHOD_CONSTANTS - - cosmetic +2011-10-12 Jocelyn Fiat Addition to "http" library, separated constants into - HTTP_MIME_TYPES - HTTP_HEADER_NAMES - HTTP_REQUEST_METHODS - HTTP_STATUS_CODE (already exists) Do not set the "Status" header when using WGI_RESPONSE_BUFFER.write_header (...) Cosmetic -2011-10-11 Jocelyn Fiat - - Fixed errors recently introduced - - sync with latest JSON - -2011-10-11 jvelilla +2011-10-11 jvelilla Update order_handler, fix json_order_converter -2011-10-11 Jocelyn Fiat +2011-10-11 Jocelyn Fiat Use local curl if compiler is < 7.0.8.7340 otherwise, use ISE_LIBRARY cURL Temporary fixed issue of using modified cURL (which is cURL provided with EiffelStudio 7.0) This changes will be reverted in the future -2011-10-10 Jocelyn Fiat - - Updated readme related to mirrored Eiffel cURL library +2011-10-10 Jocelyn Fiat added submodule ext/ise_library/curl to use the updated Eiffel cURL from ISE. - cosmetic - -2011-10-07 Jocelyn Fiat +2011-10-07 Jocelyn Fiat added http diagrams found on the web - Added the possibility to specify the supported content types Added FIXME +2011-10-07 Jocelyn Fiat - Cosmetic + Added license.lic and copyright to Javier + +2011-10-07 jfiat + + Minor changes + cosmetics Added conversion from STRING to JSON_STRING to help + users. + +2011-10-07 Jocelyn Fiat Added "Date:" helper feature in EWF_HEADER Added license.lic to restbuck example, and mainly copyright to Javier Use HTTP_STATUS_CODES Minor improvements using object tests Cosmetic (indentation, ..) -2011-10-06 Jocelyn Fiat +2011-10-06 Jocelyn Fiat Added a first simple test client to test the restbuck client added support for data in POST request -2011-10-06 jvelilla +2011-10-06 jvelilla Added REQUEST_RESOURCE_HANDLER_HELPER class to contain common http method behavior. Updated ORDER_HANLDER to use this new class. -2011-10-05 Jocelyn Fiat +2011-10-05 Jocelyn Fiat Added `base_url' for REQUEST_ROUTER (and descendants) Fixed implementation of REST_REQUEST_AGENT_HANDLER to avoid wrong path in inherited routine. Allow @@ -1067,29 +2788,7 @@ more attribute (status or settings) to URI_TEMPLATE, we'll be able to change the `template' without breaking the settings - added missing call to pre_execute and post_execute - - Fixed missing http:// in absolute URL - - remove pre_execute, and post_execute, and make process_request frozen this - way, the user won't be tempted to redefine feature not being part of pure - EWSGI interface. - - better argument name, to precise the timeout is in second also in comment. - -2011-10-04 Jocelyn Fiat - - Fixed agent handler for rest library - - fixed inheritance and precursor bad usage. - -2011-10-03 jvelilla - - Updated support for PUT. Now the example support GET, POST, PUT, DELETE. - -2011-09-28 Jocelyn Fiat - - fixed compilation for ewsgi/tests/tests.ecf file +2011-09-28 Jocelyn Fiat Made WGI_VALUE.name as READABLE_STRING_32 .. otherwise it is a pain to manipulate. Changed return type of meta_variable to be WGI_STRING_VALUE ... @@ -1104,12 +2803,16 @@ restructured ewsgi to avoid too many sub cluster -2011-09-28 jvelilla +2011-09-28 jvelilla Updated Restbucks examples, handle not method allowed in a better way, added the readme file. -2011-09-26 Jocelyn Fiat +2011-09-27 jfiat + + Be sure to set the Result /= 0 (i.e ECURLE_OK) when error occurred. + +2011-09-26 Jocelyn Fiat fixed compilation of rest example @@ -1118,104 +2821,71 @@ Changed ITERATION_CURSOR [WGI_VALUE] into ITERABLE [WGI_VALUE] for WGI_REQUEST.*parameters* and similar Applied recent changes on EWF_HEADER -2011-09-23 Jocelyn Fiat +2011-09-23 Jocelyn Fiat Updated changelogs.txt sync with nino and doc +2011-09-23 Jocelyn Fiat + Added AutoTest simple cases for ewsgi using Nino web server Fixing issue with experimental WGI_MULTIPLE_STRING_VALUE Fixed issue with RAW_POST_DATA - Removed `put_redirection' and replaced by `put_location' Removed useless code - in some features - Use READABLE_STRING(_*) instead of just STRING(_*) - Added feature to shutdown the Nino http server - Added error reporting in HTTP_CLIENT_RESPONSE Added missing set_connect_timeout -2011-09-23 jvelilla - - Added validations. - -2011-09-22 Jocelyn Fiat - - Added code to create an HTTP_AUTHORIZATION from the client side as well. So - now we can either interpret an HTTP_AUTHORIZATION or build one - HTTP_AUTHORIZATION So far , only Basic auth is supported. +2011-09-22 Jocelyn Fiat Made all libraries compilable in any mode (voidsafe or not) Fixed related examples -2011-09-22 jvelilla +2011-09-22 jvelilla Initial import, work in progress restbuck example. Only support create a resource -2011-09-21 Jocelyn Fiat - - Fixed issue where Content-Type and Content-Length were translated into - HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH instead of just CONTENT_TYPE and - CONTENT_LENGTH +2011-09-21 Jocelyn Fiat better assertion to ensure `base' is a valid base url - synch with Nino - better return type for http client functions added helper features -2011-09-20 Jocelyn Fiat +2011-09-20 Jocelyn Fiat fixed case sensitive path - missing -safe.ecf config file for http_client - Now using READABLE_STRING_... type Added simple HTTP client. For now the implementation is using Eiffel cURL library. It requires Eiffel cURL coming with next EiffelStudio 7.0 (or from eiffelstudio's repo from rev#87244 ) -2011-09-16 Jocelyn Fiat +2011-09-16 Jocelyn Fiat Fixed issues in WGI_REQUEST's invariant Fixed issues with guessing the default format for REST handling Fixed issue with .._ROUTING_.. component. - Fixed issue with uri template router .. it was applying on request_uri - instead of path_info now it match on PATH_INFO - more flexible authenticated query .. on handler, and not anymore on context object - fixed wrong order in parameter for callers of set_meta_string_variable - - added debug_output to WGI_VALUE - first version of http authorization .. for now, only basic digest - added request_handler_routes_recorder to provide an implementation for - `REQUEST_HANDLER.on_handler_mapped' - Added "on_handler_mapped" callback to allow any REQUEST_HANDLER to record the existing routes. typo -2011-09-15 Jocelyn Fiat +2011-09-15 Jocelyn Fiat minor enhancement of error lib Added WGI_MULTIPLE_STRING_VALUE Renamed value as WGI_STRING_VALUE.string Renamed a few classes .._CONTEXT_I as .._CONTEXT updated example. - cosmetic - - updated README.md - -2011-09-14 Jocelyn Fiat +2011-09-14 Jocelyn Fiat Simplified interface of "router" library classes @@ -1234,13 +2904,7 @@ *_parameters and similar functions - renamed parameter as item - provided helper function to handle "string" value parameters Experimental for now. - better result type (using READABLE_..) - - sync with nino - -2011-09-13 Jocelyn Fiat - - updated changelogs +2011-09-13 Jocelyn Fiat Added first draft for RESTful library note: the interfaces are likely to change in the future @@ -1249,7 +2913,7 @@ adding routing handler few renaming -2011-09-09 Jocelyn Fiat +2011-09-09 Jocelyn Fiat changing design to use generic instead of anchor types @@ -1259,53 +2923,41 @@ /foo.{format}{/vars} or /foo.{format}{?vars} where no literal exists between the uri template expressions - better type for argument and result (using READABLE_...) - - change to standard default values - -2011-09-08 jvelilla - - Sync to jocelyn EWF master - - Update - -2011-09-07 Jocelyn Fiat - - sync doc/wiki +2011-09-07 Jocelyn Fiat use `resource' as generic name for uri or uri_template - added changelogs.txt - Added request methods criteria for the router component. Now one can decide map_agent_with_request_methods ("/foo/bar/{bar_id}", agent handle_foo_bar, <<"GET">>) (and similar for non agent way) This might be useful in pure RESTful environment. - fixed example .. where we forgot to set the status, and send the header (DbC - helped here) - renamed (un)set_meta_parameter as (un)set_meta_variable - Missing HTTP_ prefix for header meta variable in REQUEST +2011-09-05 jvelilla -2011-08-30 Jocelyn Fiat + Fixed ecf files that cause a cat-call in the example web server. + +2011-08-30 Jocelyn Fiat Changed prefix from EWSGI_ to WGI_ Changed meta variable type to READABLE_STRING_32 -2011-08-29 Jocelyn Fiat +2011-08-30 Jocelyn Fiat + + Changed prefix class name from EWSGI_ to WGI_ changes in interface for + REQUEST and RESPONSE + +2011-08-29 Jocelyn Fiat naming: meta_variable(s) changed some string type to READABLE_STRING_32 or READABLE_STRING_8 for now regarding Meta variables (need decision here..) -2011-08-25 Jocelyn Fiat +2011-08-25 Jocelyn Fiat changed prefix GW_ into EWF_ for EiffelWebFramework use READABLE_STRING_GENERAL instead of just STRING - sync wiki doc - Merged REQUEST and ENVIRONMENT into REQUEST renamed ENVIRONMENT_NAMES into META_NAMES better usage of READABLE_STRING_GENERAL, and other strings abstract RESPONSE_BUFFER in implementation of EWSGI for the implementation, @@ -1315,19 +2967,17 @@ META_NAMES better usage of READABLE_STRING_GENERAL, and other strings for the implementation, inheriting from deferred specification (more to come later) -2011-08-24 Jocelyn Fiat - - fixing wrong feature usage - -2011-08-18 Jocelyn Fiat +2011-08-18 Jocelyn Fiat code cleaning, and prepare for internal review -2011-08-04 Jocelyn Fiat +2011-08-02 jocelyn - enhanced the ERROR_HANDLER + Updated EWSGI : open questions (markdown) -2011-08-02 Jocelyn Fiat + Updated EWSGI: open questions (markdown) + +2011-08-02 Jocelyn Fiat minor improvements on response_as_result code @@ -1335,9 +2985,7 @@ add "write_headers_string" to RESPONSE_BUFFER -2011-08-01 Jocelyn Fiat - - sync wiki +2011-08-01 Jocelyn Fiat moved ewsgi-full config file under tests (this is mainly for dev purpose, to be able to compile and edit all classes related to ewsgi) @@ -1351,34 +2999,26 @@ to be able to test EWSGI compliant library against the pure specification (experimental). Renamed most of the GW_... into EWSGI_... -2011-07-29 Jocelyn Fiat - - added http_accept feature to represent "Accept:" HTTP header +2011-07-29 Jocelyn Fiat added hello_routed_world example few changes on new `router' library (still in-progress) Added first draft for a URI and/or URI-template base request router. - cosmetic - Added "flush" to the EWSGI_RESPONSE_STREAM added missing non-void-safe .ecf added missing non-void-safe .ecf -2011-07-28 Jocelyn Fiat +2011-07-28 Jocelyn Fiat Fixed various issue with URI template, added corresponding tests - It seems good convention to also add the "Status:" header - fix hello world example - ignore tests/temp - -2011-07-27 Jocelyn Fiat +2011-07-27 Jocelyn Fiat added script to test compilations of .ecf in EWF @@ -1412,11 +3052,11 @@ the future) removed any implementation from GW_REQUEST, and put it in GW_REQUEST_IMP -2011-07-26 Jocelyn Fiat +2011-07-26 Jocelyn Fiat replace write_string by write in RESPONSE -2011-07-25 Jocelyn Fiat +2011-07-25 Jocelyn Fiat various alternative implementation for response @@ -1424,14 +3064,12 @@ interface Redesigned the uploaded file part to be more object oriented Move some implementation from REQUEST to REQUEST_IMP -2011-07-22 Jocelyn Fiat +2011-07-22 Jocelyn Fiat added doc/spec for uri template Fixed issue with matcher - fixed typo - Improvement and revert back to support draft 04 (but using custom variable, allow the user to follow draft 05 spec) @@ -1439,15 +3077,11 @@ added URI_TEMPLATE_MATCH_RESULT -2011-07-21 Jocelyn Fiat - - sync +2011-07-21 Jocelyn Fiat updated README - updated README - -2011-07-20 Jocelyn Fiat +2011-07-20 Jocelyn Fiat added use of URL-encoder to unencode the URL values (to fill the parameters) review design of GW_RESPONSE to hide the output, and remove the header @@ -1460,29 +3094,21 @@ The matcher is basic, it does not handle all the details of the string builder, but that seems ok for now. -2011-07-18 Jocelyn Fiat +2011-07-18 Jocelyn Fiat added format and request method constants classes + license file - added default rescue code on exception rescue - - nicer Eiffel code, let's not try to achieve everything-in-one-line style ... - - restrict creation only by GW_APPLICATION and descendant - - add output helper feature to RESPONSE - - Fixed issue with nino handler and base url - sync nino and json -2011-07-14 Jocelyn Fiat +2011-07-15 Javier Velilla + + Refactor to use the new library structure convention. + +2011-07-14 Jocelyn Fiat rename new_request_context by new_request -2011-07-13 Jocelyn Fiat - - cosmetic +2011-07-13 Jocelyn Fiat renamed GW_REQUEST_CONTEXT as GW_REQUEST @@ -1493,15 +3119,11 @@ Make a simple hello world based on nino -2011-07-12 Jocelyn Fiat +2011-07-12 Jocelyn Fiat Added GW_HEADER Added pre_, post_ and rescue_execute for GW_APPLICATION Fixed an unknown class in export clause cosmetic + copyright - fixed submodule path ... Windows path separator issue.. - - added instruction to get the source code - First integration of the new GW_ design more centralized on connector, and does not require specific feature on GW_APPLICATION depending on the connector. So this is really more flexible this way, and much easier to write @@ -1509,26 +3131,310 @@ hello_world This is a first version, more will come later, mainly migrating from Eiffel Web Reloaded to this Eiffel Web Framework project. -2011-07-08 Jocelyn Fiat +2011-07-12 Jocelyn Fiat + + let's have a nino-safe.ecf and also a nino.ecf for non void-safe system + +2011-07-11 jvelilla + + Added test cases from getest to autotest. First version. + +2011-07-08 Jocelyn Fiat focus on GW_APPLICATION -2011-07-07 Jocelyn Fiat +2011-07-07 Jocelyn Fiat a few renaming better GW_ENVIRONMENT interface -2011-07-06 Jocelyn Fiat +2011-07-07 jfiat + + Converted the autotest test suite to void-safety + cosmetics + + Now if you want to use the json utilities for gobo, you just need to include + the json_gobo_extension.ecf (note that the related gobo classes are not + void-safe) + cosmetics + +2011-07-07 jvelilla + + Updated eJSON to use Eiffel 6.8 version. Basically the changes are: Replace + ? by detachable indexing by note removing `is' from features, and in some + places replaced by = In the ecf now we need to include every gobo library, + because the gobo.ecf, exclude libraries that are needed. TODO: the test-suite + is not void-safety. + +2011-07-06 jvelilla + + Updated History and Readme files. + +2011-07-06 Jocelyn Fiat updated doc -2011-07-05 Jocelyn Fiat +2011-07-05 Jocelyn Fiat cosmetic, license, copyright +2011-07-05 jocelyn + + Updated Tasks Roadmap (markdown) + + Updated Tasks (markdown) + +2011-07-05 Jocelyn Fiat + added doc/wiki (wiki from github) First draft for the ewsgi spec -2011-06-29 Jocelyn +2011-06-01 Jocelyn Fiat - Let's start the Eiffel Web Framework + Fixed the HTTP_SERVER.shutdown_server + +2011-05-30 Jocelyn Fiat + + left adjust request_header_map items. + +2011-05-28 Javier Velilla + + Update Readme files + + Commit Jocelyn changes. + +2011-05-27 Jocelyn Fiat + + Reset values after processing the request Added port information when + starting the server + + Added force_single_threaded option Modified the interface of process request + default port is now 80 + + Moving things around to make it more structured. and turn into library + + 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) + +2011-05-26 Jocelyn Fiat + + A few change to make it more customizable and prepare integration to + EiffelWebReloaded (see on github) + +2011-05-20 Javier Velilla + + Import HTTPD Eiffel + +2011-01-13 manus + + * Use READABLE_STRING_GENERAL instead of STRING_GENERAL for routines + expecting a string. This enables us to use IMMUTABLE_STRINGs as argument + without conversion. * As a consequence we are also now using `same_string' + instead of `is_equal' to compare strings which will handle any type of + strings. * Enforced the rule that arguments are READABLE_STRING_GENERAL and + queries are STRING_32 when unicode is expected. * The most delicate part of + the change was the update of the encoding library. Now we have two + queries:last_converted_string_32 and last_converted_string_8 in addition of + the typeless last_converted_string. The idea is that if you know that you are + converting to something where characters are at least 2 bytes wide, you know + that you have to use STRING_32, otherwise it will be STRING_8. * Unlike + STRING_GENERAL, READABLE_STRING_GENERAL does not have a conversion to + STRING_32 and thus in a few places we had to use `as_string_32' for explicit + conversion which I found better. + +2010-03-16 manus + + Moved the experimental branch to be the default for libraries. + +2010-03-09 jvelilla + + Removed obsolete cluster. + + Added autotest test suite + +2010-03-08 paul.cohen + + Added getest based test program + +2010-03-08 jvelilla + + Updated Eiffel configuration file, updated to the new clusters + +2010-03-08 paul.cohen + + Ported r75 (all JSON value classes) from POC_CONVERTERS_FACTORY branch to + trunk + + Merged converters and factory classes from POC_CONVERTERS_FACTORY to trunk + + New directory layout created + +2010-03-05 jvelilla + + Added History, Readme and License files + +2009-08-25 larryl + + Added automatic license files for docking and cURL library + +2009-08-04 jfiat + + Optimized code, and removed extra dependencies. Added void-safe version + +2009-05-18 dfurrer + + - Adding the necessary platform-specific implementations (stubs atm) to build + EiffelStudio using the Cocoa Vision2 implementation (without GTK+ + dependencies). - There is a new target "bench_cocoa" in ec.ecf which builds + the native Mac version of EiffelStudio + +2009-05-18 larryl + + Updated cURL library to use API wrapper library Then removed useless classes + such as {API_LOADER} {API_LOADER_IMP}, removed useless library references + such as Vision2 and WEL + +2009-05-01 manus + + Updated to 1-5-0 schema version of ECFs. + +2009-04-09 manus + + Use new `note' syntax. + +2009-03-19 jfiat + + Added curl_easy_getinfo. Associated constants and also CURLOPT_USERPWD. Minor + optimization and cosmetics. + +2009-03-18 jfiat + + Cosmetic + Optimization + Assertion + Void-safety (no significant interface + changes) + +2009-02-27 larryl + + Added features related with curlopt_readfunction (for setting and using read + function), so users can read data from local machine and send the data to + server. Added curlopt_put and other constance to {CURL_OPT_CONSTATNS} which + used by {CURL_EASY_EXTERNALS} Contributed by Heiko Gering + +2009-02-24 manus + + Use new syntax for object test and attached/detachable type. + +2009-02-04 manus + + Added back vision2 since used for the API_LOADER_IMP on Unix but this time + with an explicit conditional. + + Made the cURL library void-safe. + +2008-12-29 manus + + Removal of `is' keyword. Replacement of `is' by `=' for constant definitions. + Replaced `indexing' by `note'. + +2008-12-01 manus + + Moved API_LOADER class to where it was used, i.e. the cURL library. + +2008-08-29 jvelilla + + Add descriptions. Change in skip_withe_spaces to handle newline %N and + carriage Return %R + +2008-08-27 berend + + SmartEiffel doesn't have is_space. + +2008-08-25 jvelilla + + Add accept method (JSON_VISITOR), remove is_xxx queries, remove to_json + feature. Improve comments + + Add Visitor Pattern , JSON_VISITOR and PRINT_JSON_VISITOR + +2008-08-05 berend + + Reformatted code to Gobo standard. + +2008-06-09 jvelilla + + Add new files to test ejson, based on json t test material + http://www.json.org/JSON_checker/test.zip + + Update JSON_OBJECT, put routine, now follows Eiffel Style based on HAST_TABLE + + Update Parser with is_parsed. Update parse_string + +2008-05-25 jvelilla + + Update test + + Update JSON_VALUE and JSON_OBJECT interface + + CDD classes + +2008-05-24 jvelilla + + Update JSON_STRING rutine is_equal Update JSON_OBJECT new features (has_keys, + item,get_keys), and fixed an incorrect use of HASH_TABLE + + eJson tests initial import + + eJson initial import + +2008-03-05 larryl + + Use precondition instead of raising an exception. Fixed bug#14062: CURL + dynamic library not found exception is causing an internal failure in WEL + +2008-02-29 larryl + + Raise an exception when cURL dynamic library not found. + +2008-01-09 larryl + + Added `global_cleanup' which declared as curl_global_cleanup() in C. Added + comments. + +2007-12-31 larryl + + Added http header related features. It means we can change http header by + setting a list ourself. Wrapped more cURL constants. Added `release_item' + in {CURL_FORM} which is useful to clean the {CURL_FORM} generated by + {CURL_EXTERNALS}.formadd_string_string. + +2007-12-07 jfiat + + Fully automated EiffelStudio's building using geant scripts: It integrates + part of the work done by "es-make" project from ETH (mainly on the checker + script) This is a first step in rewriting the previous + $EIFFEL_SRC/scripts/*.eant scripts to build 'ec' and make a new delivery. + Added a few standalone geant scripts in the EiffelStudio's source code, to + ease the compilation. + +2007-12-07 manus + + Ensured that the library also works in finalized mode. The issue is that in + finalized mode more than one copy of `eiffel_curl.h' could be present, + meaning that multiple values of each static declared variables could be + present at run-time and in one case, one was properly initialized, but not + the other. Fixes bug#13671. + +2007-11-18 manus + + Fixed various errors in the C interface. Use new C external syntax. + +2007-11-08 larryl + + Improved cURL wrapper library. We can write functions from curl_easy_setopt + in pure Eiffel now. Before we have to implement the functions in C. + +2007-10-30 larryl + + Made cURL wrapper library works on Linux. + +2007-10-26 larryl + + We can start our executables even without dll (so) files. From fffa763d057aeb47c5d77ceccd52e4cbfcddd818 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 6 May 2015 22:37:55 +0200 Subject: [PATCH 31/33] Updated a few comments. --- .../concurrency/scoop/httpd_connection_handler.e | 9 ++++----- .../httpd/configuration/httpd_configuration_i.e | 15 +++++++-------- .../src/httpd/httpd_connection_handler_i.e | 2 +- .../src/httpd/httpd_request_handler_i.e | 5 ++--- .../standalone/src/httpd/httpd_server_i.e | 10 +++++----- library/server/wsf/src/wsf_execution.e | 7 +++---- 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e index 757d46bd..9a5f4664 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -31,8 +31,7 @@ feature {NONE} -- Initialization end initialize_pool (p: like pool; n: INTEGER) - -- Initialize pool of separate connection handlers. - --| set the pool capacity to n. + -- Initialize Concurrent pool of `n' potential separate connection handlers. do p.set_count (n) end @@ -60,7 +59,7 @@ feature {HTTPD_SERVER_I} -- Execution end pool_gracefull_stop (p: like pool) - -- Graceful stop pool of separate connection handlers. + -- Graceful stop concurrent pool of separate connection handlers. do p.gracefull_stop end @@ -97,7 +96,7 @@ feature {HTTPD_SERVER_I} -- Execution end process_handler (hdl: separate HTTPD_REQUEST_HANDLER) - -- Process request handler `hdl' concurrently. + -- Process request handler `hdl' as soon as `hdl' is connected to accepted socket. require hdl.is_connected do @@ -123,7 +122,7 @@ feature {HTTPD_SERVER_I} -- Status report feature {NONE} -- Implementation separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET - -- Client socket for handler `hdl'. + -- Client socket for request handler `hdl'. do Result := hdl.client_socket end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e index 6046dc2e..93492678 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_configuration_i.e @@ -63,7 +63,7 @@ feature -- Access: SSL -- private key to the certificate. ssl_protocol: NATURAL - -- By default protocol is tls 1.2. + -- By default protocol is tls 1.2. feature -- Element change @@ -71,7 +71,6 @@ feature -- Element change do if v = Void then unset_http_server_name --- http_server_name := Void else create {IMMUTABLE_STRING_8} http_server_name.make_from_separate (v) end @@ -79,6 +78,7 @@ feature -- Element change end unset_http_server_name + -- Unset `http_server_name' value. do http_server_name := Void ensure @@ -162,12 +162,11 @@ feature -- Element change else is_secure := False end - --| Missing postcondition - --| ensure - -- is_secure_set : has_ssl_support implies is_secure - -- http_server_port_set: has_ssl_support implies http_server_port = 443 - -- is_not_secure: not has_ssl_support implies not is_secure - -- default_port: not has_ssl_support implies http_server_port = 80 + ensure + is_secure_set: has_ssl_support implies is_secure + -- http_server_port_set: has_ssl_support implies http_server_port = 443 + is_not_secure: not has_ssl_support implies not is_secure + -- default_port: not has_ssl_support implies http_server_port = 80 end feature -- Element change diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e index fa89d1fa..be3e51f3 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_connection_handler_i.e @@ -79,7 +79,7 @@ feature {NONE} -- Implementation end separate_server_log (a_server: like server; a_message: separate READABLE_STRING_8) - -- Separete log from a server `a_server' with message `a_message'. + -- Concurrent call to `a_server.log (a_message)'. do a_server.log (a_message) end diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index de42e66f..b394d6d5 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -1,5 +1,5 @@ note - description: "Represent a handler interface that process HTTP requests." + description: "HTTPD handler interface processing request." date: "$Date$" revision: "$Revision$" @@ -126,7 +126,7 @@ feature -- Change feature -- Execution safe_execute - -- Execute incoming request. + -- Execute accepted incoming connection as request. local retried: BOOLEAN do @@ -219,7 +219,6 @@ feature -- Execution if has_error then -- check catch_bad_incoming_connection: False end if is_verbose then --- check invalid_incoming_request: False end log ("ERROR: invalid HTTP incoming request") end else diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e index 39a7c894..b4115f1c 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_server_i.e @@ -14,9 +14,10 @@ inherit feature {NONE} -- Initialization make (a_factory: like factory) + -- Create current httpd server with `a_factory' of connection handlers. -- `a_factory': connection handler builder require - fac_is_separated: {PLATFORM}.is_scoop_capable implies not attached {HTTPD_REQUEST_HANDLER_FACTORY} a_factory + a_factory_is_separated: {PLATFORM}.is_scoop_capable implies not attached {HTTPD_REQUEST_HANDLER_FACTORY} a_factory do make_configured (create {like configuration}.make, a_factory) end @@ -66,7 +67,7 @@ feature -- Callbacks observer: detachable separate HTTPD_SERVER_OBSERVER set_observer (obs: like observer) - -- Set `observer' with `obs' + -- Set `observer' to `obs'. do observer := obs end @@ -252,7 +253,6 @@ feature -- Event require not_launched: not is_launched do --- print ("port=" + a_port.out + "%N") is_launched := True port := a_port if attached observer as obs then @@ -320,7 +320,7 @@ feature -- Output output: detachable FILE set_log_output (f: FILE) - -- Set `output' with `f'. + -- Set `output' to `f'. do output := f ensure @@ -328,7 +328,7 @@ feature -- Output end log (a_message: separate READABLE_STRING_8) - -- Log `a_message' + -- Log `a_message'. local m: STRING do diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e index 36d5d7d4..0f0ddb5f 100644 --- a/library/server/wsf/src/wsf_execution.e +++ b/library/server/wsf/src/wsf_execution.e @@ -1,5 +1,5 @@ note - description: "Object that represent a request execution with request and response. " + description: "Request execution based on attributes `request' and `response'. " date: "$Date$" revision: "$Revision$" @@ -51,7 +51,7 @@ feature -- Access feature -- Execution execute - -- Execute Current `request', + -- Execute Current request, -- getting data from `request' -- and response to client via `response'. deferred @@ -90,14 +90,13 @@ feature -- Helpers end put_error (err: READABLE_STRING_8) - -- Report error described by `a_message'. + -- Report error message `err' on the error output of the associated connector. require message_writable: message_writable do response.put_error (err) end - feature -- Cleaning clean From dd5c89e31c11151d5d59db02d1dcc6c125fdd5a7 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Thu, 7 May 2015 10:44:38 +0200 Subject: [PATCH 32/33] Fixed compilation of SSL_TCP_STREAM_SOCKET with recent do_accept changes. --- .../standalone/src/httpd/ssl/ssl_tcp_stream_socket.e | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e index 0ad0f7c7..f1043ad7 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/ssl/ssl_tcp_stream_socket.e @@ -11,7 +11,8 @@ inherit SSL_NETWORK_STREAM_SOCKET create - make_server_by_address_and_port, make_server_by_port + make_server_by_address_and_port, make_server_by_port, + make_empty create {SSL_NETWORK_STREAM_SOCKET} make_from_descriptor_and_address From 64463df5524eb2dd917e227574489a298e334840 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 5 Jun 2015 12:17:53 +0200 Subject: [PATCH 33/33] Fixed various compilation error or warning. --- examples/debug/debug.ecf | 3 +- examples/restbucksCRUD/restbucks-safe.ecf | 14 ++++---- examples/upload_image/upload_image-safe.ecf | 6 ++-- .../concurrency/none/httpd_request_handler.e | 10 ++++++ .../src/httpd/httpd_request_handler_i.e | 35 +++++++++++++++---- .../v0/ewsgi/connectors/libfcgi/libfcgi.ecf | 9 ++++- .../v0/ewsgi/connectors/nino/nino.ecf | 2 +- library/server/wsf/src/wsf_request.e | 2 +- tests/all-safe.ecf | 10 ++++++ 9 files changed, 71 insertions(+), 20 deletions(-) diff --git a/examples/debug/debug.ecf b/examples/debug/debug.ecf index 642cd4cc..5c6d642c 100644 --- a/examples/debug/debug.ecf +++ b/examples/debug/debug.ecf @@ -20,14 +20,15 @@ - + + diff --git a/examples/restbucksCRUD/restbucks-safe.ecf b/examples/restbucksCRUD/restbucks-safe.ecf index 626f0d5e..acf2f5dd 100644 --- a/examples/restbucksCRUD/restbucks-safe.ecf +++ b/examples/restbucksCRUD/restbucks-safe.ecf @@ -1,5 +1,5 @@ - + /EIFGENs$ @@ -8,16 +8,16 @@ - + - + - + @@ -30,7 +30,7 @@ @@ -42,7 +42,7 @@ diff --git a/examples/upload_image/upload_image-safe.ecf b/examples/upload_image/upload_image-safe.ecf index 66fb0fcc..77f989d3 100644 --- a/examples/upload_image/upload_image-safe.ecf +++ b/examples/upload_image/upload_image-safe.ecf @@ -8,17 +8,17 @@ /\.svn$
    - + - + diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e index 5055af02..c033de78 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/concurrency/none/httpd_request_handler.e @@ -8,6 +8,16 @@ deferred class inherit HTTPD_REQUEST_HANDLER_I + redefine + is_persistent_connection_supported + end + +feature -- Status report + + is_persistent_connection_supported: BOOLEAN = False + -- + -- When there is no concurrency support, do not try to support + -- persistent connection! note copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e index b394d6d5..3c5d0487 100644 --- a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_request_handler_i.e @@ -108,6 +108,16 @@ feature -- Settings is_verbose: BOOLEAN + is_persistent_connection_supported: BOOLEAN + -- Is persistent connection supported? + do + Result := {HTTPD_SERVER}.is_persistent_connection_supported + end + + persistent_connection_timeout: INTEGER = 5 -- seconds + -- Number of seconds for persistent connection timeout. + -- Default: 5 sec. + feature -- Status report has_error: BOOLEAN @@ -168,7 +178,7 @@ feature -- Execution n := n + 1 -- FIXME: it seems to be called one more time, mostly to see this is done. execute_request - l_exit := not {HTTPD_SERVER}.is_persistent_connection_supported + l_exit := not is_persistent_connection_supported or has_error or l_socket.is_closed or not l_socket.is_open_read or not is_persistent_connection_requested reset_request @@ -196,10 +206,21 @@ feature -- Execution debug ("dbglog") dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER") end - l_socket.set_timeout (5) -- 5 seconds! + --| TODO: add configuration options for socket timeout. --| set by default 5 seconds. - l_ready_for_reading := l_socket.ready_for_reading +-- l_socket.set_timeout (persistent_connection_timeout) -- 5 seconds! + l_socket.set_timeout (1) -- 1 second! + from + i := persistent_connection_timeout -- * 1 sec + until + l_ready_for_reading or i <= 0 or has_error + loop + l_ready_for_reading := l_socket.ready_for_reading + check not l_socket.is_closed end + i := i - 1 + end + if l_ready_for_reading then create l_remote_info if attached l_socket.peer_address as l_addr then @@ -217,9 +238,11 @@ feature -- Execution end if has_error then --- check catch_bad_incoming_connection: False end - if is_verbose then - log ("ERROR: invalid HTTP incoming request") + if l_ready_for_reading then + -- check catch_bad_incoming_connection: False end + if is_verbose then + log ("ERROR: invalid HTTP incoming request") + end end else process_request (l_socket) diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf index b99fe98b..c4196cfd 100644 --- a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf +++ b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf @@ -13,6 +13,13 @@ - + + + /wgi_.*_handler.e$ + /wgi_.*_connector.e$ + /.*_service.e$ + + +
    diff --git a/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf b/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf index feee5fa9..25198b63 100644 --- a/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf +++ b/library/server/obsolete/v0/ewsgi/connectors/nino/nino.ecf @@ -23,6 +23,6 @@ /.*_service.e$
    - + diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index ed082696..608b92cf 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -41,7 +41,7 @@ inherit {NONE} all end -create {WSF_TO_WGI_SERVICE, WSF_EXECUTION, WGI_EXPORTER} +create {WSF_EXECUTION, WGI_EXPORTER} make_from_wgi convert diff --git a/tests/all-safe.ecf b/tests/all-safe.ecf index 84a9e075..6bf2afa2 100644 --- a/tests/all-safe.ecf +++ b/tests/all-safe.ecf @@ -60,11 +60,21 @@ + + Compiling with None concurrency + + + Compiling with SCOOP concurrency + + Compiling with Eiffel Thread concurrency + + + Compiling as Windows , on other platforms than Windows