Compare commits

...

16 Commits

Author SHA1 Message Date
d28f794828 Implemented chunked Transfer-Encoding in net_http_client.
Implemented support for buffer_size and chunk_size for net_http_client.
2016-10-12 16:49:08 +02:00
9e92b8c0fa Fixed typo in restbuck name. 2016-10-12 11:21:42 +02:00
ef704790a8 Fixed the "wsf_tests" autocase suite, which was wrong for cookies, and other minor changes. 2016-10-12 11:21:27 +02:00
57b1691243 Added support for debug.ini to debug example. 2016-10-12 11:19:54 +02:00
29590b1c0d Fixed potential issue related to PATH_INFO, and percent_encoded_path_info computing , when script name is in different path. 2016-10-12 11:19:23 +02:00
ed959042d7 Fixed issue with input using "Transfer-Encoding: chunked". 2016-10-12 11:12:37 +02:00
1170417e54 Fixed regression with persistent connection, be sure to keep the remote_info data for all successive requests within a same persistent connection. 2016-10-11 17:34:07 +02:00
2cfe00e61b Updated desktop_app example with embedded standalone web server. 2016-10-11 17:30:50 +02:00
a498a167ed Updated desktop application example for scoop concurrency mode. 2016-10-11 16:20:04 +02:00
f12158e535 Use the ..._noexception network features in the WGI standalone input and output classes. 2016-10-11 10:57:05 +02:00
080881368a Also check for SOCKET.was_error when accessing the socket data. 2016-10-11 10:29:38 +02:00
Jocelyn Fiat
3e935c7e33 Use `was_error' to get expected behavior on Linux. 2016-10-10 22:27:45 +02:00
Jocelyn Fiat
ad2bb0d1a7 Fixed C compilation on non Windows platform for EiffelStudio until 16.05 .
(the required c function are coming with EiffelNet from EiffelStudio 16.11 ).
2016-10-10 22:17:41 +02:00
7a546622bc Updated deprecated EiffelWeb nino to make it compilable with upcoming EiffelStudio 16.11.
Updated various projects to make them up-to-date and compilable with this latest EiffelWeb.
2016-10-10 21:40:15 +02:00
aed7461faf Improved networking implementation for httpd server and sockets.
Use new EiffelNet routines that do not raise exception on error.
Made compilable with 16.05 and dev-and-upcoming release 16.11.
Fixed various minor issues related to base_url, and added comments.
2016-10-08 01:10:16 +02:00
56819d6793 Replace Nino by Standalone whenever it is relevant. 2016-10-08 01:02:12 +02:00
101 changed files with 1629 additions and 1355 deletions

View File

@@ -17,10 +17,21 @@ create
make_server_by_port
create {NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
make_from_descriptor_and_address,
make_empty
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
-- Create a network stream socket.
do
@@ -28,16 +39,6 @@ feature {NONE} -- Initialization
set_reuse_address
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
send_message (a_msg: STRING)

View File

@@ -29,16 +29,6 @@ feature {NONE} -- Initialization
set_reuse_address
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
send_message (a_msg: STRING)

View File

@@ -22,13 +22,13 @@
<file_rule>
<exclude>tcp_stream_socket.e</exclude>
<condition>
<version type="compiler" max="15.01.9.6506"/>
<version type="compiler" max="16.11"/>
</condition>
</file_rule>
</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>
<version type="compiler" max="15.01.9.6506"/>
<version type="compiler" max="16.11"/>
</condition>
</cluster>
</target>

View File

@@ -1,35 +1,35 @@
<?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">
<target name="nino">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
<cluster name="nino" location=".\library\" recursive="true">
<file_rule>
<exclude>spec</exclude>
</file_rule>
<file_rule>
<exclude>tcp_stream_socket.e</exclude>
<condition>
<version type="compiler" max="15.01.9.6506"/>
</condition>
</file_rule>
</cluster>
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
<condition>
<version type="compiler" max="15.01.9.6506"/>
</condition>
</cluster>
</target>
</system>
<?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">
<target name="nino">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
<cluster name="nino" location=".\library\" recursive="true">
<file_rule>
<exclude>spec</exclude>
</file_rule>
<file_rule>
<exclude>tcp_stream_socket.e</exclude>
<condition>
<version type="compiler" max="16.11"/>
</condition>
</file_rule>
</cluster>
<cluster name="spec_until_16_05" location=".\library\spec\until_16_05\" recursive="true">
<condition>
<version type="compiler" max="16.11"/>
</condition>
</cluster>
</target>
</system>

View File

@@ -1,22 +1,29 @@
The main goal of the connectors is to let you choose a target at compile time.
This allows you to concentrate on your business during development time and then decide which target you choose at deployment time.
The current connectors are:
* Nino
* Standalone
* FastCGI
* CGI
* OpenShift
* Nino (obsolete, replaced by Standalone)
The most widely used workflow is to use Nino on your development machine and FastCGI on your production server.
Nino being a web server written entirely in Eiffel, you can inspect your HTTP requests and respones in EiffelStudio which is great during development.
The most widely used workflow is to use Standalone on your development machine and FastCGI on your production server.
Standalone being a web server written entirely in Eiffel, you can inspect your HTTP requests and respones in EiffelStudio which is great during development.
On the other hand, FastCGI is great at handling concurrent requests and coupled with Apache (or another web production server), you don't even need to worry about the lifecyle of your application (creation and destruction) as Apache will do it for you!
Let's now dig into each of the connecters.
# Nino
# Standalone
EiffelWeb standalone is connector based on the EiffelWeb httpd server entirely written in Eiffel
(note: httpd is under standalone connector, so you can consider Standalone as the EiffelWeb standalone web server).
The goal of Standalone is to provide a simple web server for development (like Java, Python and Ruby provide).
# Nino (obsolete and replaced by Standalone)
Nino is a web server entirely written in Eiffel.
The goal of Nino is to provide a simple web server for development (like Java, Python and Ruby provide).
Nino is currently maintained by Javier Velilla and the repository can be found here: https://github.com/jvelilla/EiffelWebNino
Nino is currently maintained by Jocelyn Fiat and Javier Velilla and the repository can be found here: https://github.com/jvelilla/EiffelWebNino
# FastCGI

View File

@@ -61,7 +61,7 @@ Using EWF, your service is built on top of underlying httpd solution/connectors.
Currently 3 main connectors are available:
* __CGI__: following the CGI interface, this is an easy solution to run the service on any platform.
* __libFCGI__: based on the libfcgi solution, this can be used with Apache, IIS, nginx, ...
* __nino__: a standalone server: Eiffel Web Nino allow you to embed a web server anywhere, on any platform without any dependencies on other httpd server.
* __standalone__: a standalone server: EiffelWeb Standalone web server allows you to embed a web server anywhere, on any platform without any dependencies on other httpd server.
At compilation time, you can use a default connector (by using the associated default lib), but you can also use a mixed of them and choose which one to execute at runtime.
It is fairly easy to add new connector, it just has to follow the EWSGI interface

View File

@@ -4,7 +4,7 @@ Now you have to implement each handler. You need to inherit from WSF_SKELETON_HA
## Communicating between routines
Depending upon the connector (Nino, CGI, FastCGI etc.) that you are using, your handler may be invoked concurrently for multiple requests. Therefore it is unsafe to save state in normal attributes. WSF_REQUEST has a pair of getter/setter routines, execution_variable/set_execution_variable, which you can use for this purpose.
Depending upon the connector (Standalone, CGI, FastCGI etc.) that you are using, your handler may be invoked concurrently for multiple requests. Therefore it is unsafe to save state in normal attributes. WSF_REQUEST has a pair of getter/setter routines, execution_variable/set_execution_variable, which you can use for this purpose.
Internally, the framework uses the following execution variable names, so you must avoid them:
1. REQUEST_ENTITY

View File

@@ -59,7 +59,7 @@ feature -- Basic operations
end
```
When using the "nino" connector or the new "standalone" connector, by default the service listens on port 80, but often this port is already used by other applications, so it is recommended to use another port.
When using the "standalone" connector (or the deprecated "nino" connector), by default the service listens on port 80, but often this port is already used by other applications, so it is recommended to use another port.
To define another port, redefine the feature `initialize' and set up a new port number using the service options (see below).
@@ -90,7 +90,7 @@ The **WSF_REQUEST** gives access to the incoming data; the class provides featur
The **WSF_RESPONSE** provides features to define the response with information such as HTTP status codes (10x,20x, 30x, 40x, and 50x), response headers (Content-Type, Content-Length, etc.) and obviously the body of the message itself.
**APPLICATION** is the root class of our example, it launches the application, using the corresponding connector, Which connector? this depends how you want to run it cgi, fcgi,nino or standalone. For development is recommended to use a standalone web server written in Eiffel, and run the execution within the EiffelStudio debugger. For production fcgi (or cgi) using Apache or another popular web server.
**APPLICATION** is the root class of our example, it launches the application, using the corresponding connector, Which connector? this depends how you want to run it cgi, fcgi,standalone. For development is recommended to use a standalone web server written in Eiffel, and run the execution within the EiffelStudio debugger. For production fcgi (or cgi) using Apache or another popular web server.
![Launcher Hierarchy](./Launcher Hierarchy.png "Launcher Hierarchy")
@@ -149,9 +149,10 @@ The source code is available on Github. You can get it by running the command:
```git clone https://github.com/EiffelWebFramework/ewf.git```
The example of simple service that generate plain text response is located in the directory $PATH/ewf/doc/workbook/basics/simple, where $PATH is where you run ```git clone``` . Just double click on the simple.ecf file and select the simple_nino target or if you prefer the command line, run the command:
The example of simple service that generate plain text response is located in the directory $PATH/ewf/doc/workbook/basics/simple, where $PATH is where you run ```git clone``` .
Just double click on the simple.ecf file and select the simple_standalone target or if you prefer the command line, run the command:
```estudio -config simple.ecf -target simple_nino```
```estudio -config simple.ecf -target simple_standalone```
<a name="html"></a>
@@ -204,9 +205,10 @@ The source code is available on Github. You can get it by running the command:
```git clone https://github.com/EiffelWebFramework/ewf.git```
The example of the service that generates HTML is located in the directory $PATH/ewf/doc/workbook/basics/simple_html, where $PATH is where you run ```git clone``` . Just double click on the simple_html.ecf file and select the simple_html_nino target or if you prefer the command line, run the command:
The example of the service that generates HTML is located in the directory $PATH/ewf/doc/workbook/basics/simple_html, where $PATH is where you run ```git clone``` .
Just double click on the simple_html.ecf file and select the simple_html_standalone target or if you prefer the command line, run the command:
```estudio -config simple_html.ecf -target simple_html_nino```
```estudio -config simple_html.ecf -target simple_html_standalone```
Nav: [Workbook](../workbook.md) :: [Handling Requests: Form/Query Parameter](../handling_request/form.md)

View File

@@ -13,14 +13,6 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="simple_nino" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<cluster name="simple" location=".\" recursive="true"/>
</target>
<target name="simple_cgi" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
@@ -45,6 +37,6 @@
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="simple" location=".\" recursive="true"/>
</target>
<target name="simple" extends="simple_nino">
<target name="simple" extends="simple_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="simple_html_nino" extends="common">
<target name="simple_html_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="simple_html" location=".\" recursive="true"/>
</target>
<target name="simple_html_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="simple_html" location=".\" recursive="true"/>
</target>
<target name="simple_html" extends="simple_html_nino">
<target name="simple_html" extends="simple_html_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="exel_nino" extends="common">
<target name="exel_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="exel" location=".\" recursive="true"/>
</target>
<target name="exel_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="exel" location=".\" recursive="true"/>
</target>
<target name="exel" extends="exel_nino">
<target name="exel" extends="exel_standalone">
</target>
</system>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
"1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="headers" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="headers">
<target name="common" abstract="true">
<file_rule>
@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="headers_nino" extends="common">
<target name="headers_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="headers" location=".\" recursive="true"/>
</target>
<target name="headers_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="headers" location=".\" recursive="true"/>
</target>
<target name="headers" extends="headers_nino">
<target name="headers" extends="headers_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="search_nino" extends="common">
<target name="search_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="search" location=".\" recursive="true"/>
</target>
<target name="search_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="search" location=".\" recursive="true"/>
</target>
<target name="search" extends="search_nino">
<target name="search" extends="search_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="status_nino" extends="common">
<target name="status_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="status" location=".\" recursive="true"/>
</target>
<target name="status_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="status" location=".\" recursive="true"/>
</target>
<target name="status" extends="status_nino">
<target name="status" extends="status_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="example_nino" extends="common">
<target name="example_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="example" location=".\" recursive="true"/>
</target>
<target name="example_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="example" location=".\" recursive="true"/>
</target>
<target name="example" extends="example_nino">
<target name="example" extends="example_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="form_nino" extends="common">
<target name="form_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="form" location=".\" recursive="true"/>
</target>
<target name="form_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="form" location=".\" recursive="true"/>
</target>
<target name="form" extends="form_nino">
<target name="form" extends="form_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="form_nino" extends="common">
<target name="form_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="form" location=".\" recursive="true"/>
</target>
<target name="form_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="form" location=".\" recursive="true"/>
</target>
<target name="form" extends="form_nino">
<target name="form" extends="form_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="browsers_nino" extends="common">
<target name="browsers_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="browsers" location=".\" recursive="true"/>
</target>
<target name="browsers_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="browsers" location=".\" recursive="true"/>
</target>
<target name="browsers" extends="browsers_nino">
<target name="browsers" extends="browsers_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="cgi_variables_nino" extends="common">
<target name="cgi_variables_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="cgi_variables" location=".\" recursive="true"/>
</target>
<target name="cgi_variables_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="cgi_variables" location=".\" recursive="true"/>
</target>
<target name="cgi_variables" extends="cgi_variables_nino">
<target name="cgi_variables" extends="cgi_variables_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="header_fields_nino" extends="common">
<target name="header_fields_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="header_fields" location=".\" recursive="true"/>
</target>
<target name="header_fields_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="header_fields" location=".\" recursive="true"/>
</target>
<target name="header_fields" extends="header_fields_nino">
<target name="header_fields" extends="header_fields_standalone">
</target>
</system>

View File

@@ -13,12 +13,12 @@
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="upload_nino" extends="common">
<target name="upload_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="upload" location=".\" recursive="true"/>
</target>
<target name="upload_cgi" extends="common">
@@ -37,6 +37,6 @@
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="upload" location=".\" recursive="true"/>
</target>
<target name="upload" extends="upload_nino">
<target name="upload" extends="upload_standalone">
</target>
</system>

View File

@@ -14,9 +14,9 @@
<library name="wsf" location="..\..\..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
<library name="wsf_js_widget" location="..\..\wsf_js_widget-safe.ecf" readonly="false"/>
</target>
<target name="js_widget_template_nino" extends="common">
<target name="js_widget_template_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<library name="default_nino" location="..\..\..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="..\..\..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
<cluster name="js_widget_template" location=".\src\" recursive="true">
</cluster>
</target>
@@ -30,6 +30,6 @@
<library name="default_libfcgi" location="..\..\..\..\..\..\library\server\wsf\default\libfcgi-safe.ecf"/>
<cluster name="js_widget_template" location=".\src\" recursive="true"/>
</target>
<target name="js_widget_template" extends="js_widget_template_nino">
<target name="js_widget_template" extends="js_widget_template_standalone">
</target>
</system>

View File

@@ -14,9 +14,9 @@
<library name="wsf" location="..\..\..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
<library name="wsf_js_widget" location="..\..\wsf_js_widget-safe.ecf" readonly="false"/>
</target>
<target name="js_custom_widget_nino" extends="common">
<target name="js_custom_widget_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<library name="default_nino" location="..\..\..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="..\..\..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
<cluster name="js_custom_widget" location=".\src\" recursive="true">
</cluster>
</target>
@@ -30,6 +30,6 @@
<library name="default_libfcgi" location="..\..\..\..\..\..\library\server\wsf\default\libfcgi-safe.ecf"/>
<cluster name="js_custom_widget" location=".\src\" recursive="true"/>
</target>
<target name="js_custom_widget" extends="js_custom_widget_nino">
<target name="js_custom_widget" extends="js_custom_widget_standalone">
</target>
</system>

View File

@@ -16,12 +16,12 @@
<library name="wsf" location="..\..\..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
<library name="wsf_js_widget" location="..\..\wsf_js_widget-safe.ecf" readonly="false"/>
</target>
<target name="demo_nino" extends="common">
<target name="demo_standalone" extends="common">
<root class="APPLICATION" feature="make_and_launch"/>
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="default_nino" location="..\..\..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="..\..\..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
<cluster name="demo" location=".\" recursive="true"/>
</target>
<target name="demo_cgi" extends="common">
@@ -40,6 +40,6 @@
<library name="default_libfcgi" location="..\..\..\..\..\..\library\server\wsf\default\libfcgi-safe.ecf"/>
<cluster name="demo" location=".\" recursive="true"/>
</target>
<target name="demo" extends="demo_nino">
<target name="demo" extends="demo_standalone">
</target>
</system>

View File

@@ -17,13 +17,13 @@
<root class="${APP_ROOT}" feature="make_and_launch"/>
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="${APPNAME}_nino" extends="common">
<target name="${APPNAME}_standalone" extends="common">
<root class="${APP_ROOT}" feature="make_and_launch"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
@@ -40,6 +40,6 @@
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="${APPNAME}" extends="${APPNAME}_nino"/>
<target name="${APPNAME}" extends="${APPNAME}_standalone"/>
</system>

View File

@@ -2,7 +2,7 @@
<root class="${APP_ROOT}" feature="make_and_launch"/>
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>

View File

@@ -22,8 +22,8 @@ feature -- Execution
nature: like launcher_nature
do
nature := launcher_nature
if nature = Void or else nature = nature_nino then
launch_nino (a_service, opts)
if nature = Void or else nature = nature_standalone then
launch_standalone (a_service, opts)
elseif nature = nature_cgi then
launch_cgi (a_service, opts)
elseif nature = nature_libfcgi then
@@ -38,7 +38,7 @@ feature {NONE} -- Access
launcher_nature: detachable READABLE_STRING_8
-- Initialize the launcher nature
-- either cgi, libfcgi, or nino.
-- either cgi, libfcgi, or standalone.
--| We could extend with more connector if needed.
--| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time.
local
@@ -51,8 +51,8 @@ feature {NONE} -- Access
ext := l_entry.extension
end
if ext /= Void then
if ext.same_string (nature_nino) then
Result := nature_nino
if ext.same_string (nature_standalone) then
Result := nature_standalone
end
if ext.same_string (nature_cgi) then
Result := nature_cgi
@@ -63,13 +63,13 @@ feature {NONE} -- Access
end
end
feature {NONE} -- nino
feature {NONE} -- standalone
nature_nino: STRING = "nino"
nature_standalone: STRING = "standalone"
launch_nino (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
launch_standalone (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_NINO_SERVICE_LAUNCHER
launcher: WSF_STANDALONE_SERVICE_LAUNCHER
do
create launcher.make_and_launch (a_service, opts)
end

View File

@@ -21,7 +21,6 @@
<setting name="concurrency" value="thread"/>
<library name="cgi" location="..\..\library\server\wsf\connector\cgi-safe.ecf" readonly="false"/>
<library name="libfcgi" location="..\..\library\server\wsf\connector\libfcgi-safe.ecf" readonly="false"/>
<library name="nino" location="..\..\library\server\wsf\connector\nino-safe.ecf" readonly="false"/>
<library name="standalone" location="..\..\library\server\wsf\connector\standalone-safe.ecf" readonly="false"/>
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
@@ -33,12 +32,6 @@
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="debug_nino" extends="common">
<root class="EWF_DEBUG_SERVER" feature="make_and_launch"/>
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="debug_cgi" extends="common">
<root class="EWF_DEBUG_SERVER" feature="make_and_launch"/>
<library name="default_cgi" location="..\..\library\server\wsf\default\cgi-safe.ecf" readonly="false"/>
@@ -51,6 +44,6 @@
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="debug" extends="debug_nino">
<target name="debug" extends="debug_standalone">
</target>
</system>

View File

@@ -24,8 +24,6 @@ feature -- Execution
nature := launcher_nature
if nature = Void or else nature = nature_standalone then
launch_standalone (opts)
elseif nature = nature_nino then
launch_nino (opts)
elseif nature = nature_cgi then
launch_cgi (opts)
elseif nature = nature_libfcgi then
@@ -40,7 +38,7 @@ feature {NONE} -- Access
launcher_nature: detachable READABLE_STRING_8
-- Initialize the launcher nature
-- either cgi, libfcgi, or nino.
-- either cgi, libfcgi, or standalone.
--| We could extend with more connector if needed.
--| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time.
local
@@ -55,9 +53,6 @@ feature {NONE} -- Access
if ext.same_string (nature_standalone) then
Result := nature_standalone
end
if ext.same_string (nature_nino) then
Result := nature_nino
end
if ext.same_string (nature_cgi) then
Result := nature_cgi
end
@@ -68,7 +63,7 @@ feature {NONE} -- Access
Result := nature_standalone
end
feature {NONE} -- nino
feature {NONE} -- Standalone
nature_standalone: STRING = "standalone"
@@ -79,17 +74,6 @@ feature {NONE} -- nino
create launcher.make_and_launch (opts)
end
feature {NONE} -- nino
nature_nino: STRING = "nino"
launch_nino (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_NINO_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature {NONE} -- cgi
nature_cgi: STRING = "cgi"

View File

@@ -28,6 +28,7 @@ feature {NONE} -- Initialization
-- set_service_option ("verbose", True)
set_service_option ("port", 9090)
-- 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
-- execute (req: WSF_REQUEST; res: WSF_RESPONSE)

View File

@@ -1,2 +1,2 @@
This example demonstrates the use of embedded Vision2 web browser component, and embedded EWF server (using nino).
This example demonstrates the use of embedded Vision2 web browser component, and embedded EWF server (using standalone).

View File

@@ -1,13 +1,13 @@
<?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>
<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>
<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"/>
</option>
<setting name="concurrency" value="thread"/>
<setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-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"/>
<cluster name="src" location=".\src\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
</cluster>
</target>

View File

@@ -24,20 +24,25 @@ feature {NONE} -- Initialization
-- then launch the application.
local
l_win: like main_window
l_embedded_service: APP_EMBEDDED_WEB_SERVICE
l_embedded_service: separate APP_EMBEDDED_WEB_SERVICE
do
default_create
create l_win.make
main_window := l_win
l_win.show
create l_embedded_service.make
l_embedded_service.set_port_number (0) -- Use first available port number
l_embedded_service.on_launched_actions.force (agent on_web_service_launched (l_win, l_embedded_service))
l_embedded_service.launch
setup_and_launch_web_service (l_embedded_service)
launch
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
do
if attached main_window as win then
@@ -45,13 +50,15 @@ feature {NONE} -- Initialization
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
add_idle_action_kamikaze (agent wait_for_termination (s, Void))
add_idle_action_kamikaze (agent a_win.open_link)
if attached main_window as win then
add_idle_action_kamikaze (agent wait_for_termination (a_web_service, Void))
add_idle_action_kamikaze (agent win.open_link)
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
t: detachable EV_TIMEOUT
do
@@ -60,7 +67,7 @@ feature {NONE} -- Initialization
t.set_interval (0)
end
if
attached s.observer as obs and then
attached a_web_service.observer as obs and then
observer_has_terminaded (obs)
then
if t /= Void then
@@ -70,7 +77,7 @@ feature {NONE} -- Initialization
else
if t = Void then
create t
t.actions.extend (agent wait_for_termination (s, t))
t.actions.extend (agent wait_for_termination (a_web_service, t))
else
t.set_interval (1_000)
end

View File

@@ -17,19 +17,21 @@ inherit
feature {NONE} -- Execution
execute_embedded
execute_embedded
-- Execute the request
-- See `request.input' for input stream
-- `request.meta_variables' for the CGI meta variable
-- and `response' for output buffer
local
filter: WSF_AGENT_FILTER
m: WSF_PAGE_RESPONSE
do
if local_connection_restriction_enabled then
if
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
execute
else
@@ -41,7 +43,7 @@ feature {NONE} -- Execution
execute
end
end
execute
deferred
end

View File

@@ -16,7 +16,6 @@ feature -- Initialization
make
do
create on_launched_actions
end
feature -- Execution
@@ -27,7 +26,6 @@ feature -- Execution
opts: WSF_SERVICE_LAUNCHER_OPTIONS
do
create opts.default_create
opts.set_verbose (True)
opts.set_option ("port", port_number)
create launcher.make (opts)
observer := launcher.connector.observer
@@ -40,11 +38,23 @@ feature -- Execution
on_launched (conn: WGI_STANDALONE_CONNECTOR [G])
do
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
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

View File

@@ -7,7 +7,6 @@
<exclude>/\.svn$</exclude>
</file_rule>
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="provisional">
<debug name="nino" enabled="true"/>
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
@@ -20,11 +19,6 @@
<library name="wsf_extension" location="..\..\library\server\wsf\wsf_extension-safe.ecf" readonly="true"/>
<library name="wsf_router_context" location="..\..\library\server\wsf\wsf_router_context-safe.ecf" readonly="true"/>
</target>
<target name="filter_nino" extends="common">
<root class="FILTER_SERVER" feature="make"/>
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="true"/>
<cluster name="filter" location="src\" recursive="true"/>
</target>
<target name="filter_standalone" extends="common">
<root class="FILTER_SERVER" feature="make"/>
<setting name="concurrency" value="thread"/>
@@ -36,6 +30,6 @@
<library name="default_libfcgi" location="..\..\library\server\wsf\default\libfcgi-safe.ecf"/>
<cluster name="filter" location="src\" recursive="true"/>
</target>
<target name="filter" extends="filter_nino">
<target name="filter" extends="filter_standalone">
</target>
</system>

View File

@@ -25,7 +25,7 @@ Note: <br/>
RESTBUCKS_SERVER
----------------
This class implement the main entry of our REST CRUD service, we are using a default connector (Nino Connector,
This class implement the main entry of our REST CRUD service, we are using a default connector (Standalone Connector,
using a WebServer written in Eiffel).
We are inheriting from URI_TEMPLATE_ROUTED_SERVICE, this allows us to map our service contrat, as is shown in the previous
table, the mapping is defined in the feature setup_router, this also show that the class ORDER_HANDLER will be encharge
@@ -41,7 +41,7 @@ of to handle different type of request to the ORDER resource.
URI_TEMPLATE_ROUTED_SERVICE
DEFAULT_SERVICE
-- Here we are using a default connector using the default Nino Connector,
-- Here we are using a default connector using the default Standalone Connector,
-- but it's possible to use other connector (CGI or FCGI).
create

View File

@@ -12,7 +12,6 @@ Currently, 4 connectors are available within EWF (but others are available outsi
*­ CGI: the common CGI application (apache, iis, ...)
* FastCGI: on any server supporting libfcgi handling (apache, iis, ...)
* Standalone: a standalone Eiffel Web server, it can be run anywhere easily, and debug simply with EiffelStudio's debugger. It supports all concurrency modes, and require EiffelStudio >= 15.05.
* Nino: similar to the "standalone" connectors, but lack good concurrency support.
Supporting a new connector is fairly simple, it just has to support the simple EWSGI specification which is really small. Then EWF will bring the power on top of it.

View File

@@ -13,7 +13,7 @@
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="wsf" location="..\..\..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
<library name="default_nino" location="..\..\..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="..\..\..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
<cluster name="src" location=".\"/>
</target>

View File

@@ -27,7 +27,7 @@ feature {NONE} -- Initialization
--| Uncomment the following line, to be able to load options from the file ewf.ini
-- create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("ewf.ini")
--| You can also uncomment the following line if you use the Nino connector
--| You can also uncomment the following line if you use the Standalone connector
--| so that the server listens on port 9999
--| quite often the port 80 is already busy
set_service_option ("port", 9999)

View File

@@ -1,4 +1,4 @@
# For nino connector, use port 9999
# For Standalone connector, use port 9999
port=9999
#verbose=true

View File

@@ -28,7 +28,7 @@ feature {NONE} -- Initialization
--| Uncomment the following line, to be able to load options from the file ewf.ini
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("ewf.ini")
--| You can also uncomment the following line if you use the Nino connector
--| You can also uncomment the following line if you use the Standalone connector
--| so that the server listens on port 9999
--| quite often the port 80 is already busy
-- set_service_option ("port", 9999)

View File

@@ -1,4 +1,4 @@
# For nino connector, use port 9999
# For standalone connector, use port 9999
port=9999
#verbose=true

View File

@@ -22,7 +22,7 @@ feature {NONE} -- Initialization
make
-- Initialize Current
do
-- To use particular port number (as 9090) with Nino connector
-- To use particular port number (as 9090) with Standalone connector
-- Uncomment the following line
set_service_option ("port", 9090)
make_and_launch

View File

@@ -20,10 +20,13 @@
</target>
<target name="upload_image_standalone" extends="upload_image_common">
<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"/>
<cluster name="src" location="src\" recursive="true"/>
</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">
<root class="IMAGE_UPLOADER" feature="make"/>
<setting name="concurrency" value="none"/>

View File

@@ -22,8 +22,8 @@ cgi-safe : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\cgi\cgi-safe
cgi : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\cgi\cgi.ecf
libfcgi-safe : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\libfcgi\libfcgi-safe.ecf
libfcgi : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\libfcgi\libfcgi.ecf
nino-safe : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\nino\nino-safe.ecf
nino : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\nino\nino.ecf
standalone-safe : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\standalone\standalone-safe.ecf
standalone : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\standalone\standalone.ecf
null-safe : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\null\null-safe.ecf
null : C:\_dev\projects\ewf\ewf\library\server\ewsgi\connectors\null\null.ecf
libfcgi-safe : C:\_dev\projects\ewf\ewf\library\server\libfcgi\libfcgi-safe.ecf
@@ -43,15 +43,15 @@ cgi-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\cgi-safe.ecf
cgi : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\cgi.ecf
libfcgi-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\libfcgi-safe.ecf
libfcgi : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\libfcgi.ecf
nino-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\nino-safe.ecf
nino : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\nino.ecf
standalone-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\standalone-safe.ecf
standalone : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\standalone.ecf
openshift-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\connector\openshift-safe.ecf
cgi-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\default\cgi-safe.ecf
cgi : C:\_dev\projects\ewf\ewf\library\server\wsf\default\cgi.ecf
libfcgi-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\default\libfcgi-safe.ecf
libfcgi : C:\_dev\projects\ewf\ewf\library\server\wsf\default\libfcgi.ecf
nino-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\default\nino-safe.ecf
nino : C:\_dev\projects\ewf\ewf\library\server\wsf\default\nino.ecf
standalone-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\default\standalone-safe.ecf
standalone : C:\_dev\projects\ewf\ewf\library\server\wsf\default\standalone.ecf
openshift-safe : C:\_dev\projects\ewf\ewf\library\server\wsf\default\openshift-safe.ecf
wsf_html-safe : C:\_dev\projects\ewf\ewf\library\server\wsf_html\wsf_html-safe.ecf
wsf_html : C:\_dev\projects\ewf\ewf\library\server\wsf_html\wsf_html.ecf

View File

@@ -164,11 +164,24 @@ feature -- Settings
Result := session.ignore_content_length
end
buffer_size: NATURAL
-- Set the buffer size for request. This option will
-- only be set if buffer_size is positive
buffer_size: INTEGER
-- Buffer size for request,
-- initialized from the session buffer_size value, or default 2_048.
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
default_response_charset: detachable READABLE_STRING_8
@@ -249,7 +262,7 @@ feature {NONE} -- Utilities: encoding
end
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)"
source: "[
Eiffel Software

View File

@@ -243,9 +243,13 @@ feature -- Settings
ignore_content_length: BOOLEAN
-- 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
-- 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 encoding of responses. Used if no charset is provided by the host.
@@ -405,8 +409,18 @@ feature -- Element change
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
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)"
source: "[
Eiffel Software

View File

@@ -100,6 +100,7 @@ feature -- Access
l_boundary: READABLE_STRING_8
l_is_http_1_0_request: BOOLEAN
l_is_keep_alive: BOOLEAN
l_is_chunked_transfer_encoding: BOOLEAN
retried: BOOLEAN
do
if not retried then
@@ -179,6 +180,8 @@ feature -- Access
end
-- 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.has_upload_filename then
l_upload_filename := ctx.upload_filename
@@ -195,14 +198,21 @@ feature -- Access
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
l_upload_data := ctx.form_parameters_to_url_encoded_string
headers.force (l_upload_data.count.out, "Content-Length")
else
if l_is_chunked_transfer_encoding then
-- 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
l_boundary := new_mime_boundary
l_boundary := new_mime_boundary (l_form_data)
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)
headers.extend (l_upload_data.count.out, "Content-Length")
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")
if l_is_chunked_transfer_encoding then
-- Discard chunked transfer encoding
headers.remove ("Transfer-Encoding")
l_is_chunked_transfer_encoding := False
end
end
elseif l_upload_data /= Void then
@@ -210,12 +220,16 @@ feature -- Access
if not headers.has ("Content-Type") then
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
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
check ctx.has_upload_filename end
create l_upload_file.make_with_name (l_upload_filename)
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
check l_upload_file /= Void end
end
@@ -289,12 +303,7 @@ feature -- Access
--| End of client header.
s.append (Http_end_of_header_line)
if l_upload_data /= Void then
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
--| Note that any remaining data or file to upload will be done directly via the socket
--| to optimize memory usage
@@ -315,9 +324,20 @@ feature -- Access
end
l_socket.put_string (s)
--| 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
-- i.e: not yet processed
append_file_content_to_socket (l_upload_file, l_upload_file.count, l_socket)
if l_is_chunked_transfer_encoding then
-- 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
--|-------------------------|--
@@ -498,8 +518,85 @@ feature {NONE} -- Helpers
Result := utf.utf_32_string_to_utf_8_string_8 (s)
end
append_file_content_to_socket (a_file: FILE; a_len: INTEGER; a_output: NETWORK_STREAM_SOCKET)
-- Append `a_file' content to `a_output'.
put_string_using_chunked_transfer_encoding (a_string: READABLE_STRING_8; a_chunk_size: INTEGER; a_output: NETWORK_STREAM_SOCKET)
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.
require
a_file_readable: a_file.exists and then a_file.is_access_readable
@@ -523,7 +620,44 @@ feature {NONE} -- Helpers
until
l_count = 0 or a_file.exhausted
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)
l_count := l_count - a_file.bytes_read
end
@@ -541,6 +675,7 @@ feature {NONE} -- Helpers
local
l_was_open: BOOLEAN
l_count: INTEGER
l_buffer_size: INTEGER
do
if a_len >= 0 then
l_count := a_len
@@ -555,11 +690,11 @@ feature {NONE} -- Helpers
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 (2_048))
a_file.read_stream_thread_aware (l_count.min (l_buffer_size))
a_output.append (a_file.last_string)
l_count := l_count - a_file.bytes_read
end
@@ -632,7 +767,7 @@ feature {NONE} -- Helpers
-- FIXME: check solution!
from
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.
until
n < l_chunk_size or not a_socket.readable
@@ -718,16 +853,42 @@ feature {NONE} -- Helpers
end
end
new_mime_boundary: STRING
new_mime_boundary (a_data: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]): STRING
-- New MIME boundary.
local
s: STRING
ran: RANDOM
n: INTEGER
i,j: INTEGER
do
-- FIXME: better boundary creation
Result := "----------------------------5eadfcf3bb3e"
across
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
crlf: STRING = "%R%N"
-- CR and NL sequence.
invariant
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)"
source: "[
Eiffel Software

View File

@@ -64,4 +64,9 @@ feature -- Tests
test_get_with_authentication
end
net_test_post_with_file_using_chunked_transfer_encoding
do
test_post_with_file_using_chunked_transfer_encoding
end
end

View File

@@ -253,6 +253,38 @@ feature -- Factory
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
local
sess: HTTP_CLIENT_SESSION

View File

@@ -8,7 +8,7 @@ class
inherit
ANY
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
@@ -21,7 +21,7 @@ feature {NONE} -- Initialization
make_and_launch
local
launcher: WSF_NINO_SERVICE_LAUNCHER [APPLICATION_EXECUTION]
launcher: WSF_STANDALONE_SERVICE_LAUNCHER [APPLICATION_EXECUTION]
opts: WSF_SERVICE_LAUNCHER_OPTIONS
do
create opts.make
@@ -32,24 +32,22 @@ feature {NONE} -- Initialization
launcher.launch
end
on_launched (conn: WGI_CONNECTOR)
on_launched (a_connector: WGI_STANDALONE_CONNECTOR [APPLICATION_EXECUTION])
local
e: EXECUTION_ENVIRONMENT
cmd: STRING_32
do
if attached {WGI_NINO_CONNECTOR [APPLICATION_EXECUTION]} conn as nino then
e := execution_environment
create cmd.make (32)
if attached e.item ("COMSPEC") as l_comspec then
cmd.append (l_comspec)
cmd.append ({STRING_32} " /C start ")
end
cmd.append ("http://localhost:")
cmd.append_integer (nino.port)
cmd.append_character ({CHARACTER_32} '/')
e.launch (cmd)
e := execution_environment
create cmd.make (32)
if attached e.item ("COMSPEC") as l_comspec then
cmd.append (l_comspec)
cmd.append ({STRING_32} " /C start ")
end
cmd.append ("http://localhost:")
cmd.append_integer (a_connector.port)
cmd.append_character ({CHARACTER_32} '/')
e.launch (cmd)
end
end

View File

@@ -42,12 +42,12 @@ feature {NONE} -- Initialization
m.set_title ("EWF::OpenID demo")
create s.make_empty
s.append ("<form action=%"" + req.script_url ("/openid") + "%" method=%"POST%">%N")
s.append ("<strong>OpenID identifier</strong> <input type='text' name='openid_identifier' value='' size='60'/>")
s.append ("<strong>Any OpenID identifier</strong> <input type='text' name='openid_identifier' value='' size='60'/>")
s.append ("<input type='submit' name='op' value='sign with OpenID' />")
s.append ("</form>%N")
s.append ("<form action=%"" + req.script_url ("/openid") + "%" method=%"POST%">%N")
s.append ("<strong>OpenID identifier</strong> <input type='text' name='openid_identifier' value='https://www.google.com/accounts/o8/id' size='60'/>")
s.append ("<input type='submit' name='op' value='sign with Google' />")
s.append ("<strong>OpenID identifier</strong> <input type='text' name='openid_identifier' value='https://me.yahoo.com/YOUR_YAHOO_USERNAME' size='60'/>")
s.append ("<input type='submit' name='op' value='sign with Yahoo' />")
s.append ("</form>%N")
m.set_body (s)
res.send (m)

View File

@@ -1,23 +1,26 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-12-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-12-0 http://www.eiffel.com/developers/xml/configuration-1-12-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">
<root class="APPLICATION" feature="make_and_launch"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="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"/>
</option>
<setting name="concurrency" value="thread"/>
<setting name="concurrency" value="scoop"/>
<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_nino_connector" location="..\..\..\..\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="ewsgi_standalone_connector" location="..\..\..\..\server\ewsgi\connectors\standalone\standalone-safe.ecf" readonly="false"/>
<library name="http" location="..\..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="openid" location="..\openid-safe.ecf" readonly="false"/>
<library name="wsf" location="..\..\..\..\server\wsf\wsf-safe.ecf" readonly="false"/>
<library name="wsf_nino_connector" location="..\..\..\..\server\wsf\connector\nino-safe.ecf" readonly="false"/>
<library name="wsf_standalone_connector" location="..\..\..\..\server\wsf\connector\standalone-safe.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
<target name="demo_mt" extends="demo">
<setting name="concurrency" value="thread"/>
</target>
</system>

View File

@@ -15,7 +15,7 @@
<library name="http_auth" location="..\http_authorization-safe.ecf"/>
<library name="encoders" location="..\..\..\..\text\encoder\encoder-safe.ecf"/>
<library name="wsf" location="..\..\..\wsf\wsf-safe.ecf"/>
<library name="default_nino" location="..\..\..\wsf\default\nino-safe.ecf"/>
<library name="default_standalone" location="..\..\..\wsf\default\standalone-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -2,7 +2,7 @@
## Overview
The main goal of this library is to provide a common layer on top of many different connectors.
A connector is a library used for the integration of Eiffel web server application with an underlying httpd server technology such as CGI, libFCGI, or even standalone Eiffel Web Nino (which is a httpd server written in Eiffel).
A connector is a library used for the integration of Eiffel web server application with an underlying httpd server technology such as CGI, libFCGI, or even standalone Eiffel Web Standalone (which is a httpd server written in Eiffel).
Then one can build an Eiffel web service compliant with EWSGI specification, and thus with the same code (or almost), this could be compiled to run on any available connectors.

View File

@@ -18,21 +18,36 @@
</condition>
</library>
<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\">
<file_rule>
<exclude>/httpd_stream_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
</file_rule>
<cluster name="ssl_network" location="$|ssl\" recursive="true">
<condition>
<version type="compiler" min="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
<file_rule>
<exclude>/httpd_stream_ssl_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</file_rule>
</cluster>
</cluster>
<cluster name="network_until_16_05" location=".\network\until_16_05\" recursive="false">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
<cluster name="ssl_network_until_16_05" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
</cluster>
</target>
</system>

View File

@@ -19,19 +19,33 @@
</condition>
</library>
<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\">
<file_rule>
<exclude>/httpd_stream_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
</file_rule>
<cluster name="ssl_network" location="$|ssl\" recursive="true">
<condition>
<version type="compiler" min="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
<file_rule>
<exclude>/httpd_stream_ssl_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</file_rule>
</cluster>
</cluster>
<cluster name="network_until_16_05" location=".\network\until_16_05\" recursive="false">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
<cluster name="ssl_network_until_16_05" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
</cluster>

View File

@@ -11,6 +11,16 @@
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="scoop"/>
<external_include location="$ECF_CONFIG_PATH/spec/include">
<condition>
<version type="compiler" min="16.11.0.0"/>
</condition>
</external_include>
<external_include location="$ECF_CONFIG_PATH/spec/include_until_16_05">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</external_include>
<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_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
@@ -24,29 +34,12 @@
</condition>
</library>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="network" location=".\network" recursive="false">
<cluster name="ssl_network" location="$|ssl" recursive="true">
<condition>
<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>
<exclude>/concurrency$</exclude>
<exclude>/network$</exclude>
<exclude>/no_ssl$</exclude>
<exclude>/ssl$</exclude>
<exclude>/network$</exclude>
</file_rule>
<cluster name="no_ssl" location="$|no_ssl\" recursive="true">
<condition>
@@ -74,5 +67,36 @@
</condition>
</cluster>
</cluster>
<cluster name="network" location=".\network\">
<file_rule>
<exclude>/httpd_stream_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</file_rule>
<cluster name="ssl_network" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
<file_rule>
<exclude>/httpd_stream_ssl_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</file_rule>
</cluster>
</cluster>
<cluster name="network_until_16_05" location=".\network\until_16_05\" recursive="false">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
<cluster name="ssl_network_until_16_05" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
</cluster>
</target>
</system>

View File

@@ -23,20 +23,34 @@
</condition>
</library>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<cluster name="network" location=".\network" recursive="false">
<cluster name="ssl_network" location="$|ssl" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</cluster>
<cluster name="network_until_16_05" location="$|until_16_05\">
<cluster name="network" location=".\network\">
<file_rule>
<exclude>/httpd_stream_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
<cluster name="network_from_16_11" location="$|from_16_11\">
</file_rule>
<cluster name="ssl_network" location="$|ssl\" recursive="true">
<condition>
<version type="compiler" min="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
<file_rule>
<exclude>/httpd_stream_ssl_socket_ext.e$</exclude>
<condition>
<version type="compiler" max="16.11.0.0"/>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</file_rule>
</cluster>
</cluster>
<cluster name="network_until_16_05" location=".\network\until_16_05\" recursive="false">
<condition>
<version type="compiler" max="16.11.0.0"/>
</condition>
<cluster name="ssl_network_until_16_05" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
<version type="compiler" max="16.11.0.0"/>
</condition>
</cluster>
</cluster>

View File

@@ -31,7 +31,7 @@ feature {NONE} -- Initialization
reset
do
reset_request
reset_request (False)
reset_error
if attached internal_client_socket as l_sock then
@@ -40,10 +40,18 @@ feature {NONE} -- Initialization
internal_client_socket := Void
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
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
remote_info := Void
-- FIXME: optimize to just wipe_out if needed
create method.make_empty
@@ -154,7 +162,7 @@ feature -- Settings
feature -- Status report
has_error: BOOLEAN
-- Error occurred during `analyze_request_message'
-- Error occurred during `get_request_header'
feature -- Status change
@@ -208,11 +216,21 @@ feature -- Execution
is_connected: is_connected
local
l_socket: like client_socket
l_remote_info: detachable like remote_info
l_exit: BOOLEAN
n,m: INTEGER
do
l_socket := client_socket
l_socket.set_recv_timeout (socket_recv_timeout)
-- Compute remote info once for the persistent connection.
create l_remote_info
if attached l_socket.peer_address as l_addr then
l_remote_info.addr := l_addr.host_address.host_address
l_remote_info.hostname := l_addr.host_address.host_name
l_remote_info.port := l_addr.port
end
remote_info := l_remote_info
check
socket_attached: l_socket /= Void
socket_valid: l_socket.is_open_read and then l_socket.is_open_write
@@ -237,7 +255,7 @@ feature -- Execution
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
reset_request (not l_exit)
end
if l_exit and has_error and not l_socket.is_closed then
l_socket.close
@@ -251,10 +269,9 @@ feature -- Execution
is_connected: is_connected
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
no_error: not has_error
remote_info_set: remote_info /= Void
local
l_remote_info: detachable like remote_info
l_socket: like client_socket
l_is_ready: BOOLEAN
do
debug ("dbglog")
if a_is_reusing_connection then
@@ -276,50 +293,34 @@ feature -- Execution
dbglog ("execute_request socket=" + l_socket.descriptor.out + " ENTER")
end
if a_is_reusing_connection then
--| set by default 5 seconds.
l_socket.set_recv_timeout (keep_alive_timeout) -- in seconds!
l_is_ready := socket_has_incoming_data (l_socket)
else
l_is_ready := True
end
-- Try to get request header.
-- If the request is reusing persistent connection, use `keep_alive_timeout',
-- otherwise `socket_recv_timeout'.
get_request_header (l_socket, a_is_reusing_connection)
if l_is_ready then
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
l_remote_info.hostname := l_addr.host_address.host_name
l_remote_info.port := l_addr.port
remote_info := l_remote_info
end
analyze_request_message (l_socket)
if has_error then
-- check catch_bad_incoming_connection: False end
if has_error then
if a_is_reusing_connection and then request_header.is_empty then
-- Close persistent connection, since no new connection occurred in the delay `keep_alive_timeout'.
debug ("dbglog")
dbglog ("execute_request socket=" + l_socket.descriptor.out + "} close persistent connection.")
end
else
if is_verbose then
log (request_header + "%NWARNING: invalid HTTP incoming request", warning_level)
end
process_bad_request (l_socket)
is_persistent_connection_requested := False
else
if is_verbose then
log (request_header, information_level)
end
process_request (l_socket)
end
else
check is_reusing_connection: a_is_reusing_connection end
-- Close persistent connection, since no new connection occurred in the delay `keep_alive_timeout'.
is_persistent_connection_requested := False
debug ("dbglog")
dbglog ("execute_request socket=" + l_socket.descriptor.out + "} close persistent connection.")
end
end
is_persistent_connection_requested := False
else
if is_verbose then
log (request_header, information_level)
end
process_request (l_socket)
end
debug ("dbglog")
dbglog ("execute_request {" + l_socket.descriptor.out + "} LEAVE")
end
debug ("dbglog")
dbglog ("execute_request {" + l_socket.descriptor.out + "} LEAVE")
end
end
end
@@ -377,8 +378,11 @@ feature -- Request processing
feature -- Parsing
analyze_request_message (a_socket: HTTPD_STREAM_SOCKET)
-- Analyze message extracted from `a_socket' as HTTP request
get_request_header (a_socket: HTTPD_STREAM_SOCKET; a_is_reusing_connection: BOOLEAN)
-- Analyze message extracted from `a_socket' as HTTP request.
-- If `a_is_reusing_connection' is True, then first use
-- Note: it reads from socket.
-- Note: it updates `request_header' and `request_header_map', and eventually `is_persistent_connection_requested'.
require
input_readable: a_socket /= Void and then a_socket.is_open_read
local
@@ -391,76 +395,90 @@ feature -- Parsing
do
create txt.make (64)
request_header := txt
l_is_verbose := is_verbose
if
not has_error and then
a_socket.readable
then
if a_is_reusing_connection then
a_socket.set_recv_timeout (keep_alive_timeout) -- in seconds!
else
a_socket.set_recv_timeout (socket_recv_timeout) -- FIXME: return a 408 Request Timeout response ..
end
if
attached next_line (a_socket) as l_request_line and then
not l_request_line.is_empty
not l_request_line.is_empty and then
not has_error
then
txt.append (l_request_line)
txt.append_character ('%N')
analyze_request_line (l_request_line)
if not has_error then
if a_is_reusing_connection then
-- Restore normal recv timeout!
a_socket.set_recv_timeout (socket_recv_timeout) -- FIXME: return a 408 Request Timeout response ..
end
from
line := next_line (a_socket)
until
line = Void or end_of_stream or has_error
loop
n := line.count
debug ("ew_standalone")
if l_is_verbose then
log (line, debug_level)
end
end
pos := line.index_of (':', 1)
if pos > 0 then
k := line.substring (1, pos - 1)
if line [pos + 1].is_space then
pos := pos + 1
end
if line [n] = '%R' then
n := n - 1
end
val := line.substring (pos + 1, n)
request_header_map.put (val, k)
end
txt.append (line)
txt.append_character ('%N')
if line.is_empty or else line [1] = '%R' then
end_of_stream := True
else
line := next_line (a_socket)
end
end
-- Except for HTTP/1.0, persistent connection is the default.
is_persistent_connection_requested := True
if is_http_version_1_0 then
is_persistent_connection_requested := attached request_header_map.item ("Connection") as l_connection and then
l_connection.is_case_insensitive_equal_general ("keep-alive")
else
-- By default HTTP:1/1 support persistent connection.
if attached request_header_map.item ("Connection") as l_connection then
if l_connection.is_case_insensitive_equal_general ("close") then
is_persistent_connection_requested := False
end
else
is_persistent_connection_requested := True
end
end
end
else
report_error ("Bad header line (empty)")
end
else
report_error ("Socket is not readable")
end
l_is_verbose := is_verbose
if not has_error then
from
line := next_line (a_socket)
until
line = Void or end_of_stream or has_error
loop
n := line.count
debug ("ew_standalone")
if l_is_verbose then
log (line, debug_level)
end
end
pos := line.index_of (':', 1)
if pos > 0 then
k := line.substring (1, pos - 1)
if line [pos + 1].is_space then
pos := pos + 1
end
if line [n] = '%R' then
n := n - 1
end
val := line.substring (pos + 1, n)
request_header_map.put (val, k)
end
txt.append (line)
txt.append_character ('%N')
if line.is_empty or else line [1] = '%R' then
end_of_stream := True
else
line := next_line (a_socket)
end
end
-- Except for HTTP/1.0, persistent connection is the default.
is_persistent_connection_requested := True
if is_http_version_1_0 then
is_persistent_connection_requested := attached request_header_map.item ("Connection") as l_connection and then
l_connection.is_case_insensitive_equal_general ("keep-alive")
else
-- By default HTTP:1/1 support persistent connection.
if attached request_header_map.item ("Connection") as l_connection then
if l_connection.is_case_insensitive_equal_general ("close") then
is_persistent_connection_requested := False
end
else
is_persistent_connection_requested := True
end
end
end
end
analyze_request_line (line: STRING)
-- Analyze `line' as a HTTP request line
-- Analyze `line' as a HTTP request line.
-- note: may update `has_error'.
require
valid_line: line /= Void and then not line.is_empty
local
@@ -488,28 +506,26 @@ feature -- Parsing
next_line (a_socket: HTTPD_STREAM_SOCKET): detachable STRING
-- Next line fetched from `a_socket' is available.
-- note: may update `has_error'.
require
not_has_error: not has_error or is_verbose
not_has_error: not has_error
is_readable: a_socket.is_open_read
local
retried: BOOLEAN
do
if retried then
report_error ("Rescue in next_line")
a_socket.close
Result := Void
elseif
a_socket.readable and then
socket_has_incoming_data (a_socket)
then
a_socket.read_line_thread_aware
elseif a_socket.readable then
a_socket.read_line_noexception
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.
if not a_socket.socket_ok then
if a_socket.was_error then
report_error ("Socket error")
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
else
@@ -520,6 +536,7 @@ feature -- Parsing
end
end
rescue
-- In case of network error exception (as EiffelNet reports error raising exception)
retried := True
retry
end
@@ -558,7 +575,9 @@ feature {NONE} -- Helpers
a_socket.readable
do
-- FIXME: check if both are really needed.
Result := a_socket.ready_for_reading and then a_socket.has_incoming_data
-- Result := a_socket.ready_for_reading --and then a_socket.has_incoming_data
-- Result := a_socket.has_incoming_data
Result := True
end
invariant

View File

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

View File

@@ -1,369 +1,235 @@
note
description: "[
Summary description for {HTTPD_STREAM_SOCKET}
that can be used for http or https connection.
]"
description: "Summary description for {HTTPD_STREAM_SOCKET}."
date: "$Date$"
revision: "$Revision$"
class
HTTPD_STREAM_SOCKET
inherit
NETWORK_STREAM_SOCKET
HTTPD_STREAM_SOCKET_EXT
create
make_server_by_address_and_port,
make_server_by_port,
make_client_by_address_and_port,
make_client_by_port,
make_from_separate,
make_empty
make, make_empty,
make_client_by_port, make_client_by_address_and_port,
make_server_by_port, make_server_by_address_and_port, make_loopback_server_by_port
create {HTTPD_STREAM_SOCKET}
make
create {NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
feature -- Input
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
read_character_noexception
-- Read a new character.
-- Make result available in `last_character'.
-- No exception raised!
do
create {TCP_STREAM_SOCKET} socket.make_server_by_address_and_port (an_address, a_port)
read_to_managed_pointer_noexception (socket_buffer, 0, character_8_bytes)
if bytes_read /= character_8_bytes then
socket_error := "Peer closed connection"
else
last_character := socket_buffer.read_character (0)
socket_error := Void
end
end
make_server_by_port (a_port: INTEGER)
read_stream_noexception (nb_char: INTEGER)
-- Read a string of at most `nb_char' characters.
-- Make result available in `last_string'.
local
ext: C_STRING
return_val: INTEGER
do
create {TCP_STREAM_SOCKET} socket.make_server_by_port (a_port)
create ext.make_empty (nb_char + 1)
return_val := c_read_stream_noexception (descriptor, nb_char, ext.item)
bytes_read := return_val
if return_val >= 0 then
ext.set_count (return_val)
last_string := ext.substring (1, return_val)
else
socket_error := "Peer error [0x" + return_val.to_hex_string + "]"
last_string.wipe_out
end
end
make_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
read_to_managed_pointer_noexception (p: MANAGED_POINTER; start_pos, nb_bytes: INTEGER)
-- Read at most `nb_bytes' bound bytes and make result
-- available in `p' at position `start_pos'.
-- No exception raised!
do
create {TCP_STREAM_SOCKET} socket.make_client_by_address_and_port (an_address, a_port)
read_into_pointer_noexception (p.item, start_pos, nb_bytes)
end
make_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING)
read_line_noexception
-- Read a line of characters (ended by a new_line).
-- No exception raised!
local
l_last_string: like last_string
do
create {TCP_STREAM_SOCKET} socket.make_client_by_port (a_peer_port, a_peer_host)
create l_last_string.make (512)
read_character_noexception
from
until
last_character = '%N' or else was_error
loop
l_last_string.extend (last_character)
read_character_noexception
end
last_string := l_last_string
end
make_from_separate (s: separate HTTPD_STREAM_SOCKET)
peek_stream_noexception (nb_char: INTEGER)
-- Read a string of at most `nb_char' characters without removing the data from the queue.
-- Make result available in last_string.
-- No exception raised!
require
descriptor_available: s.descriptor_available
readable: readable
socket_exists: exists
local
ext: C_STRING
retval: INTEGER
l: like last_string
do
create {TCP_STREAM_SOCKET} socket.make_from_separate (s.socket)
end
make_empty
do
create {TCP_STREAM_SOCKET} socket.make_empty
end
retrieve_socket (s: HTTPD_STREAM_SOCKET): INTEGER
do
Result := s.socket.descriptor
end
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)
create ext.make_empty (nb_char + 1)
retval := c_recv_noexception (descriptor, ext.item, nb_char, c_peekmsg)
if retval = 0 then
last_string.wipe_out
socket_error := Void
elseif retval > 0 then
ext.set_count (retval)
l := last_string
l.wipe_out
l.grow (retval)
l.set_count (retval)
ext.read_substring_into (l, 1, retval)
socket_error := Void
else
last_string.wipe_out
socket_error := "Socket error (MSG_PEEK)"
end
ensure
last_string_not_void: last_string /= Void
end
set_connect_timeout (n: INTEGER)
do
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
l_socket.set_connect_timeout (n)
end
end
feature {NONE} -- Input
set_accept_timeout (n: INTEGER)
do
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
l_socket.set_accept_timeout (n)
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
do
Result := socket.last_string
end
last_character: CHARACTER
do
Result := socket.last_character
end
peer_address: detachable NETWORK_SOCKET_ADDRESS
-- Peer address of socket
do
if attached {NETWORK_SOCKET_ADDRESS} socket.peer_address as l_peer_address then
Result := l_peer_address
end
end
feature -- Input
read_line_thread_aware
do
socket.read_line_thread_aware
end
read_stream_thread_aware (nb: INTEGER)
do
socket.read_stream_thread_aware (nb)
end
read_stream (nb: INTEGER)
do
socket.read_stream (nb)
end
read_character
do
socket.read_character
end
peek_stream (nb_char: INTEGER)
read_into_pointer_noexception (p: POINTER; start_pos, nb_bytes: INTEGER_32)
-- Read at most `nb_bytes' bound bytes and make result
-- available in `p' at position `start_pos'.
-- No exception raised!
require
nb_char_positive: nb_char > 0
p_not_void: p /= default_pointer
nb_bytes_non_negative: nb_bytes >= 0
is_readable: readable
local
l_read: INTEGER_32
l_last_read: INTEGER_32
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
l_socket.peek_stream (nb_char)
from
l_last_read := 1
until
l_read = nb_bytes or l_last_read <= 0
loop
l_last_read := c_read_stream_noexception (descriptor, nb_bytes - l_read, p + start_pos + l_read)
if l_last_read >= 0 then
l_read := l_read + l_last_read
end
end
end
bytes_read: INTEGER
do
Result := socket.bytes_read
bytes_read := l_read
ensure
bytes_read_updated: 0 <= bytes_read and bytes_read <= nb_bytes
end
feature -- Output
send_message (a_msg: STRING)
bytes_sent: INTEGER
-- Last number of bytes sent by `put_managed_pointer_noexception' (i.e `put_pointer_content_noexception').
put_managed_pointer_noexception (p: MANAGED_POINTER; start_pos, nb_bytes: INTEGER_32)
-- Put data of length `nb_bytes' pointed by `start_pos' index in `p' at
-- current position.
-- Update `bytes_sent'.
-- No exception raised!
require
p_not_void: p /= Void
p_large_enough: p.count >= nb_bytes + start_pos
nb_bytes_non_negative: nb_bytes >= 0
extendible: extendible
do
put_string (a_msg)
put_pointer_content_noexception (p.item, start_pos, nb_bytes)
end
put_pointer_content_noexception (a_pointer: POINTER; a_offset, a_byte_count: INTEGER)
-- Write `a_byte_count' bytes to the socket.
-- The data is taken from the memory area pointed to by `a_pointer', at offset `a_offset'.
-- Update `bytes_sent'.
-- No exception raised!
require
pointer_not_void: a_pointer /= default_pointer
byte_count_non_negative: a_byte_count >= 0
extendible: extendible
local
l_sent: INTEGER_32
l_last_sent: INTEGER_32
do
from
l_last_sent := 1
until
l_sent = a_byte_count or l_last_sent <= 0
loop
l_last_sent := c_put_stream_noexception (descriptor, a_pointer + a_offset + l_sent, a_byte_count - l_sent)
if l_last_sent >= 0 then
l_sent := l_sent + l_last_sent
elseif l_sent < a_byte_count then
socket_error := "No all bytes sent!"
end
end
bytes_sent := l_sent
ensure
bytes_sent_updated: not was_error implies (0 <= bytes_sent and bytes_sent <= a_byte_count)
end
put_character_noexception (c: CHARACTER)
-- Write character `c' to socket.
do
socket_buffer.put_character (c, 0)
put_managed_pointer_noexception (socket_buffer, 0, character_8_bytes)
end
put_readable_string_8_noexception (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
-- No exception raised!
local
ext: C_STRING
do
create ext.make (s)
put_managed_pointer_noexception (ext.managed_data, 0, s.count)
end
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
local
ext: C_STRING
do
if attached {TCP_STREAM_SOCKET} socket as l_tcp_stream_socket then
l_tcp_stream_socket.put_readable_string_8 (s)
else
put_string (s)
end
create ext.make (s)
put_managed_pointer (ext.managed_data, 0, s.count)
end
put_string (s: STRING)
do
socket.put_string (s)
end
put_character (c: CHARACTER)
do
socket.put_character (c)
end
feature -- Status Report
descriptor_available: BOOLEAN
-- Is descriptor available?
do
Result := socket.descriptor_available
end
descriptor: INTEGER
do
Result := socket.descriptor
end
port: INTEGER
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.port
end
end
exists: BOOLEAN
do
Result := socket.exists
end
is_blocking: BOOLEAN
do
Result := socket.is_blocking
end
is_bound: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.is_bound
end
end
is_connected: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.is_connected
end
end
is_created: BOOLEAN
do
if attached {NETWORK_SOCKET} socket as l_socket then
Result := l_socket.is_created
end
end
socket_ok: BOOLEAN
do
Result := socket.socket_ok
end
is_open_read: BOOLEAN
do
Result := socket.is_open_read
end
is_open_write: BOOLEAN
do
Result := socket.is_open_write
end
is_closed: BOOLEAN
do
Result := socket.is_closed
end
is_readable: BOOLEAN
do
Result := socket.is_readable
end
cleanup
do
socket.cleanup
end
ready_for_writing: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.ready_for_writing
end
end
connect
do
socket.connect
end
close
do
socket.close
end
listen (a_queue: INTEGER)
do
socket.listen (a_queue)
end
accept
do
socket.accept
end
accept_to (other: separate HTTPD_STREAM_SOCKET)
-- Accept a new connection on listen socket.
-- Socket of accepted connection is available in `other'.
do
if
attached {NETWORK_STREAM_SOCKET} socket as l_socket and then
attached {separate NETWORK_STREAM_SOCKET} other.socket as l_other_socket
then
l_socket.accept_to (l_other_socket)
end
end
set_blocking
do
socket.set_blocking
end
set_non_blocking
do
socket.set_non_blocking
end
readable: BOOLEAN
do
Result := socket.readable
end
feature -- Status report
has_incoming_data: BOOLEAN
-- Check if Current has available data to be read.
-- note: no data will not be removed from the queue.
require
socket_exists: exists
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.has_incoming_data
end
peek_stream_noexception (1)
Result := last_string.count = 1
end
ready_for_reading: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.ready_for_reading
end
end
try_ready_for_reading: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.try_ready_for_reading
end
end
accepted: detachable HTTPD_STREAM_SOCKET
do
if attached {NETWORK_STREAM_SOCKET} socket.accepted as l_accepted then
create Result.make (l_accepted)
end
end
feature {HTTPD_STREAM_SOCKET} -- Implementation
make (a_socket: STREAM_SOCKET)
do
socket := a_socket
end
socket: STREAM_SOCKET
network_stream_socket: detachable NETWORK_STREAM_SOCKET
do
if attached {NETWORK_STREAM_SOCKET} socket as s then
Result := s
end
end
;note
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: "[
@@ -373,4 +239,5 @@ feature {HTTPD_STREAM_SOCKET} -- Implementation
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,13 @@
note
description: "[
Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD.
]"
deferred class
HTTPD_STREAM_SOCKET_EXT
feature {NONE} -- No-Exception network operation
end

View File

@@ -1,8 +1,5 @@
note
description: "[
Summary description for {HTTPD_STREAM_SSL_SOCKET}
that can be used for http or https connection.
]"
description: "SSL tcp stream socket."
date: "$Date$"
revision: "$Revision$"
@@ -11,159 +8,142 @@ class
inherit
HTTPD_STREAM_SOCKET
undefine
make_empty, make_from_descriptor_and_address,
error_number,
readstream, read_stream,
read_into_pointer,
read_to_managed_pointer,
put_pointer_content,
write, send,
close_socket,
connect, shutdown,
do_accept
redefine
port,
is_bound,
ready_for_writing,
ready_for_reading,
try_ready_for_reading,
put_readable_string_8,
make_empty
put_managed_pointer,
read_stream_noexception,
read_into_pointer_noexception,
put_pointer_content_noexception
end
SSL_NETWORK_STREAM_SOCKET
redefine
put_managed_pointer -- Redefine to allow support of compiler before 16.11.
end
HTTPD_STREAM_SSL_SOCKET_EXT
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_empty
make, make_empty,
make_client_by_port, make_client_by_address_and_port,
make_server_by_port, make_server_by_address_and_port, make_loopback_server_by_port
create {HTTPD_STREAM_SOCKET}
make
create {SSL_NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
feature -- Input
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)
read_stream_noexception (nb_char: INTEGER)
-- Read a string of at most `nb_char' characters.
-- Make result available in `last_string'.
local
l_socket: SSL_TCP_STREAM_SOCKET
ext: C_STRING
return_val: INTEGER
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_fn, a_key_fn)
if
attached context as l_context and then
attached l_context.last_ssl as l_ssl
then
create ext.make_empty (nb_char + 1)
return_val := l_ssl.read (ext.item , nb_char)
bytes_read := return_val
if return_val >= 0 then
ext.set_count (return_val)
last_string := ext.substring (1, return_val)
else
socket_error := "Peer error [0x" + return_val.to_hex_string + "]"
last_string.wipe_out
end
else
check has_context: False end
end
end
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_fn, a_key_fn)
end
feature {NONE} -- Input
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)
read_into_pointer_noexception (p: POINTER; start_pos, nb_bytes: INTEGER_32)
-- Read at most `nb_bytes' bound bytes and make result
-- available in `p' at position `start_pos'.
-- No exception raised!
local
l_socket: SSL_TCP_STREAM_SOCKET
l_read: INTEGER
l_last_read: INTEGER
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_fn, a_key_fn)
end
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_fn, a_key_fn)
end
make_empty
-- <Precursor>.
do
create {SSL_TCP_STREAM_SOCKET} socket.make_empty
if
attached context as l_context and then
attached l_context.last_ssl as l_ssl
then
from
l_last_read := 1
until
l_read = nb_bytes or l_last_read <= 0
loop
l_last_read := l_ssl.read (p + start_pos + l_read, nb_bytes - l_read)
if l_last_read >= 0 then
l_read := l_read + l_last_read
end
end
bytes_read := l_read
else
check has_context: False end
end
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- <Precursor>
put_managed_pointer (p: MANAGED_POINTER; start_pos, nb_bytes: INTEGER)
-- Put data of length `nb_bytes' pointed by `start_pos' index in `p' at
-- current position.
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
l_ssl_socket.put_readable_string_8 (s)
else
Precursor (s)
end
Precursor {HTTPD_STREAM_SOCKET} (p, start_pos, nb_bytes)
end
feature -- Status Report
port: INTEGER
-- <Precursor>
put_pointer_content_noexception (a_pointer: POINTER; a_offset, a_byte_count: INTEGER)
-- Write `a_byte_count' bytes to the socket.
-- The data is taken from the memory area pointed to by `a_pointer', at offset `a_offset'.
-- Update `bytes_sent'.
-- No exception raised!
local
l_bytes_sent: INTEGER
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.port
else
Result := Precursor
end
end
is_bound: BOOLEAN
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.is_bound
else
Result := Precursor
end
end
ready_for_writing: BOOLEAN
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.ready_for_writing
else
Result := Precursor
end
end
ready_for_reading: BOOLEAN
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.ready_for_reading
else
Result := Precursor
end
end
try_ready_for_reading: BOOLEAN
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.try_ready_for_reading
else
Result := Precursor
end
end
feature {HTTPD_STREAM_SOCKET} -- Implementation
set_certificates (a_crt_filename, a_key_filename: detachable READABLE_STRING_GENERAL)
do
if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then
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)
if
attached context as l_context and then
attached l_context.last_ssl as l_ssl
then
l_bytes_sent := ssl_write (l_ssl, a_pointer + a_offset, a_byte_count)
if l_bytes_sent < a_byte_count then
socket_error := "No all bytes sent!"
end
bytes_sent := l_bytes_sent
else
check has_last_ssl: False end
end
end
feature -- Element change
set_certificate_filenames (a_crt_filename, a_key_filename: detachable READABLE_STRING_GENERAL)
do
if a_crt_filename /= Void then
set_certificate_file_name (a_crt_filename)
end
if a_key_filename /= Void then
set_key_file_name (a_key_filename)
end
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat 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

View File

@@ -0,0 +1,23 @@
note
description: "[
Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD.
]"
deferred class
HTTPD_STREAM_SSL_SOCKET_EXT
feature {NONE} -- SSL bridge
ssl_write (a_ssl: SSL; a_pointer: POINTER; a_byte_count: INTEGER): INTEGER
do
Result := a_ssl.write (a_pointer, a_byte_count)
if a_ssl.was_error then
if Result >= 0 then
Result := -1
end
end
end
end

View File

@@ -1,73 +0,0 @@
note
description: "SSL tcp stream socket."
date: "$Date$"
revision: "$Revision$"
class
SSL_TCP_STREAM_SOCKET
inherit
SSL_NETWORK_STREAM_SOCKET
create
make_server_by_address_and_port, make_server_by_port,
make_client_by_address_and_port, make_client_by_port,
make_empty
create {SSL_NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
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
send_message (a_msg: STRING)
do
put_string (a_msg)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
local
ext: C_STRING
do
create ext.make (s)
put_managed_pointer (ext.managed_data, 0, s.count)
end
feature -- Status report
try_ready_for_reading: BOOLEAN
-- Is data available for reading from the socket right now?
require
socket_exists: exists
local
retval: INTEGER
do
retval := c_select_poll_with_timeout (descriptor, True, 0)
Result := (retval > 0)
end
feature {NONE}-- Implementation
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -1,153 +0,0 @@
note
description: "Summary description for {TCP_STREAM_SOCKET}."
date: "$Date$"
revision: "$Revision$"
class
TCP_STREAM_SOCKET
inherit
NETWORK_STREAM_SOCKET
redefine
make
end
TCP_STREAM_SOCKET_EXT
create
make_server_by_address_and_port,
make_server_by_port,
make_client_by_address_and_port,
make_client_by_port,
make_from_separate,
make_empty
create {NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
make
-- Create a network stream socket.
do
Precursor
debug
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
make_from_separate (s: separate STREAM_SOCKET)
require
descriptor_available: s.descriptor_available
do
create_from_descriptor (s.descriptor)
end
feature -- Basic operation
peek_stream (nb_char: INTEGER)
-- Read a string of at most `nb_char' characters without removing the data from the queue.
-- Make result available in last_string.
require
readable: readable
socket_exists: exists
local
ext: C_STRING
retval: INTEGER
l: like last_string
do
create ext.make_empty (nb_char + 1)
retval := clib_recv (descriptor, ext.item, nb_char, c_peekmsg)
if retval = 0 then
last_string.wipe_out
socket_error := Void
elseif retval > 0 then
ext.set_count (retval)
l := last_string
l.wipe_out
l.grow (retval)
l.set_count (retval)
ext.read_substring_into (l, 1, retval)
socket_error := Void
else
last_string.wipe_out
socket_error := "Socket error (MSG_PEEK)"
end
ensure
last_string_not_void: last_string /= Void
end
send_message (a_msg: STRING)
do
put_string (a_msg)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
local
ext: C_STRING
do
create ext.make (s)
put_managed_pointer (ext.managed_data, 0, s.count)
end
feature -- Status report
has_incoming_data: BOOLEAN
-- Check if Current has available data to be read.
-- note: no data will not be removed from the queue.
require
socket_exists: exists
do
peek_stream (1)
Result := last_string.count = 1
end
try_ready_for_reading: BOOLEAN
-- Is data available for reading from the socket right now?
require
socket_exists: exists
local
retval: INTEGER
do
retval := c_select_poll_with_timeout (descriptor, True, 0)
Result := (retval > 0)
end
feature {NONE} -- C implementation
clib_recv (a_fd: INTEGER; buf: POINTER; len: INTEGER; flags: INTEGER): INTEGER
-- External routine to receive at most `len' number of
-- bytes into buffer `buf' from socket `fd' with `flags' options.
external
"C inline"
alias
"[
return (EIF_INTEGER) recv ((int) $a_fd, (char *) $buf, (int) $len, (int) $flags);
]"
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

View File

@@ -0,0 +1,160 @@
note
description: "[
Until 16.05, the EiffelNet socket interface DOES NOT have
- make_server_by_address_and_port
- recv_timeout
- send_timeout.
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD.
]"
deferred class
HTTPD_STREAM_SOCKET_EXT
inherit
PLATFORM
feature -- Initialization
make
deferred
end
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
set_address (create {like address_type}.make_from_address_and_port (a_address, a_port))
bind
end
feature -- Basic operation
bind
deferred
end
feature -- Access
set_address (addr: detachable like address_type)
deferred
end
address_type: NETWORK_SOCKET_ADDRESS
deferred
end
descriptor: INTEGER
-- Socket descriptor of current socket
deferred
end
feature -- Socket Recv and Send timeout.
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
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 use %"ew_httpd_net.h%""
alias
"[
#ifdef SO_RCVTIMEO
int flag = SO_RCVTIMEO;
#else
int flag = 0x1006;
#endif
#ifdef EIF_WINDOWS
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
setsockopt((int) $a_fd, (int) $a_level, flag, (char *) &arg, sizeof(arg));
#else
struct timeval tv;
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
tv.tv_usec = 0;
setsockopt((int) $a_fd, (int) $a_level, flag, (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 use %"ew_httpd_net.h%""
alias
"[
#ifdef SO_RCVTIMEO
int flag = SO_SNDTIMEO;
#else
int flag = 0x1005;
#endif
#ifdef EIF_WINDOWS
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
setsockopt((int) $a_fd, (int) $a_level, flag, (char *) &arg, sizeof(arg));
#else
struct timeval tv;
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
tv.tv_usec = 0;
setsockopt((int) $a_fd, (int) $a_level, flag, (struct timeval *)&tv, sizeof(struct timeval));
#endif
]"
end
feature {NONE} -- No-Exception network operation
c_recv_noexception (a_fd: INTEGER; buf: POINTER; len: INTEGER; flags: INTEGER): INTEGER
-- External routine to read a `len' number of characters
-- into buffer `buf' from socket `a_fd' with options `flags'.
external
"C inline use %"ew_httpd_net.h%""
alias
"[
recv((int) $a_fd, (char *) $buf, (int) $len, (int) $flags)
]"
end
c_read_stream_noexception (a_fd: INTEGER; len: INTEGER; buf: POINTER): INTEGER
-- External routine to read a `len' number of characters
-- into buffer `buf' from socket `a_fd'.
do
Result := c_recv_noexception (a_fd, buf, len, 0)
end
c_put_stream_noexception (a_fd: INTEGER; buf: POINTER; len: INTEGER): INTEGER
-- External routine to write stream pointed by `s' of
-- length `length' to socket `fd'.
-- Note: does not raise exception on error, but return error value as Result.
external
"C inline use %"ew_httpd_net.h%""
alias
"[
send((int) $a_fd, (char *) $buf, (int) $len, (int) 0)
]"
end
end

View File

@@ -0,0 +1,41 @@
note
description: "[
Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD.
]"
deferred class
HTTPD_STREAM_SSL_SOCKET_EXT
feature {NONE} -- SSL bridge
ssl_write (a_ssl: SSL; a_pointer: POINTER; a_byte_count: INTEGER): INTEGER
do
-- In delivery until 16.05
-- SSL.write does not return any value!
-- So let's use `c_ssl_write' from Current class
-- instead of:
-- a_ssl.write (a_pointer, a_byte_count)
Result := c_ssl_write (a_ssl.ptr, a_pointer, a_byte_count)
if a_ssl.was_error then
-- Until 16.05, there is no error check for `SSL.write'
-- so nothing can be done here.
if Result >= 0 then
Result := -1
end
end
end
c_ssl_write (an_ssl_ptr: POINTER; buffer: POINTER; nb_bytes: INTEGER_32): INTEGER_32
-- External call to SSL_write
-- (export status {NONE})
external
"C use %"eif_openssl.h%""
alias
"SSL_write"
end
end

View File

@@ -1,95 +0,0 @@
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
c_set_sock_recv_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
-- C routine to set socket option `SO_RCVTIMEO' with `a_timeout_seconds' seconds.
external
"C inline"
alias
"[
#ifdef EIF_WINDOWS
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
setsockopt((SOCKET) $a_fd, (int) $a_level, (int) SO_RCVTIMEO, (char *) &arg, sizeof(arg));
#else
struct timeval tv;
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
setsockopt((int) $a_fd, (int) $a_level, (int) SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
#endif
]"
end
c_set_sock_send_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
-- C routine to set socket option `SO_SNDTIMEO' with `a_timeout_seconds' seconds.
external
"C inline"
alias
"[
#ifdef EIF_WINDOWS
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
setsockopt((SOCKET) $a_fd, (int) $a_level, (int) SO_SNDTIMEO, (char *) &arg, sizeof(arg));
#else
struct timeval tv;
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
setsockopt((int) $a_fd, (int) $a_level, (int) SO_SNDTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
#endif
]"
end
end

View File

@@ -0,0 +1,52 @@
/*
indexing
description: "Functions used by the EiffelWeb httpd networking classes. "
copyright: "Copyright (c) 2011-2016, Jocelyn Fiat, 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
]"
*/
#ifndef _ew_httpd_net_h_
#define _ew_httpd_net_h_
#include "eif_config.h"
#ifdef EIF_WINDOWS
# ifndef _WINSOCKAPI_
# define FD_SETSIZE 256
# include <winsock2.h>
# include <Ws2tcpip.h>
# include <stdio.h>
# endif
#else /* unix-specific */
# include <sys/socket.h>
# include <unistd.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* extern declarations ... */
#ifdef EIF_WINDOWS
extern int setsockopt(int, int, int, char*, int);
extern int recv(int, char *, int, int);
extern int send(int, char *, int, int);
#else
extern int setsockopt(int, int, int, const void*, socklen_t);
extern ssize_t recv(int, void *, size_t, int);
extern ssize_t send(int, const void *, size_t, int);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -20,13 +20,19 @@ create
feature {NONE} -- Factory
new_listening_socket (a_addr: detachable INET_ADDRESS; a_http_port: INTEGER): HTTPD_STREAM_SOCKET
local
s_ssl: HTTPD_STREAM_SSL_SOCKET
do
if configuration.is_secure then
if a_addr /= Void then
create {HTTPD_STREAM_SSL_SOCKET} Result.make_ssl_server_by_address_and_port (a_addr, a_http_port, configuration.ssl_protocol, configuration.ca_crt, configuration.ca_key)
create s_ssl.make_server_by_address_and_port (a_addr, a_http_port)
Result := s_ssl
else
create {HTTPD_STREAM_SSL_SOCKET} Result.make_ssl_server_by_port (a_http_port, configuration.ssl_protocol, configuration.ca_crt, configuration.ca_key)
create s_ssl.make_server_by_port (a_http_port)
end
s_ssl.set_tls_protocol (configuration.ssl_protocol)
s_ssl.set_certificate_filenames (configuration.ca_crt, configuration.ca_key)
Result := s_ssl
else
Result := Precursor (a_addr, a_http_port)
end

View File

@@ -35,10 +35,10 @@ feature {NONE} -- Initialization
initialize_server (server)
end
make_with_base (a_base: like base)
make_with_base (a_base: detachable separate READABLE_STRING_8)
-- Create current standalone connector with base url `a_base'
require
a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies a_base.starts_with ("/")
a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies is_valid_base (a_base)
do
make
set_base (a_base)
@@ -109,7 +109,8 @@ feature -- Status report
feature -- Callbacks
on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]]]
-- Actions triggered when launched
-- Actions triggered when launched.
-- WARNING: only supported for now with SCOOP concurrency mode. [2016-oct-07]
feature -- Event
@@ -123,16 +124,25 @@ feature -- Event
feature -- Element change
set_base (v: like base)
set_base (v: detachable separate READABLE_STRING_8)
-- Set base url `base' to `v'.
require
b_starts_with_slash: (v /= Void and then not v.is_empty) implies v.starts_with ("/")
b_starts_with_slash: (v /= Void and then not v.is_empty) implies is_valid_base (v)
do
base := v
if v = Void then
base := Void
else
create {STRING_8} base.make_from_separate (v)
end
ensure
valid_base: (attached base as l_base and then not l_base.is_empty) implies l_base.starts_with ("/")
end
is_valid_base (v: separate READABLE_STRING_8): BOOLEAN
do
Result := not v.is_whitespace and then v[1] = '/'
end
set_port_number (a_port_number: INTEGER)
-- Set port number to `a_port_number'.
require
@@ -141,6 +151,13 @@ feature -- Element change
set_port_on_configuration (a_port_number, configuration)
end
set_socket_recv_timeout (a_nb_seconds: INTEGER)
require
a_nb_seconds_positive_or_zero: a_nb_seconds >= 0
do
set_socket_recv_timeout_on_configuration (a_nb_seconds, configuration)
end
set_max_concurrent_connections (nb: INTEGER)
-- Set maximum concurrent connections to `nb'.
require
@@ -164,6 +181,13 @@ feature -- Element change
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 web server listening.
do
@@ -189,12 +213,12 @@ feature -- Events
require
obs.started -- SCOOP wait condition.
do
-- FIXME: this works only with SCOOP concurrency mode. [2016-oct-07]
if obs.port > 0 then
on_launched (obs.port)
end
end
feature {NONE} -- Implementation
server_controller (a_server: like server): separate HTTPD_CONTROLLER
@@ -238,6 +262,11 @@ feature {NONE} -- Implementation: element change
cfg.set_http_server_port (a_port_number)
end
set_socket_recv_timeout_on_configuration (a_nb_seconds: INTEGER; cfg: like configuration)
do
cfg.set_socket_recv_timeout (a_nb_seconds)
end
set_max_concurrent_connections_on_configuration (nb: INTEGER; cfg: like configuration)
do
cfg.set_max_concurrent_connections (nb)

View File

@@ -42,8 +42,8 @@ feature -- Input
src: like source
do
src := source
if src.readable then
src.read_character
if src.readable and not src.was_error then
src.read_character_noexception
last_character := src.last_character
else
last_character := '%U'
@@ -56,8 +56,8 @@ feature -- Input
do
src := source
last_string.wipe_out
if src.readable then
src.read_stream_thread_aware (nb)
if src.readable and not src.was_error then
src.read_stream_noexception (nb)
last_string.append_string (src.last_string)
end
end
@@ -85,11 +85,11 @@ feature -- Status report
end_of_input: BOOLEAN
-- Has the end of input stream been reached?
do
Result := not source.readable
Result := not source.readable or source.was_error
end
;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)"
source: "[
Eiffel Software

View File

@@ -75,23 +75,23 @@ feature -- Output
-- Send `s' to http client
do
last_target_call_succeed := False
target.put_readable_string_8 (s)
last_target_call_succeed := True
target.put_readable_string_8_noexception (s)
last_target_call_succeed := not target.was_error
end
put_string (s: READABLE_STRING_8)
-- Send `s' to http client
do
last_target_call_succeed := False
target.put_readable_string_8 (s)
last_target_call_succeed := True
target.put_readable_string_8_noexception (s)
last_target_call_succeed := not target.was_error
end
put_character (c: CHARACTER_8)
do
last_target_call_succeed := False
target.put_character (c)
last_target_call_succeed := True
target.put_character_noexception (c)
last_target_call_succeed := not target.was_error
end
feature -- Status report
@@ -116,7 +116,7 @@ feature -- Basic operations
end
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)"
source: "[
Eiffel Software

View File

@@ -11,7 +11,7 @@
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="connector_nino" location="..\..\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="connector_standalone" location="..\..\connectors\standalone\standalone-safe.ecf" readonly="false"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<cluster name="src" location="src\" recursive="true"/>
</target>

View File

@@ -11,7 +11,7 @@
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="connector_nino" location="..\..\connectors\nino\nino.ecf" readonly="false"/>
<library name="connector_standalone" location="..\..\connectors\standalone\standalone.ecf" readonly="false"/>
<library name="ewsgi" location="..\..\ewsgi.ecf" readonly="false"/>
<cluster name="src" location="src\" recursive="true"/>
</target>

View File

@@ -14,14 +14,14 @@ feature {NONE} -- Initialization
make
do
print ("Example: start a Nino web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:8123/%N")
(create {NINO_SERVICE [HELLO_WORLD_EXECUTION]}.make_custom ("")).listen (port_number)
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 {WGI_STANDALONE_CONNECTOR [HELLO_WORLD_EXECUTION]}.make_with_base ("")).launch_on_port (port_number)
end
port_number: INTEGER = 8123
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)"
source: "[
Eiffel Software

View File

@@ -18,12 +18,12 @@ feature {NONE} -- Initialization
execute
do
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")
end
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)"
source: "[
Eiffel Software

View File

@@ -35,6 +35,9 @@ feature -- Input
read_character
-- Read the next character in input stream.
-- Make the result available in `last_character'
local
d: like last_chunk_data
l_index_in_chunk: INTEGER
do
index := index + 1
if index > chunk_upper then
@@ -45,10 +48,24 @@ feature -- Input
read_trailer_and_crlf
last_character := '%U'
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
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
@@ -77,13 +94,13 @@ feature -- Input
i - index + 1 = nb or last_chunk_size = 0
loop
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
else
-- Need to read new chunk
-- first get all available data from current chunk
if i <= chunk_upper then
last_string.append (last_chunk_data.substring (i - chunk_lower + 1, chunk_upper - chunk_lower + 1))
if i > chunk_upper then
last_string.append (last_chunk_data.substring (i - chunk_lower + 1, chunk_index (chunk_upper)))
i := chunk_upper
end
-- then continue
@@ -166,9 +183,25 @@ feature -- Status report
Result := last_trailer /= Void
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
read_chunk_block
@@ -190,8 +223,10 @@ feature {NONE} -- Parser
check last_chunk_data.count = last_chunk_size end
l_input := input
check not l_input.end_of_input end
l_input.read_character
check l_input.last_character = '%R' end
check not l_input.end_of_input end
l_input.read_character
check l_input.last_character = '%N' end
end
@@ -214,8 +249,8 @@ feature {NONE} -- Parser
l_input.read_string (last_chunk_size)
last_chunk_data := l_input.last_string
ensure
last_chunk_attached: attached last_chunk_data as el_last_chunk
last_chunk_size_ok: el_last_chunk.count = last_chunk_size
last_chunk_attached: last_chunk_data /= Void
last_chunk_size_ok: last_chunk_data.count = last_chunk_size
end
read_chunk_size
@@ -350,7 +385,7 @@ feature {NONE} -- Implementation
-- Input Stream
;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)"
source: "[
Eiffel Software

View File

@@ -12,11 +12,12 @@
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="connector_cgi" location="..\..\ewsgi\connectors\cgi\cgi-safe.ecf"/>
<library name="connector_libfcgi" location="..\..\ewsgi\connectors\libfcgi\libfcgi-safe.ecf"/>
<library name="connector_nino" location="..\..\ewsgi\connectors\nino\nino-safe.ecf"/>
<library name="connector_standalone" location="..\..\ewsgi\connectors\standalone\standalone-safe.ecf"/>
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="error" location="..\..\..\utility\general\error\error-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf"/>
<library name="http" location="..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="standalone" location="standalone-safe.ecf" readonly="false"/>
<library name="nino" location="nino-safe.ecf" readonly="false">
<renaming old_name="HTTP_CONSTANTS" new_name="NINO_HTTP_CONSTANTS"/>
</library>
@@ -24,6 +25,6 @@
<library name="wsf" location="..\wsf-safe.ecf"/>
<cluster name="wsf_cgi" location=".\cgi\" recursive="true"/>
<cluster name="wsf_libfcgi" location=".\libfcgi\" recursive="true"/>
<cluster name="wsf_nino" location=".\nino\" recursive="true"/>
<cluster name="wsf_standalone" location=".\standalone\" recursive="true"/>
</target>
</system>

View File

@@ -12,7 +12,7 @@
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<library name="wsf_connector_nino" location="nino-safe.ecf"/>
<library name="wsf_connector_standalone" location="standalone-safe.ecf"/>
<cluster name="wsf_openshift" location=".\openshift\" recursive="true"/>
</target>
</system>

View File

@@ -2,13 +2,12 @@ note
description: "[
Component to launch the service using the default connector
Eiffel Web Nino customized for OpenShift
EiffelWeb standalone customized for OpenShift
This default connector support options:
base: base_url (very specific to standalone server)
verbose: to display verbose output, useful for Nino
force_single_threaded: use only one thread, useful for Nino
verbose: to display verbose output, useful for standalone
check WSF_SERVICE_LAUNCHER for more documentation
]"
@@ -19,7 +18,7 @@ class
WSF_OPENSHIFT_SERVICE_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit
WSF_NINO_SERVICE_LAUNCHER [G]
WSF_STANDALONE_SERVICE_LAUNCHER [G]
redefine
initialize
end

View File

@@ -64,7 +64,7 @@ feature {NONE} -- Initialization
verbose := False
verbose_level := notice_level
base_url := ""
base_url := Void
if attached options as opts then
if attached {READABLE_STRING_GENERAL} opts.option ("server_name") as l_server_name then
@@ -175,7 +175,12 @@ feature -- Execution
else
io.error.put_string ("localhost")
end
io.error.put_string (":" + port_number.out + "/" + base_url + "%N")
io.error.put_string (":" + port_number.out)
if attached base_url as b and then not b.is_empty then
io.error.put_string (b + "%N")
else
io.error.put_string ("/%N")
end
end
end
update_configuration (conn.configuration)
@@ -201,7 +206,7 @@ feature {NONE} -- Implementation
server_name: detachable READABLE_STRING_8
base_url: READABLE_STRING_8
base_url: detachable READABLE_STRING_8
verbose: BOOLEAN
verbose_level: INTEGER

View File

@@ -2,11 +2,10 @@ note
description: "[
Options used by WSF_SERVICE_LAUNCHER
For instance options supported by Nino as default connector::
For instance options supported by Standalone as default connector::
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, useful for Standalone
]"
date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
revision: "$Revision: 99106 $"

View File

@@ -288,7 +288,7 @@ feature -- Access: Input
end
end
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.
end
end
@@ -833,6 +833,7 @@ feature -- Access: CGI meta parameters - 1.1
local
l_result: like internal_percent_encoded_path_info
r: READABLE_STRING_8
pi: READABLE_STRING_32
i,m,n,spos: INTEGER
do
l_result := internal_percent_encoded_path_info
@@ -844,11 +845,23 @@ feature -- Access: CGI meta parameters - 1.1
else
l_result := r.string
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
l_result := l_result.substring (s.count + 1, l_result.count)
else
--| Handle Rewrite url engine, to have clean path
--| Handle Rewrite url engine, to have clean path
from
i := 1
m := l_result.count
@@ -2083,7 +2096,7 @@ invariant
wgi_request.content_type /= Void implies content_type /= Void
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)"
source: "[
Eiffel Software

View File

@@ -11,9 +11,9 @@
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="connector_nino" location="..\..\..\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="connector_standalone" location="..\..\..\ewsgi\connectors\standalone\standalone-safe.ecf" readonly="false"/>
<library name="connector_null" location="..\..\..\ewsgi\connectors\null\null-safe.ecf" readonly="false"/>
<library name="dft_nino" location="..\..\default\nino-safe.ecf"/>
<library name="dft_standalone" location="..\..\default\standalone-safe.ecf"/>
<library name="ewsgi" location="..\..\..\ewsgi\ewsgi-safe.ecf" readonly="false"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<library name="wsf" location="..\..\wsf-safe.ecf" readonly="false"/>

View File

@@ -13,11 +13,17 @@ feature {NONE} -- Initialization
make
-- Initialize `Current'.
local
base_url: detachable READABLE_STRING_8
do
print ("Test Server that could be used for autotest%N")
-- base_url := "/test/"
base_url := {TEST_SETTINGS}.base_url
if base_url.is_whitespace then
base_url := Void
end
set_service_option ("port", 9091)
set_service_option ("port", {TEST_SETTINGS}.port_number)
set_service_option ("base", base_url)
set_service_option ("verbose", True)
make_and_launch
end

View File

@@ -35,6 +35,13 @@ feature -- Helper
end
base_url: detachable STRING
once
Result := {TEST_SETTINGS}.base_url
if Result.is_whitespace then
Result := Void
end
end
test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8
local
@@ -44,7 +51,7 @@ feature -- Helper
if b = Void then
b := ""
end
Result := "/" + b + a_query_url
Result := b + a_query_url
end
end

View File

@@ -0,0 +1,16 @@
note
description: "Summary description for {TEST_SETTINGS}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
TEST_SETTINGS
feature -- Access
port_number: INTEGER = 9091
base_url: STRING = "/test/"
end

View File

@@ -19,33 +19,49 @@ inherit
feature {NONE} -- Events
web_app: detachable NINO_SERVICE [TEST_EXECUTION]
web_connector: detachable separate WGI_STANDALONE_CONNECTOR [TEST_EXECUTION]
port_number: INTEGER
base_url: detachable STRING
base_url: detachable separate STRING
once
if attached local_base_url as b and then not b.is_whitespace then
create Result.make_from_separate (b)
end
end
local_base_url: detachable STRING
once
create Result.make_from_string ({TEST_SETTINGS}.base_url)
if Result.is_whitespace then
Result := Void
end
end
on_prepare
-- <Precursor>
local
app: NINO_SERVICE [TEST_EXECUTION]
wt: WORKER_THREAD
conn: separate WGI_STANDALONE_CONNECTOR [TEST_EXECUTION]
e: EXECUTION_ENVIRONMENT
do
create e
-- port_number := 9091 -- Uncomment to use with server outside this process
-- port_number := {TEST_SETTINGS}.port_number -- Uncomment to use with server outside this process
if port_number = 0 then
server_log ("== Current directory: " + e.current_working_directory)
port_number := 0
base_url := "/test/"
create app.make_custom (base_url)
web_app := app
create wt.make (agent app.listen (port_number))
wt.launch
e.sleep (1_000_000_000 * 5)
port_number := app.port
server_log ("Server port=" + port_number.out)
if attached base_url as b then
create conn.make_with_base (b)
else
create conn.make
end
web_connector := conn
setup_connector (conn)
launch_connector (conn)
-- e.sleep (1_000_000_000 * 5)
get_port_number (conn)
-- get_port_number (app.connector)
else
server_log ("Use existing server")
server_log ("== Current directory: " + e.current_working_directory)
@@ -53,6 +69,26 @@ feature {NONE} -- Events
end
end
setup_connector (conn: attached like web_connector)
do
conn.set_is_verbose (True)
conn.set_port_number (port_number)
conn.set_socket_recv_timeout (5)
end
launch_connector (conn: attached like web_connector)
do
conn.launch
end
get_port_number (conn: attached like web_connector)
require
conn.port > 0
do
port_number := conn.port
server_log ("Server port=" + port_number.out)
end
server_log_name: STRING
local
fn: FILE_NAME
@@ -78,9 +114,9 @@ feature {NONE} -- Events
test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8
local
b: like base_url
b: like local_base_url
do
b := base_url
b := local_base_url
if b = Void then
b := ""
end
@@ -90,24 +126,29 @@ feature {NONE} -- Events
on_clean
-- <Precursor>
do
if attached web_app as app then
app.shutdown
if attached web_connector as conn then
shutdown_server (conn)
end
end
shutdown_server (conn: attached like web_connector)
do
conn.shutdown_server
end
http_session: detachable HTTP_CLIENT_SESSION
get_http_session
local
h: LIBCURL_HTTP_CLIENT
b: like base_url
h: DEFAULT_HTTP_CLIENT
b: like local_base_url
do
create h.make
b := base_url
create h
b := local_base_url
if b = Void then
b := "/"
end
if attached {HTTP_CLIENT_SESSION} h.new_session ("localhost:" + port_number.out + b) as sess then
if attached {HTTP_CLIENT_SESSION} h.new_session ("http://localhost:" + port_number.out + b) as sess then
http_session := sess
sess.set_timeout (-1)
sess.set_is_debug (True)
@@ -120,15 +161,24 @@ feature {NONE} -- Events
do
get_http_session
if attached http_session as sess then
print ("Request: " + a_url + " ...%N")
if attached sess.get (a_url, adapted_context (ctx)) as res then
if attached res.body as l_body then
if res.error_occurred then
assert ("Request %""+a_url+"%" failed, got=[" + l_body + "]", False)
if attached res.error_message as err_msg then
assert ("Request %""+a_url+"%" failed, got=[" + l_body + "] error:" + err_msg, False)
else
assert ("Request %""+a_url+"%" failed, got=[" + l_body + "] error:N/A", False)
end
else
assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
end
else
assert ("Request %""+a_url+"%" failed, no body, status=" + res.status.out , False)
if attached res.error_message as err_msg then
assert ("Request %""+a_url+"%" failed, no body, status=" + res.status.out + " error:" + err_msg, False)
else
assert ("Request %""+a_url+"%" failed, no body, status=" + res.status.out + " error:N/A", False)
end
end
end
end
@@ -146,18 +196,34 @@ feature {NONE} -- Events
end
end
test_post_request_with_filename (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_fn: STRING; a_expected_body: READABLE_STRING_8)
test_post_request_with_filename (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_fn: STRING; a_expected_body: detachable READABLE_STRING_8; a_expected_starting_body: detachable READABLE_STRING_8)
do
get_http_session
if attached http_session as sess then
if attached sess.post_file (a_url, adapted_context (ctx), a_fn) as res and then not res.error_occurred and then attached res.body as l_body then
assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
if
attached sess.post_file (a_url, adapted_context (ctx), a_fn) as res and then
not res.error_occurred and then
attached res.body as l_body
then
assert ("Good answer got=%""+l_body+"%" expected=%""+ safe_out (a_expected_body) +"%"",
(a_expected_body /= Void implies l_body.same_string (a_expected_body))
and (a_expected_starting_body /= Void implies l_body.starts_with (a_expected_starting_body))
)
else
assert ("Request %""+a_url+"%" failed", False)
end
end
end
safe_out (s: detachable READABLE_STRING_8): STRING
do
if s = Void then
Result := "Void"
else
Result := s.out
end
end
adapted_context (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_REQUEST_CONTEXT
do
if ctx /= Void then
@@ -173,6 +239,7 @@ feature -- Test routines
test_get_request_01
-- New test routine
do
assert ("has port", port_number > 0)
get_http_session
if attached http_session as sess then
test_get_request ("get/01", Void, "get-01")
@@ -199,11 +266,11 @@ feature -- Test routines
s := "This is an uploaded file%NTesting purpose%N"
f.put_string (s)
f.close
test_post_request_with_filename ("post/file/01", Void, fn.string, "post-file-01%N" + s)
test_post_request_with_filename ("post/file/01 #1", Void, fn.string, "post-file-01", "post-file-01")
create ctx.make
ctx.add_form_parameter ("foo", "bar")
test_post_request_with_filename ("post/file/01", ctx, fn.string, "post-file-01%N" + s)
test_post_request_with_filename ("post/file/01 #2", ctx, fn.string, Void, "post-file-01")
else
assert ("not_implemented", False)
end

View File

@@ -32,7 +32,7 @@ feature -- Execution
feature -- Tests
test_script_url
test_script_url_1
local
req: WSF_REQUEST
s: READABLE_STRING_8
@@ -48,7 +48,13 @@ feature -- Tests
)
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/"))
end
test_script_url_2
local
req: WSF_REQUEST
s: READABLE_STRING_8
do
--| Case #2
req := new_request (<<
["REQUEST_METHOD", "GET"],
@@ -60,7 +66,13 @@ feature -- Tests
)
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/"))
end
test_script_url_3
local
req: WSF_REQUEST
s: READABLE_STRING_8
do
--| Case #3
req := new_request (<<
["REQUEST_METHOD", "GET"],

View File

@@ -44,17 +44,17 @@ feature -- Test Cases
l_cookie.set_path ("/")
l_cookie.set_secure (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.add_cookie (l_cookie)
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
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
test_add_multiple_cookiewith_similar_cookie_name
test_add_multiple_cookies_with_similar_cookie_name
local
w_res: WSF_RESPONSE
l_cookie: WSF_COOKIE
@@ -73,7 +73,7 @@ feature -- Test Cases
l_cookie.set_path ("/")
l_cookie.set_secure (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.add_cookie (l_cookie)
@@ -84,16 +84,16 @@ feature -- Test Cases
l_cookie.set_path ("/")
l_cookie.set_secure (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.set_status_code ({HTTP_STATUS_CODE}.ok)
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
test_add_multiple_cookie_with_similar_cookie_name_2
test_add_multiple_cookies_with_similar_cookie_name_2
local
w_res: WSF_RESPONSE
l_cookie: WSF_COOKIE
@@ -113,7 +113,7 @@ feature -- Test Cases
l_cookie.set_path ("/")
l_cookie.set_secure (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)
@@ -123,7 +123,7 @@ feature -- Test Cases
l_cookie.set_path ("/")
l_cookie.set_secure (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
@@ -134,11 +134,11 @@ feature -- Test Cases
l_cookie.set_path ("/")
l_cookie.set_secure (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.set_status_code ({HTTP_STATUS_CODE}.ok)
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

View File

@@ -1,27 +1,27 @@
<?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="wsf_tests" uuid="C4FF9CDA-B4E4-4841-97E0-7F799B85B657">
<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="wsf_tests" uuid="C4FF9CDA-B4E4-4841-97E0-7F799B85B657">
<target name="server">
<root class="TEST" feature="make"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="provisional">
<assertions precondition="true" postcondition="true" check="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
<setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="connector_nino" location="..\..\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="connector_null" location="..\..\ewsgi\connectors\null\null-safe.ecf" readonly="false"/>
<library name="dft_nino" location="..\default\nino-safe.ecf"/>
<library name="connector_standalone" location="..\..\ewsgi\connectors\standalone\standalone-safe.ecf" readonly="false"/>
<library name="dft_standalone" location="..\default\standalone-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf" readonly="false">
<option>
<assertions precondition="true" postcondition="true" check="true" supplier_precondition="true"/>
</option>
</library>
<library name="http" location="..\..\..\network\protocol\http\http-safe.ecf" readonly="false"/>
<library name="http_client" location="..\..\..\network\http_client\http_client-safe.ecf" readonly="false"/>
<library name="http_client" location="..\..\..\network\http_client\net_http_client-safe.ecf" readonly="false"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="..\wsf-safe.ecf" readonly="false">
@@ -29,6 +29,7 @@
<assertions precondition="true" postcondition="true" check="true" supplier_precondition="true"/>
</option>
</library>
<library name="wsf_standalone" location="..\..\wsf\connector\standalone-safe.ecf" readonly="false"/>
<cluster name="server" location=".\server\" recursive="true"/>
</target>
<target name="wsf_tests" extends="server">

View File

@@ -11,15 +11,16 @@
</option>
<setting name="concurrency" value="thread"/>
<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="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="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="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<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"/>
</target>
<target name="wsf_tests" extends="server">

View File

@@ -85,7 +85,7 @@ def runTestForProject(where):
# compile the restbucks
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)
sleep(1)

View File

@@ -18,7 +18,6 @@
{if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>{/if}
{if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>{/if}
{if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>{/if}
{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"}<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>{/if}
<cluster name="launcher" location=".\launcher\" recursive="true">
<cluster name="any_launcher" location="$|any"/>
</cluster>
@@ -35,16 +34,6 @@
</cluster>
<cluster name="src" location=".\src\" recursive="true"/>
</target>{/if}
{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"}
<target name="{$WIZ.project.name/}_nino" extends="common">
<root class="{$APP_ROOT/}" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\">
<cluster name="default_launcher" location="$|default"/>
</cluster>
<cluster name="src" location=".\src\" recursive="true"/>
</target>{/if}
{if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}
<target name="{$WIZ.project.name/}_cgi" extends="common">
<root class="{$APP_ROOT/}" feature="make_and_launch"/>

View File

@@ -1,4 +1,4 @@
# For nino connector, use port {$WIZ.standalone_connector.port/}
# For Standalone connector, use port {$WIZ.standalone_connector.port/}
port={$WIZ.standalone_connector.port/}
#verbose=true

View File

@@ -31,7 +31,7 @@ feature -- Execution
-- Choose a default -> standalone
create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if}
{if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal}
elseif is_nino_launcher_id (l_id) then
elseif is_standalone_launcher_id (l_id) then
create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if}
{if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}{literal}
elseif is_libfcgi_launcher_id (l_id) then
@@ -39,9 +39,9 @@ feature -- Execution
{if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}{literal}
elseif is_cgi_launcher_id (l_id) then
create {WSF_CGI_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if}
{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"}{literal}
elseif is_nino_launcher_id (l_id) then
create {WSF_NINO_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if}
{if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal}
elseif is_standalone_launcher_id (l_id) then
create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if}
{literal}
else
io.error.put_string ("Application launcher not found!%N")
@@ -52,7 +52,7 @@ feature -- Execution
launcher_id: detachable READABLE_STRING_GENERAL
-- Launcher id based on the executable extension name if any.
-- This can be redefine to customize for your application.
--| ex: nino, cgi, libfcgi or Void.
--| ex: standalone, cgi, libfcgi or Void.
do
if attached (create {PATH}.make_from_string (execution_environment.arguments.command_name)).extension as ext then
Result := ext
@@ -62,17 +62,11 @@ feature -- Execution
feature -- Status report
{/literal}
{if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}
is_nino_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN
is_standalone_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN
do
Result := a_id.is_case_insensitive ("standalone")
end{/if}
{if condition="$WIZ.connectors.use_nino ~ $WIZ_YES"}
is_nino_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN
do
Result := a_id.is_case_insensitive ("nino")
end{/if}
{if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}
is_cgi_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN
do

Some files were not shown because too many files have changed in this diff Show More