diff --git a/examples/simple/application.e b/examples/simple/application.e index 7d079309..5bd66e71 100644 --- a/examples/simple/application.e +++ b/examples/simple/application.e @@ -23,11 +23,7 @@ feature {NONE} -- Initialization -- Specific to `standalone' connector (the EiffelWeb server). -- See `{WSF_STANDALONE_SERVICE_LAUNCHER}.initialize' set_service_option ("port", 9090) - set_service_option ("max_concurrent_connections", 10) - set_service_option ("keep_alive_timeout", 1) - set_service_option ("verbose", True) + import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("simple.ini")) end - - end diff --git a/examples/simple/simple.ini b/examples/simple/simple.ini new file mode 100644 index 00000000..ae90215c --- /dev/null +++ b/examples/simple/simple.ini @@ -0,0 +1,8 @@ +verbose=true +verbose_level=ALERT +port=9090 +#max_concurrent_connections=100 +#keep_alive_timeout=15 +#max_tcp_clients=100 +#socket_timeout=300 +#max_keep_alive_requests=300 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 55a7e605..5a5e98ab 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 @@ -10,17 +10,26 @@ 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 + http_server_port := default_http_server_port + max_concurrent_connections := default_max_concurrent_connections + max_tcp_clients := default_max_tcp_clients + socket_timeout := default_socket_timeout + keep_alive_timeout := default_keep_alive_timeout + max_keep_alive_requests := default_max_keep_alive_requests is_secure := False create ca_crt.make_empty create ca_key.make_empty end +feature -- Defaults + + default_http_server_port: INTEGER = 80 + default_max_concurrent_connections: INTEGER = 100 + default_max_tcp_clients: INTEGER = 100 + default_socket_timeout: INTEGER = 300 -- seconds + default_keep_alive_timeout: INTEGER = 15 -- seconds + default_max_keep_alive_requests: INTEGER = 100 + feature -- Access Server_details: STRING_8 @@ -31,9 +40,15 @@ feature -- Access 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 + -- Listen on socket for at most `queue' connections. + + socket_timeout: INTEGER assign set_socket_timeout + -- Amount of seconds that the server waits for receipts and transmissions during communications. + -- note: with timeout of 0, socket can wait for ever. + -- By default: 300 seconds, which is appropriate for most situations. + 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 + -- Max number of concurrent connections. force_single_threaded: BOOLEAN assign set_force_single_threaded do @@ -43,15 +58,35 @@ feature -- Access is_verbose: BOOLEAN assign set_is_verbose -- Display verbose message to the output? + verbose_level: INTEGER assign set_verbose_level + -- Verbosity of output. + keep_alive_timeout: INTEGER assign set_keep_alive_timeout - -- Persistent connection timeout + -- Persistent connection timeout. + -- Number of seconds the server waits after a request has been served before it closes the connection. -- Timeout unit in Seconds. + -- By default: 5 seconds. + + max_keep_alive_requests: INTEGER assign set_max_keep_alive_requests + -- Maximum number of requests allowed per persistent connection. + -- Recommended a high setting. + -- To disable KeepAlive, set `max_keep_alive_requests' to 0. + -- By default: 100 . has_ssl_support: BOOLEAN -- Has SSL support? deferred end + request_settings: HTTPD_REQUEST_SETTINGS + do + Result.is_verbose := is_verbose + Result.verbose_level := verbose_level + Result.timeout := socket_timeout + Result.keep_alive_timeout := keep_alive_timeout + Result.max_keep_alive_requests := max_keep_alive_requests + end + feature -- Access: SSL is_secure: BOOLEAN @@ -75,7 +110,6 @@ feature -- Element change else create {IMMUTABLE_STRING_8} http_server_name.make_from_separate (v) end - --| Missing postcondition. end unset_http_server_name @@ -110,27 +144,35 @@ feature -- Element change max_concurrent_connections_set : max_concurrent_connections = v end - set_socket_accept_timeout (v: like socket_accept_timeout) - -- Set `socket_accept_timeout' with `v' + set_socket_timeout (a_nb_seconds: like socket_timeout) + -- Set `socket_timeout' with `a_nb_seconds' do - socket_accept_timeout := v + socket_timeout := a_nb_seconds ensure - socket_accept_timeout_set: socket_accept_timeout = v + socket_timeout_set: socket_timeout = a_nb_seconds end - set_socket_connect_timeout (v: like socket_connect_timeout) - -- Set `socket_connect_timeout' with `v' + set_keep_alive_timeout (a_seconds: like keep_alive_timeout) + -- Set `keep_alive_timeout' with `a_seconds' do - socket_connect_timeout := v + keep_alive_timeout := a_seconds ensure - socket_connect_timeout_set: socket_connect_timeout = v + keep_alive_timeout_set: keep_alive_timeout = a_seconds + end + + set_max_keep_alive_requests (nb: like max_keep_alive_requests) + -- Set `max_keep_alive_requests' with `nb' + do + max_keep_alive_requests := nb + ensure + max_keep_alive_requests_set: max_keep_alive_requests = nb end set_force_single_threaded (v: like force_single_threaded) -- Force server to handle incoming request in a single thread. -- i.e set max_concurrent_connections to 0! obsolete - "Use set_max_concurrent_connections (0) [June/2016]" + "Use set_max_concurrent_connections (0) [June/2016]" do if v then set_max_concurrent_connections (0) @@ -148,12 +190,12 @@ feature -- Element change is_verbose_set: is_verbose = b end - set_keep_alive_timeout (a_seconds: like keep_alive_timeout) - -- Set `keep_alive_timeout' with `a_seconds' + set_verbose_level (lev: INTEGER) + -- Set `verbose_level' to `lev'. do - keep_alive_timeout := a_seconds + verbose_level := lev ensure - keep_alive_timeout_set: keep_alive_timeout = a_seconds + verbose_level_set: verbose_level = lev end mark_secure diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_request_settings.e b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_request_settings.e new file mode 100644 index 00000000..146b193a --- /dev/null +++ b/library/server/ewsgi/connectors/standalone/src/httpd/configuration/httpd_request_settings.e @@ -0,0 +1,64 @@ +note + description: "[ + Request settings for the standalone HTTPd server. + ]" + author: "$Author$" + date: "$Date$" + revision: "$Revision$" + +expanded class + HTTPD_REQUEST_SETTINGS + +feature -- Access + + is_verbose: BOOLEAN assign set_is_verbose + -- Is verbose? + + verbose_level: INTEGER assign set_verbose_level + -- Verbosity of output. + + timeout: INTEGER assign set_timeout + -- Amount of seconds that the server waits for receipts and transmissions during communications. + + keep_alive_timeout: INTEGER assign set_keep_alive_timeout + -- Keep-alive timeout, also known as persistent-connection timeout. + -- Number of seconds the server waits after a request has been served before it closes the connection. + -- Unit in Seconds. + + max_keep_alive_requests: INTEGER assign set_max_keep_alive_requests + -- Maximum number of requests allowed per persistent connection. + +feature -- Change + + set_is_verbose (b: BOOLEAN) + -- Set `is_verbose' to `b'. + do + is_verbose := b + end + + set_verbose_level (lev: INTEGER) + -- Set `verbose_level' to `lev'. + do + verbose_level := lev + end + + set_timeout (a_timeout_in_seconds: INTEGER) + -- Set `timeout' to `a_timeout_in_seconds'. + do + timeout := a_timeout_in_seconds + end + + set_keep_alive_timeout (a_timeout_in_seconds: INTEGER) + -- Set `keep_alive_timeout' to `a_timeout_in_seconds'. + do + keep_alive_timeout := a_timeout_in_seconds + end + + set_max_keep_alive_requests (nb: like max_keep_alive_requests) + -- Set `max_keep_alive_requests' with `nb' + do + max_keep_alive_requests := nb + end + +end + diff --git a/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger_constants.e b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger_constants.e new file mode 100644 index 00000000..c75bec49 --- /dev/null +++ b/library/server/ewsgi/connectors/standalone/src/httpd/httpd_logger_constants.e @@ -0,0 +1,22 @@ +note + description: "[ + Constant value to define the logging level. + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + HTTPD_LOGGER_CONSTANTS + +feature -- Access + + alert_level: INTEGER = 1 -- 0000 0001 + critical_level: INTEGER = 2 -- 0000 0010 + error_level: INTEGER = 4 -- 0000 0100 + warning_level: INTEGER = 8 -- 0000 1000 + + notice_level: INTEGER = 16 -- 0001 0000 + information_level: INTEGER = 32 -- 0010 0000 + debug_level: INTEGER = 64 -- 0100 0000 + +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 48b70397..cb07e103 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 @@ -9,12 +9,20 @@ deferred class inherit HTTPD_DEBUG_FACILITIES + HTTPD_LOGGER_CONSTANTS + feature {NONE} -- Initialization - make + make (a_request_settings: HTTPD_REQUEST_SETTINGS) do reset - persistent_connection_timeout := 5 -- seconds + -- Import global request settings. + timeout := a_request_settings.timeout -- seconds + keep_alive_timeout := a_request_settings.keep_alive_timeout -- seconds + max_keep_alive_requests := a_request_settings.max_keep_alive_requests + + is_verbose := a_request_settings.is_verbose + verbose_level := a_request_settings.verbose_level end reset @@ -108,16 +116,29 @@ feature -- Access feature -- Settings is_verbose: BOOLEAN + -- Output messages? + + verbose_level: INTEGER + -- Output verbosity. is_persistent_connection_supported: BOOLEAN -- Is persistent connection supported? do - Result := {HTTPD_SERVER}.is_persistent_connection_supported - end + Result := {HTTPD_SERVER}.is_persistent_connection_supported and then max_keep_alive_requests > 0 + end - persistent_connection_timeout: INTEGER -- seconds + is_next_persistent_connection_supported: BOOLEAN + -- Is next persistent connection supported? + -- note: it is relevant only if `is_persistent_connection_supported' is True. + + timeout: INTEGER -- seconds + -- Amount of seconds that the server waits for receipts and transmissions during communications. + + max_keep_alive_requests: INTEGER + -- Maximum number of requests allowed per persistent connection. + + keep_alive_timeout: INTEGER -- seconds -- Number of seconds for persistent connection timeout. - -- Default: 5 sec. feature -- Status report @@ -163,7 +184,7 @@ feature -- Execution local l_socket: like client_socket l_exit: BOOLEAN - n: INTEGER + n,m: INTEGER do l_socket := client_socket check @@ -173,15 +194,21 @@ feature -- Execution from -- Process persistent connection as long the socket is not closed. n := 0 + m := max_keep_alive_requests + is_next_persistent_connection_supported := True until l_exit loop n := n + 1 + if n >= m then + is_next_persistent_connection_supported := False + end -- FIXME: it seems to be called one more time, mostly to see this is done. execute_request 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_next_persistent_connection_supported -- related to `max_keep_alive_requests' or not is_persistent_connection_requested + or has_error or l_socket.is_closed or not l_socket.is_open_read reset_request end end @@ -193,7 +220,6 @@ feature -- Execution l_remote_info: detachable like remote_info l_socket: like client_socket l_is_ready: BOOLEAN - i: INTEGER do l_socket := client_socket check @@ -211,10 +237,11 @@ feature -- Execution --| TODO: add configuration options for socket timeout. --| set by default 5 seconds. - l_socket.set_timeout (persistent_connection_timeout) -- 5 seconds! + l_socket.set_timeout (keep_alive_timeout) -- 5 seconds! l_is_ready := l_socket.ready_for_reading if l_is_ready then + l_socket.set_timeout (timeout) -- FIXME: return a 408 Request Timeout response .. create l_remote_info if attached l_socket.peer_address as l_addr then l_remote_info.addr := l_addr.host_address.host_address @@ -234,10 +261,13 @@ feature -- Execution if l_is_ready then -- check catch_bad_incoming_connection: False end if is_verbose then - log ("ERROR: invalid HTTP incoming request") + log (request_header + "%NWARNING: invalid HTTP incoming request", warning_level) end end else + if is_verbose then + log (request_header, information_level) + end process_request (l_socket) end debug ("dbglog") @@ -281,11 +311,11 @@ feature -- Parsing do create txt.make (64) request_header := txt - if + if not has_error and then a_socket.is_readable and then attached next_line (a_socket) as l_request_line and then - not l_request_line.is_empty + not l_request_line.is_empty then txt.append (l_request_line) txt.append_character ('%N') @@ -302,8 +332,10 @@ feature -- Parsing line = Void or end_of_stream or has_error loop n := line.count - if l_is_verbose then - log (line) + debug ("ew_standalone") + if l_is_verbose then + log (line, debug_level) + end end pos := line.index_of (':', 1) if pos > 0 then @@ -350,9 +382,11 @@ feature -- Parsing local n, pos, next_pos: INTEGER do - if is_verbose then - log ("%N## Parse HTTP request line ##") - log (line) + debug ("ew_standalone") + if is_verbose then + log ("%N## Parse HTTP request line ##", debug_level) + log (line, debug_level) + end end pos := line.index_of (' ', 1) method := line.substring (1, pos - 1) @@ -369,7 +403,7 @@ feature -- Parsing next_line (a_socket: HTTPD_STREAM_SOCKET): detachable STRING -- Next line fetched from `a_socket' is available. require - not_has_error: not has_error + not_has_error: not has_error or is_verbose is_readable: a_socket.is_open_read local retried: BOOLEAN @@ -380,19 +414,19 @@ feature -- Parsing elseif a_socket.readable then a_socket.read_line_thread_aware Result := a_socket.last_string - -- Do no check `socket_ok' before socket operation, + -- Do no check `socket_ok' before socket operation, -- otherwise it may be False, due to error during other socket operation in same thread. if not a_socket.socket_ok then has_error := True if is_verbose then - log ("%N## Socket is not ok! ##") + log (request_header +"%N" + Result + "%N## socket_ok=False! ##", debug_level) end end else -- Error with socket... has_error := True if is_verbose then - log ("%N## Socket is not readable! ##") + log (request_header + "%N## Socket is not readable! ##", debug_level) end end rescue @@ -412,13 +446,17 @@ feature -- Output logger_set: logger = a_logger end - log (m: STRING) + log (m: STRING; a_level: INTEGER) -- Log message `m'. + require + is_verbose: is_verbose do - if attached logger as l_logger then - l_logger.log (m) - else - io.put_string (m + "%N") + if is_verbose and (verbose_level & a_level) = a_level then + if attached logger as l_logger then + l_logger.log (m) + else + io.put_string (m + "%N") + end end 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 326ed715..ec02bd07 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 @@ -51,6 +51,9 @@ feature -- Access is_verbose: BOOLEAN -- Is verbose for output messages. + verbose_level: INTEGER + -- Verbosity of output. + configuration: HTTPD_CONFIGURATION -- Associated server configuration. @@ -100,7 +103,16 @@ feature -- Execution apply_configuration is_terminated := False if is_verbose then - log ("%N%NStarting Web Application Server (port=" + configuration.http_server_port.out + "):%N") + log ("%N%NStarting Web Application Server ...") + log (" - port = " + configuration.http_server_port.out) + log (" - max_tcp_clients = " + configuration.max_tcp_clients.out) + log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out) + log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds") + log (" - keep_alive_timeout = " + configuration.keep_alive_timeout.out + " seconds") + log (" - max_keep_alive_requests = " + configuration.max_keep_alive_requests.out) + if configuration.verbose_level > 0 then + log (" - verbose_level = " + configuration.verbose_level.out) + end end is_shutdown_requested := False listen @@ -150,7 +162,7 @@ feature -- Listening if not l_listening_socket.is_bound then if is_verbose then - log ("Socket could not be bound on port " + l_http_port.out) + log ("Socket could not be bound on port " + l_http_port.out + " !") end else l_http_port := l_listening_socket.port @@ -159,9 +171,9 @@ feature -- Listening l_listening_socket.listen (configuration.max_tcp_clients) 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 + "/") + log ("%NListening 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 + "/") + log ("%NListening on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/") end end on_launched (l_http_port) @@ -312,6 +324,7 @@ feature -- Configuration change is_not_launched: not is_launched do is_verbose := configuration.is_verbose + verbose_level := configuration.verbose_level end feature -- Output 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 3abd5220..dc95fb21 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 @@ -24,13 +24,10 @@ create feature {NONE} -- Initialization - make_with_connector (conn: like connector) + make_with_connector (a_request_settings: HTTPD_REQUEST_SETTINGS; conn: like connector) do - make + make (a_request_settings) connector := conn --- if conn /= Void then --- set_is_verbose (is_connector_verbose (conn)) --- end end feature -- Access @@ -56,11 +53,6 @@ feature -- SCOOP helpers 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) @@ -87,7 +79,7 @@ feature -- Request processing else l_output.set_http_version (version) end - res.set_is_persistent_connection_supported ({HTTPD_SERVER}.is_persistent_connection_supported) + res.set_is_persistent_connection_supported (is_persistent_connection_supported and is_next_persistent_connection_supported) res.set_is_persistent_connection_requested (is_persistent_connection_requested) req.set_meta_string_variable ("RAW_HEADER_DATA", request_header) 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 613962b0..5dc7c4b4 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 @@ -14,19 +14,23 @@ feature -- Access connector: detachable separate WGI_STANDALONE_CONNECTOR [G] -- httpd solution. + request_settings: HTTPD_REQUEST_SETTINGS + -- Settings specific to request handling. + feature -- Element change - update_with (conn: like connector) + update_with (conn: like connector; a_conf: separate HTTPD_CONFIGURATION) -- Set `connector' with `conn'. do connector := conn + request_settings := a_conf.request_settings end feature -- Factory new_handler: separate WGI_HTTPD_REQUEST_HANDLER [G] do - create Result.make_with_connector (connector) + create Result.make_with_connector (request_settings, connector) end note 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 7bf4d4de..56ec6c79 100644 --- a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_connector.e @@ -27,11 +27,11 @@ feature {NONE} -- Initialization -- Server create fac + request_handler_factory := fac create server.make (fac) create observer configuration := server_configuration (server) controller := server_controller (server) - set_factory_connector (Current, fac) initialize_server (server) end @@ -51,9 +51,9 @@ feature {NONE} -- Separate helper a_server.set_observer (observer) end - set_factory_connector (conn: detachable separate WGI_STANDALONE_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]) + update_factory (conn: detachable separate WGI_STANDALONE_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]; a_conf: separate HTTPD_CONFIGURATION) do - fac.update_with (conn) + fac.update_with (conn, a_conf) end server_configuration (a_server: like server): like configuration @@ -74,6 +74,9 @@ feature -- Access server: separate HTTPD_SERVER -- HTTPd server object. + request_handler_factory: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G] + -- Factory for request handlers. + controller: separate HTTPD_CONTROLLER -- Controller used to shutdown server. @@ -97,9 +100,6 @@ feature -- Status report -- Listening port. --| 0: not launched - is_verbose: BOOLEAN - -- Is verbose? - feature -- Callbacks on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]]] @@ -190,18 +190,22 @@ feature {NONE} -- Implementation Result := a_server.controller end - configure_server (a_configuration: like configuration) + apply_configuration (a_configuration: like configuration) + local + v: BOOLEAN do - if a_configuration.is_verbose then - if attached base as l_base then + v := a_configuration.is_verbose + if v then + if attached base as l_base and then not l_base.is_whitespace then io.error.put_string ("Base=" + l_base + "%N") end end + update_factory (Current, request_handler_factory, a_configuration) end launch_server (a_server: like server) do - configure_server (a_server.configuration) + apply_configuration (a_server.configuration) a_server.launch end @@ -229,7 +233,6 @@ feature {NONE} -- Implementation: element change set_is_verbose_on_configuration (b: BOOLEAN; cfg: like configuration) do - is_verbose := b cfg.set_is_verbose (b) end diff --git a/library/server/ewsgi/connectors/standalone/src/wgi_standalone_httpd_logger_constants.e b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_httpd_logger_constants.e new file mode 100644 index 00000000..c0e75022 --- /dev/null +++ b/library/server/ewsgi/connectors/standalone/src/wgi_standalone_httpd_logger_constants.e @@ -0,0 +1,10 @@ +note + description: "Export HTTPD_LOGGER_CONSTANTS to Standlone connector interfaces." + +class + WGI_STANDALONE_HTTPD_LOGGER_CONSTANTS + +inherit + HTTPD_LOGGER_CONSTANTS + +end 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 ad19d07e..40a65e5e 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 @@ -108,7 +108,6 @@ feature -- Header output operation 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) diff --git a/library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e b/library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e index f1311499..38eda984 100644 --- a/library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e +++ b/library/server/wsf/connector/standalone/wsf_standalone_service_launcher.e @@ -25,6 +25,8 @@ inherit launchable end + WGI_STANDALONE_HTTPD_LOGGER_CONSTANTS + create make, make_and_launch @@ -34,12 +36,20 @@ feature {NONE} -- Initialization initialize local conn: like connector + s: READABLE_STRING_GENERAL do create on_launched_actions create on_stopped_actions port_number := 80 --| Default, but quite often, this port is already used ... - keep_alive_timeout := 5_000 -- 5 seconds. + max_concurrent_connections := 100 + max_tcp_clients := 100 + socket_timeout := 300 -- 300 seconds + keep_alive_timeout := 15 -- 15 seconds. + max_keep_alive_requests := 100 + verbose := False + verbose_level := notice_level + base_url := "" if attached options as opts then @@ -50,13 +60,44 @@ feature {NONE} -- Initialization base_url := l_base_str.as_string_8 end verbose := opts.option_boolean_value ("verbose", verbose) + -- See `{HTTPD_REQUEST_HANDLER_I}.*_verbose_level` + + if opts.has_integer_option ("verbose_level") then + verbose_level := opts.option_integer_value ("verbose_level", verbose_level) + elseif attached {READABLE_STRING_GENERAL} opts.option ("verbose_level") as s_verbose_level then + verbose_level := 0 -- Reset + across + s_verbose_level.split ('+') as ic + loop + s := ic.item + if s.is_case_insensitive_equal ("alert") then + verbose_level := verbose_level | alert_level + elseif s.is_case_insensitive_equal ("critical") then + verbose_level := verbose_level | critical_level + elseif s.is_case_insensitive_equal ("error") then + verbose_level := verbose_level | error_level + elseif s.is_case_insensitive_equal ("warning") then + verbose_level := verbose_level | warning_level + elseif s.is_case_insensitive_equal ("notice") then + verbose_level := verbose_level | notice_level + elseif s.is_case_insensitive_equal ("information") then + verbose_level := verbose_level | information_level + elseif s.is_case_insensitive_equal ("debug") then + verbose_level := verbose_level | debug_level + else + end + end + end port_number := opts.option_integer_value ("port", port_number) - if opts.option_boolean_value ("force_single_threaded", single_threaded) then + if opts.option_boolean_value ("force_single_threaded", False) then force_single_threaded end max_concurrent_connections := opts.option_integer_value ("max_concurrent_connections", max_concurrent_connections) + max_tcp_clients := opts.option_integer_value ("max_tcp_clients", max_tcp_clients) + socket_timeout := opts.option_integer_value ("socket_timeout", socket_timeout) keep_alive_timeout := opts.option_integer_value ("keep_alive_timeout", keep_alive_timeout) + max_keep_alive_requests := opts.option_integer_value ("max_keep_alive_requests", max_keep_alive_requests) end create conn.make @@ -78,13 +119,14 @@ feature -- Execution update_configuration (cfg: like connector.configuration) do cfg.set_is_verbose (verbose) - if attached server_name as l_server_name then - cfg.set_http_server_name (l_server_name) - end + cfg.set_verbose_level (verbose_level) + cfg.set_http_server_name (server_name) cfg.http_server_port := port_number cfg.set_max_concurrent_connections (max_concurrent_connections) + cfg.set_max_tcp_clients (max_tcp_clients) + cfg.set_socket_timeout (socket_timeout) cfg.set_keep_alive_timeout (keep_alive_timeout) --- conn.update_configuration (cfg) + cfg.set_max_keep_alive_requests (max_keep_alive_requests) end launch @@ -131,16 +173,21 @@ feature {NONE} -- Implementation base_url: READABLE_STRING_8 verbose: BOOLEAN + verbose_level: INTEGER + -- Help defining the verbosity. + -- The higher, the more output. + + max_concurrent_connections: INTEGER + max_tcp_clients: INTEGER + socket_timeout: INTEGER + keep_alive_timeout: INTEGER + max_keep_alive_requests: INTEGER single_threaded: BOOLEAN do Result := max_concurrent_connections = 0 end - max_concurrent_connections: INTEGER - - keep_alive_timeout: INTEGER - feature -- Status report connector: WGI_STANDALONE_CONNECTOR [G] diff --git a/library/server/wsf/src/service/wsf_service_launcher_options.e b/library/server/wsf/src/service/wsf_service_launcher_options.e index b2827fdc..82e65a6f 100644 --- a/library/server/wsf/src/service/wsf_service_launcher_options.e +++ b/library/server/wsf/src/service/wsf_service_launcher_options.e @@ -85,6 +85,21 @@ feature -- Access feature -- Helpers + has_integer_option (a_opt_name: READABLE_STRING_GENERAL): BOOLEAN + -- Is there any INTEGER value associated to option name `a_opt_name'? + local + s: READABLE_STRING_GENERAL + do + if attached option (a_opt_name) as opt then + if attached {INTEGER} opt as i then + Result := True + else + s := opt.out + Result := s.is_integer + end + end + end + option_integer_value (a_opt_name: READABLE_STRING_GENERAL; a_default: INTEGER): INTEGER -- INTEGER value associated to option name `a_opt_name', other return `a_default'. local diff --git a/library/text/parser/feed/tests/msys-iconv-2.dll b/library/text/parser/feed/tests/msys-iconv-2.dll new file mode 100644 index 00000000..111ded94 Binary files /dev/null and b/library/text/parser/feed/tests/msys-iconv-2.dll differ