Compare commits

...

2 Commits

Author SHA1 Message Date
113aa69efc Added advanced settings for standalone connector
- max_concurrent_connections=100
- keep_alive_timeout=15
- max_tcp_clients=100
- socket_timeout=300
- max_keep_alive_requests=300
And then can be set via the options as well, and via .ini file.
Also improved the verbose console output system.
2016-06-15 09:19:23 +02:00
af5fc75743 Using passive regions.
Improve connector options mainly for standalone connector.
Updated "simple" example to return a timestamp.
2016-06-14 16:01:37 +02:00
19 changed files with 430 additions and 139 deletions

View File

@@ -20,9 +20,10 @@ feature {NONE} -- Initialization
initialize
-- Initialize current service.
do
set_service_option ("port", 9090)
-- Specific to `standalone' connector (the EiffelWeb server).
-- See `{WSF_STANDALONE_SERVICE_LAUNCHER}.initialize'
set_service_option ("port", 9090)
import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("simple.ini"))
end
end

View File

@@ -17,10 +17,13 @@ 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!"
dt: HTTP_DATE
do
-- To send a response we need to setup, the status code and
-- the response headers.
s := "Hello World!"
create dt.make_now_utc
s.append (" (UTC time is " + dt.rfc850_string + ").")
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

View File

@@ -1,35 +1,28 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="simple" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="simple">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="simple" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="simple">
<target name="common" abstract="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<option warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="transitional" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
</target>
<target name="simple_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<setting name="concurrency" value="scoop"/>
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf"/>
<cluster name="simple" location=".\" recursive="true"/>
</target>
<target name="simple_nino" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf"/>
<cluster name="simple" location=".\" recursive="true"/>
</target>
<target name="simple_cgi" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">

View File

@@ -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

View File

@@ -23,8 +23,8 @@ feature {NONE} -- Initialization
local
n: INTEGER
p: like pool
do
n := max_concurrent_connections (server)
do
n := max_concurrent_connections (server).max (1) -- At least one processor!
create p.make (n)
initialize_pool (p, n)
pool := p

View File

@@ -23,7 +23,7 @@ feature {NONE} -- Initialization
local
n: INTEGER
do
n := max_concurrent_connections (server)
n := max_concurrent_connections (server).max (1) -- At least one thread!
create pool.make (n.to_natural_32)
end

View File

@@ -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,26 +40,53 @@ 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
Result := (max_concurrent_connections = 0)
Result := max_concurrent_connections = 0
end
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
@@ -74,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
@@ -109,23 +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]"
do
if v then
set_max_concurrent_connections (0)
@@ -143,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

View File

@@ -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

View File

@@ -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

View File

@@ -9,11 +9,20 @@ deferred class
inherit
HTTPD_DEBUG_FACILITIES
HTTPD_LOGGER_CONSTANTS
feature {NONE} -- Initialization
make
make (a_request_settings: HTTPD_REQUEST_SETTINGS)
do
reset
-- 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
@@ -107,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 = 5 -- 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
@@ -162,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
@@ -172,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
@@ -192,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
@@ -210,19 +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 (1) -- 1 second!
from
i := persistent_connection_timeout -- * 1 sec
until
l_is_ready or i <= 0 or has_error
loop
l_is_ready := l_socket.ready_for_reading
check not l_socket.is_closed end
i := i - 1
end
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
@@ -242,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")
@@ -289,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')
@@ -310,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
@@ -358,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)
@@ -377,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
@@ -388,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
@@ -420,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

View File

@@ -37,7 +37,7 @@ feature {NONE} -- Initialization
build_controller
-- Build `controller'.
do
create controller
create <NONE> controller
end
initialize
@@ -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

View File

@@ -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)

View File

@@ -1,5 +1,5 @@
note
description: "Implementation of WGI request handler factory for WGI_STANDALOE_CONNECTOR."
description: "Implementation of WGI request handler factory for WGI_STANDALONE_CONNECTOR."
date: "$Date$"
revision: "$Revision$"
@@ -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
set_connector (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

View File

@@ -26,12 +26,12 @@ feature {NONE} -- Initialization
create on_launched_actions
-- Server
create fac
create <NONE> fac
request_handler_factory := fac
create server.make (fac)
create observer
create <NONE> 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.set_connector (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

View File

@@ -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

View File

@@ -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)

View File

@@ -25,6 +25,8 @@ inherit
launchable
end
WGI_STANDALONE_HTTPD_LOGGER_CONSTANTS
create
make,
make_and_launch
@@ -34,38 +36,68 @@ 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 ...
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
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")
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
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")
port_number := opts.option_integer_value ("port", port_number)
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
@@ -76,18 +108,25 @@ feature {NONE} -- Initialization
update_configuration (conn.configuration)
end
force_single_threaded
-- Set `single_threaded' to True.
do
max_concurrent_connections := 1
end
feature -- Execution
update_configuration (cfg: like connector.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
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)
cfg.set_max_keep_alive_requests (max_keep_alive_requests)
end
launch
@@ -98,7 +137,7 @@ feature -- Execution
do
conn := connector
conn.set_base (base_url)
debug ("nino")
debug ("ew_standalone")
if verbose then
io.error.put_string ("Launching standalone web server on port " + port_number.out)
if attached server_name as l_name then
@@ -134,8 +173,20 @@ 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
feature -- Status report

View File

@@ -83,6 +83,57 @@ feature -- Access
Result := options.item (a_name)
end
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
s: READABLE_STRING_GENERAL
do
Result := a_default
if attached option (a_opt_name) as opt then
if attached {INTEGER} opt as i then
Result := i
else
s := opt.out
if s.is_integer then
Result := s.to_integer
end
end
end
end
option_boolean_value (a_opt_name: READABLE_STRING_GENERAL; a_default: BOOLEAN): BOOLEAN
-- BOOLEAN value associated to option name `a_opt_name', other return `a_default'.
local
s: READABLE_STRING_GENERAL
do
Result := a_default
if attached option (a_opt_name) as opt then
if attached {BOOLEAN} opt as b then
Result := b
else
s := opt.out
Result := s.is_case_insensitive_equal ("true")
end
end
end
feature -- Access
new_cursor: TABLE_ITERATION_CURSOR [detachable ANY, READABLE_STRING_GENERAL]

Binary file not shown.