Compare commits
14 Commits
net_noexce
...
es_rev9929
| Author | SHA1 | Date | |
|---|---|---|---|
| d28f794828 | |||
| 9e92b8c0fa | |||
| ef704790a8 | |||
| 57b1691243 | |||
| 29590b1c0d | |||
| ed959042d7 | |||
| 1170417e54 | |||
| 2cfe00e61b | |||
| a498a167ed | |||
| f12158e535 | |||
| 080881368a | |||
|
|
3e935c7e33 | ||
|
|
ad2bb0d1a7 | ||
| 7a546622bc |
@@ -17,10 +17,21 @@ create
|
|||||||
make_server_by_port
|
make_server_by_port
|
||||||
|
|
||||||
create {NETWORK_STREAM_SOCKET}
|
create {NETWORK_STREAM_SOCKET}
|
||||||
make_from_descriptor_and_address
|
make_from_descriptor_and_address,
|
||||||
|
make_empty
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make_server_by_address_and_port (a_address: INET_ADDRESS; a_port: INTEGER)
|
||||||
|
-- Create server socket on `a_address' and `a_port'.
|
||||||
|
require
|
||||||
|
valid_port: a_port >= 0
|
||||||
|
do
|
||||||
|
make
|
||||||
|
create address.make_from_address_and_port (a_address, a_port)
|
||||||
|
bind
|
||||||
|
end
|
||||||
|
|
||||||
make
|
make
|
||||||
-- Create a network stream socket.
|
-- Create a network stream socket.
|
||||||
do
|
do
|
||||||
@@ -28,16 +39,6 @@ feature {NONE} -- Initialization
|
|||||||
set_reuse_address
|
set_reuse_address
|
||||||
end
|
end
|
||||||
|
|
||||||
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
|
|
||||||
-- Create server socket on `an_address' and `a_port'.
|
|
||||||
require
|
|
||||||
valid_port: a_port >= 0
|
|
||||||
do
|
|
||||||
make
|
|
||||||
create address.make_from_address_and_port (an_address, a_port)
|
|
||||||
bind
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Basic operation
|
feature -- Basic operation
|
||||||
|
|
||||||
send_message (a_msg: STRING)
|
send_message (a_msg: STRING)
|
||||||
@@ -29,16 +29,6 @@ feature {NONE} -- Initialization
|
|||||||
set_reuse_address
|
set_reuse_address
|
||||||
end
|
end
|
||||||
|
|
||||||
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
|
|
||||||
-- Create server socket on `an_address' and `a_port'.
|
|
||||||
require
|
|
||||||
valid_port: a_port >= 0
|
|
||||||
do
|
|
||||||
make
|
|
||||||
create address.make_from_address_and_port (an_address, a_port)
|
|
||||||
bind
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Basic operation
|
feature -- Basic operation
|
||||||
|
|
||||||
send_message (a_msg: STRING)
|
send_message (a_msg: STRING)
|
||||||
|
|||||||
@@ -22,13 +22,13 @@
|
|||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>tcp_stream_socket.e</exclude>
|
<exclude>tcp_stream_socket.e</exclude>
|
||||||
<condition>
|
<condition>
|
||||||
<version type="compiler" max="15.01.9.6506"/>
|
<version type="compiler" max="16.11"/>
|
||||||
</condition>
|
</condition>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
</cluster>
|
</cluster>
|
||||||
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
|
<cluster name="spec_until_16_05" location=".\library\spec\until_16_05\" recursive="true">
|
||||||
<condition>
|
<condition>
|
||||||
<version type="compiler" max="15.01.9.6506"/>
|
<version type="compiler" max="16.11"/>
|
||||||
</condition>
|
</condition>
|
||||||
</cluster>
|
</cluster>
|
||||||
</target>
|
</target>
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="nino" uuid="32C1D67D-33DE-4F1E-864B-D45388F2E3E6" library_target="nino">
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="nino" uuid="32C1D67D-33DE-4F1E-864B-D45388F2E3E6" library_target="nino">
|
||||||
<target name="nino">
|
<target name="nino">
|
||||||
<root all_classes="true"/>
|
<root all_classes="true"/>
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>/.git$</exclude>
|
<exclude>/.git$</exclude>
|
||||||
<exclude>/EIFGENs$</exclude>
|
<exclude>/EIFGENs$</exclude>
|
||||||
<exclude>/CVS$</exclude>
|
<exclude>/CVS$</exclude>
|
||||||
<exclude>/.svn$</exclude>
|
<exclude>/.svn$</exclude>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<option warning="true" void_safety="none">
|
<option warning="true" void_safety="none">
|
||||||
<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="thread"/>
|
<setting name="concurrency" value="thread"/>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
|
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
|
||||||
<cluster name="nino" location=".\library\" recursive="true">
|
<cluster name="nino" location=".\library\" recursive="true">
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>spec</exclude>
|
<exclude>spec</exclude>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>tcp_stream_socket.e</exclude>
|
<exclude>tcp_stream_socket.e</exclude>
|
||||||
<condition>
|
<condition>
|
||||||
<version type="compiler" max="15.01.9.6506"/>
|
<version type="compiler" max="16.11"/>
|
||||||
</condition>
|
</condition>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
</cluster>
|
</cluster>
|
||||||
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
|
<cluster name="spec_until_16_05" location=".\library\spec\until_16_05\" recursive="true">
|
||||||
<condition>
|
<condition>
|
||||||
<version type="compiler" max="15.01.9.6506"/>
|
<version type="compiler" max="16.11"/>
|
||||||
</condition>
|
</condition>
|
||||||
</cluster>
|
</cluster>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ feature {NONE} -- Initialization
|
|||||||
-- set_service_option ("verbose", True)
|
-- set_service_option ("verbose", True)
|
||||||
set_service_option ("port", 9090)
|
set_service_option ("port", 9090)
|
||||||
-- set_service_option ("base", "/www-debug/debug_service.fcgi/")
|
-- set_service_option ("base", "/www-debug/debug_service.fcgi/")
|
||||||
|
import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("debug.ini"))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
-- execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="desktop_app" uuid="E015841A-D456-46E1-8A18-E0CEB9E69CD5">
|
<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="desktop_app" uuid="E015841A-D456-46E1-8A18-E0CEB9E69CD5">
|
||||||
<description>Vision2+web browser widget+embedded web service</description>
|
<description>Vision2+web browser widget+embedded web service</description>
|
||||||
<target name="desktop_app">
|
<target name="desktop_app">
|
||||||
<description>This example demonstrates how to build a vision2 desktop application that embed a web browser accessing the service of an embedded web service.</description>
|
<description>This example demonstrates how to build a vision2 desktop application that embed a web browser accessing the service of an embedded web service.</description>
|
||||||
<root class="DESKTOP_APP" feature="make_and_launch"/>
|
<root class="DESKTOP_APP" feature="make_and_launch"/>
|
||||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
|
<option warning="true" full_class_checking="true" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="transitional">
|
||||||
<assertions precondition="true" postcondition="true" check="true"/>
|
<assertions precondition="true" postcondition="true" check="true"/>
|
||||||
</option>
|
</option>
|
||||||
<setting name="concurrency" value="thread"/>
|
<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="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf"/>
|
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf"/>
|
||||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
<library name="wsf_standalone_connector" location="..\..\library\server\ewsgi\connectors\standalone\standalone-safe.ecf"/>
|
<library name="wsf_standalone_connector" location="..\..\library\server\ewsgi\connectors\standalone\standalone-safe.ecf"/>
|
||||||
<cluster name="src" location=".\src\" recursive="true">
|
<cluster name="src" location=".\src\" recursive="true">
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>/EIFGENs$</exclude>
|
|
||||||
<exclude>/CVS$</exclude>
|
|
||||||
<exclude>/.svn$</exclude>
|
<exclude>/.svn$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
</cluster>
|
</cluster>
|
||||||
</target>
|
</target>
|
||||||
|
|||||||
@@ -24,20 +24,25 @@ feature {NONE} -- Initialization
|
|||||||
-- then launch the application.
|
-- then launch the application.
|
||||||
local
|
local
|
||||||
l_win: like main_window
|
l_win: like main_window
|
||||||
l_embedded_service: APP_EMBEDDED_WEB_SERVICE
|
l_embedded_service: separate APP_EMBEDDED_WEB_SERVICE
|
||||||
do
|
do
|
||||||
default_create
|
default_create
|
||||||
create l_win.make
|
create l_win.make
|
||||||
main_window := l_win
|
main_window := l_win
|
||||||
l_win.show
|
l_win.show
|
||||||
create l_embedded_service.make
|
create l_embedded_service.make
|
||||||
l_embedded_service.set_port_number (0) -- Use first available port number
|
setup_and_launch_web_service (l_embedded_service)
|
||||||
|
|
||||||
l_embedded_service.on_launched_actions.force (agent on_web_service_launched (l_win, l_embedded_service))
|
|
||||||
l_embedded_service.launch
|
|
||||||
launch
|
launch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
setup_and_launch_web_service (a_web_service: separate APP_EMBEDDED_WEB_SERVICE)
|
||||||
|
do
|
||||||
|
a_web_service.set_port_number (0) -- Use first available port number
|
||||||
|
a_web_service.set_on_launched_action (agent on_web_service_launched (a_web_service))
|
||||||
|
a_web_service.launch
|
||||||
|
end
|
||||||
|
|
||||||
on_quit
|
on_quit
|
||||||
do
|
do
|
||||||
if attached main_window as win then
|
if attached main_window as win then
|
||||||
@@ -45,13 +50,15 @@ feature {NONE} -- Initialization
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
on_web_service_launched (a_win: attached like main_window; s: APP_EMBEDDED_WEB_SERVICE)
|
on_web_service_launched (a_web_service: separate APP_EMBEDDED_WEB_SERVICE)
|
||||||
do
|
do
|
||||||
add_idle_action_kamikaze (agent wait_for_termination (s, Void))
|
if attached main_window as win then
|
||||||
add_idle_action_kamikaze (agent a_win.open_link)
|
add_idle_action_kamikaze (agent wait_for_termination (a_web_service, Void))
|
||||||
|
add_idle_action_kamikaze (agent win.open_link)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wait_for_termination (s: APP_EMBEDDED_WEB_SERVICE; a_timeout: detachable EV_TIMEOUT)
|
wait_for_termination (a_web_service: separate APP_EMBEDDED_WEB_SERVICE; a_timeout: detachable EV_TIMEOUT)
|
||||||
local
|
local
|
||||||
t: detachable EV_TIMEOUT
|
t: detachable EV_TIMEOUT
|
||||||
do
|
do
|
||||||
@@ -60,7 +67,7 @@ feature {NONE} -- Initialization
|
|||||||
t.set_interval (0)
|
t.set_interval (0)
|
||||||
end
|
end
|
||||||
if
|
if
|
||||||
attached s.observer as obs and then
|
attached a_web_service.observer as obs and then
|
||||||
observer_has_terminaded (obs)
|
observer_has_terminaded (obs)
|
||||||
then
|
then
|
||||||
if t /= Void then
|
if t /= Void then
|
||||||
@@ -70,7 +77,7 @@ feature {NONE} -- Initialization
|
|||||||
else
|
else
|
||||||
if t = Void then
|
if t = Void then
|
||||||
create t
|
create t
|
||||||
t.actions.extend (agent wait_for_termination (s, t))
|
t.actions.extend (agent wait_for_termination (a_web_service, t))
|
||||||
else
|
else
|
||||||
t.set_interval (1_000)
|
t.set_interval (1_000)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,19 +17,21 @@ inherit
|
|||||||
|
|
||||||
feature {NONE} -- Execution
|
feature {NONE} -- Execution
|
||||||
|
|
||||||
execute_embedded
|
execute_embedded
|
||||||
-- Execute the request
|
-- Execute the request
|
||||||
-- See `request.input' for input stream
|
-- See `request.input' for input stream
|
||||||
-- `request.meta_variables' for the CGI meta variable
|
-- `request.meta_variables' for the CGI meta variable
|
||||||
-- and `response' for output buffer
|
-- and `response' for output buffer
|
||||||
local
|
local
|
||||||
filter: WSF_AGENT_FILTER
|
|
||||||
m: WSF_PAGE_RESPONSE
|
m: WSF_PAGE_RESPONSE
|
||||||
do
|
do
|
||||||
if local_connection_restriction_enabled then
|
if local_connection_restriction_enabled then
|
||||||
if
|
if
|
||||||
attached request.remote_addr as l_remote_addr and then
|
attached request.remote_addr as l_remote_addr and then
|
||||||
l_remote_addr.is_case_insensitive_equal_general ("127.0.0.1")
|
(
|
||||||
|
l_remote_addr.is_case_insensitive_equal_general ("127.0.0.1")
|
||||||
|
or else l_remote_addr.is_case_insensitive_equal_general ("localhost")
|
||||||
|
)
|
||||||
then
|
then
|
||||||
execute
|
execute
|
||||||
else
|
else
|
||||||
@@ -41,7 +43,7 @@ feature {NONE} -- Execution
|
|||||||
execute
|
execute
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
execute
|
execute
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ feature -- Initialization
|
|||||||
|
|
||||||
make
|
make
|
||||||
do
|
do
|
||||||
create on_launched_actions
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Execution
|
feature -- Execution
|
||||||
@@ -27,7 +26,6 @@ feature -- Execution
|
|||||||
opts: WSF_SERVICE_LAUNCHER_OPTIONS
|
opts: WSF_SERVICE_LAUNCHER_OPTIONS
|
||||||
do
|
do
|
||||||
create opts.default_create
|
create opts.default_create
|
||||||
opts.set_verbose (True)
|
|
||||||
opts.set_option ("port", port_number)
|
opts.set_option ("port", port_number)
|
||||||
create launcher.make (opts)
|
create launcher.make (opts)
|
||||||
observer := launcher.connector.observer
|
observer := launcher.connector.observer
|
||||||
@@ -40,11 +38,23 @@ feature -- Execution
|
|||||||
on_launched (conn: WGI_STANDALONE_CONNECTOR [G])
|
on_launched (conn: WGI_STANDALONE_CONNECTOR [G])
|
||||||
do
|
do
|
||||||
set_port_number (conn.port)
|
set_port_number (conn.port)
|
||||||
on_launched_actions.call (Void)
|
if attached on_launched_action as act then
|
||||||
|
call_action (act)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
call_action (act: attached like on_launched_action)
|
||||||
|
do
|
||||||
|
act.call (Void)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
on_launched_actions: ACTION_SEQUENCE [TUPLE]
|
on_launched_action: detachable separate PROCEDURE [ANY, TUPLE]
|
||||||
|
|
||||||
|
set_on_launched_action (act: like on_launched_action)
|
||||||
|
do
|
||||||
|
on_launched_action := act
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,10 +20,13 @@
|
|||||||
</target>
|
</target>
|
||||||
<target name="upload_image_standalone" extends="upload_image_common">
|
<target name="upload_image_standalone" extends="upload_image_common">
|
||||||
<root class="IMAGE_UPLOADER" feature="make"/>
|
<root class="IMAGE_UPLOADER" feature="make"/>
|
||||||
<setting name="concurrency" value="thread"/>
|
<setting name="concurrency" value="scoop"/>
|
||||||
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf" readonly="false" use_application_options="true"/>
|
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf" readonly="false" use_application_options="true"/>
|
||||||
<cluster name="src" location="src\" recursive="true"/>
|
<cluster name="src" location="src\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
|
<target name="upload_image_standalone_st" extends="upload_image_standalone">
|
||||||
|
<setting name="concurrency" value="none"/>
|
||||||
|
</target>
|
||||||
<target name="upload_image_libfcgi" extends="upload_image_common">
|
<target name="upload_image_libfcgi" extends="upload_image_common">
|
||||||
<root class="IMAGE_UPLOADER" feature="make"/>
|
<root class="IMAGE_UPLOADER" feature="make"/>
|
||||||
<setting name="concurrency" value="none"/>
|
<setting name="concurrency" value="none"/>
|
||||||
|
|||||||
@@ -164,11 +164,24 @@ feature -- Settings
|
|||||||
Result := session.ignore_content_length
|
Result := session.ignore_content_length
|
||||||
end
|
end
|
||||||
|
|
||||||
buffer_size: NATURAL
|
buffer_size: INTEGER
|
||||||
-- Set the buffer size for request. This option will
|
-- Buffer size for request,
|
||||||
-- only be set if buffer_size is positive
|
-- initialized from the session buffer_size value, or default 2_048.
|
||||||
do
|
do
|
||||||
Result := session.buffer_size
|
Result := session.buffer_size.to_integer_32
|
||||||
|
if Result <= 0 then
|
||||||
|
Result := 2_048
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
chunk_size: INTEGER
|
||||||
|
-- Chunk size for request, when "Transfer-Encoding: chunked"
|
||||||
|
-- initialized from the session buffer_size value, or default 2_048.
|
||||||
|
do
|
||||||
|
Result := session.chunk_size.to_integer_32
|
||||||
|
if Result <= 0 then
|
||||||
|
Result := 2_048
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
default_response_charset: detachable READABLE_STRING_8
|
default_response_charset: detachable READABLE_STRING_8
|
||||||
@@ -249,7 +262,7 @@ feature {NONE} -- Utilities: encoding
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -243,9 +243,13 @@ feature -- Settings
|
|||||||
ignore_content_length: BOOLEAN
|
ignore_content_length: BOOLEAN
|
||||||
-- Does this session ignore Content-Size headers?
|
-- Does this session ignore Content-Size headers?
|
||||||
|
|
||||||
buffer_size: NATURAL
|
buffer_size: NATURAL assign set_buffer_size
|
||||||
-- Set the buffer size for request. This option will
|
-- Set the buffer size for request. This option will
|
||||||
-- only be set if buffer_size is positive
|
-- only be set if buffer_size > 0.
|
||||||
|
|
||||||
|
chunk_size: NATURAL assign set_chunk_size
|
||||||
|
-- Set the chunk size for request, when "Transfer-Encoding: chunked".
|
||||||
|
-- This option will only be set if chunk_size > 0.
|
||||||
|
|
||||||
default_response_charset: detachable READABLE_STRING_8
|
default_response_charset: detachable READABLE_STRING_8
|
||||||
-- Default encoding of responses. Used if no charset is provided by the host.
|
-- Default encoding of responses. Used if no charset is provided by the host.
|
||||||
@@ -405,8 +409,18 @@ feature -- Element change
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
set_buffer_size (a_size: like buffer_size)
|
||||||
|
do
|
||||||
|
buffer_size := a_size
|
||||||
|
end
|
||||||
|
|
||||||
|
set_chunk_size (a_size: like chunk_size)
|
||||||
|
do
|
||||||
|
chunk_size := a_size
|
||||||
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ feature -- Access
|
|||||||
l_boundary: READABLE_STRING_8
|
l_boundary: READABLE_STRING_8
|
||||||
l_is_http_1_0_request: BOOLEAN
|
l_is_http_1_0_request: BOOLEAN
|
||||||
l_is_keep_alive: BOOLEAN
|
l_is_keep_alive: BOOLEAN
|
||||||
|
l_is_chunked_transfer_encoding: BOOLEAN
|
||||||
retried: BOOLEAN
|
retried: BOOLEAN
|
||||||
do
|
do
|
||||||
if not retried then
|
if not retried then
|
||||||
@@ -179,6 +180,8 @@ feature -- Access
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle sending data
|
-- handle sending data
|
||||||
|
l_is_chunked_transfer_encoding := attached headers.item ("Transfer-Encoding") as l_transfer_encoding and then l_transfer_encoding.same_string ("chunked")
|
||||||
|
|
||||||
if ctx /= Void then
|
if ctx /= Void then
|
||||||
if ctx.has_upload_filename then
|
if ctx.has_upload_filename then
|
||||||
l_upload_filename := ctx.upload_filename
|
l_upload_filename := ctx.upload_filename
|
||||||
@@ -195,14 +198,21 @@ feature -- Access
|
|||||||
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
|
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
|
||||||
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
||||||
headers.force (l_upload_data.count.out, "Content-Length")
|
headers.force (l_upload_data.count.out, "Content-Length")
|
||||||
|
if l_is_chunked_transfer_encoding then
|
||||||
else
|
-- Discard chunked transfer encoding
|
||||||
|
headers.remove ("Transfer-Encoding")
|
||||||
|
l_is_chunked_transfer_encoding := False
|
||||||
|
end
|
||||||
|
elseif l_form_data /= Void then
|
||||||
-- create form using multipart/form-data encoding
|
-- create form using multipart/form-data encoding
|
||||||
l_boundary := new_mime_boundary
|
l_boundary := new_mime_boundary (l_form_data)
|
||||||
headers.extend ("multipart/form-data; boundary=" + l_boundary, "Content-Type")
|
headers.extend ("multipart/form-data; boundary=" + l_boundary, "Content-Type")
|
||||||
if l_form_data /= Void then
|
l_upload_data := form_date_and_uploaded_files_to_mime_string (l_form_data, l_upload_filename, l_boundary)
|
||||||
l_upload_data := form_date_and_uploaded_files_to_mime_string (l_form_data, l_upload_filename, l_boundary)
|
headers.extend (l_upload_data.count.out, "Content-Length")
|
||||||
headers.extend (l_upload_data.count.out, "Content-Length")
|
if l_is_chunked_transfer_encoding then
|
||||||
|
-- Discard chunked transfer encoding
|
||||||
|
headers.remove ("Transfer-Encoding")
|
||||||
|
l_is_chunked_transfer_encoding := False
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif l_upload_data /= Void then
|
elseif l_upload_data /= Void then
|
||||||
@@ -210,12 +220,16 @@ feature -- Access
|
|||||||
if not headers.has ("Content-Type") then
|
if not headers.has ("Content-Type") then
|
||||||
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
|
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
|
||||||
end
|
end
|
||||||
headers.extend (l_upload_data.count.out, "Content-Length")
|
if not l_is_chunked_transfer_encoding then
|
||||||
|
headers.extend (l_upload_data.count.out, "Content-Length")
|
||||||
|
end
|
||||||
elseif l_upload_filename /= Void then
|
elseif l_upload_filename /= Void then
|
||||||
check ctx.has_upload_filename end
|
check ctx.has_upload_filename end
|
||||||
create l_upload_file.make_with_name (l_upload_filename)
|
create l_upload_file.make_with_name (l_upload_filename)
|
||||||
if l_upload_file.exists and then l_upload_file.readable then
|
if l_upload_file.exists and then l_upload_file.readable then
|
||||||
headers.extend (l_upload_file.count.out, "Content-Length")
|
if not l_is_chunked_transfer_encoding then
|
||||||
|
headers.extend (l_upload_file.count.out, "Content-Length")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
check l_upload_file /= Void end
|
check l_upload_file /= Void end
|
||||||
end
|
end
|
||||||
@@ -289,12 +303,7 @@ feature -- Access
|
|||||||
--| End of client header.
|
--| End of client header.
|
||||||
s.append (Http_end_of_header_line)
|
s.append (Http_end_of_header_line)
|
||||||
|
|
||||||
if l_upload_data /= Void then
|
--| Note that any remaining data or file to upload will be done directly via the socket
|
||||||
s.append (l_upload_data)
|
|
||||||
s.append (http_end_of_header_line)
|
|
||||||
end
|
|
||||||
|
|
||||||
--| Note that any remaining file to upload will be done directly via the socket
|
|
||||||
--| to optimize memory usage
|
--| to optimize memory usage
|
||||||
|
|
||||||
|
|
||||||
@@ -315,9 +324,20 @@ feature -- Access
|
|||||||
end
|
end
|
||||||
l_socket.put_string (s)
|
l_socket.put_string (s)
|
||||||
--| Send remaining payload data, if needed.
|
--| Send remaining payload data, if needed.
|
||||||
|
if l_upload_data /= Void then
|
||||||
|
if l_is_chunked_transfer_encoding then
|
||||||
|
put_string_using_chunked_transfer_encoding (l_upload_data, chunk_size, l_socket)
|
||||||
|
else
|
||||||
|
l_socket.put_string (l_upload_data)
|
||||||
|
end
|
||||||
|
end
|
||||||
if l_upload_file /= Void then
|
if l_upload_file /= Void then
|
||||||
-- i.e: not yet processed
|
if l_is_chunked_transfer_encoding then
|
||||||
append_file_content_to_socket (l_upload_file, l_upload_file.count, l_socket)
|
-- i.e: not yet processed
|
||||||
|
append_file_content_to_socket_using_chunked_transfer_encoding (l_upload_file, l_upload_file.count, chunk_size, l_socket)
|
||||||
|
else
|
||||||
|
append_file_content_to_socket (l_upload_file, l_upload_file.count, l_socket)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--|-------------------------|--
|
--|-------------------------|--
|
||||||
@@ -498,8 +518,85 @@ feature {NONE} -- Helpers
|
|||||||
Result := utf.utf_32_string_to_utf_8_string_8 (s)
|
Result := utf.utf_32_string_to_utf_8_string_8 (s)
|
||||||
end
|
end
|
||||||
|
|
||||||
append_file_content_to_socket (a_file: FILE; a_len: INTEGER; a_output: NETWORK_STREAM_SOCKET)
|
put_string_using_chunked_transfer_encoding (a_string: READABLE_STRING_8; a_chunk_size: INTEGER; a_output: NETWORK_STREAM_SOCKET)
|
||||||
-- Append `a_file' content to `a_output'.
|
local
|
||||||
|
i,n: INTEGER
|
||||||
|
do
|
||||||
|
from
|
||||||
|
i := 1
|
||||||
|
n := a_string.count
|
||||||
|
until
|
||||||
|
i > n
|
||||||
|
loop
|
||||||
|
put_chunk (a_string.substring (i, i + a_chunk_size), Void, a_output)
|
||||||
|
i := i + a_chunk_size
|
||||||
|
end
|
||||||
|
put_chunk_end (Void, Void, a_output)
|
||||||
|
end
|
||||||
|
|
||||||
|
put_chunk (a_content: READABLE_STRING_8; a_ext: detachable READABLE_STRING_8; a_output: NETWORK_STREAM_SOCKET)
|
||||||
|
-- Write chunk non empty `a_content' to `a_output'
|
||||||
|
-- with optional extension `a_ext': chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
||||||
|
-- Note: that header "Transfer-Encoding: chunked" is required.
|
||||||
|
require
|
||||||
|
a_content_not_empty: a_content /= Void and then not a_content.is_empty
|
||||||
|
valid_chunk_extension: (a_ext /= Void and then not a_ext.is_empty) implies
|
||||||
|
( a_ext.starts_with (";") and not a_ext.has ('%N') and not not a_ext.has ('%R') )
|
||||||
|
local
|
||||||
|
l_chunk_size_line: STRING_8
|
||||||
|
i: INTEGER
|
||||||
|
do
|
||||||
|
--| Remove all left '0'
|
||||||
|
l_chunk_size_line := a_content.count.to_hex_string
|
||||||
|
from
|
||||||
|
i := 1
|
||||||
|
until
|
||||||
|
l_chunk_size_line[i] /= '0'
|
||||||
|
loop
|
||||||
|
i := i + 1
|
||||||
|
end
|
||||||
|
if i > 1 then
|
||||||
|
l_chunk_size_line := l_chunk_size_line.substring (i, l_chunk_size_line.count)
|
||||||
|
end
|
||||||
|
|
||||||
|
if a_ext /= Void then
|
||||||
|
l_chunk_size_line.append (a_ext)
|
||||||
|
end
|
||||||
|
l_chunk_size_line.append (crlf)
|
||||||
|
|
||||||
|
a_output.put_string (l_chunk_size_line)
|
||||||
|
a_output.put_string (a_content)
|
||||||
|
a_output.put_string (crlf)
|
||||||
|
end
|
||||||
|
|
||||||
|
put_chunk_end (a_ext: detachable READABLE_STRING_8; a_trailer: detachable READABLE_STRING_8; a_output: NETWORK_STREAM_SOCKET)
|
||||||
|
-- Put end of chunked content,
|
||||||
|
-- with optional extension `a_ext': chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
||||||
|
-- and with optional trailer `a_trailer' : trailer= *(entity-header CRLF)
|
||||||
|
local
|
||||||
|
l_chunk_size_line: STRING_8
|
||||||
|
do
|
||||||
|
-- Chunk end
|
||||||
|
create l_chunk_size_line.make (1)
|
||||||
|
l_chunk_size_line.append_integer (0)
|
||||||
|
|
||||||
|
if a_ext /= Void then
|
||||||
|
l_chunk_size_line.append (a_ext)
|
||||||
|
end
|
||||||
|
l_chunk_size_line.append (crlf)
|
||||||
|
a_output.put_string (l_chunk_size_line)
|
||||||
|
|
||||||
|
-- Optional trailer
|
||||||
|
if a_trailer /= Void and then not a_trailer.is_empty then
|
||||||
|
a_output.put_string (a_trailer)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Final CRLF
|
||||||
|
a_output.put_string (crlf)
|
||||||
|
end
|
||||||
|
|
||||||
|
append_file_content_to_socket_using_chunked_transfer_encoding (a_file: FILE; a_len: INTEGER; a_chunk_size: INTEGER; a_output: NETWORK_STREAM_SOCKET)
|
||||||
|
-- Append `a_file' content as chunks of `a_chunk_size' length to `a_output'.
|
||||||
-- If `a_len' >= 0 then read only `a_len' characters.
|
-- If `a_len' >= 0 then read only `a_len' characters.
|
||||||
require
|
require
|
||||||
a_file_readable: a_file.exists and then a_file.is_access_readable
|
a_file_readable: a_file.exists and then a_file.is_access_readable
|
||||||
@@ -523,7 +620,44 @@ feature {NONE} -- Helpers
|
|||||||
until
|
until
|
||||||
l_count = 0 or a_file.exhausted
|
l_count = 0 or a_file.exhausted
|
||||||
loop
|
loop
|
||||||
a_file.read_stream_thread_aware (l_count.min (2_048))
|
a_file.read_stream_thread_aware (l_count.min (a_chunk_size))
|
||||||
|
put_chunk (a_file.last_string, Void, a_output)
|
||||||
|
l_count := l_count - a_file.bytes_read
|
||||||
|
end
|
||||||
|
if not l_was_open then
|
||||||
|
a_file.close
|
||||||
|
end
|
||||||
|
put_chunk_end (Void, Void, a_output)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
append_file_content_to_socket (a_file: FILE; a_len: INTEGER; a_output: NETWORK_STREAM_SOCKET)
|
||||||
|
-- Append `a_file' content to `a_output'.
|
||||||
|
-- If `a_len' >= 0 then read only `a_len' characters.
|
||||||
|
require
|
||||||
|
a_file_readable: a_file.exists and then a_file.is_access_readable
|
||||||
|
local
|
||||||
|
l_was_open: BOOLEAN
|
||||||
|
l_count, l_buffer_size: INTEGER
|
||||||
|
do
|
||||||
|
if a_len >= 0 then
|
||||||
|
l_count := a_len
|
||||||
|
else
|
||||||
|
l_count := a_file.count
|
||||||
|
end
|
||||||
|
if l_count > 0 then
|
||||||
|
l_was_open := a_file.is_open_read
|
||||||
|
if a_file.is_open_read then
|
||||||
|
l_was_open := True
|
||||||
|
else
|
||||||
|
a_file.open_read
|
||||||
|
end
|
||||||
|
from
|
||||||
|
l_buffer_size := buffer_size
|
||||||
|
until
|
||||||
|
l_count = 0 or a_file.exhausted
|
||||||
|
loop
|
||||||
|
a_file.read_stream_thread_aware (l_count.min (l_buffer_size))
|
||||||
a_output.put_string (a_file.last_string)
|
a_output.put_string (a_file.last_string)
|
||||||
l_count := l_count - a_file.bytes_read
|
l_count := l_count - a_file.bytes_read
|
||||||
end
|
end
|
||||||
@@ -541,6 +675,7 @@ feature {NONE} -- Helpers
|
|||||||
local
|
local
|
||||||
l_was_open: BOOLEAN
|
l_was_open: BOOLEAN
|
||||||
l_count: INTEGER
|
l_count: INTEGER
|
||||||
|
l_buffer_size: INTEGER
|
||||||
do
|
do
|
||||||
if a_len >= 0 then
|
if a_len >= 0 then
|
||||||
l_count := a_len
|
l_count := a_len
|
||||||
@@ -555,11 +690,11 @@ feature {NONE} -- Helpers
|
|||||||
a_file.open_read
|
a_file.open_read
|
||||||
end
|
end
|
||||||
from
|
from
|
||||||
|
l_buffer_size := buffer_size
|
||||||
until
|
until
|
||||||
l_count = 0 or a_file.exhausted
|
l_count = 0 or a_file.exhausted
|
||||||
loop
|
loop
|
||||||
a_file.read_stream_thread_aware (l_count.min (2_048))
|
a_file.read_stream_thread_aware (l_count.min (l_buffer_size))
|
||||||
a_output.append (a_file.last_string)
|
a_output.append (a_file.last_string)
|
||||||
l_count := l_count - a_file.bytes_read
|
l_count := l_count - a_file.bytes_read
|
||||||
end
|
end
|
||||||
@@ -632,7 +767,7 @@ feature {NONE} -- Helpers
|
|||||||
-- FIXME: check solution!
|
-- FIXME: check solution!
|
||||||
from
|
from
|
||||||
l_count := 0
|
l_count := 0
|
||||||
l_chunk_size := 1_024
|
l_chunk_size := buffer_size
|
||||||
n := l_chunk_size --| value to satisfy until condition on first loop.
|
n := l_chunk_size --| value to satisfy until condition on first loop.
|
||||||
until
|
until
|
||||||
n < l_chunk_size or not a_socket.readable
|
n < l_chunk_size or not a_socket.readable
|
||||||
@@ -718,16 +853,42 @@ feature {NONE} -- Helpers
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
new_mime_boundary: STRING
|
new_mime_boundary (a_data: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]): STRING
|
||||||
-- New MIME boundary.
|
-- New MIME boundary.
|
||||||
|
local
|
||||||
|
s: STRING
|
||||||
|
ran: RANDOM
|
||||||
|
n: INTEGER
|
||||||
|
i,j: INTEGER
|
||||||
do
|
do
|
||||||
-- FIXME: better boundary creation
|
across
|
||||||
Result := "----------------------------5eadfcf3bb3e"
|
a_data as ic
|
||||||
|
loop
|
||||||
|
i := i + ic.item.count + ic.key.count
|
||||||
|
end
|
||||||
|
create ran.set_seed (i) -- FIXME: use a real random seed.
|
||||||
|
ran.start
|
||||||
|
ran.forth
|
||||||
|
n := (20 * ran.real_item).truncated_to_integer
|
||||||
|
create Result.make_filled ('-', 3 + n)
|
||||||
|
s := "_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
from
|
||||||
|
until
|
||||||
|
Result.count >= 40
|
||||||
|
loop
|
||||||
|
ran.forth
|
||||||
|
j := (ran.real_item * s.count).truncated_to_integer.max (1)
|
||||||
|
Result.append_character (s[j])
|
||||||
|
end
|
||||||
|
check Result.count = 40 and Result.starts_with ("---") end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
crlf: STRING = "%R%N"
|
||||||
|
-- CR and NL sequence.
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -64,4 +64,9 @@ feature -- Tests
|
|||||||
test_get_with_authentication
|
test_get_with_authentication
|
||||||
end
|
end
|
||||||
|
|
||||||
|
net_test_post_with_file_using_chunked_transfer_encoding
|
||||||
|
do
|
||||||
|
test_post_with_file_using_chunked_transfer_encoding
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -253,6 +253,38 @@ feature -- Factory
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test_post_with_file_using_chunked_transfer_encoding
|
||||||
|
local
|
||||||
|
sess: HTTP_CLIENT_SESSION
|
||||||
|
h: STRING_8
|
||||||
|
l_ctx: HTTP_CLIENT_REQUEST_CONTEXT
|
||||||
|
do
|
||||||
|
if attached global_requestbin_path as requestbin_path then
|
||||||
|
|
||||||
|
-- POST REQUEST WITH A FILE AND FORM DATA
|
||||||
|
-- check requestbin to ensure the file and form parameters are correctly received
|
||||||
|
-- set filename to a local file
|
||||||
|
sess := new_session ("http://requestb.in")
|
||||||
|
create l_ctx.make
|
||||||
|
l_ctx.add_header ("Transfer-Encoding", "chunked")
|
||||||
|
l_ctx.set_upload_filename ("logo.jpg")
|
||||||
|
create h.make_empty
|
||||||
|
if
|
||||||
|
attached sess.post (requestbin_path, l_ctx, Void) as res and then
|
||||||
|
attached res.headers as hds
|
||||||
|
then
|
||||||
|
across
|
||||||
|
hds as c
|
||||||
|
loop
|
||||||
|
h.append (c.item.name + ": " + c.item.value + "%R%N")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print (h)
|
||||||
|
else
|
||||||
|
assert ("Has requestbin path", False)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test_get_with_redirection
|
test_get_with_redirection
|
||||||
local
|
local
|
||||||
sess: HTTP_CLIENT_SESSION
|
sess: HTTP_CLIENT_SESSION
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="demo" uuid="DC4D6549-D5F4-4E1A-959A-6BD536737A21" library_target="demo">
|
<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="demo" uuid="DC4D6549-D5F4-4E1A-959A-6BD536737A21" library_target="demo">
|
||||||
<target name="demo">
|
<target name="demo">
|
||||||
<root class="APPLICATION" feature="make_and_launch"/>
|
<root class="APPLICATION" feature="make_and_launch"/>
|
||||||
<file_rule>
|
<file_rule>
|
||||||
@@ -7,9 +7,10 @@
|
|||||||
<exclude>/CVS$</exclude>
|
<exclude>/CVS$</exclude>
|
||||||
<exclude>/EIFGENs$</exclude>
|
<exclude>/EIFGENs$</exclude>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<option concurrency="scoop" root_catcall_detection="none" root_concurrency="scoop" root_void_safety="all" warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="transitional">
|
<option warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="transitional">
|
||||||
<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="ewsgi" location="..\..\..\..\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
|
<library name="ewsgi" location="..\..\..\..\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
|
||||||
<library name="ewsgi_standalone_connector" location="..\..\..\..\server\ewsgi\connectors\standalone\standalone-safe.ecf" readonly="false"/>
|
<library name="ewsgi_standalone_connector" location="..\..\..\..\server\ewsgi\connectors\standalone\standalone-safe.ecf" readonly="false"/>
|
||||||
@@ -20,6 +21,6 @@
|
|||||||
<cluster name="src" location=".\" recursive="true"/>
|
<cluster name="src" location=".\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
<target name="demo_mt" extends="demo">
|
<target name="demo_mt" extends="demo">
|
||||||
<option concurrency="thread" />
|
<setting name="concurrency" value="thread"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
reset
|
reset
|
||||||
do
|
do
|
||||||
reset_request
|
reset_request (False)
|
||||||
|
|
||||||
reset_error
|
reset_error
|
||||||
if attached internal_client_socket as l_sock then
|
if attached internal_client_socket as l_sock then
|
||||||
@@ -40,10 +40,18 @@ feature {NONE} -- Initialization
|
|||||||
internal_client_socket := Void
|
internal_client_socket := Void
|
||||||
end
|
end
|
||||||
|
|
||||||
reset_request
|
reset_request (a_is_reusing_connection: BOOLEAN)
|
||||||
|
-- Reset the request, and `a_is_reusing_connection' says if the peristent connection is
|
||||||
|
-- still alive.
|
||||||
do
|
do
|
||||||
|
if a_is_reusing_connection then
|
||||||
|
-- Keep `remote_info' as it stays the same for the successive
|
||||||
|
-- persistent connections.
|
||||||
|
else
|
||||||
|
remote_info := Void
|
||||||
|
end
|
||||||
|
|
||||||
version := Void
|
version := Void
|
||||||
remote_info := Void
|
|
||||||
|
|
||||||
-- FIXME: optimize to just wipe_out if needed
|
-- FIXME: optimize to just wipe_out if needed
|
||||||
create method.make_empty
|
create method.make_empty
|
||||||
@@ -247,7 +255,7 @@ feature -- Execution
|
|||||||
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 (not l_exit)
|
||||||
end
|
end
|
||||||
if l_exit and has_error and not l_socket.is_closed then
|
if l_exit and has_error and not l_socket.is_closed then
|
||||||
l_socket.close
|
l_socket.close
|
||||||
@@ -261,6 +269,7 @@ feature -- Execution
|
|||||||
is_connected: is_connected
|
is_connected: is_connected
|
||||||
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
|
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
|
||||||
no_error: not has_error
|
no_error: not has_error
|
||||||
|
remote_info_set: remote_info /= Void
|
||||||
local
|
local
|
||||||
l_socket: like client_socket
|
l_socket: like client_socket
|
||||||
do
|
do
|
||||||
@@ -511,12 +520,12 @@ feature -- Parsing
|
|||||||
elseif a_socket.readable then
|
elseif a_socket.readable then
|
||||||
a_socket.read_line_noexception
|
a_socket.read_line_noexception
|
||||||
Result := a_socket.last_string
|
Result := a_socket.last_string
|
||||||
-- Do no check `socket_ok' before socket operation,
|
-- Do no check `was_error' before socket operation,
|
||||||
-- otherwise it may be False, due to error during other socket operation in same thread.
|
-- otherwise it may be False, due to error during other socket operation in same thread.
|
||||||
if not a_socket.socket_ok then
|
if a_socket.was_error then
|
||||||
report_error ("Socket error")
|
report_error ("Socket error")
|
||||||
if is_verbose then
|
if is_verbose then
|
||||||
log (request_header +"%N" + Result + "%N## socket_ok=False! ##", debug_level)
|
log (request_header +"%N" + Result + "%N## was_error=False! ##", debug_level)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ extern int setsockopt(int, int, int, char*, int);
|
|||||||
extern int recv(int, char *, int, int);
|
extern int recv(int, char *, int, int);
|
||||||
extern int send(int, char *, int, int);
|
extern int send(int, char *, int, int);
|
||||||
#else
|
#else
|
||||||
extern int setsockopt(int, int, int, (struct timeval*), int);
|
extern int setsockopt(int, int, int, const void*, socklen_t);
|
||||||
extern int recv(int, char *, int, int);
|
extern ssize_t recv(int, void *, size_t, int);
|
||||||
extern int send(int, char *, int, int);
|
extern ssize_t send(int, const void *, size_t, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ feature {NONE} -- Initialization
|
|||||||
make_with_base (a_base: detachable separate READABLE_STRING_8)
|
make_with_base (a_base: detachable separate READABLE_STRING_8)
|
||||||
-- Create current standalone connector with base url `a_base'
|
-- Create current standalone connector with base url `a_base'
|
||||||
require
|
require
|
||||||
a_base_starts_with_slash: a_base /= Void implies is_valid_base (a_base)
|
a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies is_valid_base (a_base)
|
||||||
do
|
do
|
||||||
make
|
make
|
||||||
set_base (a_base)
|
set_base (a_base)
|
||||||
@@ -181,6 +181,13 @@ feature -- Element change
|
|||||||
|
|
||||||
feature -- Server
|
feature -- Server
|
||||||
|
|
||||||
|
launch_on_port (a_port_number: INTEGER)
|
||||||
|
-- Launch server listening on port `a_port_number'.
|
||||||
|
do
|
||||||
|
set_port_number (a_port_number)
|
||||||
|
launch
|
||||||
|
end
|
||||||
|
|
||||||
launch
|
launch
|
||||||
-- Launch web server listening.
|
-- Launch web server listening.
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ feature -- Input
|
|||||||
src: like source
|
src: like source
|
||||||
do
|
do
|
||||||
src := source
|
src := source
|
||||||
if src.readable then
|
if src.readable and not src.was_error then
|
||||||
src.read_character
|
src.read_character_noexception
|
||||||
last_character := src.last_character
|
last_character := src.last_character
|
||||||
else
|
else
|
||||||
last_character := '%U'
|
last_character := '%U'
|
||||||
@@ -56,8 +56,8 @@ feature -- Input
|
|||||||
do
|
do
|
||||||
src := source
|
src := source
|
||||||
last_string.wipe_out
|
last_string.wipe_out
|
||||||
if src.readable then
|
if src.readable and not src.was_error then
|
||||||
src.read_stream_thread_aware (nb)
|
src.read_stream_noexception (nb)
|
||||||
last_string.append_string (src.last_string)
|
last_string.append_string (src.last_string)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -85,11 +85,11 @@ feature -- Status report
|
|||||||
end_of_input: BOOLEAN
|
end_of_input: BOOLEAN
|
||||||
-- Has the end of input stream been reached?
|
-- Has the end of input stream been reached?
|
||||||
do
|
do
|
||||||
Result := not source.readable
|
Result := not source.readable or source.was_error
|
||||||
end
|
end
|
||||||
|
|
||||||
;note
|
;note
|
||||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ feature -- Output
|
|||||||
put_character (c: CHARACTER_8)
|
put_character (c: CHARACTER_8)
|
||||||
do
|
do
|
||||||
last_target_call_succeed := False
|
last_target_call_succeed := False
|
||||||
target.put_character (c)
|
target.put_character_noexception (c)
|
||||||
last_target_call_succeed := not target.was_error
|
last_target_call_succeed := not target.was_error
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ feature {NONE} -- Initialization
|
|||||||
make
|
make
|
||||||
do
|
do
|
||||||
print ("Example: start a Standalone web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:8123/%N")
|
print ("Example: start a Standalone web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:8123/%N")
|
||||||
(create {STANDALONE_SERVICE [HELLO_WORLD_EXECUTION]}.make_custom ("")).listen (port_number)
|
(create {WGI_STANDALONE_CONNECTOR [HELLO_WORLD_EXECUTION]}.make_with_base ("")).launch_on_port (port_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
port_number: INTEGER = 8123
|
port_number: INTEGER = 8123
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Eiffel Software and others"
|
copyright: "2011-2016, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ feature {NONE} -- Initialization
|
|||||||
execute
|
execute
|
||||||
do
|
do
|
||||||
response.set_status_code (200, Void)
|
response.set_status_code (200, Void)
|
||||||
response.put_header_text ("Content-Type: text/plain%R%N")
|
response.put_header_text ("Content-Length: 13%R%NContent-Type: text/plain%R%N")
|
||||||
response.put_string ("Hello World!%N")
|
response.put_string ("Hello World!%N")
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Eiffel Software and others"
|
copyright: "2011-2016, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ feature -- Input
|
|||||||
read_character
|
read_character
|
||||||
-- Read the next character in input stream.
|
-- Read the next character in input stream.
|
||||||
-- Make the result available in `last_character'
|
-- Make the result available in `last_character'
|
||||||
|
local
|
||||||
|
d: like last_chunk_data
|
||||||
|
l_index_in_chunk: INTEGER
|
||||||
do
|
do
|
||||||
index := index + 1
|
index := index + 1
|
||||||
if index > chunk_upper then
|
if index > chunk_upper then
|
||||||
@@ -45,10 +48,24 @@ feature -- Input
|
|||||||
read_trailer_and_crlf
|
read_trailer_and_crlf
|
||||||
last_character := '%U'
|
last_character := '%U'
|
||||||
else
|
else
|
||||||
last_character := last_chunk_data.item (index)
|
l_index_in_chunk := chunk_index (index)
|
||||||
|
d := last_chunk_data
|
||||||
|
if d.valid_index (l_index_in_chunk) then
|
||||||
|
last_character := d [l_index_in_chunk]
|
||||||
|
else
|
||||||
|
check has_character: False end
|
||||||
|
last_character := '%U'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
last_character := last_chunk_data.item (index)
|
l_index_in_chunk := chunk_index (index)
|
||||||
|
d := last_chunk_data
|
||||||
|
if d.valid_index (l_index_in_chunk) then
|
||||||
|
last_character := d [l_index_in_chunk]
|
||||||
|
else
|
||||||
|
check has_character: False end
|
||||||
|
last_character := '%U'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -77,13 +94,13 @@ feature -- Input
|
|||||||
i - index + 1 = nb or last_chunk_size = 0
|
i - index + 1 = nb or last_chunk_size = 0
|
||||||
loop
|
loop
|
||||||
if i + nb - 1 <= chunk_upper then
|
if i + nb - 1 <= chunk_upper then
|
||||||
last_string.append (last_chunk_data.substring (i - chunk_lower + 1, i - chunk_lower + 1 + nb - 1))
|
last_string.append (last_chunk_data.substring (chunk_index (i), chunk_index (i) + nb - 1))
|
||||||
i := i + nb - 1
|
i := i + nb - 1
|
||||||
else
|
else
|
||||||
-- Need to read new chunk
|
-- Need to read new chunk
|
||||||
-- first get all available data from current chunk
|
-- first get all available data from current chunk
|
||||||
if i <= chunk_upper then
|
if i > chunk_upper then
|
||||||
last_string.append (last_chunk_data.substring (i - chunk_lower + 1, chunk_upper - chunk_lower + 1))
|
last_string.append (last_chunk_data.substring (i - chunk_lower + 1, chunk_index (chunk_upper)))
|
||||||
i := chunk_upper
|
i := chunk_upper
|
||||||
end
|
end
|
||||||
-- then continue
|
-- then continue
|
||||||
@@ -166,9 +183,25 @@ feature -- Status report
|
|||||||
Result := last_trailer /= Void
|
Result := last_trailer /= Void
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Parser
|
feature {NONE} -- Access: chunk
|
||||||
|
|
||||||
|
chunk_index (a_index: INTEGER): INTEGER
|
||||||
|
-- Index in `last_chunk_data' for global input index `a_index'.
|
||||||
|
do
|
||||||
|
Result := a_index - chunk_lower + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
index: INTEGER
|
||||||
|
-- Global input index.
|
||||||
|
|
||||||
|
chunk_lower: INTEGER
|
||||||
|
-- Lower global index for `last_chunk_data'.
|
||||||
|
|
||||||
|
chunk_upper: INTEGER
|
||||||
|
-- Upper global index for `last_chunk_data'.
|
||||||
|
|
||||||
|
feature {NONE} -- Chunk parsing
|
||||||
|
|
||||||
index, chunk_lower, chunk_upper: INTEGER
|
|
||||||
tmp_hex_chunk_size: STRING_8
|
tmp_hex_chunk_size: STRING_8
|
||||||
|
|
||||||
read_chunk_block
|
read_chunk_block
|
||||||
@@ -190,8 +223,10 @@ feature {NONE} -- Parser
|
|||||||
check last_chunk_data.count = last_chunk_size end
|
check last_chunk_data.count = last_chunk_size end
|
||||||
|
|
||||||
l_input := input
|
l_input := input
|
||||||
|
check not l_input.end_of_input end
|
||||||
l_input.read_character
|
l_input.read_character
|
||||||
check l_input.last_character = '%R' end
|
check l_input.last_character = '%R' end
|
||||||
|
check not l_input.end_of_input end
|
||||||
l_input.read_character
|
l_input.read_character
|
||||||
check l_input.last_character = '%N' end
|
check l_input.last_character = '%N' end
|
||||||
end
|
end
|
||||||
@@ -214,8 +249,8 @@ feature {NONE} -- Parser
|
|||||||
l_input.read_string (last_chunk_size)
|
l_input.read_string (last_chunk_size)
|
||||||
last_chunk_data := l_input.last_string
|
last_chunk_data := l_input.last_string
|
||||||
ensure
|
ensure
|
||||||
last_chunk_attached: attached last_chunk_data as el_last_chunk
|
last_chunk_attached: last_chunk_data /= Void
|
||||||
last_chunk_size_ok: el_last_chunk.count = last_chunk_size
|
last_chunk_size_ok: last_chunk_data.count = last_chunk_size
|
||||||
end
|
end
|
||||||
|
|
||||||
read_chunk_size
|
read_chunk_size
|
||||||
@@ -350,7 +385,7 @@ feature {NONE} -- Implementation
|
|||||||
-- Input Stream
|
-- Input Stream
|
||||||
|
|
||||||
;note
|
;note
|
||||||
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ feature -- Access: Input
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if raw_input_data_recorded then
|
if raw_input_data_recorded then
|
||||||
set_raw_input_data (buf.substring (buf_initial_size + 1, buf.count))
|
set_raw_input_data (buf.substring (buf_initial_size + 1, buf.count))
|
||||||
-- Only the input data! And differente reference.
|
-- Only the input data! And differente reference.
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -833,6 +833,7 @@ feature -- Access: CGI meta parameters - 1.1
|
|||||||
local
|
local
|
||||||
l_result: like internal_percent_encoded_path_info
|
l_result: like internal_percent_encoded_path_info
|
||||||
r: READABLE_STRING_8
|
r: READABLE_STRING_8
|
||||||
|
pi: READABLE_STRING_32
|
||||||
i,m,n,spos: INTEGER
|
i,m,n,spos: INTEGER
|
||||||
do
|
do
|
||||||
l_result := internal_percent_encoded_path_info
|
l_result := internal_percent_encoded_path_info
|
||||||
@@ -844,11 +845,23 @@ feature -- Access: CGI meta parameters - 1.1
|
|||||||
else
|
else
|
||||||
l_result := r.string
|
l_result := r.string
|
||||||
end
|
end
|
||||||
if attached script_name as s then
|
pi := path_info
|
||||||
|
i := 0
|
||||||
|
if pi.is_valid_as_string_8 then
|
||||||
|
i := l_result.substring_index (pi.to_string_8, 1)
|
||||||
|
if i > 0 then
|
||||||
|
-- Path info is included in REQUEST_URI
|
||||||
|
-- so let's get the percent encoded path info from request uri.
|
||||||
|
l_result := l_result.substring (i, l_result.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--| here "i = 0" means request_uri does not start with `path_info',
|
||||||
|
--| thus let's compute it from `script_name'.
|
||||||
|
if i = 0 and attached script_name as s then
|
||||||
if l_result.starts_with (s) then
|
if l_result.starts_with (s) then
|
||||||
l_result := l_result.substring (s.count + 1, l_result.count)
|
l_result := l_result.substring (s.count + 1, l_result.count)
|
||||||
else
|
else
|
||||||
--| Handle Rewrite url engine, to have clean path
|
--| Handle Rewrite url engine, to have clean path
|
||||||
from
|
from
|
||||||
i := 1
|
i := 1
|
||||||
m := l_result.count
|
m := l_result.count
|
||||||
@@ -2083,7 +2096,7 @@ invariant
|
|||||||
wgi_request.content_type /= Void implies content_type /= Void
|
wgi_request.content_type /= Void implies content_type /= Void
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ feature -- Helper
|
|||||||
if b = Void then
|
if b = Void then
|
||||||
b := ""
|
b := ""
|
||||||
end
|
end
|
||||||
Result := "/" + b + a_query_url
|
Result := b + a_query_url
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ feature -- Access
|
|||||||
|
|
||||||
port_number: INTEGER = 9091
|
port_number: INTEGER = 9091
|
||||||
|
|
||||||
base_url: STRING = "" --"/test/"
|
base_url: STRING = "/test/"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ feature -- Execution
|
|||||||
|
|
||||||
feature -- Tests
|
feature -- Tests
|
||||||
|
|
||||||
test_script_url
|
test_script_url_1
|
||||||
local
|
local
|
||||||
req: WSF_REQUEST
|
req: WSF_REQUEST
|
||||||
s: READABLE_STRING_8
|
s: READABLE_STRING_8
|
||||||
@@ -48,7 +48,13 @@ feature -- Tests
|
|||||||
)
|
)
|
||||||
s := req.script_url ("/new/path/")
|
s := req.script_url ("/new/path/")
|
||||||
assert ("script_url (/new/path/) = %""+s+"%" but should be %"/foo/bar/new/path/%"", s.same_string ("/foo/bar/new/path/"))
|
assert ("script_url (/new/path/) = %""+s+"%" but should be %"/foo/bar/new/path/%"", s.same_string ("/foo/bar/new/path/"))
|
||||||
|
end
|
||||||
|
|
||||||
|
test_script_url_2
|
||||||
|
local
|
||||||
|
req: WSF_REQUEST
|
||||||
|
s: READABLE_STRING_8
|
||||||
|
do
|
||||||
--| Case #2
|
--| Case #2
|
||||||
req := new_request (<<
|
req := new_request (<<
|
||||||
["REQUEST_METHOD", "GET"],
|
["REQUEST_METHOD", "GET"],
|
||||||
@@ -60,7 +66,13 @@ feature -- Tests
|
|||||||
)
|
)
|
||||||
s := req.script_url ("/new/path/")
|
s := req.script_url ("/new/path/")
|
||||||
assert ("script_url (/new/path/) = %""+s+"%" but should be %"/foo/bar/new/path/%"", s.same_string ("/foo/bar/new/path/"))
|
assert ("script_url (/new/path/) = %""+s+"%" but should be %"/foo/bar/new/path/%"", s.same_string ("/foo/bar/new/path/"))
|
||||||
|
end
|
||||||
|
|
||||||
|
test_script_url_3
|
||||||
|
local
|
||||||
|
req: WSF_REQUEST
|
||||||
|
s: READABLE_STRING_8
|
||||||
|
do
|
||||||
--| Case #3
|
--| Case #3
|
||||||
req := new_request (<<
|
req := new_request (<<
|
||||||
["REQUEST_METHOD", "GET"],
|
["REQUEST_METHOD", "GET"],
|
||||||
|
|||||||
@@ -44,17 +44,17 @@ feature -- Test Cases
|
|||||||
l_cookie.set_path ("/")
|
l_cookie.set_path ("/")
|
||||||
l_cookie.set_secure (True)
|
l_cookie.set_secure (True)
|
||||||
l_cookie.set_http_only (True)
|
l_cookie.set_http_only (True)
|
||||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||||
|
|
||||||
w_res.put_header_text (l_header.string)
|
w_res.put_header_text (l_header.string)
|
||||||
w_res.add_cookie (l_cookie)
|
w_res.add_cookie (l_cookie)
|
||||||
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
w_res.put_string ("Test")
|
w_res.put_string ("Test")
|
||||||
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%N%R%NTest") )
|
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly%R%N%R%NTest") )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
test_add_multiple_cookiewith_similar_cookie_name
|
test_add_multiple_cookies_with_similar_cookie_name
|
||||||
local
|
local
|
||||||
w_res: WSF_RESPONSE
|
w_res: WSF_RESPONSE
|
||||||
l_cookie: WSF_COOKIE
|
l_cookie: WSF_COOKIE
|
||||||
@@ -73,7 +73,7 @@ feature -- Test Cases
|
|||||||
l_cookie.set_path ("/")
|
l_cookie.set_path ("/")
|
||||||
l_cookie.set_secure (True)
|
l_cookie.set_secure (True)
|
||||||
l_cookie.set_http_only (True)
|
l_cookie.set_http_only (True)
|
||||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||||
w_res.put_header_text (l_header.string)
|
w_res.put_header_text (l_header.string)
|
||||||
w_res.add_cookie (l_cookie)
|
w_res.add_cookie (l_cookie)
|
||||||
|
|
||||||
@@ -84,16 +84,16 @@ feature -- Test Cases
|
|||||||
l_cookie.set_path ("/")
|
l_cookie.set_path ("/")
|
||||||
l_cookie.set_secure (True)
|
l_cookie.set_secure (True)
|
||||||
l_cookie.set_http_only (True)
|
l_cookie.set_http_only (True)
|
||||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=newUser; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=newUser; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||||
|
|
||||||
w_res.add_cookie (l_cookie) -- Ignored
|
w_res.add_cookie (l_cookie) -- Ignored
|
||||||
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
w_res.put_string ("Test")
|
w_res.put_string ("Test")
|
||||||
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%N%R%NTest") )
|
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly%R%N%R%NTest") )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
test_add_multiple_cookie_with_similar_cookie_name_2
|
test_add_multiple_cookies_with_similar_cookie_name_2
|
||||||
local
|
local
|
||||||
w_res: WSF_RESPONSE
|
w_res: WSF_RESPONSE
|
||||||
l_cookie: WSF_COOKIE
|
l_cookie: WSF_COOKIE
|
||||||
@@ -113,7 +113,7 @@ feature -- Test Cases
|
|||||||
l_cookie.set_path ("/")
|
l_cookie.set_path ("/")
|
||||||
l_cookie.set_secure (True)
|
l_cookie.set_secure (True)
|
||||||
l_cookie.set_http_only (True)
|
l_cookie.set_http_only (True)
|
||||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||||
|
|
||||||
|
|
||||||
w_res.add_cookie (l_cookie)
|
w_res.add_cookie (l_cookie)
|
||||||
@@ -123,7 +123,7 @@ feature -- Test Cases
|
|||||||
l_cookie.set_path ("/")
|
l_cookie.set_path ("/")
|
||||||
l_cookie.set_secure (True)
|
l_cookie.set_secure (True)
|
||||||
l_cookie.set_http_only (True)
|
l_cookie.set_http_only (True)
|
||||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=newUser; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=newUser; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||||
|
|
||||||
w_res.add_cookie (l_cookie) -- Ignored
|
w_res.add_cookie (l_cookie) -- Ignored
|
||||||
|
|
||||||
@@ -134,11 +134,11 @@ feature -- Test Cases
|
|||||||
l_cookie.set_path ("/")
|
l_cookie.set_path ("/")
|
||||||
l_cookie.set_secure (True)
|
l_cookie.set_secure (True)
|
||||||
l_cookie.set_http_only (True)
|
l_cookie.set_http_only (True)
|
||||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: ewf_sessionid=test; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: ewf_sessionid=test; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||||
|
|
||||||
w_res.add_cookie (l_cookie)
|
w_res.add_cookie (l_cookie)
|
||||||
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
w_res.put_string ("Test")
|
w_res.put_string ("Test")
|
||||||
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%NSet-Cookie: ewf_sessionid=test; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%N%R%NTest") )
|
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly%R%NSet-Cookie: ewf_sessionid=test; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly%R%N%R%NTest") )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,15 +11,16 @@
|
|||||||
</option>
|
</option>
|
||||||
<setting name="concurrency" value="thread"/>
|
<setting name="concurrency" value="thread"/>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||||
<library name="connector_nino" location="..\..\ewsgi\connectors\nino\nino.ecf" readonly="false"/>
|
|
||||||
<library name="connector_null" location="..\..\ewsgi\connectors\null\null.ecf" readonly="false"/>
|
<library name="connector_null" location="..\..\ewsgi\connectors\null\null.ecf" readonly="false"/>
|
||||||
<library name="dft_nino" location="..\default\nino.ecf"/>
|
<library name="connector_standalone" location="..\..\ewsgi\connectors\standalone\standalone.ecf" readonly="false"/>
|
||||||
|
<library name="dft_standalone" location="..\default\standalone.ecf"/>
|
||||||
<library name="ewsgi" location="..\..\ewsgi\ewsgi.ecf" readonly="false"/>
|
<library name="ewsgi" location="..\..\ewsgi\ewsgi.ecf" readonly="false"/>
|
||||||
<library name="http" location="..\..\..\network\protocol\http\http.ecf" readonly="false"/>
|
<library name="http" location="..\..\..\network\protocol\http\http.ecf" readonly="false"/>
|
||||||
<library name="http_client" location="..\..\..\network\http_client\http_client.ecf" readonly="false"/>
|
<library name="http_client" location="..\..\..\network\http_client\net_http_client.ecf" readonly="false"/>
|
||||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
|
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
|
||||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||||
<library name="wsf" location="..\wsf.ecf" readonly="false"/>
|
<library name="wsf" location="..\wsf.ecf" readonly="false"/>
|
||||||
|
<library name="wsf_standalone" location="..\..\wsf\connector\standalone.ecf" readonly="false"/>
|
||||||
<cluster name="server" location=".\server\" recursive="true"/>
|
<cluster name="server" location=".\server\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
<target name="wsf_tests" extends="server">
|
<target name="wsf_tests" extends="server">
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ def runTestForProject(where):
|
|||||||
|
|
||||||
# compile the restbucks
|
# compile the restbucks
|
||||||
print "# Compiling restbucks example"
|
print "# Compiling restbucks example"
|
||||||
cmd = "ecb -config %s -target restbucks -batch -c_compile -project_path . " % (os.path.join ("examples", "restbucks", "restbucks-safe.ecf"))
|
cmd = "ecb -config %s -target restbucks -batch -c_compile -project_path . " % (os.path.join ("examples", "restbucksCRUD", "restbucks-safe.ecf"))
|
||||||
res = eval_cmd(cmd)
|
res = eval_cmd(cmd)
|
||||||
|
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user