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:
29
examples/simple_ssl/application.e
Normal file
29
examples/simple_ssl/application.e
Normal 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
|
||||
41
examples/simple_ssl/application_execution.e
Normal file
41
examples/simple_ssl/application_execution.e
Normal 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
|
||||
15
examples/simple_ssl/simple.crt
Normal file
15
examples/simple_ssl/simple.crt
Normal 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-----
|
||||
28
examples/simple_ssl/simple.ini
Normal file
28
examples/simple_ssl/simple.ini
Normal 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
|
||||
15
examples/simple_ssl/simple.key
Normal file
15
examples/simple_ssl/simple.key
Normal 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-----
|
||||
27
examples/simple_ssl/simple_ssl.ecf
Normal file
27
examples/simple_ssl/simple_ssl.ecf
Normal 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>
|
||||
@@ -25,20 +25,27 @@ feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
|
||||
release
|
||||
-- <Precursor>
|
||||
local
|
||||
d: STRING
|
||||
d: detachable STRING
|
||||
do
|
||||
if attached internal_client_socket as l_socket then
|
||||
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
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".release: ENTER {" + d + "}")
|
||||
end
|
||||
Precursor {HTTPD_REQUEST_HANDLER_I}
|
||||
release_pool_item
|
||||
debug ("dbglog")
|
||||
if d /= Void then
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
else
|
||||
dbglog (generator + ".release: LEAVE {N/A}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -18,21 +18,28 @@ inherit
|
||||
feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation
|
||||
|
||||
release
|
||||
-- <Precursor>
|
||||
local
|
||||
d: STRING
|
||||
d: detachable STRING
|
||||
do
|
||||
-- FIXME: for log purpose
|
||||
if attached internal_client_socket as l_socket then
|
||||
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
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".release: ENTER {" + d + "}")
|
||||
end
|
||||
Precursor {HTTPD_REQUEST_HANDLER_I}
|
||||
debug ("dbglog")
|
||||
if d /= Void then
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
else
|
||||
dbglog (generator + ".release: LEAVE {N/A}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ note
|
||||
deferred class
|
||||
HTTPD_CONFIGURATION_I
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
@@ -14,6 +19,7 @@ feature {NONE} -- Initialization
|
||||
max_concurrent_connections := default_max_concurrent_connections
|
||||
max_tcp_clients := default_max_tcp_clients
|
||||
socket_timeout := default_socket_timeout
|
||||
socket_recv_timeout := default_socket_recv_timeout
|
||||
keep_alive_timeout := default_keep_alive_timeout
|
||||
max_keep_alive_requests := default_max_keep_alive_requests
|
||||
is_secure := False
|
||||
@@ -21,15 +27,6 @@ feature {NONE} -- Initialization
|
||||
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
|
||||
@@ -45,7 +42,12 @@ feature -- Access
|
||||
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.
|
||||
-- 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 number of concurrent connections.
|
||||
@@ -83,8 +85,10 @@ feature -- Access
|
||||
Result.is_verbose := is_verbose
|
||||
Result.verbose_level := verbose_level
|
||||
Result.timeout := socket_timeout
|
||||
Result.socket_recv_timeout := socket_recv_timeout
|
||||
Result.keep_alive_timeout := keep_alive_timeout
|
||||
Result.max_keep_alive_requests := max_keep_alive_requests
|
||||
Result.is_secure := is_secure
|
||||
end
|
||||
|
||||
feature -- Access: SSL
|
||||
@@ -92,10 +96,10 @@ feature -- Access: SSL
|
||||
is_secure: BOOLEAN
|
||||
-- Is SSL/TLS session?.
|
||||
|
||||
ca_crt: IMMUTABLE_STRING_8
|
||||
ca_crt: detachable IMMUTABLE_STRING_32
|
||||
-- the signed certificate.
|
||||
|
||||
ca_key: IMMUTABLE_STRING_8
|
||||
ca_key: detachable IMMUTABLE_STRING_32
|
||||
-- private key to the certificate.
|
||||
|
||||
ssl_protocol: NATURAL
|
||||
@@ -103,6 +107,22 @@ feature -- Access: SSL
|
||||
|
||||
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)
|
||||
do
|
||||
if v = Void then
|
||||
@@ -152,6 +172,14 @@ feature -- Element change
|
||||
socket_timeout_set: socket_timeout = a_nb_seconds
|
||||
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' with `a_seconds'
|
||||
do
|
||||
@@ -198,17 +226,33 @@ feature -- Element change
|
||||
verbose_level_set: verbose_level = lev
|
||||
end
|
||||
|
||||
mark_secure
|
||||
-- Set is_secure in True
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set `is_secure' to `b'.
|
||||
do
|
||||
if has_ssl_support then
|
||||
if b and has_ssl_support then
|
||||
is_secure := True
|
||||
if http_server_port = 80 then
|
||||
if
|
||||
http_server_port = 80
|
||||
then
|
||||
set_http_server_port (443)
|
||||
end
|
||||
else
|
||||
is_secure := False
|
||||
if
|
||||
http_server_port = 443
|
||||
then
|
||||
set_http_server_port (80)
|
||||
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
|
||||
is_secure_set: has_ssl_support implies is_secure
|
||||
-- http_server_port_set: has_ssl_support implies http_server_port = 443
|
||||
@@ -218,16 +262,24 @@ 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'.
|
||||
do
|
||||
if a_value /= Void then
|
||||
create ca_crt.make_from_separate (a_value)
|
||||
else
|
||||
ca_crt := Void
|
||||
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'.
|
||||
do
|
||||
if a_value /= Void then
|
||||
create ca_key.make_from_separate (a_value)
|
||||
else
|
||||
ca_key := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ssl_protocol (a_version: NATURAL)
|
||||
@@ -238,6 +290,24 @@ feature -- Element change
|
||||
ssl_protocol_set: ssl_protocol = a_version
|
||||
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
|
||||
|
||||
set_ssl_protocol_to_ssl_2_or_3
|
||||
|
||||
@@ -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
|
||||
@@ -17,9 +17,15 @@ feature -- Access
|
||||
verbose_level: INTEGER assign set_verbose_level
|
||||
-- Verbosity of output.
|
||||
|
||||
is_secure: BOOLEAN assign set_is_secure
|
||||
-- Is using secure connection? i.e SSL?
|
||||
|
||||
timeout: INTEGER assign set_timeout
|
||||
-- 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, also known as persistent-connection timeout.
|
||||
-- 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
|
||||
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' to `a_timeout_in_seconds'.
|
||||
do
|
||||
timeout := a_timeout_in_seconds
|
||||
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' to `a_timeout_in_seconds'.
|
||||
do
|
||||
|
||||
@@ -10,20 +10,29 @@
|
||||
<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"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<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">
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<cluster name="network" location=".\network" recursive="false">
|
||||
<cluster name="ssl_network" location="$|ssl" recursive="true">
|
||||
<cluster name="network" location=".\network\">
|
||||
<cluster name="ssl_network" location="$|ssl\" recursive="true">
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</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>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -24,6 +24,16 @@
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</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>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -30,6 +30,16 @@
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</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 name="httpd_server" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
|
||||
@@ -29,6 +29,16 @@
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</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 name="httpd_server" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
|
||||
@@ -11,6 +11,8 @@ inherit
|
||||
|
||||
HTTPD_LOGGER_CONSTANTS
|
||||
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_request_settings: HTTPD_REQUEST_SETTINGS)
|
||||
@@ -18,11 +20,13 @@ feature {NONE} -- Initialization
|
||||
reset
|
||||
-- Import global request settings.
|
||||
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
|
||||
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
|
||||
is_secure := a_request_settings.is_secure
|
||||
end
|
||||
|
||||
reset
|
||||
@@ -68,7 +72,7 @@ feature -- Access
|
||||
do
|
||||
s := internal_client_socket
|
||||
if s = Void then
|
||||
create s.make_empty
|
||||
s := new_client_socket (is_secure)
|
||||
internal_client_socket := s
|
||||
end
|
||||
Result := s
|
||||
@@ -121,6 +125,10 @@ feature -- Settings
|
||||
verbose_level: INTEGER
|
||||
-- Output verbosity.
|
||||
|
||||
is_secure: BOOLEAN
|
||||
-- Is secure socket?
|
||||
-- i.e: SSL?
|
||||
|
||||
is_persistent_connection_supported: BOOLEAN
|
||||
-- Is persistent connection supported?
|
||||
do
|
||||
@@ -134,6 +142,9 @@ feature -- Settings
|
||||
timeout: INTEGER -- seconds
|
||||
-- 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
|
||||
-- Maximum number of requests allowed per persistent connection.
|
||||
|
||||
@@ -187,6 +198,7 @@ feature -- Execution
|
||||
n,m: INTEGER
|
||||
do
|
||||
l_socket := client_socket
|
||||
l_socket.set_recv_timeout (socket_recv_timeout)
|
||||
check
|
||||
socket_attached: l_socket /= Void
|
||||
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)
|
||||
end
|
||||
-- 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
|
||||
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
|
||||
if l_exit and has_error and not l_socket.is_closed then
|
||||
l_socket.close
|
||||
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
|
||||
is_connected: is_connected
|
||||
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
|
||||
local
|
||||
l_remote_info: detachable like remote_info
|
||||
l_socket: like client_socket
|
||||
@@ -237,13 +255,16 @@ feature -- Execution
|
||||
dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER")
|
||||
end
|
||||
|
||||
--| TODO: add configuration options for socket timeout.
|
||||
if a_is_reusing_connection then
|
||||
--| 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
|
||||
else
|
||||
l_is_ready := True
|
||||
end
|
||||
|
||||
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
|
||||
if attached l_socket.peer_address as l_addr then
|
||||
l_remote_info.addr := l_addr.host_address.host_address
|
||||
@@ -326,8 +347,7 @@ feature -- Parsing
|
||||
has_error := True
|
||||
end
|
||||
l_is_verbose := is_verbose
|
||||
if not has_error or l_is_verbose then
|
||||
-- if `is_verbose' we can try to print the request, even if it is a bad HTTP request
|
||||
if not has_error then
|
||||
from
|
||||
line := next_line (a_socket)
|
||||
until
|
||||
|
||||
@@ -108,6 +108,7 @@ feature -- Execution
|
||||
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 (" - socket_recv_timeout = " + configuration.socket_recv_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
|
||||
|
||||
@@ -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
|
||||
@@ -62,6 +62,7 @@ feature {NONE} -- Initialization
|
||||
feature -- Change
|
||||
|
||||
set_timeout (n: INTEGER)
|
||||
-- Set timeout to `n' seconds.
|
||||
do
|
||||
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
l_socket.set_timeout (n)
|
||||
@@ -82,6 +83,22 @@ feature -- Change
|
||||
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
|
||||
|
||||
last_string: STRING
|
||||
|
||||
@@ -17,58 +17,66 @@ inherit
|
||||
ready_for_writing,
|
||||
ready_for_reading,
|
||||
try_ready_for_reading,
|
||||
put_readable_string_8
|
||||
put_readable_string_8,
|
||||
make_empty
|
||||
end
|
||||
|
||||
create
|
||||
make_ssl_server_by_address_and_port, make_ssl_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_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}
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_ssl_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
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
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_server_by_address_and_port (an_address, a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
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
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_server_by_port (a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
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
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_client_by_address_and_port (an_address, a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
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
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_client_by_port (a_peer_port, a_peer_host)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
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
|
||||
|
||||
feature -- Output
|
||||
@@ -136,15 +144,15 @@ feature -- Status Report
|
||||
|
||||
feature {HTTPD_STREAM_SOCKET} -- Implementation
|
||||
|
||||
set_certificates (a_crt: STRING; a_key: STRING)
|
||||
local
|
||||
a_file_name: FILE_NAME
|
||||
set_certificates (a_crt_filename, a_key_filename: detachable READABLE_STRING_GENERAL)
|
||||
do
|
||||
if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
create a_file_name.make_from_string (a_crt)
|
||||
l_socket.set_certificate_file_name (a_file_name)
|
||||
create a_file_name.make_from_string (a_key)
|
||||
l_socket.set_key_file_name (a_file_name)
|
||||
if a_crt_filename /= Void then
|
||||
l_socket.set_certificate_file_name (a_crt_filename)
|
||||
end
|
||||
if a_key_filename /= Void then
|
||||
l_socket.set_key_file_name (a_key_filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ inherit
|
||||
make
|
||||
end
|
||||
|
||||
TCP_STREAM_SOCKET_EXT
|
||||
|
||||
create
|
||||
make_server_by_address_and_port,
|
||||
make_server_by_port,
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -230,6 +230,9 @@ feature -- Request processing
|
||||
set_environment_variable (l_server_port, "SERVER_PORT", Result)
|
||||
set_environment_variable (version, "SERVER_PROTOCOL", Result)
|
||||
set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result)
|
||||
if is_secure then
|
||||
set_environment_variable ("on", "HTTPS", Result)
|
||||
end
|
||||
|
||||
--| Apply `base' value
|
||||
l_base := base
|
||||
|
||||
@@ -2,8 +2,8 @@ note
|
||||
description: "[
|
||||
Standalone Web Server connector.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
|
||||
revision: "$Revision: 99106 $"
|
||||
|
||||
class
|
||||
WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end]
|
||||
@@ -155,6 +155,12 @@ feature -- Element change
|
||||
set_is_verbose_on_configuration (b, configuration)
|
||||
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
|
||||
|
||||
@@ -242,6 +248,11 @@ feature {NONE} -- Implementation: element change
|
||||
cfg.set_is_verbose (b)
|
||||
end
|
||||
|
||||
set_is_secure_on_configuration (b: BOOLEAN; cfg: like configuration)
|
||||
do
|
||||
cfg.set_is_secure (b)
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
|
||||
@@ -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
|
||||
@@ -4,12 +4,25 @@ note
|
||||
|
||||
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)
|
||||
verbose: to display verbose output, useful for standalone connector
|
||||
force_single_threaded: use only one thread, useful for standalone connector
|
||||
|
||||
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)
|
||||
|
||||
|
||||
check WSF_SERVICE_LAUNCHER for more documentation
|
||||
]"
|
||||
@@ -41,12 +54,13 @@ feature {NONE} -- Initialization
|
||||
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
|
||||
port_number := {WGI_STANDALONE_CONSTANTS}.default_http_server_port --| Default, but quite often, this port is already used ...
|
||||
max_concurrent_connections := {WGI_STANDALONE_CONSTANTS}.default_max_concurrent_connections
|
||||
max_tcp_clients := {WGI_STANDALONE_CONSTANTS}.default_max_tcp_clients
|
||||
socket_timeout := {WGI_STANDALONE_CONSTANTS}.default_socket_timeout -- seconds
|
||||
socket_recv_timeout := {WGI_STANDALONE_CONSTANTS}.default_socket_recv_timeout -- seconds
|
||||
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_level := notice_level
|
||||
|
||||
@@ -59,6 +73,7 @@ feature {NONE} -- Initialization
|
||||
if attached {READABLE_STRING_GENERAL} opts.option ("base") as l_base_str then
|
||||
base_url := l_base_str.as_string_8
|
||||
end
|
||||
|
||||
verbose := opts.option_boolean_value ("verbose", verbose)
|
||||
-- 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_tcp_clients := opts.option_integer_value ("max_tcp_clients", max_tcp_clients)
|
||||
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)
|
||||
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
|
||||
|
||||
create conn.make
|
||||
@@ -120,11 +143,13 @@ feature -- Execution
|
||||
do
|
||||
cfg.set_is_verbose (verbose)
|
||||
cfg.set_verbose_level (verbose_level)
|
||||
cfg.set_ssl_settings (ssl_settings)
|
||||
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_socket_recv_timeout (socket_recv_timeout)
|
||||
cfg.set_keep_alive_timeout (keep_alive_timeout)
|
||||
cfg.set_max_keep_alive_requests (max_keep_alive_requests)
|
||||
end
|
||||
@@ -140,11 +165,17 @@ feature -- Execution
|
||||
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
|
||||
io.error.put_string ("%N http://" + l_name + ":" + port_number.out + "/" + base_url + "%N")
|
||||
if ssl_enabled then
|
||||
io.error.put_string ("%N https://")
|
||||
else
|
||||
io.error.put_string ("%N http://localhost:" + port_number.out + "/" + base_url + "%N")
|
||||
io.error.put_string ("%N http://")
|
||||
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
|
||||
update_configuration (conn.configuration)
|
||||
@@ -177,9 +208,18 @@ feature {NONE} -- Implementation
|
||||
-- Help defining the verbosity.
|
||||
-- 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_tcp_clients: INTEGER
|
||||
socket_timeout: INTEGER
|
||||
socket_recv_timeout: INTEGER
|
||||
keep_alive_timeout: INTEGER
|
||||
max_keep_alive_requests: INTEGER
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ note
|
||||
For instance, you can use
|
||||
create s.make_and_launch_and_options (agent execute, <<["port", 8099]>>)
|
||||
|
||||
And if Nino is the default connector it will support:
|
||||
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")
|
||||
base: base_url (very specific to standalone server)
|
||||
force_single_threaded: use only one thread, useful for Nino
|
||||
verbose: to display verbose output, useful for Nino
|
||||
verbose: to display verbose output.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
@@ -8,8 +8,8 @@ note
|
||||
force_single_threaded: use only one thread, useful for Nino
|
||||
verbose: to display verbose output, useful for Nino
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
|
||||
revision: "$Revision: 99106 $"
|
||||
|
||||
class
|
||||
WSF_SERVICE_LAUNCHER_OPTIONS
|
||||
@@ -85,6 +85,12 @@ feature -- Access
|
||||
|
||||
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
|
||||
-- Is there any INTEGER value associated to option name `a_opt_name'?
|
||||
local
|
||||
@@ -100,6 +106,29 @@ feature -- Helpers
|
||||
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
|
||||
-- INTEGER value associated to option name `a_opt_name', other return `a_default'.
|
||||
local
|
||||
|
||||
Reference in New Issue
Block a user