Fixed SSL support on the httpd component, and also on the EiffelWeb standalone connector.

- the standalone connector support for SSL, is using certicate files for now (no in-memory support).
  - to enable ssl support, set ecf variable `httpd_ssl_enabled=true`.
  - added the `simple_ssl` example to demonstrate how to have standalone ssl server.
    (be careful when using EiffelNet SSL and the http_client library, disable the libcurl
      via ecf variable `libcurl_http_client_disabled=true` )

Added support for recv timeout to the EiffelWeb standalone connector.
  - made EiffelWeb compilable with 16.05 and upcoming 16.11.
    Done via ecfs condition on version to accept EiffelNet with recv_timeout (from 16.11), and without (until 16.05).
  - adding recv timeout prevents server to hang for ever if a client wait too long to send data.

Updated various comments.
This commit is contained in:
2016-09-27 16:11:47 +02:00
parent 356eb143ea
commit 21407f8dcf
30 changed files with 711 additions and 88 deletions

View File

@@ -0,0 +1,29 @@
note
description : "simple application root class"
date : "$Date$"
revision : "$Revision$"
class
APPLICATION
inherit
WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]
redefine
initialize
end
create
make_and_launch
feature {NONE} -- Initialization
initialize
-- Initialize current service.
do
-- 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

@@ -0,0 +1,41 @@
note
description : "simple application execution"
date : "$Date$"
revision : "$Revision$"
class
APPLICATION_EXECUTION
inherit
WSF_EXECUTION
create
make
feature -- Basic operations
execute
local
s: STRING
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 + ").")
if request.is_https then
s.append ("<p>This is a secured connection! (https)</p>%N")
end
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

View File

@@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAJnXGtV+PtiYMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNDAzMjIxNTA0WhcNMTYwNDAyMjIxNTA0WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDFMK6ojzg+KlklhTossR13c51izMgGc3B0z9ttfHIcx2kxra3HtHcKIl5wSUvn
G8zmSyFAyQTs5LUv65q46FM9qU8tP+vTeFCfNXvjRcIEpouta3J53K0xuUlxz4d4
4D6qvdDWAez/0AkI4y5etW5zXtg7IQorJhsI9TmfGuruzwIDAQABo1AwTjAdBgNV
HQ4EFgQUbWpk2HoHa0YqpEwr7CGEatBFTMkwHwYDVR0jBBgwFoAUbWpk2HoHa0Yq
pEwr7CGEatBFTMkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAi+h4/
IgEocWkdRZBKHEcTrRxz5WhEDJMoVo9LhnXvCfn1G/4p6Un6sYv7Xzpi9NuSY8uV
cjfJJXhtF3AtyZ70iTAxWaRWjGaZ03PYOjlledJ5rqJEt6CCn8m+JsfznduZvbxQ
zQ6jCLXfyD/tvemB+yYEI3NntvRKx5/zt6Q26Q==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
##########################################################
### EiffelWeb settings for related connector ###
### Mostly for EiffelWeb standalone connector ###
### See {WGI_STANDALONE_CONSTANTS} for default values. ###
##########################################################
### Connection settings
port=9090
#max_concurrent_connections=100
#max_tcp_clients=100
### Timeout settings
#socket_timeout=60
#socket_recv_timeout=5
### Persistent connection settings
#keep_alive_timeout=15
#max_keep_alive_requests=100
### SSL settings
# enable SSL, with file certificate.
ssl_enabled=true
ssl_ca_key=simple.key
ssl_ca_crt=simple.crt
### App settings
verbose=true
verbose_level=ALERT

View File

@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDFMK6ojzg+KlklhTossR13c51izMgGc3B0z9ttfHIcx2kxra3H
tHcKIl5wSUvnG8zmSyFAyQTs5LUv65q46FM9qU8tP+vTeFCfNXvjRcIEpouta3J5
3K0xuUlxz4d44D6qvdDWAez/0AkI4y5etW5zXtg7IQorJhsI9TmfGuruzwIDAQAB
AoGAR5efMg+dieRyLU8rieJcImxVbfOPg9gRsjdtIVkXTR+RL7ow59q7hXBo/Td/
WU8cm1gXoJ/bK+71YYqWyB+BaLRIWvRWb7Gdw203tu4e136Ca5uuY+71qdbVTVcl
NQ7J+T+eAQFP+a+DdT3ZQxu9eze87SMbu6i5YSpIk2kusOECQQDunv/DQ+nc+NgR
DF+Td3sNYUVRT9a1CWi6abAG6reXwp8MS4NobWDf+Ps4JODhEEwlIdq5qL7qqYBZ
Gc1TJJ53AkEA0404Fn6vAzzegBcS4RLlYTK7nMr0m4pMmDMCI6YzAYdMmKHp1e6f
IwxSmQrmwyAgwcT01bc0+A8yipcC2BWQaQJBAJ01QZm635OGmos41KsKF5bsE8gL
SpBBH69Yu/ECqGwie7iU84FUNnO4zIHjwghlPVVlZX3Vz9o4S+fn2N9DC+cCQGyZ
QyCxGdC0r5fbwHJQS/ZQn+UGfvlVzqoXDVMVn3t6ZES6YZrT61eHnOM5qGqklIxE
Old3vDZXPt/MU8Zvk3kCQBOgUx2VxvTrHN37hk9/QIDiM62+RenBm1M3ah8xTosf
1mSeEb6d9Kwb3TgPBmA7YXzJuAQfRIvEPMPxT5SSr6Q=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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_ssl" uuid="C2FE296C-3C18-4609-A5AB-F604BDEE4410" library_target="simple_ssl">
<target name="simple_ssl">
<description>Simple EiffelWeb standalone server with SSL support (Concurrent connection supported thanks to SCOOP).</description>
<root class="APPLICATION" feature="make_and_launch"/>
<file_rule>
<exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions/>
</option>
<setting name="console_application" value="true"/>
<setting name="concurrency" value="scoop"/>
<variable name="httpd_ssl_enabled" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf"/>
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
<cluster name="simple" location=".\" recursive="true"/>
</target>
<target name="simple_ssl_st" extends="simple_ssl">
<description>Simple EiffelWeb standalone server with SSL support (Single threaded, thus no concurrent connection.)</description>
<setting name="concurrency" value="none"/>
</target>
</system>

View File

@@ -25,20 +25,27 @@ feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
release release
-- <Precursor> -- <Precursor>
local local
d: STRING d: detachable STRING
do do
if attached internal_client_socket as l_socket then
d := l_socket.descriptor.out
else
d := "N/A"
end
debug ("dbglog") debug ("dbglog")
if
attached internal_client_socket as l_socket and then
l_socket.descriptor_available
then
d := l_socket.descriptor.out
else
d := "N/A"
end
dbglog (generator + ".release: ENTER {" + d + "}") dbglog (generator + ".release: ENTER {" + d + "}")
end end
Precursor {HTTPD_REQUEST_HANDLER_I} Precursor {HTTPD_REQUEST_HANDLER_I}
release_pool_item release_pool_item
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".release: LEAVE {" + d + "}") if d /= Void then
dbglog (generator + ".release: LEAVE {" + d + "}")
else
dbglog (generator + ".release: LEAVE {N/A}")
end
end end
end end

View File

@@ -18,21 +18,28 @@ inherit
feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation
release release
-- <Precursor>
local local
d: STRING d: detachable STRING
do do
-- FIXME: for log purpose
if attached internal_client_socket as l_socket then
d := l_socket.descriptor.out
else
d := "N/A"
end
debug ("dbglog") debug ("dbglog")
if
attached internal_client_socket as l_socket and then
l_socket.descriptor_available
then
d := l_socket.descriptor.out
else
d := "N/A"
end
dbglog (generator + ".release: ENTER {" + d + "}") dbglog (generator + ".release: ENTER {" + d + "}")
end end
Precursor {HTTPD_REQUEST_HANDLER_I} Precursor {HTTPD_REQUEST_HANDLER_I}
debug ("dbglog") debug ("dbglog")
dbglog (generator + ".release: LEAVE {" + d + "}") if d /= Void then
dbglog (generator + ".release: LEAVE {" + d + "}")
else
dbglog (generator + ".release: LEAVE {N/A}")
end
end end
end end

View File

@@ -6,6 +6,11 @@ note
deferred class deferred class
HTTPD_CONFIGURATION_I HTTPD_CONFIGURATION_I
inherit
ANY
HTTPD_CONSTANTS
feature {NONE} -- Initialization feature {NONE} -- Initialization
make make
@@ -14,6 +19,7 @@ feature {NONE} -- Initialization
max_concurrent_connections := default_max_concurrent_connections max_concurrent_connections := default_max_concurrent_connections
max_tcp_clients := default_max_tcp_clients max_tcp_clients := default_max_tcp_clients
socket_timeout := default_socket_timeout socket_timeout := default_socket_timeout
socket_recv_timeout := default_socket_recv_timeout
keep_alive_timeout := default_keep_alive_timeout keep_alive_timeout := default_keep_alive_timeout
max_keep_alive_requests := default_max_keep_alive_requests max_keep_alive_requests := default_max_keep_alive_requests
is_secure := False is_secure := False
@@ -21,15 +27,6 @@ feature {NONE} -- Initialization
create ca_key.make_empty create ca_key.make_empty
end 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 feature -- Access
Server_details: STRING_8 Server_details: STRING_8
@@ -45,7 +42,12 @@ feature -- Access
socket_timeout: INTEGER assign set_socket_timeout socket_timeout: INTEGER assign set_socket_timeout
-- Amount of seconds that the server waits for receipts and transmissions during communications. -- Amount of seconds that the server waits for receipts and transmissions during communications.
-- note: with timeout of 0, socket can wait for ever. -- note: with timeout of 0, socket can wait for ever.
-- By default: 300 seconds, which is appropriate for most situations. -- By default: 60 seconds, which is appropriate for most situations.
socket_recv_timeout: INTEGER assign set_socket_recv_timeout
-- Amount of seconds that the server waits for receiving data during communications.
-- note: with timeout of 0, socket can wait for ever.
-- By default: 5 seconds.
max_concurrent_connections: INTEGER assign set_max_concurrent_connections max_concurrent_connections: INTEGER assign set_max_concurrent_connections
-- Max number of concurrent connections. -- Max number of concurrent connections.
@@ -83,8 +85,10 @@ feature -- Access
Result.is_verbose := is_verbose Result.is_verbose := is_verbose
Result.verbose_level := verbose_level Result.verbose_level := verbose_level
Result.timeout := socket_timeout Result.timeout := socket_timeout
Result.socket_recv_timeout := socket_recv_timeout
Result.keep_alive_timeout := keep_alive_timeout Result.keep_alive_timeout := keep_alive_timeout
Result.max_keep_alive_requests := max_keep_alive_requests Result.max_keep_alive_requests := max_keep_alive_requests
Result.is_secure := is_secure
end end
feature -- Access: SSL feature -- Access: SSL
@@ -92,10 +96,10 @@ feature -- Access: SSL
is_secure: BOOLEAN is_secure: BOOLEAN
-- Is SSL/TLS session?. -- Is SSL/TLS session?.
ca_crt: IMMUTABLE_STRING_8 ca_crt: detachable IMMUTABLE_STRING_32
-- the signed certificate. -- the signed certificate.
ca_key: IMMUTABLE_STRING_8 ca_key: detachable IMMUTABLE_STRING_32
-- private key to the certificate. -- private key to the certificate.
ssl_protocol: NATURAL ssl_protocol: NATURAL
@@ -103,6 +107,22 @@ feature -- Access: SSL
feature -- Element change feature -- Element change
set_ssl_settings (v: detachable separate TUPLE [protocol: separate READABLE_STRING_GENERAL; ca_crt, ca_key: detachable separate READABLE_STRING_GENERAL])
local
prot: STRING_32
do
is_secure := False
ca_crt := Void
ca_key := Void
if v /= Void then
is_secure := True
create prot.make_from_separate (v.protocol)
set_ssl_protocol_from_string (prot)
set_ca_crt (v.ca_crt)
set_ca_key (v.ca_key)
end
end
set_http_server_name (v: detachable separate READABLE_STRING_8) set_http_server_name (v: detachable separate READABLE_STRING_8)
do do
if v = Void then if v = Void then
@@ -152,6 +172,14 @@ feature -- Element change
socket_timeout_set: socket_timeout = a_nb_seconds socket_timeout_set: socket_timeout = a_nb_seconds
end end
set_socket_recv_timeout (a_nb_seconds: like socket_recv_timeout)
-- Set `socket_recv_timeout' with `a_nb_seconds'
do
socket_recv_timeout := a_nb_seconds
ensure
socket_recv_timeout_set: socket_recv_timeout = a_nb_seconds
end
set_keep_alive_timeout (a_seconds: like keep_alive_timeout) set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
-- Set `keep_alive_timeout' with `a_seconds' -- Set `keep_alive_timeout' with `a_seconds'
do do
@@ -198,17 +226,33 @@ feature -- Element change
verbose_level_set: verbose_level = lev verbose_level_set: verbose_level = lev
end end
mark_secure set_is_secure (b: BOOLEAN)
-- Set is_secure in True -- Set `is_secure' to `b'.
do do
if has_ssl_support then if b and has_ssl_support then
is_secure := True is_secure := True
if http_server_port = 80 then if
http_server_port = 80
then
set_http_server_port (443) set_http_server_port (443)
end end
else else
is_secure := False is_secure := False
if
http_server_port = 443
then
set_http_server_port (80)
end
end end
ensure
is_secure_set: has_ssl_support implies is_secure
is_not_secure: not has_ssl_support implies not is_secure
end
mark_secure
-- Set is_secure in True
do
set_is_secure (True)
ensure ensure
is_secure_set: has_ssl_support implies is_secure is_secure_set: has_ssl_support implies is_secure
-- http_server_port_set: has_ssl_support implies http_server_port = 443 -- http_server_port_set: has_ssl_support implies http_server_port = 443
@@ -218,16 +262,24 @@ feature -- Element change
feature -- Element change feature -- Element change
set_ca_crt (a_value: separate READABLE_STRING_8) set_ca_crt (a_value: detachable separate READABLE_STRING_GENERAL)
-- Set `ca_crt' from `a_value'. -- Set `ca_crt' from `a_value'.
do do
create ca_crt.make_from_separate (a_value) if a_value /= Void then
create ca_crt.make_from_separate (a_value)
else
ca_crt := Void
end
end end
set_ca_key (a_value: separate READABLE_STRING_8) set_ca_key (a_value: detachable separate READABLE_STRING_GENERAL)
-- Set `ca_key' with `a_value'. -- Set `ca_key' with `a_value'.
do do
create ca_key.make_from_separate (a_value) if a_value /= Void then
create ca_key.make_from_separate (a_value)
else
ca_key := Void
end
end end
set_ssl_protocol (a_version: NATURAL) set_ssl_protocol (a_version: NATURAL)
@@ -238,6 +290,24 @@ feature -- Element change
ssl_protocol_set: ssl_protocol = a_version ssl_protocol_set: ssl_protocol = a_version
end end
set_ssl_protocol_from_string (a_ssl_version: READABLE_STRING_GENERAL)
-- Set `ssl_protocol' with `a_ssl_version'
do
if a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
set_ssl_protocol_to_ssl_2_or_3
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_0") then
set_ssl_protocol_to_tls_1_0
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_1") then
set_ssl_protocol_to_tls_1_1
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_2") then
set_ssl_protocol_to_tls_1_2
elseif a_ssl_version.is_case_insensitive_equal ("dtls_1_0") then
set_ssl_protocol_to_dtls_1_0
else -- Default
set_ssl_protocol_to_tls_1_2
end
end
feature -- SSL Helpers feature -- SSL Helpers
set_ssl_protocol_to_ssl_2_or_3 set_ssl_protocol_to_ssl_2_or_3

View File

@@ -0,0 +1,28 @@
note
description: "[
Various constant values used in httpd settings.
]"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_CONSTANTS
feature -- Default connection settings
default_http_server_port: INTEGER = 80
default_max_concurrent_connections: INTEGER = 100
default_max_tcp_clients: INTEGER = 100
feature -- Default timeout settings
default_socket_timeout: INTEGER = 60 -- seconds
default_socket_recv_timeout: INTEGER = 5 -- seconds
feature -- Default persistent connection settings
default_keep_alive_timeout: INTEGER = 15 -- seconds
default_max_keep_alive_requests: INTEGER = 100
end

View File

@@ -17,9 +17,15 @@ feature -- Access
verbose_level: INTEGER assign set_verbose_level verbose_level: INTEGER assign set_verbose_level
-- Verbosity of output. -- Verbosity of output.
is_secure: BOOLEAN assign set_is_secure
-- Is using secure connection? i.e SSL?
timeout: INTEGER assign set_timeout timeout: INTEGER assign set_timeout
-- Amount of seconds that the server waits for receipts and transmissions during communications. -- Amount of seconds that the server waits for receipts and transmissions during communications.
socket_recv_timeout: INTEGER assign set_socket_recv_timeout
-- Amount of seconds that the server waits for receiving data on socket during communications.
keep_alive_timeout: INTEGER assign set_keep_alive_timeout keep_alive_timeout: INTEGER assign set_keep_alive_timeout
-- Keep-alive timeout, also known as persistent-connection 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. -- Number of seconds the server waits after a request has been served before it closes the connection.
@@ -42,12 +48,24 @@ feature -- Change
verbose_level := lev verbose_level := lev
end end
set_is_secure (b: BOOLEAN)
-- Set `is_secure' to `b'.
do
is_secure := b
end
set_timeout (a_timeout_in_seconds: INTEGER) set_timeout (a_timeout_in_seconds: INTEGER)
-- Set `timeout' to `a_timeout_in_seconds'. -- Set `timeout' to `a_timeout_in_seconds'.
do do
timeout := a_timeout_in_seconds timeout := a_timeout_in_seconds
end end
set_socket_recv_timeout (a_timeout_in_seconds: INTEGER)
-- Set `socket_recv_timeout' to `a_timeout_in_seconds'.
do
socket_recv_timeout := a_timeout_in_seconds
end
set_keep_alive_timeout (a_timeout_in_seconds: INTEGER) set_keep_alive_timeout (a_timeout_in_seconds: INTEGER)
-- Set `keep_alive_timeout' to `a_timeout_in_seconds'. -- Set `keep_alive_timeout' to `a_timeout_in_seconds'.
do do

View File

@@ -10,20 +10,29 @@
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="standard"> <option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="standard">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/> <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option> </option>
<setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/> <library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf" readonly="false"/>
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf"> <library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
<condition> <condition>
<custom name="net_ssl_enabled" value="true"/> <custom name="net_ssl_enabled" value="true"/>
</condition> </condition>
</library> </library>
<cluster name="network" location=".\network" recursive="false"> <cluster name="network" location=".\network\">
<cluster name="ssl_network" location="$|ssl" recursive="true"> <cluster name="ssl_network" location="$|ssl\" recursive="true">
<condition> <condition>
<custom name="net_ssl_enabled" value="true"/> <custom name="net_ssl_enabled" value="true"/>
</condition> </condition>
</cluster> </cluster>
<cluster name="network_until_16_05" location="$|until_16_05\">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
<condition>
<version type="compiler" min="16.11.0.0"/>
</condition>
</cluster>
</cluster> </cluster>
</target> </target>
</system> </system>

View File

@@ -24,6 +24,16 @@
<custom name="net_ssl_enabled" value="true"/> <custom name="net_ssl_enabled" value="true"/>
</condition> </condition>
</cluster> </cluster>
<cluster name="network_until_16_05" location="$|until_16_05\">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
<condition>
<version type="compiler" min="16.11.0.0"/>
</condition>
</cluster>
</cluster> </cluster>
</target> </target>
</system> </system>

View File

@@ -30,6 +30,16 @@
<custom name="httpd_ssl_enabled" value="true"/> <custom name="httpd_ssl_enabled" value="true"/>
</condition> </condition>
</cluster> </cluster>
<cluster name="network_until_16_05" location="$|until_16_05\">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
<condition>
<version type="compiler" min="16.11.0.0"/>
</condition>
</cluster>
</cluster> </cluster>
<cluster name="httpd_server" location=".\" recursive="true"> <cluster name="httpd_server" location=".\" recursive="true">
<file_rule> <file_rule>

View File

@@ -29,6 +29,16 @@
<custom name="httpd_ssl_enabled" value="true"/> <custom name="httpd_ssl_enabled" value="true"/>
</condition> </condition>
</cluster> </cluster>
<cluster name="network_until_16_05" location="$|until_16_05\">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
<condition>
<version type="compiler" min="16.11.0.0"/>
</condition>
</cluster>
</cluster> </cluster>
<cluster name="httpd_server" location=".\" recursive="true"> <cluster name="httpd_server" location=".\" recursive="true">
<file_rule> <file_rule>

View File

@@ -11,6 +11,8 @@ inherit
HTTPD_LOGGER_CONSTANTS HTTPD_LOGGER_CONSTANTS
HTTPD_SOCKET_FACTORY
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_request_settings: HTTPD_REQUEST_SETTINGS) make (a_request_settings: HTTPD_REQUEST_SETTINGS)
@@ -18,11 +20,13 @@ feature {NONE} -- Initialization
reset reset
-- Import global request settings. -- Import global request settings.
timeout := a_request_settings.timeout -- seconds timeout := a_request_settings.timeout -- seconds
socket_recv_timeout := a_request_settings.socket_recv_timeout -- seconds
keep_alive_timeout := a_request_settings.keep_alive_timeout -- seconds keep_alive_timeout := a_request_settings.keep_alive_timeout -- seconds
max_keep_alive_requests := a_request_settings.max_keep_alive_requests max_keep_alive_requests := a_request_settings.max_keep_alive_requests
is_verbose := a_request_settings.is_verbose is_verbose := a_request_settings.is_verbose
verbose_level := a_request_settings.verbose_level verbose_level := a_request_settings.verbose_level
is_secure := a_request_settings.is_secure
end end
reset reset
@@ -68,7 +72,7 @@ feature -- Access
do do
s := internal_client_socket s := internal_client_socket
if s = Void then if s = Void then
create s.make_empty s := new_client_socket (is_secure)
internal_client_socket := s internal_client_socket := s
end end
Result := s Result := s
@@ -121,6 +125,10 @@ feature -- Settings
verbose_level: INTEGER verbose_level: INTEGER
-- Output verbosity. -- Output verbosity.
is_secure: BOOLEAN
-- Is secure socket?
-- i.e: SSL?
is_persistent_connection_supported: BOOLEAN is_persistent_connection_supported: BOOLEAN
-- Is persistent connection supported? -- Is persistent connection supported?
do do
@@ -134,6 +142,9 @@ feature -- Settings
timeout: INTEGER -- seconds timeout: INTEGER -- seconds
-- Amount of seconds that the server waits for receipts and transmissions during communications. -- Amount of seconds that the server waits for receipts and transmissions during communications.
socket_recv_timeout: INTEGER -- seconds
-- Amount of seconds that the server waits for receiving data on socket during communications.
max_keep_alive_requests: INTEGER max_keep_alive_requests: INTEGER
-- Maximum number of requests allowed per persistent connection. -- Maximum number of requests allowed per persistent connection.
@@ -187,6 +198,7 @@ feature -- Execution
n,m: INTEGER n,m: INTEGER
do do
l_socket := client_socket l_socket := client_socket
l_socket.set_recv_timeout (socket_recv_timeout)
check check
socket_attached: l_socket /= Void socket_attached: l_socket /= Void
socket_valid: l_socket.is_open_read and then l_socket.is_open_write socket_valid: l_socket.is_open_read and then l_socket.is_open_write
@@ -206,18 +218,24 @@ feature -- Execution
log ("Reuse connection (" + n.out + ")", information_level) log ("Reuse connection (" + n.out + ")", information_level)
end end
-- FIXME: it seems to be called one more time, mostly to see this is done. -- FIXME: it seems to be called one more time, mostly to see this is done.
execute_request execute_request (n > 1)
l_exit := not is_persistent_connection_supported l_exit := not is_persistent_connection_supported
or not is_next_persistent_connection_supported -- related to `max_keep_alive_requests' or not is_next_persistent_connection_supported -- related to `max_keep_alive_requests'
or not is_persistent_connection_requested or not is_persistent_connection_requested
or has_error or l_socket.is_closed or not l_socket.is_open_read or has_error or l_socket.is_closed or not l_socket.is_open_read
reset_request reset_request
end end
if l_exit and has_error and not l_socket.is_closed then
l_socket.close
end
end end
execute_request execute_request (a_is_reusing_connection: BOOLEAN)
-- Execute http request, and if `a_is_reusing_connection' is True
-- the execution is reusing the persistent connection.
require require
is_connected: is_connected is_connected: is_connected
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
local local
l_remote_info: detachable like remote_info l_remote_info: detachable like remote_info
l_socket: like client_socket l_socket: like client_socket
@@ -237,13 +255,16 @@ feature -- Execution
dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER") dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER")
end end
--| TODO: add configuration options for socket timeout. if a_is_reusing_connection then
--| set by default 5 seconds. --| set by default 5 seconds.
l_socket.set_timeout (keep_alive_timeout) -- 5 seconds! l_socket.set_recv_timeout (keep_alive_timeout) -- in seconds!
l_is_ready := l_socket.ready_for_reading l_is_ready := l_socket.ready_for_reading
else
l_is_ready := True
end
if l_is_ready then if l_is_ready then
l_socket.set_timeout (timeout) -- FIXME: return a 408 Request Timeout response .. l_socket.set_recv_timeout (socket_recv_timeout) -- FIXME: return a 408 Request Timeout response ..
create l_remote_info create l_remote_info
if attached l_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.addr := l_addr.host_address.host_address
@@ -326,8 +347,7 @@ feature -- Parsing
has_error := True has_error := True
end end
l_is_verbose := is_verbose l_is_verbose := is_verbose
if not has_error or l_is_verbose then if not has_error then
-- if `is_verbose' we can try to print the request, even if it is a bad HTTP request
from from
line := next_line (a_socket) line := next_line (a_socket)
until until

View File

@@ -108,6 +108,7 @@ feature -- Execution
log (" - max_tcp_clients = " + configuration.max_tcp_clients.out) log (" - max_tcp_clients = " + configuration.max_tcp_clients.out)
log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out) log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out)
log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds") log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds")
log (" - socket_recv_timeout = " + configuration.socket_recv_timeout.out + " seconds")
log (" - keep_alive_timeout = " + configuration.keep_alive_timeout.out + " seconds") log (" - keep_alive_timeout = " + configuration.keep_alive_timeout.out + " seconds")
log (" - max_keep_alive_requests = " + configuration.max_keep_alive_requests.out) log (" - max_keep_alive_requests = " + configuration.max_keep_alive_requests.out)
if configuration.verbose_level > 0 then if configuration.verbose_level > 0 then

View File

@@ -0,0 +1,9 @@
note
description: "[
Since 16.11, the EiffelNet socket interface has recv_timeout and send_timeout.
]"
deferred class
TCP_STREAM_SOCKET_EXT
end

View File

@@ -62,6 +62,7 @@ feature {NONE} -- Initialization
feature -- Change feature -- Change
set_timeout (n: INTEGER) set_timeout (n: INTEGER)
-- Set timeout to `n' seconds.
do do
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
l_socket.set_timeout (n) l_socket.set_timeout (n)
@@ -82,6 +83,22 @@ feature -- Change
end end
end end
set_recv_timeout (a_timeout_seconds: INTEGER)
-- Set the receive timeout in seconds on Current socket.
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
l_socket.set_recv_timeout (a_timeout_seconds)
end
end
set_send_timeout (a_timeout_seconds: INTEGER)
-- Set the send timeout in seconds on Current socket.
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
l_socket.set_send_timeout (a_timeout_seconds)
end
end
feature -- Access feature -- Access
last_string: STRING last_string: STRING

View File

@@ -17,58 +17,66 @@ inherit
ready_for_writing, ready_for_writing,
ready_for_reading, ready_for_reading,
try_ready_for_reading, try_ready_for_reading,
put_readable_string_8 put_readable_string_8,
make_empty
end end
create create
make_ssl_server_by_address_and_port, make_ssl_server_by_port, make_ssl_server_by_address_and_port, make_ssl_server_by_port,
make_server_by_address_and_port, make_server_by_port, make_server_by_address_and_port, make_server_by_port,
make_ssl_client_by_address_and_port, make_ssl_client_by_port, make_ssl_client_by_address_and_port, make_ssl_client_by_port,
make_client_by_address_and_port, make_client_by_port make_client_by_address_and_port, make_client_by_port,
make_empty
create {HTTPD_STREAM_SOCKET} create {HTTPD_STREAM_SOCKET}
make make
feature {NONE} -- Initialization 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) make_ssl_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
local local
l_socket: SSL_TCP_STREAM_SOCKET l_socket: SSL_TCP_STREAM_SOCKET
do do
create l_socket.make_server_by_address_and_port (an_address, a_port) create l_socket.make_server_by_address_and_port (an_address, a_port)
l_socket.set_tls_protocol (a_ssl_protocol) l_socket.set_tls_protocol (a_ssl_protocol)
socket := l_socket socket := l_socket
set_certificates (a_crt, a_key) set_certificates (a_crt_fn, a_key_fn)
end end
make_ssl_server_by_port (a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING) make_ssl_server_by_port (a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
local local
l_socket: SSL_TCP_STREAM_SOCKET l_socket: SSL_TCP_STREAM_SOCKET
do do
create l_socket.make_server_by_port (a_port) create l_socket.make_server_by_port (a_port)
l_socket.set_tls_protocol (a_ssl_protocol) l_socket.set_tls_protocol (a_ssl_protocol)
socket := l_socket socket := l_socket
set_certificates (a_crt, a_key) set_certificates (a_crt_fn, a_key_fn)
end end
make_ssl_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING) make_ssl_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
local local
l_socket: SSL_TCP_STREAM_SOCKET l_socket: SSL_TCP_STREAM_SOCKET
do do
create l_socket.make_client_by_address_and_port (an_address, a_port) create l_socket.make_client_by_address_and_port (an_address, a_port)
l_socket.set_tls_protocol (a_ssl_protocol) l_socket.set_tls_protocol (a_ssl_protocol)
socket := l_socket socket := l_socket
set_certificates (a_crt, a_key) set_certificates (a_crt_fn, a_key_fn)
end end
make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING) make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
local local
l_socket: SSL_TCP_STREAM_SOCKET l_socket: SSL_TCP_STREAM_SOCKET
do do
create l_socket.make_client_by_port (a_peer_port, a_peer_host) create l_socket.make_client_by_port (a_peer_port, a_peer_host)
l_socket.set_tls_protocol (a_ssl_protocol) l_socket.set_tls_protocol (a_ssl_protocol)
socket := l_socket socket := l_socket
set_certificates (a_crt, a_key) set_certificates (a_crt_fn, a_key_fn)
end
make_empty
-- <Precursor>.
do
create {SSL_TCP_STREAM_SOCKET} socket.make_empty
end end
feature -- Output feature -- Output
@@ -136,15 +144,15 @@ feature -- Status Report
feature {HTTPD_STREAM_SOCKET} -- Implementation feature {HTTPD_STREAM_SOCKET} -- Implementation
set_certificates (a_crt: STRING; a_key: STRING) set_certificates (a_crt_filename, a_key_filename: detachable READABLE_STRING_GENERAL)
local
a_file_name: FILE_NAME
do do
if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then
create a_file_name.make_from_string (a_crt) if a_crt_filename /= Void then
l_socket.set_certificate_file_name (a_file_name) l_socket.set_certificate_file_name (a_crt_filename)
create a_file_name.make_from_string (a_key) end
l_socket.set_key_file_name (a_file_name) if a_key_filename /= Void then
l_socket.set_key_file_name (a_key_filename)
end
end end
end end

View File

@@ -12,6 +12,8 @@ inherit
make make
end end
TCP_STREAM_SOCKET_EXT
create create
make_server_by_address_and_port, make_server_by_address_and_port,
make_server_by_port, make_server_by_port,

View File

@@ -0,0 +1,104 @@
note
description: "[
Until 16.05, the EiffelNet socket interface DOES NOT have recv_timeout and send_timeout.
]"
deferred class
TCP_STREAM_SOCKET_EXT
feature -- Access
descriptor: INTEGER
-- Socket descriptor of current socket
deferred
end
feature -- Socket Recv and Send timeout.
-- recv_timeout: INTEGER
-- -- Receive timeout in seconds on Current socket.
-- do
-- Result := c_get_sock_recv_timeout (descriptor, level_sol_socket)
-- ensure
-- result_not_negative: Result >= 0
-- end
--
-- send_timeout: INTEGER
-- -- Send timeout in seconds on Current socket.
-- do
-- Result := c_get_sock_send_timeout (descriptor, level_sol_socket)
-- ensure
-- result_not_negative: Result >= 0
-- end
set_recv_timeout (a_timeout_seconds: INTEGER)
-- Set the receive timeout in seconds on Current socket.
-- if `0' the related operations will never timeout.
require
positive_timeout: a_timeout_seconds >= 0
do
c_set_sock_recv_timeout (descriptor, level_sol_socket, a_timeout_seconds)
end
set_send_timeout (a_timeout_seconds: INTEGER)
-- Set the send timeout in milliseconds on Current socket.
-- if `0' the related operations will never timeout.
require
positive_timeout: a_timeout_seconds >= 0
do
c_set_sock_send_timeout (descriptor, level_sol_socket, a_timeout_seconds)
end
feature {NONE} -- Externals
level_sol_socket: INTEGER
-- SOL_SOCKET level of options
deferred
end
-- set_so_rcvtimeo (a_timeout_seconds: INTEGER)
-- -- Set the receive timeout in seconds on Current socket.
-- -- if `0' the related operations will never timeout.
-- require
-- positive_timeout: a_timeout_seconds >= 0
-- do
-- c_set_sock_recv_timeout (descriptor, level_sol_socket, a_timeout_seconds)
-- end
c_set_sock_recv_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
-- C routine to set socket option `SO_RCVTIMEO' with `a_timeout_seconds' seconds.
external
"C inline"
alias
"[
#ifdef EIF_WINDOWS
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
setsockopt((SOCKET) $a_fd, (int) $a_level, (int) SO_RCVTIMEO, (char *) &arg, sizeof(arg));
#else
struct timeval tv;
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
setsockopt((int) $a_fd, (int) $a_level, (int) SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
#endif
]"
end
c_set_sock_send_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
-- C routine to set socket option `SO_SNDTIMEO' with `a_timeout_seconds' seconds.
external
"C inline"
alias
"[
#ifdef EIF_WINDOWS
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
setsockopt((SOCKET) $a_fd, (int) $a_level, (int) SO_SNDTIMEO, (char *) &arg, sizeof(arg));
#else
struct timeval tv;
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
setsockopt((int) $a_fd, (int) $a_level, (int) SO_SNDTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
#endif
]"
end
end

View File

@@ -0,0 +1,17 @@
note
description: "Summary description for {HTTPD_SOCKET_FACTORY}."
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_SOCKET_FACTORY
feature -- Access
new_client_socket (a_is_secure: BOOLEAN): HTTPD_STREAM_SOCKET
do
check not_secure: not a_is_secure end
create Result.make_empty
end
end

View File

@@ -0,0 +1,20 @@
note
description: "Summary description for {HTTPD_SOCKET_FACTORY}."
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_SOCKET_FACTORY
feature -- Access
new_client_socket (a_is_secure: BOOLEAN): HTTPD_STREAM_SOCKET
do
if a_is_secure then
create {HTTPD_STREAM_SSL_SOCKET} Result.make_empty
else
create Result.make_empty
end
end
end

View File

@@ -230,6 +230,9 @@ feature -- Request processing
set_environment_variable (l_server_port, "SERVER_PORT", Result) set_environment_variable (l_server_port, "SERVER_PORT", Result)
set_environment_variable (version, "SERVER_PROTOCOL", Result) set_environment_variable (version, "SERVER_PROTOCOL", Result)
set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result) set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result)
if is_secure then
set_environment_variable ("on", "HTTPS", Result)
end
--| Apply `base' value --| Apply `base' value
l_base := base l_base := base

View File

@@ -2,8 +2,8 @@ note
description: "[ description: "[
Standalone Web Server connector. Standalone Web Server connector.
]" ]"
date: "$Date$" date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
revision: "$Revision$" revision: "$Revision: 99106 $"
class class
WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end] WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end]
@@ -155,6 +155,12 @@ feature -- Element change
set_is_verbose_on_configuration (b, configuration) set_is_verbose_on_configuration (b, configuration)
end end
set_is_secure (b: BOOLEAN)
-- Set is_secure connection mode.
-- i.e: using SSL.
do
set_is_secure_on_configuration (b, configuration)
end
feature -- Server feature -- Server
@@ -242,6 +248,11 @@ feature {NONE} -- Implementation: element change
cfg.set_is_verbose (b) cfg.set_is_verbose (b)
end end
set_is_secure_on_configuration (b: BOOLEAN; cfg: like configuration)
do
cfg.set_is_secure (b)
end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"

View File

@@ -0,0 +1,18 @@
note
description: "[
Constants value related to Standalone connector,
and indirectly to `httpd' component.
]"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
deferred class
WGI_STANDALONE_CONSTANTS
inherit
ANY
HTTPD_CONSTANTS
end

View File

@@ -2,14 +2,27 @@ note
description: "[ description: "[
Component to launch the service using the default connector Component to launch the service using the default connector
Eiffel Web httpd for this class EiffelWeb httpd for this class
The httpd default connector support options:
verbose: to display verbose output
port: numeric such as 8099 (or equivalent string as "8099")
base: base_url (very specific to standalone server)
max_concurrent_connections: set one, for single threaded behavior
max_tcp_clients: max number of open tcp connection
socket_timeout: connection timeout
socket_recv_timeout: read data timeout
keep_alive_timeout: amount of time the server will wait for subsequent
requests on a persistent connection,
max_keep_alive_requests: number of requests allowed on a persistent connection,
ssl_enabled: set to True for https support.
ssl_ca_crt: path to the certificat crt file (relevant when ssl_enabled is True)
ssl_ca_key: path to the certificat key file (relevant when ssl_enabled is True)
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 standalone connector
force_single_threaded: use only one thread, useful for standalone connector
check WSF_SERVICE_LAUNCHER for more documentation check WSF_SERVICE_LAUNCHER for more documentation
]" ]"
@@ -41,12 +54,13 @@ feature {NONE} -- Initialization
create on_launched_actions create on_launched_actions
create on_stopped_actions create on_stopped_actions
port_number := 80 --| Default, but quite often, this port is already used ... port_number := {WGI_STANDALONE_CONSTANTS}.default_http_server_port --| Default, but quite often, this port is already used ...
max_concurrent_connections := 100 max_concurrent_connections := {WGI_STANDALONE_CONSTANTS}.default_max_concurrent_connections
max_tcp_clients := 100 max_tcp_clients := {WGI_STANDALONE_CONSTANTS}.default_max_tcp_clients
socket_timeout := 300 -- 300 seconds socket_timeout := {WGI_STANDALONE_CONSTANTS}.default_socket_timeout -- seconds
keep_alive_timeout := 15 -- 15 seconds. socket_recv_timeout := {WGI_STANDALONE_CONSTANTS}.default_socket_recv_timeout -- seconds
max_keep_alive_requests := 100 keep_alive_timeout := {WGI_STANDALONE_CONSTANTS}.default_keep_alive_timeout -- seconds.
max_keep_alive_requests := {WGI_STANDALONE_CONSTANTS}.default_max_keep_alive_requests
verbose := False verbose := False
verbose_level := notice_level verbose_level := notice_level
@@ -59,6 +73,7 @@ feature {NONE} -- Initialization
if attached {READABLE_STRING_GENERAL} opts.option ("base") as l_base_str then if attached {READABLE_STRING_GENERAL} opts.option ("base") as l_base_str then
base_url := l_base_str.as_string_8 base_url := l_base_str.as_string_8
end end
verbose := opts.option_boolean_value ("verbose", verbose) verbose := opts.option_boolean_value ("verbose", verbose)
-- See `{HTTPD_REQUEST_HANDLER_I}.*_verbose_level` -- See `{HTTPD_REQUEST_HANDLER_I}.*_verbose_level`
@@ -96,8 +111,16 @@ feature {NONE} -- Initialization
max_concurrent_connections := opts.option_integer_value ("max_concurrent_connections", max_concurrent_connections) 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) max_tcp_clients := opts.option_integer_value ("max_tcp_clients", max_tcp_clients)
socket_timeout := opts.option_integer_value ("socket_timeout", socket_timeout) socket_timeout := opts.option_integer_value ("socket_timeout", socket_timeout)
socket_recv_timeout := opts.option_integer_value ("socket_recv_timeout", socket_recv_timeout)
keep_alive_timeout := opts.option_integer_value ("keep_alive_timeout", keep_alive_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) max_keep_alive_requests := opts.option_integer_value ("max_keep_alive_requests", max_keep_alive_requests)
if
opts.option_boolean_value ("ssl_enabled", ssl_enabled) and then
attached opts.option_string_32_value ("ssl_protocol", "tls_1_2") as ssl_prot
then
ssl_settings := [ssl_prot, opts.option_string_32_value ("ssl_ca_crt", Void), opts.option_string_32_value ("ssl_ca_key", Void)]
end
end end
create conn.make create conn.make
@@ -120,11 +143,13 @@ feature -- Execution
do do
cfg.set_is_verbose (verbose) cfg.set_is_verbose (verbose)
cfg.set_verbose_level (verbose_level) cfg.set_verbose_level (verbose_level)
cfg.set_ssl_settings (ssl_settings)
cfg.set_http_server_name (server_name) cfg.set_http_server_name (server_name)
cfg.http_server_port := port_number cfg.http_server_port := port_number
cfg.set_max_concurrent_connections (max_concurrent_connections) cfg.set_max_concurrent_connections (max_concurrent_connections)
cfg.set_max_tcp_clients (max_tcp_clients) cfg.set_max_tcp_clients (max_tcp_clients)
cfg.set_socket_timeout (socket_timeout) cfg.set_socket_timeout (socket_timeout)
cfg.set_socket_recv_timeout (socket_recv_timeout)
cfg.set_keep_alive_timeout (keep_alive_timeout) cfg.set_keep_alive_timeout (keep_alive_timeout)
cfg.set_max_keep_alive_requests (max_keep_alive_requests) cfg.set_max_keep_alive_requests (max_keep_alive_requests)
end end
@@ -140,11 +165,17 @@ feature -- Execution
debug ("ew_standalone") debug ("ew_standalone")
if verbose then if verbose then
io.error.put_string ("Launching standalone 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 if ssl_enabled then
io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N") io.error.put_string ("%N https://")
else else
io.error.put_string ("%N http://localhost:" + port_number.out + "/" + base_url + "%N") io.error.put_string ("%N http://")
end end
if attached server_name as l_name then
io.error.put_string (l_name)
else
io.error.put_string ("localhost")
end
io.error.put_string (":" + port_number.out + "/" + base_url + "%N")
end end
end end
update_configuration (conn.configuration) update_configuration (conn.configuration)
@@ -177,9 +208,18 @@ feature {NONE} -- Implementation
-- Help defining the verbosity. -- Help defining the verbosity.
-- The higher, the more output. -- The higher, the more output.
ssl_settings: detachable TUPLE [protocol: READABLE_STRING_GENERAL; ca_crt, ca_key: detachable READABLE_STRING_GENERAL]
ssl_enabled: BOOLEAN
-- Is secure server? i.e using SSL?
do
Result := attached ssl_settings as ssl and then attached ssl.protocol as prot and then not prot.is_whitespace
end
max_concurrent_connections: INTEGER max_concurrent_connections: INTEGER
max_tcp_clients: INTEGER max_tcp_clients: INTEGER
socket_timeout: INTEGER socket_timeout: INTEGER
socket_recv_timeout: INTEGER
keep_alive_timeout: INTEGER keep_alive_timeout: INTEGER
max_keep_alive_requests: INTEGER max_keep_alive_requests: INTEGER

View File

@@ -22,11 +22,11 @@ note
For instance, you can use For instance, you can use
create s.make_and_launch_and_options (agent execute, <<["port", 8099]>>) create s.make_and_launch_and_options (agent execute, <<["port", 8099]>>)
And if Nino is the default connector it will support: And if the connector is the Standalone connector,
check {WSF_STANDALONE_SERVICE_LAUNCHER} for options description, such as:
port: numeric such as 8099 (or equivalent string as "8099") port: numeric such as 8099 (or equivalent string as "8099")
base: base_url (very specific to standalone server) base: base_url (very specific to standalone server)
force_single_threaded: use only one thread, useful for Nino verbose: to display verbose output.
verbose: to display verbose output, useful for Nino
]" ]"
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"

View File

@@ -8,8 +8,8 @@ note
force_single_threaded: use only one thread, useful for Nino force_single_threaded: use only one thread, useful for Nino
verbose: to display verbose output, useful for Nino verbose: to display verbose output, useful for Nino
]" ]"
date: "$Date$" date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
revision: "$Revision$" revision: "$Revision: 99106 $"
class class
WSF_SERVICE_LAUNCHER_OPTIONS WSF_SERVICE_LAUNCHER_OPTIONS
@@ -85,6 +85,12 @@ feature -- Access
feature -- Helpers feature -- Helpers
has_option (a_opt_name: READABLE_STRING_GENERAL): BOOLEAN
-- Is there any value associated to option name `a_opt_name'?
do
Result := attached option (a_opt_name)
end
has_integer_option (a_opt_name: READABLE_STRING_GENERAL): BOOLEAN has_integer_option (a_opt_name: READABLE_STRING_GENERAL): BOOLEAN
-- Is there any INTEGER value associated to option name `a_opt_name'? -- Is there any INTEGER value associated to option name `a_opt_name'?
local local
@@ -100,6 +106,29 @@ feature -- Helpers
end end
end end
has_string_32_option (a_opt_name: READABLE_STRING_GENERAL): BOOLEAN
-- Is there any string 32 value associated to option name `a_opt_name'?
do
if attached option (a_opt_name) as opt then
Result := attached {READABLE_STRING_GENERAL} opt
end
end
option_string_32_value (a_opt_name: READABLE_STRING_GENERAL; a_default: detachable READABLE_STRING_GENERAL): detachable IMMUTABLE_STRING_32
-- Unicode String value associated to option name `a_opt_name', other return `a_default'.
do
if attached option (a_opt_name) as opt then
if attached {READABLE_STRING_32} opt as s32 then
create Result.make_from_string (s32)
elseif attached {READABLE_STRING_GENERAL} opt as s then
create Result.make_from_string_general (s)
end
end
if Result = Void and a_default /= Void then
create Result.make_from_string_general (a_default)
end
end
option_integer_value (a_opt_name: READABLE_STRING_GENERAL; a_default: INTEGER): INTEGER 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'. -- INTEGER value associated to option name `a_opt_name', other return `a_default'.
local local