Compare commits
32 Commits
es_rev9893
...
es_rev9927
| Author | SHA1 | Date | |
|---|---|---|---|
| f12158e535 | |||
| 080881368a | |||
|
|
3e935c7e33 | ||
|
|
ad2bb0d1a7 | ||
| 7a546622bc | |||
| aed7461faf | |||
| 56819d6793 | |||
| b4fd04ad9f | |||
| 71a98f3c28 | |||
| ed22be2551 | |||
| 77085364ee | |||
| 0217c6d3f4 | |||
| 55fec2423c | |||
| 1f7a81a2d6 | |||
| 612ff243c1 | |||
| 40fb3893af | |||
| 21407f8dcf | |||
| 356eb143ea | |||
| df551d4a4f | |||
| f010da04e9 | |||
| 5029049ef0 | |||
| 80254b2278 | |||
| 210fae5000 | |||
| 9cc9b95190 | |||
| 8b172b5d33 | |||
| cc2d7dbb1c | |||
| c88394b9fd | |||
| 4283662f43 | |||
| 1b951376f9 | |||
| 193cc3cbde | |||
| b49e841ac7 | |||
| 8ba74e1c90 |
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||
|
||||
@@ -101,7 +101,6 @@ Other connectors:
|
||||
|
||||
**WSF_STANDALONE_SERVICE_LAUNCHER**
|
||||
**WSF_CGI_SERVICE_LAUNCHER**
|
||||
**WSF_NINO_SERVICE_LAUNCHER**
|
||||
**WSF_LIBFCGI_SERVICE_LAUNCHER**
|
||||
|
||||
A basic EWF service inherits from **WSF_DEFAULT_SERVICE**, which has a formal generic that should conform to **WSF_EXECUTION** class with a `make' creation procedure, in our case the class **APPLICATION_EXECUTION**.
|
||||
@@ -150,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>
|
||||
|
||||
@@ -205,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)
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -13,7 +13,7 @@ EWF Deployment
|
||||
4. Deploying EWF FCGI
|
||||
5. FCGI overview
|
||||
1. Build EWF application
|
||||
2. Copy the generated exe file and the www content.htaccess CGI
|
||||
2. Copy the generated exe file and the www content.htaccess CGI
|
||||
|
||||
|
||||
|
||||
@@ -25,10 +25,14 @@ EWF Deployment
|
||||
>Apache Version: Apache 2.4.4
|
||||
>Windows: http://www.apachelounge.com/download/
|
||||
|
||||
note: on linux (debian), use
|
||||
> sudo apt-get install apache2
|
||||
|
||||
#### Deploying EWF CGI
|
||||
|
||||
#### CGI overview
|
||||
>A new process is started for each HTTP request. So if there are N requests to the same >CGI program, the code of the CGI program is loaded into memory N times.
|
||||
>A new process is started for each HTTP request. So if there are N requests to the same
|
||||
>CGI program, the code of the CGI program is loaded into memory N times.
|
||||
>When a CGI program finishes handling a request, the program terminates.
|
||||
|
||||
* Build EWF application
|
||||
@@ -95,6 +99,9 @@ Check that you have the following modules enabled
|
||||
>To deploy FCGI you will need to download the mod_fcgi module.
|
||||
>You can get it from here http://www.apachelounge.com/download/
|
||||
|
||||
note: on linux (debian), use
|
||||
> sudo apt-get install libapache2-mod-fastcgi
|
||||
|
||||
#### FCGI overview
|
||||
>FastCGI allows a single, long-running process to handle more than one user request while keeping close to the CGI programming model, retaining the simplicity while eliminating the overhead of creating a new process for each request. Unlike converting an application to a web server plug-in, FastCGI applications remain independent of the web server.
|
||||
|
||||
@@ -128,6 +135,22 @@ Copy the app.exe and the folder "www" into a folder served by apache2, for exam
|
||||
|
||||
>NOTE: By default Apache does not come with fcgid module, so you will need to download it, and put the module under Apache2/modules
|
||||
|
||||
It is also possible to set various parameters in the apache site configuration file such as:
|
||||
```
|
||||
<IfModule mod_fcgid.c>
|
||||
# FcgidIdleTimeout 600
|
||||
# FcgidBusyScanInterval 120
|
||||
# FcgidProcessLifeTime 3600
|
||||
# FcgidMaxProcesses 5
|
||||
# FcgidMaxProcessesPerClass 100
|
||||
# FcgidMinProcessesPerClass 100
|
||||
# FcgidConnectTimeout 8
|
||||
# FcgidIOTimeout 60
|
||||
# FcgidBusyTimeout 1200
|
||||
</IfModule>
|
||||
```
|
||||
See https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html for more information.
|
||||
|
||||
# .htaccess FCGI
|
||||
|
||||
```
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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).
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
29
examples/proxy/application.e
Normal file
29
examples/proxy/application.e
Normal file
@@ -0,0 +1,29 @@
|
||||
note
|
||||
description: "Launcher for reverse proxy web application."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
-- Initialize current service.
|
||||
do
|
||||
-- Specific to `standalone' connector (the EiffelWeb server).
|
||||
-- See `{WSF_STANDALONE_SERVICE_LAUNCHER}.initialize'
|
||||
set_service_option ("port", 9090)
|
||||
import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("server.ini"))
|
||||
end
|
||||
|
||||
end
|
||||
49
examples/proxy/application_execution.e
Normal file
49
examples/proxy/application_execution.e
Normal file
@@ -0,0 +1,49 @@
|
||||
note
|
||||
description: "Reverse proxy example."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_EXECUTION
|
||||
|
||||
WSF_URI_REWRITER
|
||||
rename
|
||||
uri as proxy_uri
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute
|
||||
do
|
||||
-- NOTE: please enter the target server uri here
|
||||
-- replace "http://localhost:8080/foobar"
|
||||
send_proxy_response ("http://localhost:8080/foobar", Current)
|
||||
end
|
||||
|
||||
send_proxy_response (a_remote: READABLE_STRING_8; a_rewriter: detachable WSF_URI_REWRITER)
|
||||
local
|
||||
h: WSF_SIMPLE_REVERSE_PROXY_HANDLER
|
||||
do
|
||||
create h.make (a_remote)
|
||||
h.set_uri_rewriter (a_rewriter)
|
||||
h.set_uri_rewriter (create {WSF_AGENT_URI_REWRITER}.make (agent proxy_uri))
|
||||
h.set_timeout (30) -- 30 seconds
|
||||
h.set_connect_timeout (5_000) -- milliseconds = 5 seconds
|
||||
h.execute (request, response)
|
||||
end
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
proxy_uri (a_request: WSF_REQUEST): STRING
|
||||
-- Request uri rewriten as url.
|
||||
do
|
||||
Result := a_request.request_uri
|
||||
end
|
||||
|
||||
end
|
||||
28
examples/proxy/proxy.ecf
Normal file
28
examples/proxy/proxy.ecf
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="proxy" uuid="B55F0D95-3793-4C90-BBAC-BF5F2DECD5E6" library_target="proxy">
|
||||
<target name="common" abstract="true">
|
||||
<file_rule>
|
||||
<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="transitional" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="console_application" value="true"/>
|
||||
<variable name="ssl_supported" value="false"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<library name="wsf_proxy" location="..\..\library\server\wsf_proxy\wsf_proxy-safe.ecf" readonly="false"/>
|
||||
</target>
|
||||
<target name="proxy" 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>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<cluster name="proxy" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
8
examples/proxy/server.ini
Normal file
8
examples/proxy/server.ini
Normal file
@@ -0,0 +1,8 @@
|
||||
verbose=true
|
||||
verbose_level=ALERT
|
||||
port=9090
|
||||
#max_concurrent_connections=100
|
||||
#keep_alive_timeout=15
|
||||
#max_tcp_clients=100
|
||||
#socket_timeout=300
|
||||
#max_keep_alive_requests=300
|
||||
@@ -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
|
||||
|
||||
@@ -24,6 +24,8 @@ feature -- Basic operations
|
||||
s := "Hello World!"
|
||||
create dt.make_now_utc
|
||||
s.append (" (UTC time is " + dt.rfc850_string + ").")
|
||||
s.append ("%N")
|
||||
s.append ("Your request: " + request.request_uri + " %N")
|
||||
response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", s.count.out]>>)
|
||||
response.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
response.header.put_content_type_text_html
|
||||
|
||||
29
examples/simple_ssl/application.e
Normal file
29
examples/simple_ssl/application.e
Normal file
@@ -0,0 +1,29 @@
|
||||
note
|
||||
description : "simple application root class"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
-- Initialize current service.
|
||||
do
|
||||
-- Specific to `standalone' connector (the EiffelWeb server).
|
||||
-- See `{WSF_STANDALONE_SERVICE_LAUNCHER}.initialize'
|
||||
set_service_option ("port", 9090)
|
||||
import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("simple.ini"))
|
||||
end
|
||||
|
||||
end
|
||||
41
examples/simple_ssl/application_execution.e
Normal file
41
examples/simple_ssl/application_execution.e
Normal file
@@ -0,0 +1,41 @@
|
||||
note
|
||||
description : "simple application execution"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute
|
||||
local
|
||||
s: STRING
|
||||
dt: HTTP_DATE
|
||||
do
|
||||
-- To send a response we need to setup, the status code and
|
||||
-- the response headers.
|
||||
s := "Hello World!"
|
||||
create dt.make_now_utc
|
||||
s.append (" (UTC time is " + dt.rfc850_string + ").")
|
||||
if request.is_https then
|
||||
s.append ("<p>This is a secured connection! (https)</p>%N")
|
||||
end
|
||||
|
||||
response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", s.count.out]>>)
|
||||
response.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
response.header.put_content_type_text_html
|
||||
response.header.put_content_length (s.count)
|
||||
if attached request.http_connection as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") then
|
||||
response.header.put_header_key_value ("Connection", "keep-alive")
|
||||
end
|
||||
response.put_string (s)
|
||||
end
|
||||
|
||||
end
|
||||
15
examples/simple_ssl/simple.crt
Normal file
15
examples/simple_ssl/simple.crt
Normal file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICWDCCAcGgAwIBAgIJAJnXGtV+PtiYMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNDAzMjIxNTA0WhcNMTYwNDAyMjIxNTA0WjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
|
||||
gQDFMK6ojzg+KlklhTossR13c51izMgGc3B0z9ttfHIcx2kxra3HtHcKIl5wSUvn
|
||||
G8zmSyFAyQTs5LUv65q46FM9qU8tP+vTeFCfNXvjRcIEpouta3J53K0xuUlxz4d4
|
||||
4D6qvdDWAez/0AkI4y5etW5zXtg7IQorJhsI9TmfGuruzwIDAQABo1AwTjAdBgNV
|
||||
HQ4EFgQUbWpk2HoHa0YqpEwr7CGEatBFTMkwHwYDVR0jBBgwFoAUbWpk2HoHa0Yq
|
||||
pEwr7CGEatBFTMkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAi+h4/
|
||||
IgEocWkdRZBKHEcTrRxz5WhEDJMoVo9LhnXvCfn1G/4p6Un6sYv7Xzpi9NuSY8uV
|
||||
cjfJJXhtF3AtyZ70iTAxWaRWjGaZ03PYOjlledJ5rqJEt6CCn8m+JsfznduZvbxQ
|
||||
zQ6jCLXfyD/tvemB+yYEI3NntvRKx5/zt6Q26Q==
|
||||
-----END CERTIFICATE-----
|
||||
28
examples/simple_ssl/simple.ini
Normal file
28
examples/simple_ssl/simple.ini
Normal file
@@ -0,0 +1,28 @@
|
||||
##########################################################
|
||||
### EiffelWeb settings for related connector ###
|
||||
### Mostly for EiffelWeb standalone connector ###
|
||||
### See {WGI_STANDALONE_CONSTANTS} for default values. ###
|
||||
##########################################################
|
||||
|
||||
### Connection settings
|
||||
port=9090
|
||||
#max_concurrent_connections=100
|
||||
#max_tcp_clients=100
|
||||
|
||||
### Timeout settings
|
||||
#socket_timeout=60
|
||||
#socket_recv_timeout=5
|
||||
|
||||
### Persistent connection settings
|
||||
#keep_alive_timeout=15
|
||||
#max_keep_alive_requests=100
|
||||
|
||||
### SSL settings
|
||||
# enable SSL, with file certificate.
|
||||
ssl_enabled=true
|
||||
ssl_ca_key=simple.key
|
||||
ssl_ca_crt=simple.crt
|
||||
|
||||
### App settings
|
||||
verbose=true
|
||||
verbose_level=ALERT
|
||||
15
examples/simple_ssl/simple.key
Normal file
15
examples/simple_ssl/simple.key
Normal file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQDFMK6ojzg+KlklhTossR13c51izMgGc3B0z9ttfHIcx2kxra3H
|
||||
tHcKIl5wSUvnG8zmSyFAyQTs5LUv65q46FM9qU8tP+vTeFCfNXvjRcIEpouta3J5
|
||||
3K0xuUlxz4d44D6qvdDWAez/0AkI4y5etW5zXtg7IQorJhsI9TmfGuruzwIDAQAB
|
||||
AoGAR5efMg+dieRyLU8rieJcImxVbfOPg9gRsjdtIVkXTR+RL7ow59q7hXBo/Td/
|
||||
WU8cm1gXoJ/bK+71YYqWyB+BaLRIWvRWb7Gdw203tu4e136Ca5uuY+71qdbVTVcl
|
||||
NQ7J+T+eAQFP+a+DdT3ZQxu9eze87SMbu6i5YSpIk2kusOECQQDunv/DQ+nc+NgR
|
||||
DF+Td3sNYUVRT9a1CWi6abAG6reXwp8MS4NobWDf+Ps4JODhEEwlIdq5qL7qqYBZ
|
||||
Gc1TJJ53AkEA0404Fn6vAzzegBcS4RLlYTK7nMr0m4pMmDMCI6YzAYdMmKHp1e6f
|
||||
IwxSmQrmwyAgwcT01bc0+A8yipcC2BWQaQJBAJ01QZm635OGmos41KsKF5bsE8gL
|
||||
SpBBH69Yu/ECqGwie7iU84FUNnO4zIHjwghlPVVlZX3Vz9o4S+fn2N9DC+cCQGyZ
|
||||
QyCxGdC0r5fbwHJQS/ZQn+UGfvlVzqoXDVMVn3t6ZES6YZrT61eHnOM5qGqklIxE
|
||||
Old3vDZXPt/MU8Zvk3kCQBOgUx2VxvTrHN37hk9/QIDiM62+RenBm1M3ah8xTosf
|
||||
1mSeEb6d9Kwb3TgPBmA7YXzJuAQfRIvEPMPxT5SSr6Q=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
examples/simple_ssl/simple_ssl.ecf
Normal file
27
examples/simple_ssl/simple_ssl.ecf
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="simple_ssl" uuid="C2FE296C-3C18-4609-A5AB-F604BDEE4410" library_target="simple_ssl">
|
||||
<target name="simple_ssl">
|
||||
<description>Simple EiffelWeb standalone server with SSL support (Concurrent connection supported thanks to SCOOP).</description>
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<file_rule>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions/>
|
||||
</option>
|
||||
<setting name="console_application" value="true"/>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<variable name="httpd_ssl_enabled" value="true"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<cluster name="simple" location=".\" recursive="true"/>
|
||||
</target>
|
||||
<target name="simple_ssl_st" extends="simple_ssl">
|
||||
<description>Simple EiffelWeb standalone server with SSL support (Single threaded, thus no concurrent connection.)</description>
|
||||
<setting name="concurrency" value="none"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# For nino connector, use port 9999
|
||||
# For Standalone connector, use port 9999
|
||||
port=9999
|
||||
|
||||
#verbose=true
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# For nino connector, use port 9999
|
||||
# For standalone connector, use port 9999
|
||||
port=9999
|
||||
|
||||
#verbose=true
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
29
examples/websocket/application.e
Normal file
29
examples/websocket/application.e
Normal file
@@ -0,0 +1,29 @@
|
||||
note
|
||||
description : "simple application root class"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_and_launch
|
||||
local
|
||||
l_launcher: WSF_STANDALONE_WEBSOCKET_SERVICE_LAUNCHER [APPLICATION_EXECUTION]
|
||||
opts: WSF_SERVICE_LAUNCHER_OPTIONS
|
||||
do
|
||||
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} opts.make_from_file ("ws.ini")
|
||||
create l_launcher.make_and_launch (options)
|
||||
end
|
||||
|
||||
options: WSF_SERVICE_LAUNCHER_OPTIONS
|
||||
-- Initialize current service.
|
||||
do
|
||||
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} Result.make_from_file ("ws.ini")
|
||||
end
|
||||
|
||||
end
|
||||
184
examples/websocket/application_execution.e
Normal file
184
examples/websocket/application_execution.e
Normal file
@@ -0,0 +1,184 @@
|
||||
note
|
||||
description : "simple application execution"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_WEBSOCKET_EXECUTION
|
||||
|
||||
WEB_SOCKET_EVENT_I
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute
|
||||
local
|
||||
s: STRING
|
||||
dt: HTTP_DATE
|
||||
do
|
||||
-- To send a response we need to setup, the status code and
|
||||
-- the response headers.
|
||||
if request.path_info.same_string_general ("/app") then
|
||||
s := websocket_app_html (9090)
|
||||
else
|
||||
s := "Hello World!"
|
||||
create dt.make_now_utc
|
||||
s.append (" (UTC time is " + dt.rfc850_string + ").")
|
||||
s.append ("<p><a href=%"/app%">Websocket demo</a></p>")
|
||||
end
|
||||
response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", s.count.out]>>)
|
||||
response.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
response.header.put_content_type_text_html
|
||||
response.header.put_content_length (s.count)
|
||||
if attached request.http_connection as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") then
|
||||
response.header.put_header_key_value ("Connection", "keep-alive")
|
||||
end
|
||||
response.put_string (s)
|
||||
end
|
||||
|
||||
feature -- Websocket execution
|
||||
|
||||
new_websocket_handler (ws: WEB_SOCKET): WEB_SOCKET_HANDLER
|
||||
do
|
||||
create Result.make (ws, Current)
|
||||
end
|
||||
|
||||
feature -- Websocket execution
|
||||
|
||||
on_open (ws: WEB_SOCKET)
|
||||
do
|
||||
ws.put_error ("Connecting")
|
||||
ws.send (Text_frame, "Hello, this is a simple demo with Websocket using Eiffel. (/help for more information).%N")
|
||||
end
|
||||
|
||||
on_binary (ws: WEB_SOCKET; a_message: READABLE_STRING_8)
|
||||
do
|
||||
ws.send (Binary_frame, a_message)
|
||||
end
|
||||
|
||||
on_text (ws: WEB_SOCKET; a_message: READABLE_STRING_8)
|
||||
do
|
||||
if a_message.same_string_general ("/help") then
|
||||
-- Echo the message for testing.
|
||||
ws.send (Text_frame, "Help: available commands%N - /time : return the server UTC time.%N")
|
||||
elseif a_message.starts_with_general ("/time") then
|
||||
ws.send (Text_frame, "Server time is " + (create {HTTP_DATE}.make_now_utc).string)
|
||||
else
|
||||
-- Echo the message for testing.
|
||||
ws.send (Text_frame, a_message)
|
||||
end
|
||||
end
|
||||
|
||||
on_close (ws: WEB_SOCKET)
|
||||
-- Called after the WebSocket connection is closed.
|
||||
do
|
||||
ws.put_error ("Connection closed")
|
||||
end
|
||||
|
||||
feature -- HTML Resource
|
||||
|
||||
websocket_app_html (a_port: INTEGER): STRING
|
||||
do
|
||||
Result := "[
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
|
||||
var socket;
|
||||
|
||||
function connect(){
|
||||
|
||||
var host = "ws://127.0.0.1:##PORTNUMBER##";
|
||||
|
||||
try{
|
||||
socket = new WebSocket(host);
|
||||
message('<p class="event">Socket Status: '+socket.readyState);
|
||||
socket.onopen = function(){
|
||||
message('<p class="event">Socket Status: '+socket.readyState+' (open)');
|
||||
}
|
||||
socket.onmessage = function(msg){
|
||||
message('<p class="message">Received: '+msg.data);
|
||||
}
|
||||
socket.onclose = function(){
|
||||
message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');
|
||||
}
|
||||
} catch(exception){
|
||||
message('<p>Error'+exception);
|
||||
}
|
||||
}
|
||||
|
||||
function send(){
|
||||
var text = $('#text').val();
|
||||
if(text==""){
|
||||
message('<p class="warning">Please enter a message');
|
||||
return ;
|
||||
}
|
||||
try{
|
||||
socket.send(text);
|
||||
message('<p class="event">Sent: '+text)
|
||||
} catch(exception){
|
||||
message('<p class="warning">');
|
||||
}
|
||||
$('#text').val("");
|
||||
}
|
||||
|
||||
function message(msg){
|
||||
$('#chatLog').append(msg+'</p>');
|
||||
}//End message()
|
||||
|
||||
$('#text').keypress(function(event) {
|
||||
if (event.keyCode == '13') {
|
||||
send();
|
||||
}
|
||||
});
|
||||
|
||||
$('#disconnect').click(function(){
|
||||
socket.close();
|
||||
});
|
||||
|
||||
if (!("WebSocket" in window)){
|
||||
$('#chatLog, input, button, #examples').fadeOut("fast");
|
||||
$('<p>Oh no, you need a browser that supports WebSockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');
|
||||
}else{
|
||||
//The user has WebSockets
|
||||
connect();
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
<style type="text/css">
|
||||
body {font-family:Arial, Helvetica, sans-serif;}
|
||||
#container { border:5px solid grey; width:800px; margin:0 auto; padding:10px; }
|
||||
#chatLog { padding:5px; border:1px solid black; }
|
||||
#chatLog p {margin:0;}
|
||||
.event {color:#999;}
|
||||
.warning { font-weight:bold; color:#CCC; }
|
||||
</style>
|
||||
<title>WebSockets Client</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div id="container">
|
||||
<h1>WebSockets Client</h1>
|
||||
<div id="chatLog"></div>
|
||||
<input id="text" type="text" />
|
||||
<button id="disconnect">Disconnect</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
]"
|
||||
Result.replace_substring_all ("##PORTNUMBER##", a_port.out)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
21
examples/websocket/websocket_app.ecf
Normal file
21
examples/websocket/websocket_app.ecf
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="websocket_app" uuid="75D17C20-10A8-4E4C-A059-33D72A2B6AEF">
|
||||
<target name="websocket_app">
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<file_rule>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="console_application" value="true"/>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf"/>
|
||||
<library name="standalone_websocket_connector" location="..\..\library\server\wsf\connector\standalone_websocket-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<cluster name="app" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
8
examples/websocket/ws.ini
Normal file
8
examples/websocket/ws.ini
Normal file
@@ -0,0 +1,8 @@
|
||||
verbose=true
|
||||
verbose_level=INFORMATION
|
||||
port=9090
|
||||
max_concurrent_connections=100
|
||||
keep_alive_timeout=35
|
||||
max_tcp_clients=100
|
||||
socket_timeout=30000
|
||||
max_keep_alive_requests=3000
|
||||
@@ -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
|
||||
|
||||
@@ -180,7 +180,9 @@ feature -- Header: adding
|
||||
if line [line.count] = '%R' then
|
||||
line.remove_tail (1)
|
||||
end
|
||||
add_header (line)
|
||||
if not line.is_empty then
|
||||
add_header (line)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -508,9 +508,9 @@ feature -- Helper
|
||||
|
||||
new_session (a_uri: READABLE_STRING_8): HTTP_CLIENT_SESSION
|
||||
local
|
||||
cl: LIBCURL_HTTP_CLIENT
|
||||
cl: DEFAULT_HTTP_CLIENT
|
||||
do
|
||||
create cl.make
|
||||
create cl
|
||||
Result := cl.new_session (a_uri)
|
||||
Result.set_is_insecure (True)
|
||||
Result.set_max_redirects (5)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -25,20 +25,27 @@ feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
|
||||
release
|
||||
-- <Precursor>
|
||||
local
|
||||
d: STRING
|
||||
d: detachable STRING
|
||||
do
|
||||
if attached internal_client_socket as l_socket then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
debug ("dbglog")
|
||||
if
|
||||
attached internal_client_socket as l_socket and then
|
||||
l_socket.descriptor_available
|
||||
then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
dbglog (generator + ".release: ENTER {" + d + "}")
|
||||
end
|
||||
Precursor {HTTPD_REQUEST_HANDLER_I}
|
||||
release_pool_item
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
if d /= Void then
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
else
|
||||
dbglog (generator + ".release: LEAVE {N/A}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -18,21 +18,28 @@ inherit
|
||||
feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation
|
||||
|
||||
release
|
||||
-- <Precursor>
|
||||
local
|
||||
d: STRING
|
||||
d: detachable STRING
|
||||
do
|
||||
-- FIXME: for log purpose
|
||||
if attached internal_client_socket as l_socket then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
debug ("dbglog")
|
||||
if
|
||||
attached internal_client_socket as l_socket and then
|
||||
l_socket.descriptor_available
|
||||
then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
dbglog (generator + ".release: ENTER {" + d + "}")
|
||||
end
|
||||
Precursor {HTTPD_REQUEST_HANDLER_I}
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
if d /= Void then
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
else
|
||||
dbglog (generator + ".release: LEAVE {N/A}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ note
|
||||
deferred class
|
||||
HTTPD_CONFIGURATION_I
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
@@ -14,6 +19,7 @@ feature {NONE} -- Initialization
|
||||
max_concurrent_connections := default_max_concurrent_connections
|
||||
max_tcp_clients := default_max_tcp_clients
|
||||
socket_timeout := default_socket_timeout
|
||||
socket_recv_timeout := default_socket_recv_timeout
|
||||
keep_alive_timeout := default_keep_alive_timeout
|
||||
max_keep_alive_requests := default_max_keep_alive_requests
|
||||
is_secure := False
|
||||
@@ -21,15 +27,6 @@ feature {NONE} -- Initialization
|
||||
create ca_key.make_empty
|
||||
end
|
||||
|
||||
feature -- Defaults
|
||||
|
||||
default_http_server_port: INTEGER = 80
|
||||
default_max_concurrent_connections: INTEGER = 100
|
||||
default_max_tcp_clients: INTEGER = 100
|
||||
default_socket_timeout: INTEGER = 300 -- seconds
|
||||
default_keep_alive_timeout: INTEGER = 15 -- seconds
|
||||
default_max_keep_alive_requests: INTEGER = 100
|
||||
|
||||
feature -- Access
|
||||
|
||||
Server_details: STRING_8
|
||||
@@ -45,7 +42,12 @@ feature -- Access
|
||||
socket_timeout: INTEGER assign set_socket_timeout
|
||||
-- Amount of seconds that the server waits for receipts and transmissions during communications.
|
||||
-- note: with timeout of 0, socket can wait for ever.
|
||||
-- By default: 300 seconds, which is appropriate for most situations.
|
||||
-- By default: 60 seconds, which is appropriate for most situations.
|
||||
|
||||
socket_recv_timeout: INTEGER assign set_socket_recv_timeout
|
||||
-- Amount of seconds that the server waits for receiving data during communications.
|
||||
-- note: with timeout of 0, socket can wait for ever.
|
||||
-- By default: 5 seconds.
|
||||
|
||||
max_concurrent_connections: INTEGER assign set_max_concurrent_connections
|
||||
-- Max number of concurrent connections.
|
||||
@@ -83,8 +85,10 @@ feature -- Access
|
||||
Result.is_verbose := is_verbose
|
||||
Result.verbose_level := verbose_level
|
||||
Result.timeout := socket_timeout
|
||||
Result.socket_recv_timeout := socket_recv_timeout
|
||||
Result.keep_alive_timeout := keep_alive_timeout
|
||||
Result.max_keep_alive_requests := max_keep_alive_requests
|
||||
Result.is_secure := is_secure
|
||||
end
|
||||
|
||||
feature -- Access: SSL
|
||||
@@ -92,10 +96,10 @@ feature -- Access: SSL
|
||||
is_secure: BOOLEAN
|
||||
-- Is SSL/TLS session?.
|
||||
|
||||
ca_crt: IMMUTABLE_STRING_8
|
||||
ca_crt: detachable IMMUTABLE_STRING_32
|
||||
-- the signed certificate.
|
||||
|
||||
ca_key: IMMUTABLE_STRING_8
|
||||
ca_key: detachable IMMUTABLE_STRING_32
|
||||
-- private key to the certificate.
|
||||
|
||||
ssl_protocol: NATURAL
|
||||
@@ -103,6 +107,22 @@ feature -- Access: SSL
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_ssl_settings (v: detachable separate TUPLE [protocol: separate READABLE_STRING_GENERAL; ca_crt, ca_key: detachable separate READABLE_STRING_GENERAL])
|
||||
local
|
||||
prot: STRING_32
|
||||
do
|
||||
is_secure := False
|
||||
ca_crt := Void
|
||||
ca_key := Void
|
||||
if v /= Void then
|
||||
is_secure := True
|
||||
create prot.make_from_separate (v.protocol)
|
||||
set_ssl_protocol_from_string (prot)
|
||||
set_ca_crt (v.ca_crt)
|
||||
set_ca_key (v.ca_key)
|
||||
end
|
||||
end
|
||||
|
||||
set_http_server_name (v: detachable separate READABLE_STRING_8)
|
||||
do
|
||||
if v = Void then
|
||||
@@ -152,6 +172,14 @@ feature -- Element change
|
||||
socket_timeout_set: socket_timeout = a_nb_seconds
|
||||
end
|
||||
|
||||
set_socket_recv_timeout (a_nb_seconds: like socket_recv_timeout)
|
||||
-- Set `socket_recv_timeout' with `a_nb_seconds'
|
||||
do
|
||||
socket_recv_timeout := a_nb_seconds
|
||||
ensure
|
||||
socket_recv_timeout_set: socket_recv_timeout = a_nb_seconds
|
||||
end
|
||||
|
||||
set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
|
||||
-- Set `keep_alive_timeout' with `a_seconds'
|
||||
do
|
||||
@@ -198,17 +226,33 @@ feature -- Element change
|
||||
verbose_level_set: verbose_level = lev
|
||||
end
|
||||
|
||||
mark_secure
|
||||
-- Set is_secure in True
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set `is_secure' to `b'.
|
||||
do
|
||||
if has_ssl_support then
|
||||
if b and has_ssl_support then
|
||||
is_secure := True
|
||||
if http_server_port = 80 then
|
||||
if
|
||||
http_server_port = 80
|
||||
then
|
||||
set_http_server_port (443)
|
||||
end
|
||||
else
|
||||
is_secure := False
|
||||
if
|
||||
http_server_port = 443
|
||||
then
|
||||
set_http_server_port (80)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
is_secure_set: has_ssl_support implies is_secure
|
||||
is_not_secure: not has_ssl_support implies not is_secure
|
||||
end
|
||||
|
||||
mark_secure
|
||||
-- Set is_secure in True
|
||||
do
|
||||
set_is_secure (True)
|
||||
ensure
|
||||
is_secure_set: has_ssl_support implies is_secure
|
||||
-- http_server_port_set: has_ssl_support implies http_server_port = 443
|
||||
@@ -218,16 +262,24 @@ feature -- Element change
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_ca_crt (a_value: separate READABLE_STRING_8)
|
||||
set_ca_crt (a_value: detachable separate READABLE_STRING_GENERAL)
|
||||
-- Set `ca_crt' from `a_value'.
|
||||
do
|
||||
create ca_crt.make_from_separate (a_value)
|
||||
if a_value /= Void then
|
||||
create ca_crt.make_from_separate (a_value)
|
||||
else
|
||||
ca_crt := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ca_key (a_value: separate READABLE_STRING_8)
|
||||
set_ca_key (a_value: detachable separate READABLE_STRING_GENERAL)
|
||||
-- Set `ca_key' with `a_value'.
|
||||
do
|
||||
create ca_key.make_from_separate (a_value)
|
||||
if a_value /= Void then
|
||||
create ca_key.make_from_separate (a_value)
|
||||
else
|
||||
ca_key := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ssl_protocol (a_version: NATURAL)
|
||||
@@ -238,6 +290,24 @@ feature -- Element change
|
||||
ssl_protocol_set: ssl_protocol = a_version
|
||||
end
|
||||
|
||||
set_ssl_protocol_from_string (a_ssl_version: READABLE_STRING_GENERAL)
|
||||
-- Set `ssl_protocol' with `a_ssl_version'
|
||||
do
|
||||
if a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
|
||||
set_ssl_protocol_to_ssl_2_or_3
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_0") then
|
||||
set_ssl_protocol_to_tls_1_0
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_1") then
|
||||
set_ssl_protocol_to_tls_1_1
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_2") then
|
||||
set_ssl_protocol_to_tls_1_2
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("dtls_1_0") then
|
||||
set_ssl_protocol_to_dtls_1_0
|
||||
else -- Default
|
||||
set_ssl_protocol_to_tls_1_2
|
||||
end
|
||||
end
|
||||
|
||||
feature -- SSL Helpers
|
||||
|
||||
set_ssl_protocol_to_ssl_2_or_3
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
note
|
||||
description: "[
|
||||
Various constant values used in httpd settings.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
feature -- Default connection settings
|
||||
|
||||
default_http_server_port: INTEGER = 80
|
||||
default_max_concurrent_connections: INTEGER = 100
|
||||
default_max_tcp_clients: INTEGER = 100
|
||||
|
||||
feature -- Default timeout settings
|
||||
|
||||
default_socket_timeout: INTEGER = 60 -- seconds
|
||||
default_socket_recv_timeout: INTEGER = 5 -- seconds
|
||||
|
||||
feature -- Default persistent connection settings
|
||||
|
||||
default_keep_alive_timeout: INTEGER = 15 -- seconds
|
||||
default_max_keep_alive_requests: INTEGER = 100
|
||||
|
||||
end
|
||||
@@ -17,9 +17,15 @@ feature -- Access
|
||||
verbose_level: INTEGER assign set_verbose_level
|
||||
-- Verbosity of output.
|
||||
|
||||
is_secure: BOOLEAN assign set_is_secure
|
||||
-- Is using secure connection? i.e SSL?
|
||||
|
||||
timeout: INTEGER assign set_timeout
|
||||
-- Amount of seconds that the server waits for receipts and transmissions during communications.
|
||||
|
||||
socket_recv_timeout: INTEGER assign set_socket_recv_timeout
|
||||
-- Amount of seconds that the server waits for receiving data on socket during communications.
|
||||
|
||||
keep_alive_timeout: INTEGER assign set_keep_alive_timeout
|
||||
-- Keep-alive timeout, also known as persistent-connection timeout.
|
||||
-- Number of seconds the server waits after a request has been served before it closes the connection.
|
||||
@@ -42,12 +48,24 @@ feature -- Change
|
||||
verbose_level := lev
|
||||
end
|
||||
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set `is_secure' to `b'.
|
||||
do
|
||||
is_secure := b
|
||||
end
|
||||
|
||||
set_timeout (a_timeout_in_seconds: INTEGER)
|
||||
-- Set `timeout' to `a_timeout_in_seconds'.
|
||||
do
|
||||
timeout := a_timeout_in_seconds
|
||||
end
|
||||
|
||||
set_socket_recv_timeout (a_timeout_in_seconds: INTEGER)
|
||||
-- Set `socket_recv_timeout' to `a_timeout_in_seconds'.
|
||||
do
|
||||
socket_recv_timeout := a_timeout_in_seconds
|
||||
end
|
||||
|
||||
set_keep_alive_timeout (a_timeout_in_seconds: INTEGER)
|
||||
-- Set `keep_alive_timeout' to `a_timeout_in_seconds'.
|
||||
do
|
||||
|
||||
@@ -10,20 +10,44 @@
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf" readonly="false"/>
|
||||
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<cluster name="network" location=".\network" recursive="false">
|
||||
<cluster name="ssl_network" location="$|ssl" recursive="true">
|
||||
<cluster name="network" location=".\network\">
|
||||
<file_rule>
|
||||
<exclude>/httpd_stream_socket_ext.e$</exclude>
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
<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>
|
||||
|
||||
@@ -19,9 +19,33 @@
|
||||
</condition>
|
||||
</library>
|
||||
<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="net_ssl_enabled" value="true"/>
|
||||
<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>
|
||||
|
||||
@@ -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,19 +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>
|
||||
<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>
|
||||
@@ -64,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>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl.ecf">
|
||||
<condition>
|
||||
@@ -24,11 +23,35 @@
|
||||
</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">
|
||||
<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>
|
||||
<cluster name="httpd_server" location=".\" recursive="true">
|
||||
|
||||
@@ -11,6 +11,8 @@ inherit
|
||||
|
||||
HTTPD_LOGGER_CONSTANTS
|
||||
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_request_settings: HTTPD_REQUEST_SETTINGS)
|
||||
@@ -18,18 +20,20 @@ feature {NONE} -- Initialization
|
||||
reset
|
||||
-- Import global request settings.
|
||||
timeout := a_request_settings.timeout -- seconds
|
||||
socket_recv_timeout := a_request_settings.socket_recv_timeout -- seconds
|
||||
keep_alive_timeout := a_request_settings.keep_alive_timeout -- seconds
|
||||
max_keep_alive_requests := a_request_settings.max_keep_alive_requests
|
||||
|
||||
is_verbose := a_request_settings.is_verbose
|
||||
verbose_level := a_request_settings.verbose_level
|
||||
is_secure := a_request_settings.is_secure
|
||||
end
|
||||
|
||||
reset
|
||||
do
|
||||
reset_request
|
||||
|
||||
has_error := False
|
||||
reset_error
|
||||
if attached internal_client_socket as l_sock then
|
||||
l_sock.cleanup
|
||||
end
|
||||
@@ -68,7 +72,7 @@ feature -- Access
|
||||
do
|
||||
s := internal_client_socket
|
||||
if s = Void then
|
||||
create s.make_empty
|
||||
s := new_client_socket (is_secure)
|
||||
internal_client_socket := s
|
||||
end
|
||||
Result := s
|
||||
@@ -121,6 +125,10 @@ feature -- Settings
|
||||
verbose_level: INTEGER
|
||||
-- Output verbosity.
|
||||
|
||||
is_secure: BOOLEAN
|
||||
-- Is secure socket?
|
||||
-- i.e: SSL?
|
||||
|
||||
is_persistent_connection_supported: BOOLEAN
|
||||
-- Is persistent connection supported?
|
||||
do
|
||||
@@ -134,6 +142,9 @@ feature -- Settings
|
||||
timeout: INTEGER -- seconds
|
||||
-- Amount of seconds that the server waits for receipts and transmissions during communications.
|
||||
|
||||
socket_recv_timeout: INTEGER -- seconds
|
||||
-- Amount of seconds that the server waits for receiving data on socket during communications.
|
||||
|
||||
max_keep_alive_requests: INTEGER
|
||||
-- Maximum number of requests allowed per persistent connection.
|
||||
|
||||
@@ -143,7 +154,21 @@ feature -- Settings
|
||||
feature -- Status report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Error occurred during `analyze_request_message'
|
||||
-- Error occurred during `get_request_header'
|
||||
|
||||
feature -- Status change
|
||||
|
||||
report_error (m: detachable READABLE_STRING_GENERAL)
|
||||
-- Report error occurred, with optional message `m'.
|
||||
do
|
||||
has_error := True
|
||||
end
|
||||
|
||||
reset_error
|
||||
-- Reset previous error for current request handler.
|
||||
do
|
||||
has_error := False
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
@@ -183,10 +208,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
|
||||
|
||||
-- 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
|
||||
@@ -202,25 +238,38 @@ feature -- Execution
|
||||
n := n + 1
|
||||
if n >= m then
|
||||
is_next_persistent_connection_supported := False
|
||||
elseif n > 1 and is_verbose then
|
||||
log ("Reuse connection (" + n.out + ")", information_level)
|
||||
end
|
||||
-- FIXME: it seems to be called one more time, mostly to see this is done.
|
||||
execute_request
|
||||
execute_request (n > 1)
|
||||
l_exit := not is_persistent_connection_supported
|
||||
or not is_next_persistent_connection_supported -- related to `max_keep_alive_requests'
|
||||
or not is_persistent_connection_requested
|
||||
or has_error or l_socket.is_closed or not l_socket.is_open_read
|
||||
reset_request
|
||||
end
|
||||
if l_exit and has_error and not l_socket.is_closed then
|
||||
l_socket.close
|
||||
end
|
||||
end
|
||||
|
||||
execute_request
|
||||
execute_request (a_is_reusing_connection: BOOLEAN)
|
||||
-- Execute http request, and if `a_is_reusing_connection' is True
|
||||
-- the execution is reusing the persistent connection.
|
||||
require
|
||||
is_connected: is_connected
|
||||
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
|
||||
no_error: not has_error
|
||||
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
|
||||
dbglog ("execute_request: wait on persistent connection.")
|
||||
end
|
||||
end
|
||||
reset_error
|
||||
l_socket := client_socket
|
||||
check
|
||||
socket_attached: l_socket /= Void
|
||||
@@ -228,51 +277,41 @@ feature -- Execution
|
||||
end
|
||||
if l_socket.is_closed then
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".execute_request {socket is Closed!}")
|
||||
dbglog ("execute_request {socket is Closed!}")
|
||||
end
|
||||
else
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER")
|
||||
dbglog ("execute_request socket=" + l_socket.descriptor.out + " ENTER")
|
||||
end
|
||||
|
||||
--| TODO: add configuration options for socket timeout.
|
||||
--| set by default 5 seconds.
|
||||
l_socket.set_timeout (keep_alive_timeout) -- 5 seconds!
|
||||
l_is_ready := l_socket.ready_for_reading
|
||||
-- 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_timeout (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)
|
||||
else
|
||||
has_error := True
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + "} timeout!")
|
||||
end
|
||||
end
|
||||
|
||||
if has_error then
|
||||
if l_is_ready 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)
|
||||
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 (generator + ".execute_request {" + l_socket.descriptor.out + "} LEAVE")
|
||||
end
|
||||
end
|
||||
|
||||
debug ("dbglog")
|
||||
dbglog ("execute_request {" + l_socket.descriptor.out + "} LEAVE")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -284,7 +323,7 @@ feature -- Execution
|
||||
feature -- Request processing
|
||||
|
||||
process_request (a_socket: HTTPD_STREAM_SOCKET)
|
||||
-- Process request ...
|
||||
-- Process request on socket `a_socket'.
|
||||
require
|
||||
no_error: not has_error
|
||||
a_uri_attached: uri /= Void
|
||||
@@ -295,10 +334,46 @@ feature -- Request processing
|
||||
deferred
|
||||
end
|
||||
|
||||
process_bad_request (a_socket: HTTPD_STREAM_SOCKET)
|
||||
-- Process bad request catched on `a_socket'.
|
||||
require
|
||||
has_error: has_error
|
||||
a_socket_attached: a_socket /= Void
|
||||
local
|
||||
-- h: STRING
|
||||
-- s: STRING
|
||||
do
|
||||
-- NOTE: this is experiment code, and not ready yet.
|
||||
|
||||
-- if a_socket.ready_for_writing then
|
||||
-- s := "{
|
||||
--<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
||||
--<html><head>
|
||||
--<title>400 Bad Request</title>
|
||||
--</head><body>
|
||||
--<h1>Bad Request</h1>
|
||||
--</body></html>
|
||||
-- }"
|
||||
-- create h.make (1_024)
|
||||
-- h.append ("HTTP/1.1 400 Bad Request%R%N")
|
||||
-- h.append ("Content-Length: " + s.count.out + "%R%N")
|
||||
-- h.append ("Connection: close%R%N")
|
||||
-- h.append ("Content-Type: text/html; charset=iso-8859-1%R%N")
|
||||
-- h.append ("%R%N")
|
||||
-- a_socket.put_string (h)
|
||||
-- if a_socket.ready_for_writing then
|
||||
-- a_socket.put_string (s)
|
||||
-- end
|
||||
-- end
|
||||
end
|
||||
|
||||
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
|
||||
@@ -311,72 +386,90 @@ feature -- Parsing
|
||||
do
|
||||
create txt.make (64)
|
||||
request_header := txt
|
||||
l_is_verbose := is_verbose
|
||||
|
||||
if
|
||||
not has_error and then
|
||||
a_socket.is_readable and then
|
||||
attached next_line (a_socket) as l_request_line and then
|
||||
not l_request_line.is_empty
|
||||
a_socket.readable
|
||||
then
|
||||
txt.append (l_request_line)
|
||||
txt.append_character ('%N')
|
||||
analyze_request_line (l_request_line)
|
||||
else
|
||||
has_error := True
|
||||
end
|
||||
l_is_verbose := is_verbose
|
||||
if not has_error or l_is_verbose then
|
||||
-- if `is_verbose' we can try to print the request, even if it is a bad HTTP request
|
||||
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")
|
||||
if a_is_reusing_connection then
|
||||
a_socket.set_recv_timeout (keep_alive_timeout) -- in seconds!
|
||||
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
|
||||
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 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
|
||||
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
|
||||
@@ -397,39 +490,44 @@ feature -- Parsing
|
||||
n := n - 1
|
||||
end
|
||||
version := line.substring (next_pos + 1, n)
|
||||
has_error := method.is_empty
|
||||
if method.is_empty then
|
||||
report_error ("Missing request method data")
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
has_error := True
|
||||
report_error ("Rescue in next_line")
|
||||
a_socket.close
|
||||
Result := Void
|
||||
elseif a_socket.readable then
|
||||
a_socket.read_line_thread_aware
|
||||
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
|
||||
has_error := True
|
||||
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
|
||||
-- Error with socket...
|
||||
has_error := True
|
||||
report_error ("Socket error: not readable")
|
||||
if is_verbose then
|
||||
log (request_header + "%N## Socket is not readable! ##", debug_level)
|
||||
end
|
||||
end
|
||||
rescue
|
||||
-- In case of network error exception (as EiffelNet reports error raising exception)
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
@@ -460,6 +558,19 @@ feature -- Output
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
socket_has_incoming_data (a_socket: HTTPD_STREAM_SOCKET): BOOLEAN
|
||||
-- Is there any data to read on `a_socket' ?
|
||||
require
|
||||
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.has_incoming_data
|
||||
Result := True
|
||||
end
|
||||
|
||||
invariant
|
||||
request_header_attached: request_header /= Void
|
||||
|
||||
|
||||
@@ -108,8 +108,18 @@ feature -- Execution
|
||||
log (" - max_tcp_clients = " + configuration.max_tcp_clients.out)
|
||||
log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out)
|
||||
log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds")
|
||||
log (" - socket_recv_timeout = " + configuration.socket_recv_timeout.out + " seconds")
|
||||
log (" - keep_alive_timeout = " + configuration.keep_alive_timeout.out + " seconds")
|
||||
log (" - max_keep_alive_requests = " + configuration.max_keep_alive_requests.out)
|
||||
if configuration.has_ssl_support then
|
||||
if configuration.is_secure then
|
||||
log (" - SSL = enabled")
|
||||
else
|
||||
log (" - SSL = disabled")
|
||||
end
|
||||
else
|
||||
log (" - SSL = not supported")
|
||||
end
|
||||
if configuration.verbose_level > 0 then
|
||||
log (" - verbose_level = " + configuration.verbose_level.out)
|
||||
end
|
||||
|
||||
@@ -1,334 +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)
|
||||
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)
|
||||
feature {NONE} -- Input
|
||||
|
||||
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
|
||||
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 {NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
l_socket.set_connect_timeout (n)
|
||||
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
|
||||
|
||||
set_accept_timeout (n: INTEGER)
|
||||
do
|
||||
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
l_socket.set_accept_timeout (n)
|
||||
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
|
||||
|
||||
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)
|
||||
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
|
||||
socket.put_string (s)
|
||||
peek_stream_noexception (1)
|
||||
Result := last_string.count = 1
|
||||
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
|
||||
|
||||
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: "[
|
||||
@@ -338,4 +239,5 @@ feature {HTTPD_STREAM_SOCKET} -- Implementation
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
|
||||
end
|
||||
|
||||
@@ -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
|
||||
@@ -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,151 +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
|
||||
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, 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: STRING; a_key: STRING)
|
||||
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, a_key)
|
||||
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: STRING; a_key: STRING)
|
||||
local
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_server_by_port (a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
end
|
||||
feature {NONE} -- Input
|
||||
|
||||
make_ssl_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
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, a_key)
|
||||
end
|
||||
|
||||
make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
local
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_client_by_port (a_peer_port, a_peer_host)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
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>
|
||||
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: STRING; a_key: STRING)
|
||||
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
|
||||
a_file_name: FILE_NAME
|
||||
l_bytes_sent: INTEGER
|
||||
do
|
||||
if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
create a_file_name.make_from_string (a_crt)
|
||||
l_socket.set_certificate_file_name (a_file_name)
|
||||
create a_file_name.make_from_string (a_key)
|
||||
l_socket.set_key_file_name (a_file_name)
|
||||
if
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,96 +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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,17 @@
|
||||
note
|
||||
description: "Summary description for {HTTPD_SOCKET_FACTORY}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_client_socket (a_is_secure: BOOLEAN): HTTPD_STREAM_SOCKET
|
||||
do
|
||||
check not_secure: not a_is_secure end
|
||||
create Result.make_empty
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,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
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
note
|
||||
description: "Summary description for {HTTPD_SOCKET_FACTORY}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_client_socket (a_is_secure: BOOLEAN): HTTPD_STREAM_SOCKET
|
||||
do
|
||||
if a_is_secure then
|
||||
create {HTTPD_STREAM_SSL_SOCKET} Result.make_empty
|
||||
else
|
||||
create Result.make_empty
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -97,7 +97,9 @@ feature -- Request processing
|
||||
end
|
||||
end
|
||||
rescue
|
||||
has_error := l_output = Void or else not l_output.is_available
|
||||
if l_output = Void or else not l_output.is_available then
|
||||
report_error ("Missing WGI output")
|
||||
end
|
||||
if not retried then
|
||||
retried := True
|
||||
retry
|
||||
@@ -230,6 +232,9 @@ feature -- Request processing
|
||||
set_environment_variable (l_server_port, "SERVER_PORT", Result)
|
||||
set_environment_variable (version, "SERVER_PROTOCOL", Result)
|
||||
set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result)
|
||||
if is_secure then
|
||||
set_environment_variable ("on", "HTTPS", Result)
|
||||
end
|
||||
|
||||
--| Apply `base' value
|
||||
l_base := base
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
note
|
||||
description: "[
|
||||
Standalone Web Server connector
|
||||
Standalone Web Server connector.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
|
||||
revision: "$Revision: 99106 $"
|
||||
|
||||
class
|
||||
WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end]
|
||||
@@ -20,7 +20,7 @@ feature {NONE} -- Initialization
|
||||
make
|
||||
-- Create current standalone connector.
|
||||
local
|
||||
fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]
|
||||
fac: like request_handler_factory
|
||||
do
|
||||
-- Callbacks
|
||||
create on_launched_actions
|
||||
@@ -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)
|
||||
@@ -51,7 +51,7 @@ feature {NONE} -- Separate helper
|
||||
a_server.set_observer (observer)
|
||||
end
|
||||
|
||||
update_factory (conn: detachable separate WGI_STANDALONE_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]; a_conf: separate HTTPD_CONFIGURATION)
|
||||
update_factory (conn: detachable separate WGI_STANDALONE_CONNECTOR [G]; fac: separate WGI_HTTPD_REQUEST_HANDLER_FACTORY [G]; a_conf: like configuration)
|
||||
do
|
||||
fac.update_with (conn, a_conf)
|
||||
end
|
||||
@@ -63,11 +63,17 @@ feature {NONE} -- Separate helper
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_8 = "httpd"
|
||||
name: STRING_8
|
||||
-- Name of Current connector
|
||||
once
|
||||
Result := "httpd"
|
||||
end
|
||||
|
||||
version: STRING_8 = "0.1"
|
||||
version: STRING_8
|
||||
-- Version of Current connector
|
||||
once
|
||||
Result := "1.0"
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
@@ -103,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
|
||||
|
||||
@@ -117,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
|
||||
@@ -135,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
|
||||
@@ -149,9 +172,22 @@ feature -- Element change
|
||||
set_is_verbose_on_configuration (b, configuration)
|
||||
end
|
||||
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set is_secure connection mode.
|
||||
-- i.e: using SSL.
|
||||
do
|
||||
set_is_secure_on_configuration (b, configuration)
|
||||
end
|
||||
|
||||
feature -- Server
|
||||
|
||||
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
|
||||
@@ -177,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
|
||||
@@ -226,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)
|
||||
@@ -236,9 +277,14 @@ feature {NONE} -- Implementation: element change
|
||||
cfg.set_is_verbose (b)
|
||||
end
|
||||
|
||||
set_is_secure_on_configuration (b: BOOLEAN; cfg: like configuration)
|
||||
do
|
||||
cfg.set_is_secure (b)
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
note
|
||||
description: "[
|
||||
Interface to access protected feature from {WGI_STANDALONE_CONNECTOR}.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WGI_STANDALONE_CONNECTOR_EXPORTER
|
||||
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
note
|
||||
description: "[
|
||||
Constants value related to Standalone connector,
|
||||
and indirectly to `httpd' component.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WGI_STANDALONE_CONSTANTS
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
end
|
||||
@@ -24,7 +24,7 @@ feature {NONE} -- Initialization
|
||||
set_source (a_source)
|
||||
end
|
||||
|
||||
feature {WGI_STANDALONE_CONNECTOR, WGI_SERVICE} -- Nino
|
||||
feature {WGI_STANDALONE_CONNECTOR, WGI_SERVICE, WGI_STANDALONE_CONNECTOR_EXPORTER} -- Standalone
|
||||
|
||||
set_source (i: like source)
|
||||
do
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,12 +10,11 @@
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_standalone" location="standalone-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
|
||||
<library name="httpd_edit" location="src\httpd\httpd-safe.ecf" readonly="false">
|
||||
<library name="httpd_edit" location="lib\httpd\httpd-safe.ecf" readonly="false">
|
||||
<option debug="true">
|
||||
<debug name="dbglog" enabled="true"/>
|
||||
</option>
|
||||
</library>
|
||||
<library name="net_ssl_edit" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\..\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<cluster name="tests" location="tests\" recursive="true"/>
|
||||
</target>
|
||||
@@ -27,4 +26,10 @@
|
||||
</target>
|
||||
<target name="test_connector_standalone" extends="test_standalone_scoop">
|
||||
</target>
|
||||
<target name="test_standalone_scoop_ssl" extends="test_standalone_scoop">
|
||||
<variable name="httpd_ssl_enabled" value="true"/>
|
||||
<variable name="libcurl_http_client_disabled" value="true"/>
|
||||
<variable name="net_http_client_disabled" value="false"/>
|
||||
<variable name="netssl_http_client_enabled" value="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user