Moved httpd library from ewsgi/connectors/standalone/lib/httpd to httpd.
Reused the http_network library as well inside httpd library.
This commit is contained in:
377
library/server/httpd/httpd_server_i.e
Normal file
377
library/server/httpd/httpd_server_i.e
Normal file
@@ -0,0 +1,377 @@
|
||||
note
|
||||
description: "HTTPD server interface"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_SERVER_I
|
||||
|
||||
inherit
|
||||
HTTPD_DEBUG_FACILITIES
|
||||
|
||||
HTTPD_LOGGER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_factory: like factory)
|
||||
-- Create current httpd server with `a_factory' of connection handlers.
|
||||
-- `a_factory': connection handler builder
|
||||
require
|
||||
a_factory_is_separated: {PLATFORM}.is_scoop_capable implies not attached {HTTPD_REQUEST_HANDLER_FACTORY} a_factory
|
||||
do
|
||||
make_configured (create {like configuration}.make, a_factory)
|
||||
end
|
||||
|
||||
make_configured (a_cfg: like configuration; a_factory: like factory)
|
||||
-- `a_cfg': server configuration
|
||||
-- `a_factory': connection handler builder
|
||||
do
|
||||
configuration := a_cfg
|
||||
factory := a_factory
|
||||
|
||||
build_controller
|
||||
|
||||
initialize
|
||||
end
|
||||
|
||||
build_controller
|
||||
-- Build `controller'.
|
||||
do
|
||||
create <NONE> controller
|
||||
end
|
||||
|
||||
initialize
|
||||
-- Initialize Current server.
|
||||
do
|
||||
is_shutdown_requested := False
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_verbose: BOOLEAN
|
||||
-- Is verbose for output messages.
|
||||
|
||||
verbose_level: INTEGER
|
||||
-- Verbosity of output.
|
||||
|
||||
configuration: HTTPD_CONFIGURATION
|
||||
-- Associated server configuration.
|
||||
|
||||
controller: separate HTTPD_CONTROLLER
|
||||
|
||||
factory: separate HTTPD_REQUEST_HANDLER_FACTORY
|
||||
|
||||
is_persistent_connection_supported: BOOLEAN = True
|
||||
-- Is persistent connection supported?
|
||||
|
||||
feature -- Callbacks
|
||||
|
||||
observer: detachable separate HTTPD_SERVER_OBSERVER
|
||||
|
||||
set_observer (obs: like observer)
|
||||
-- Set `observer' to `obs'.
|
||||
do
|
||||
observer := obs
|
||||
end
|
||||
|
||||
feature -- Access: listening
|
||||
|
||||
port: INTEGER
|
||||
-- Effective listening port.
|
||||
--| If 0 then it is not launched successfully!
|
||||
|
||||
feature -- Status: listening
|
||||
|
||||
is_launched: BOOLEAN
|
||||
-- Server launched and listening on `port'
|
||||
|
||||
is_terminated: BOOLEAN
|
||||
-- Is terminated?
|
||||
|
||||
is_shutdown_requested: BOOLEAN
|
||||
-- Set true to stop accept loop
|
||||
|
||||
feature {NONE} -- Access: server
|
||||
|
||||
request_counter: INTEGER
|
||||
-- request counter, incremented for each new incoming connection.
|
||||
|
||||
feature -- Execution
|
||||
|
||||
launch
|
||||
do
|
||||
apply_configuration
|
||||
is_terminated := False
|
||||
if is_verbose then
|
||||
log ("%N%NStarting Web Application Server ...")
|
||||
log (" - port = " + configuration.http_server_port.out)
|
||||
log (" - max_tcp_clients = " + configuration.max_tcp_clients.out)
|
||||
log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out)
|
||||
log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds")
|
||||
log (" - 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.has_ssl_support then
|
||||
if configuration.is_secure then
|
||||
log (" - SSL = enabled")
|
||||
else
|
||||
log (" - SSL = disabled")
|
||||
end
|
||||
else
|
||||
log (" - SSL = not supported")
|
||||
end
|
||||
if configuration.verbose_level > 0 then
|
||||
log (" - verbose_level = " + configuration.verbose_level.out)
|
||||
end
|
||||
end
|
||||
is_shutdown_requested := False
|
||||
listen
|
||||
is_terminated := True
|
||||
on_terminated
|
||||
end
|
||||
|
||||
shutdown_server
|
||||
do
|
||||
debug ("dbglog")
|
||||
dbglog ("Shutdown requested")
|
||||
end
|
||||
is_shutdown_requested := True
|
||||
controller_shutdown (controller)
|
||||
end
|
||||
|
||||
controller_shutdown (ctl: attached like controller)
|
||||
do
|
||||
ctl.shutdown
|
||||
end
|
||||
|
||||
feature -- Listening
|
||||
|
||||
listen
|
||||
-- <Precursor>
|
||||
-- Creates a socket and connects to the http server.
|
||||
-- `a_server': The main server object
|
||||
local
|
||||
l_listening_socket: detachable HTTPD_STREAM_SOCKET
|
||||
l_http_port: INTEGER
|
||||
l_connection_handler: HTTPD_CONNECTION_HANDLER
|
||||
do
|
||||
is_terminated := False
|
||||
is_launched := False
|
||||
port := 0
|
||||
is_shutdown_requested := False
|
||||
l_http_port := configuration.http_server_port
|
||||
|
||||
if
|
||||
attached configuration.http_server_name as l_servername and then
|
||||
attached (create {INET_ADDRESS_FACTORY}).create_from_name (l_servername) as l_addr
|
||||
then
|
||||
l_listening_socket := new_listening_socket (l_addr, l_http_port)
|
||||
else
|
||||
l_listening_socket := new_listening_socket (Void, l_http_port)
|
||||
end
|
||||
|
||||
if not l_listening_socket.is_bound then
|
||||
if is_verbose then
|
||||
log ("Socket could not be bound on port " + l_http_port.out + " !")
|
||||
end
|
||||
else
|
||||
l_http_port := l_listening_socket.port
|
||||
create l_connection_handler.make (Current)
|
||||
from
|
||||
l_listening_socket.listen (configuration.max_tcp_clients)
|
||||
if is_verbose then
|
||||
if configuration.is_secure then
|
||||
log ("%NListening on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/")
|
||||
else
|
||||
log ("%NListening on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/")
|
||||
end
|
||||
end
|
||||
on_launched (l_http_port)
|
||||
until
|
||||
is_shutdown_requested
|
||||
loop
|
||||
request_counter := request_counter + 1
|
||||
if is_verbose then
|
||||
log ("#" + request_counter.out + "# Waiting connection...(listening socket:" + l_listening_socket.descriptor.out + ")")
|
||||
end
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".before process_waiting_incoming_connection")
|
||||
end
|
||||
l_connection_handler.accept_incoming_connection (l_listening_socket)
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".after process_waiting_incoming_connection")
|
||||
end
|
||||
|
||||
update_is_shutdown_requested (l_connection_handler)
|
||||
end
|
||||
wait_for_connection_handler_completion (l_connection_handler)
|
||||
l_listening_socket.cleanup
|
||||
check
|
||||
socket_is_closed: l_listening_socket.is_closed
|
||||
end
|
||||
end
|
||||
if is_launched then
|
||||
on_stopped
|
||||
end
|
||||
if is_verbose then
|
||||
log ("HTTP Connection Server ends.")
|
||||
end
|
||||
rescue
|
||||
log ("HTTP Connection Server shutdown due to exception. Please relaunch manually.")
|
||||
|
||||
if l_listening_socket /= Void then
|
||||
l_listening_socket.cleanup
|
||||
check
|
||||
listening_socket_is_closed: l_listening_socket.is_closed
|
||||
end
|
||||
end
|
||||
if is_launched then
|
||||
on_stopped
|
||||
end
|
||||
is_shutdown_requested := True
|
||||
retry
|
||||
end
|
||||
|
||||
feature {NONE} -- Factory
|
||||
|
||||
new_listening_socket (a_addr: detachable INET_ADDRESS; a_http_port: INTEGER): HTTPD_STREAM_SOCKET
|
||||
do
|
||||
if a_addr /= Void then
|
||||
create Result.make_server_by_address_and_port (a_addr, a_http_port)
|
||||
else
|
||||
create Result.make_server_by_port (a_http_port)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
wait_for_connection_handler_completion (h: HTTPD_CONNECTION_HANDLER)
|
||||
do
|
||||
h.wait_for_completion
|
||||
debug ("dbglog")
|
||||
dbglog ("Shutdown ready from connection_handler point of view")
|
||||
end
|
||||
end
|
||||
|
||||
update_is_shutdown_requested (a_connection_handler: HTTPD_CONNECTION_HANDLER)
|
||||
do
|
||||
is_shutdown_requested := is_shutdown_requested or shutdown_requested (controller)
|
||||
if is_shutdown_requested then
|
||||
a_connection_handler.shutdown
|
||||
end
|
||||
end
|
||||
|
||||
shutdown_requested (a_controller: separate HTTPD_CONTROLLER): BOOLEAN
|
||||
-- Shutdown requested on concurrent `a_controller'?
|
||||
do
|
||||
Result := a_controller.shutdown_requested
|
||||
end
|
||||
|
||||
feature -- Event
|
||||
|
||||
on_launched (a_port: INTEGER)
|
||||
-- Server launched using port `a_port'
|
||||
require
|
||||
not_launched: not is_launched
|
||||
do
|
||||
is_launched := True
|
||||
port := a_port
|
||||
if attached observer as obs then
|
||||
observer_on_launched (obs, a_port)
|
||||
end
|
||||
ensure
|
||||
is_launched: is_launched
|
||||
end
|
||||
|
||||
on_stopped
|
||||
-- Server stopped
|
||||
require
|
||||
is_launched: is_launched
|
||||
do
|
||||
if attached observer as obs then
|
||||
observer_on_stopped (obs)
|
||||
end
|
||||
end
|
||||
|
||||
on_terminated
|
||||
-- Server terminated
|
||||
require
|
||||
is_terminated
|
||||
do
|
||||
if is_terminated and is_verbose then
|
||||
log ("%N%NTerminating Web Application Server (port="+ port.out +"):%N")
|
||||
end
|
||||
if attached output as o then
|
||||
o.flush
|
||||
o.close
|
||||
end
|
||||
if attached observer as obs then
|
||||
observer_on_terminated (obs)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Separate event
|
||||
|
||||
observer_on_launched (obs: attached like observer; a_port: INTEGER)
|
||||
do
|
||||
obs.on_launched (a_port)
|
||||
end
|
||||
|
||||
observer_on_stopped (obs: attached like observer)
|
||||
do
|
||||
obs.on_stopped
|
||||
end
|
||||
|
||||
observer_on_terminated (obs: attached like observer)
|
||||
do
|
||||
obs.on_terminated
|
||||
end
|
||||
|
||||
feature -- Configuration change
|
||||
|
||||
apply_configuration
|
||||
require
|
||||
is_not_launched: not is_launched
|
||||
do
|
||||
is_verbose := configuration.is_verbose
|
||||
verbose_level := configuration.verbose_level
|
||||
end
|
||||
|
||||
feature -- Output
|
||||
|
||||
output: detachable FILE
|
||||
|
||||
set_log_output (f: FILE)
|
||||
-- Set `output' to `f'.
|
||||
do
|
||||
output := f
|
||||
ensure
|
||||
output_set: output = f
|
||||
end
|
||||
|
||||
log (a_message: separate READABLE_STRING_8)
|
||||
-- Log `a_message'.
|
||||
local
|
||||
m: STRING
|
||||
do
|
||||
create m.make_from_separate (a_message)
|
||||
if attached output as o then
|
||||
o.put_string (m)
|
||||
o.put_new_line
|
||||
else
|
||||
io.error.put_string (m)
|
||||
io.error.put_new_line
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
Reference in New Issue
Block a user