Compare commits
34 Commits
es_16_05
...
net_noexce
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| 0cecb9594c | |||
| e384a6d6ed | |||
| 71a5c086a5 | |||
| dfa60bf8f5 | |||
| 113aa69efc | |||
| af5fc75743 | |||
|
|
e53c960a89 |
@@ -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
|
||||
|
||||
@@ -20,9 +20,10 @@ feature {NONE} -- Initialization
|
||||
initialize
|
||||
-- Initialize current service.
|
||||
do
|
||||
set_service_option ("port", 9090)
|
||||
-- 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
|
||||
|
||||
@@ -17,10 +17,15 @@ feature -- Basic operations
|
||||
execute
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
-- To send a response we need to setup, the status code and
|
||||
-- the response headers.
|
||||
s := "Hello World!"
|
||||
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 + ").")
|
||||
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
|
||||
|
||||
@@ -1,35 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="simple" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="simple">
|
||||
<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" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="simple">
|
||||
<target name="common" abstract="true">
|
||||
<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="transitional" syntax="transitional">
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="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"/>
|
||||
<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"/>
|
||||
</target>
|
||||
<target name="simple_standalone" extends="common">
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
|
||||
<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="thread"/>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<cluster name="simple" location=".\" recursive="true"/>
|
||||
</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="..\..\library\server\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">
|
||||
|
||||
8
examples/simple/simple.ini
Normal file
8
examples/simple/simple.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
|
||||
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
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?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="upload_image" uuid="F2400BE8-D8EB-48EB-B4E4-5D4377062A7F" library_target="upload_image">
|
||||
<target name="upload_image">
|
||||
<root class="IMAGE_UPLOADER" feature="make"/>
|
||||
<target name="upload_image_common">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
@@ -11,14 +10,26 @@
|
||||
<debug name="standalone" enabled="true"/>
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="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="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf" readonly="false" use_application_options="true"/>
|
||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="uri_template" location="..\..\library\text\parser\uri_template\uri_template-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false" use_application_options="true"/>
|
||||
</target>
|
||||
<target name="upload_image_standalone" extends="upload_image_common">
|
||||
<root class="IMAGE_UPLOADER" feature="make"/>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<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_libfcgi" extends="upload_image_common">
|
||||
<root class="IMAGE_UPLOADER" feature="make"/>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="default_libfcgi" location="..\..\library\server\wsf\default\libfcgi-safe.ecf" readonly="false" use_application_options="true"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="upload_image" extends="upload_image_standalone">
|
||||
</target>
|
||||
</system>
|
||||
|
||||
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,25 @@
|
||||
<?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-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="demo" uuid="DC4D6549-D5F4-4E1A-959A-6BD536737A21" library_target="demo">
|
||||
<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 concurrency="scoop" root_catcall_detection="none" root_concurrency="scoop" root_void_safety="all" warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="transitional">
|
||||
<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-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">
|
||||
<option concurrency="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.
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ feature {NONE} -- Initialization
|
||||
local
|
||||
n: INTEGER
|
||||
p: like pool
|
||||
do
|
||||
n := max_concurrent_connections (server)
|
||||
do
|
||||
n := max_concurrent_connections (server).max (1) -- At least one processor!
|
||||
create p.make (n)
|
||||
initialize_pool (p, n)
|
||||
pool := p
|
||||
@@ -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
|
||||
|
||||
@@ -23,7 +23,7 @@ feature {NONE} -- Initialization
|
||||
local
|
||||
n: INTEGER
|
||||
do
|
||||
n := max_concurrent_connections (server)
|
||||
n := max_concurrent_connections (server).max (1) -- At least one thread!
|
||||
create pool.make (n.to_natural_32)
|
||||
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
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
note
|
||||
description: "Configuration for the standalone HTTPd server."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_CONFIGURATION_I
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
http_server_port := default_http_server_port
|
||||
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
|
||||
create ca_crt.make_empty
|
||||
create ca_key.make_empty
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
Server_details: STRING_8
|
||||
-- Detail of the server.
|
||||
deferred
|
||||
end
|
||||
|
||||
http_server_name: detachable READABLE_STRING_8 assign set_http_server_name
|
||||
http_server_port: INTEGER assign set_http_server_port
|
||||
max_tcp_clients: INTEGER assign set_max_tcp_clients
|
||||
-- Listen on socket for at most `queue' connections.
|
||||
|
||||
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: 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.
|
||||
|
||||
force_single_threaded: BOOLEAN assign set_force_single_threaded
|
||||
do
|
||||
Result := max_concurrent_connections = 0
|
||||
end
|
||||
|
||||
is_verbose: BOOLEAN assign set_is_verbose
|
||||
-- Display verbose message to the output?
|
||||
|
||||
verbose_level: INTEGER assign set_verbose_level
|
||||
-- Verbosity of output.
|
||||
|
||||
keep_alive_timeout: INTEGER assign set_keep_alive_timeout
|
||||
-- Persistent connection timeout.
|
||||
-- Number of seconds the server waits after a request has been served before it closes the connection.
|
||||
-- Timeout unit in Seconds.
|
||||
-- By default: 5 seconds.
|
||||
|
||||
max_keep_alive_requests: INTEGER assign set_max_keep_alive_requests
|
||||
-- Maximum number of requests allowed per persistent connection.
|
||||
-- Recommended a high setting.
|
||||
-- To disable KeepAlive, set `max_keep_alive_requests' to 0.
|
||||
-- By default: 100 .
|
||||
|
||||
has_ssl_support: BOOLEAN
|
||||
-- Has SSL support?
|
||||
deferred
|
||||
end
|
||||
|
||||
request_settings: HTTPD_REQUEST_SETTINGS
|
||||
do
|
||||
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
|
||||
|
||||
is_secure: BOOLEAN
|
||||
-- Is SSL/TLS session?.
|
||||
|
||||
ca_crt: detachable IMMUTABLE_STRING_32
|
||||
-- the signed certificate.
|
||||
|
||||
ca_key: detachable IMMUTABLE_STRING_32
|
||||
-- private key to the certificate.
|
||||
|
||||
ssl_protocol: NATURAL
|
||||
-- By default protocol is tls 1.2.
|
||||
|
||||
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
|
||||
unset_http_server_name
|
||||
else
|
||||
create {IMMUTABLE_STRING_8} http_server_name.make_from_separate (v)
|
||||
end
|
||||
end
|
||||
|
||||
unset_http_server_name
|
||||
-- Unset `http_server_name' value.
|
||||
do
|
||||
http_server_name := Void
|
||||
ensure
|
||||
unset_http_server_name: http_server_name = Void
|
||||
end
|
||||
|
||||
set_http_server_port (v: like http_server_port)
|
||||
-- Set `http_server_port' with `v'.
|
||||
do
|
||||
http_server_port := v
|
||||
ensure
|
||||
http_server_port_set: http_server_port = v
|
||||
end
|
||||
|
||||
set_max_tcp_clients (v: like max_tcp_clients)
|
||||
-- Set `max_tcp_clients' with `v'.
|
||||
do
|
||||
max_tcp_clients := v
|
||||
ensure
|
||||
max_tcp_clients_set: max_tcp_clients = v
|
||||
end
|
||||
|
||||
set_max_concurrent_connections (v: like max_concurrent_connections)
|
||||
-- Set `max_concurrent_connections' with `v'.
|
||||
do
|
||||
max_concurrent_connections := v
|
||||
ensure
|
||||
max_concurrent_connections_set : max_concurrent_connections = v
|
||||
end
|
||||
|
||||
set_socket_timeout (a_nb_seconds: like socket_timeout)
|
||||
-- Set `socket_timeout' with `a_nb_seconds'
|
||||
do
|
||||
socket_timeout := a_nb_seconds
|
||||
ensure
|
||||
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
|
||||
keep_alive_timeout := a_seconds
|
||||
ensure
|
||||
keep_alive_timeout_set: keep_alive_timeout = a_seconds
|
||||
end
|
||||
|
||||
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
|
||||
-- Set `max_keep_alive_requests' with `nb'
|
||||
do
|
||||
max_keep_alive_requests := nb
|
||||
ensure
|
||||
max_keep_alive_requests_set: max_keep_alive_requests = nb
|
||||
end
|
||||
|
||||
set_force_single_threaded (v: like force_single_threaded)
|
||||
-- Force server to handle incoming request in a single thread.
|
||||
-- i.e set max_concurrent_connections to 0!
|
||||
obsolete
|
||||
"Use set_max_concurrent_connections (0) [June/2016]"
|
||||
do
|
||||
if v then
|
||||
set_max_concurrent_connections (0)
|
||||
end
|
||||
--|Missing postcondition
|
||||
--| force_single_thread_set: v implies max_concurrent_connections = 0
|
||||
--| not_single_thread: not v implies max_concurrent_connections > 0
|
||||
end
|
||||
|
||||
set_is_verbose (b: BOOLEAN)
|
||||
-- Set `is_verbose' to `b'
|
||||
do
|
||||
is_verbose := b
|
||||
ensure
|
||||
is_verbose_set: is_verbose = b
|
||||
end
|
||||
|
||||
set_verbose_level (lev: INTEGER)
|
||||
-- Set `verbose_level' to `lev'.
|
||||
do
|
||||
verbose_level := lev
|
||||
ensure
|
||||
verbose_level_set: verbose_level = lev
|
||||
end
|
||||
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set `is_secure' to `b'.
|
||||
do
|
||||
if b and has_ssl_support then
|
||||
is_secure := True
|
||||
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
|
||||
is_not_secure: not has_ssl_support implies not is_secure
|
||||
-- default_port: not has_ssl_support implies http_server_port = 80
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_ca_crt (a_value: detachable separate READABLE_STRING_GENERAL)
|
||||
-- Set `ca_crt' from `a_value'.
|
||||
do
|
||||
if a_value /= Void then
|
||||
create ca_crt.make_from_separate (a_value)
|
||||
else
|
||||
ca_crt := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ca_key (a_value: detachable separate READABLE_STRING_GENERAL)
|
||||
-- Set `ca_key' with `a_value'.
|
||||
do
|
||||
if a_value /= Void then
|
||||
create ca_key.make_from_separate (a_value)
|
||||
else
|
||||
ca_key := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ssl_protocol (a_version: NATURAL)
|
||||
-- Set `ssl_protocol' with `a_version'
|
||||
do
|
||||
ssl_protocol := a_version
|
||||
ensure
|
||||
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
|
||||
-- Set `ssl_protocol' with `Ssl_23'.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_ssl_protocol_to_tls_1_0
|
||||
-- Set `ssl_protocol' with `Tls_1_0'.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_ssl_protocol_to_tls_1_1
|
||||
-- Set `ssl_protocol' with `Tls_1_1'.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_ssl_protocol_to_tls_1_2
|
||||
-- Set `ssl_protocol' with `Tls_1_2'.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_ssl_protocol_to_dtls_1_0
|
||||
-- Set `ssl_protocol' with `Dtls_1_0'.
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2014, 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,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
|
||||
@@ -0,0 +1,82 @@
|
||||
note
|
||||
description: "[
|
||||
Request settings for the standalone HTTPd server.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
expanded class
|
||||
HTTPD_REQUEST_SETTINGS
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_verbose: BOOLEAN assign set_is_verbose
|
||||
-- Is verbose?
|
||||
|
||||
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.
|
||||
-- Unit in Seconds.
|
||||
|
||||
max_keep_alive_requests: INTEGER assign set_max_keep_alive_requests
|
||||
-- Maximum number of requests allowed per persistent connection.
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_is_verbose (b: BOOLEAN)
|
||||
-- Set `is_verbose' to `b'.
|
||||
do
|
||||
is_verbose := b
|
||||
end
|
||||
|
||||
set_verbose_level (lev: INTEGER)
|
||||
-- Set `verbose_level' to `lev'.
|
||||
do
|
||||
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
|
||||
keep_alive_timeout := a_timeout_in_seconds
|
||||
end
|
||||
|
||||
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
|
||||
-- Set `max_keep_alive_requests' with `nb'
|
||||
do
|
||||
max_keep_alive_requests := nb
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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="http_network" uuid="56DAA1CE-0A2E-451A-BFC9-7821578E79F0" library_target="http_network">
|
||||
<target name="http_network">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<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>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-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\">
|
||||
<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>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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="http_network" uuid="56DAA1CE-0A2E-451A-BFC9-7821578E79F0" library_target="http_network">
|
||||
<target name="http_network">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="false" void_safety="none" 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.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>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</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="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,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">
|
||||
@@ -27,6 +37,7 @@
|
||||
<cluster name="httpd_server" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/concurrency$</exclude>
|
||||
<exclude>/network$</exclude>
|
||||
<exclude>/no_ssl$</exclude>
|
||||
<exclude>/ssl$</exclude>
|
||||
</file_rule>
|
||||
@@ -56,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,12 +23,43 @@
|
||||
</condition>
|
||||
</library>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<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">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/concurrency$</exclude>
|
||||
<exclude>/no_ssl$</exclude>
|
||||
<exclude>/ssl$</exclude>
|
||||
<exclude>/network$</exclude>
|
||||
</file_rule>
|
||||
<cluster name="no_ssl" location="$|no_ssl\" recursive="true">
|
||||
<condition>
|
||||
@@ -0,0 +1,22 @@
|
||||
note
|
||||
description: "[
|
||||
Constant value to define the logging level.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_LOGGER_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
alert_level: INTEGER = 1 -- 0000 0001
|
||||
critical_level: INTEGER = 2 -- 0000 0010
|
||||
error_level: INTEGER = 4 -- 0000 0100
|
||||
warning_level: INTEGER = 8 -- 0000 1000
|
||||
|
||||
notice_level: INTEGER = 16 -- 0001 0000
|
||||
information_level: INTEGER = 32 -- 0010 0000
|
||||
debug_level: INTEGER = 64 -- 0100 0000
|
||||
|
||||
end
|
||||
@@ -0,0 +1,588 @@
|
||||
note
|
||||
description: "HTTPD handler interface processing request."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_REQUEST_HANDLER_I
|
||||
|
||||
inherit
|
||||
HTTPD_DEBUG_FACILITIES
|
||||
|
||||
HTTPD_LOGGER_CONSTANTS
|
||||
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_request_settings: HTTPD_REQUEST_SETTINGS)
|
||||
do
|
||||
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
|
||||
|
||||
reset_error
|
||||
if attached internal_client_socket as l_sock then
|
||||
l_sock.cleanup
|
||||
end
|
||||
internal_client_socket := Void
|
||||
end
|
||||
|
||||
reset_request
|
||||
do
|
||||
version := Void
|
||||
remote_info := Void
|
||||
|
||||
-- FIXME: optimize to just wipe_out if needed
|
||||
create method.make_empty
|
||||
create uri.make_empty
|
||||
create request_header.make_empty
|
||||
create request_header_map.make (10)
|
||||
|
||||
is_persistent_connection_requested := False
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_connected: BOOLEAN
|
||||
-- Is handler connected to incoming request via `client_socket'?
|
||||
do
|
||||
Result := client_socket.descriptor_available
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
internal_client_socket: detachable HTTPD_STREAM_SOCKET
|
||||
|
||||
client_socket: HTTPD_STREAM_SOCKET
|
||||
local
|
||||
s: like internal_client_socket
|
||||
do
|
||||
s := internal_client_socket
|
||||
if s = Void then
|
||||
s := new_client_socket (is_secure)
|
||||
internal_client_socket := s
|
||||
end
|
||||
Result := s
|
||||
end
|
||||
|
||||
request_header: STRING
|
||||
-- Header' source
|
||||
|
||||
request_header_map: HASH_TABLE [STRING, STRING]
|
||||
-- Contains key:value of the header
|
||||
|
||||
method: STRING
|
||||
-- http verb
|
||||
|
||||
uri: STRING
|
||||
-- http endpoint
|
||||
|
||||
version: detachable STRING
|
||||
-- http_version
|
||||
--| unused for now
|
||||
|
||||
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
|
||||
-- Information related to remote client
|
||||
|
||||
is_persistent_connection_requested: BOOLEAN
|
||||
-- Persistent connection requested?
|
||||
-- either has "Connection: keep-alive" header,
|
||||
-- or is HTTP/1.1 and no header "Connection: close".
|
||||
|
||||
is_http_version_1_0: BOOLEAN
|
||||
do
|
||||
Result := not attached version as v or else v.same_string ("HTTP/1.0")
|
||||
end
|
||||
|
||||
is_http_version_1_1: BOOLEAN
|
||||
do
|
||||
Result := not attached version as v or else v.same_string ("HTTP/1.1")
|
||||
end
|
||||
|
||||
is_http_version_2: BOOLEAN
|
||||
do
|
||||
Result := not attached version as v or else v.same_string ("HTTP/2.0")
|
||||
end
|
||||
|
||||
feature -- Settings
|
||||
|
||||
is_verbose: BOOLEAN
|
||||
-- Output messages?
|
||||
|
||||
verbose_level: INTEGER
|
||||
-- Output verbosity.
|
||||
|
||||
is_secure: BOOLEAN
|
||||
-- Is secure socket?
|
||||
-- i.e: SSL?
|
||||
|
||||
is_persistent_connection_supported: BOOLEAN
|
||||
-- Is persistent connection supported?
|
||||
do
|
||||
Result := {HTTPD_SERVER}.is_persistent_connection_supported and then max_keep_alive_requests > 0
|
||||
end
|
||||
|
||||
is_next_persistent_connection_supported: BOOLEAN
|
||||
-- Is next persistent connection supported?
|
||||
-- note: it is relevant only if `is_persistent_connection_supported' is True.
|
||||
|
||||
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.
|
||||
|
||||
keep_alive_timeout: INTEGER -- seconds
|
||||
-- Number of seconds for persistent connection timeout.
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- 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
|
||||
|
||||
set_is_verbose (b: BOOLEAN)
|
||||
-- Set `is_verbose' with `b'.
|
||||
do
|
||||
is_verbose := b
|
||||
ensure
|
||||
is_verbose_set: is_verbose = b
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
safe_execute
|
||||
-- Execute accepted incoming connection as request.
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
if retried then
|
||||
release
|
||||
else
|
||||
if
|
||||
not has_error and then
|
||||
is_connected
|
||||
then
|
||||
execute
|
||||
end
|
||||
release
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
execute
|
||||
require
|
||||
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
|
||||
end
|
||||
from
|
||||
-- Process persistent connection as long the socket is not closed.
|
||||
n := 0
|
||||
m := max_keep_alive_requests
|
||||
is_next_persistent_connection_supported := True
|
||||
until
|
||||
l_exit
|
||||
loop
|
||||
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 (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 (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_socket: like client_socket
|
||||
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
|
||||
socket_valid: l_socket.is_open_read and then l_socket.is_open_write
|
||||
end
|
||||
if l_socket.is_closed then
|
||||
debug ("dbglog")
|
||||
dbglog ("execute_request {socket is Closed!}")
|
||||
end
|
||||
else
|
||||
debug ("dbglog")
|
||||
dbglog ("execute_request socket=" + l_socket.descriptor.out + " ENTER")
|
||||
end
|
||||
|
||||
-- Try to get request header.
|
||||
-- If the request is reusing persistent connection, use `keep_alive_timeout',
|
||||
-- otherwise `socket_recv_timeout'.
|
||||
get_request_header (l_socket, a_is_reusing_connection)
|
||||
|
||||
if 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 ("execute_request {" + l_socket.descriptor.out + "} LEAVE")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
release
|
||||
do
|
||||
reset
|
||||
end
|
||||
|
||||
feature -- Request processing
|
||||
|
||||
process_request (a_socket: HTTPD_STREAM_SOCKET)
|
||||
-- Process request on socket `a_socket'.
|
||||
require
|
||||
no_error: not has_error
|
||||
a_uri_attached: uri /= Void
|
||||
a_method_attached: method /= Void
|
||||
a_header_map_attached: request_header_map /= Void
|
||||
a_header_text_attached: request_header /= Void
|
||||
a_socket_attached: a_socket /= Void
|
||||
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
|
||||
|
||||
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
|
||||
end_of_stream: BOOLEAN
|
||||
pos, n: INTEGER
|
||||
line: detachable STRING
|
||||
k, val: STRING
|
||||
txt: STRING
|
||||
l_is_verbose: BOOLEAN
|
||||
do
|
||||
create txt.make (64)
|
||||
request_header := txt
|
||||
l_is_verbose := is_verbose
|
||||
|
||||
if
|
||||
not has_error and then
|
||||
a_socket.readable
|
||||
then
|
||||
if a_is_reusing_connection then
|
||||
a_socket.set_recv_timeout (keep_alive_timeout) -- in seconds!
|
||||
else
|
||||
a_socket.set_recv_timeout (socket_recv_timeout) -- FIXME: return a 408 Request Timeout response ..
|
||||
end
|
||||
|
||||
if
|
||||
attached next_line (a_socket) as l_request_line and then
|
||||
not l_request_line.is_empty 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.
|
||||
-- note: may update `has_error'.
|
||||
require
|
||||
valid_line: line /= Void and then not line.is_empty
|
||||
local
|
||||
n, pos, next_pos: INTEGER
|
||||
do
|
||||
debug ("ew_standalone")
|
||||
if is_verbose then
|
||||
log ("%N## Parse HTTP request line ##", debug_level)
|
||||
log (line, debug_level)
|
||||
end
|
||||
end
|
||||
pos := line.index_of (' ', 1)
|
||||
method := line.substring (1, pos - 1)
|
||||
next_pos := line.index_of (' ', pos + 1)
|
||||
uri := line.substring (pos + 1, next_pos - 1)
|
||||
n := line.count
|
||||
if line[n] = '%R' then
|
||||
n := n - 1
|
||||
end
|
||||
version := line.substring (next_pos + 1, n)
|
||||
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
|
||||
is_readable: a_socket.is_open_read
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
if retried then
|
||||
report_error ("Rescue in next_line")
|
||||
a_socket.close
|
||||
Result := Void
|
||||
elseif a_socket.readable then
|
||||
a_socket.read_line_noexception
|
||||
Result := a_socket.last_string
|
||||
-- Do no check `socket_ok' 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
|
||||
report_error ("Socket error")
|
||||
if is_verbose then
|
||||
log (request_header +"%N" + Result + "%N## socket_ok=False! ##", debug_level)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Error with socket...
|
||||
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
|
||||
|
||||
feature -- Output
|
||||
|
||||
logger: detachable HTTPD_LOGGER
|
||||
|
||||
set_logger (a_logger: like logger)
|
||||
-- Set `logger' with `a_logger'.
|
||||
do
|
||||
logger := a_logger
|
||||
ensure
|
||||
logger_set: logger = a_logger
|
||||
end
|
||||
|
||||
log (m: STRING; a_level: INTEGER)
|
||||
-- Log message `m'.
|
||||
require
|
||||
is_verbose: is_verbose
|
||||
do
|
||||
if is_verbose and (verbose_level & a_level) = a_level then
|
||||
if attached logger as l_logger then
|
||||
l_logger.log (m)
|
||||
else
|
||||
io.put_string (m + "%N")
|
||||
end
|
||||
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
|
||||
|
||||
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
|
||||
@@ -37,7 +37,7 @@ feature {NONE} -- Initialization
|
||||
build_controller
|
||||
-- Build `controller'.
|
||||
do
|
||||
create controller
|
||||
create <NONE> controller
|
||||
end
|
||||
|
||||
initialize
|
||||
@@ -51,6 +51,9 @@ feature -- Access
|
||||
is_verbose: BOOLEAN
|
||||
-- Is verbose for output messages.
|
||||
|
||||
verbose_level: INTEGER
|
||||
-- Verbosity of output.
|
||||
|
||||
configuration: HTTPD_CONFIGURATION
|
||||
-- Associated server configuration.
|
||||
|
||||
@@ -100,7 +103,26 @@ feature -- Execution
|
||||
apply_configuration
|
||||
is_terminated := False
|
||||
if is_verbose then
|
||||
log ("%N%NStarting Web Application Server (port=" + configuration.http_server_port.out + "):%N")
|
||||
log ("%N%NStarting Web Application Server ...")
|
||||
log (" - port = " + configuration.http_server_port.out)
|
||||
log (" - max_tcp_clients = " + configuration.max_tcp_clients.out)
|
||||
log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out)
|
||||
log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds")
|
||||
log (" - socket_recv_timeout = " + configuration.socket_recv_timeout.out + " seconds")
|
||||
log (" - keep_alive_timeout = " + configuration.keep_alive_timeout.out + " seconds")
|
||||
log (" - max_keep_alive_requests = " + configuration.max_keep_alive_requests.out)
|
||||
if configuration.has_ssl_support then
|
||||
if configuration.is_secure then
|
||||
log (" - SSL = enabled")
|
||||
else
|
||||
log (" - SSL = disabled")
|
||||
end
|
||||
else
|
||||
log (" - SSL = not supported")
|
||||
end
|
||||
if configuration.verbose_level > 0 then
|
||||
log (" - verbose_level = " + configuration.verbose_level.out)
|
||||
end
|
||||
end
|
||||
is_shutdown_requested := False
|
||||
listen
|
||||
@@ -150,7 +172,7 @@ feature -- Listening
|
||||
|
||||
if not l_listening_socket.is_bound then
|
||||
if is_verbose then
|
||||
log ("Socket could not be bound on port " + l_http_port.out)
|
||||
log ("Socket could not be bound on port " + l_http_port.out + " !")
|
||||
end
|
||||
else
|
||||
l_http_port := l_listening_socket.port
|
||||
@@ -159,9 +181,9 @@ feature -- Listening
|
||||
l_listening_socket.listen (configuration.max_tcp_clients)
|
||||
if is_verbose then
|
||||
if configuration.is_secure then
|
||||
log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/")
|
||||
log ("%NListening on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/")
|
||||
else
|
||||
log ("%NHTTP Connection Server ready on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/")
|
||||
log ("%NListening on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/")
|
||||
end
|
||||
end
|
||||
on_launched (l_http_port)
|
||||
@@ -312,6 +334,7 @@ feature -- Configuration change
|
||||
is_not_launched: not is_launched
|
||||
do
|
||||
is_verbose := configuration.is_verbose
|
||||
verbose_level := configuration.verbose_level
|
||||
end
|
||||
|
||||
feature -- Output
|
||||
@@ -0,0 +1,243 @@
|
||||
note
|
||||
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, 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 {NETWORK_STREAM_SOCKET}
|
||||
make_from_descriptor_and_address
|
||||
|
||||
feature -- Input
|
||||
|
||||
read_character_noexception
|
||||
-- Read a new character.
|
||||
-- Make result available in `last_character'.
|
||||
-- No exception raised!
|
||||
do
|
||||
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
|
||||
|
||||
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 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
|
||||
|
||||
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
|
||||
read_into_pointer_noexception (p.item, start_pos, nb_bytes)
|
||||
end
|
||||
|
||||
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 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
|
||||
|
||||
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
|
||||
readable: readable
|
||||
socket_exists: exists
|
||||
local
|
||||
ext: C_STRING
|
||||
retval: INTEGER
|
||||
l: like last_string
|
||||
do
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
bytes_read := l_read
|
||||
ensure
|
||||
bytes_read_updated: 0 <= bytes_read and bytes_read <= nb_bytes
|
||||
end
|
||||
|
||||
feature -- Output
|
||||
|
||||
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_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
|
||||
create ext.make (s)
|
||||
put_managed_pointer (ext.managed_data, 0, s.count)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_incoming_data: BOOLEAN
|
||||
-- Check if Current has available data to be read.
|
||||
-- note: no data will not be removed from the queue.
|
||||
require
|
||||
socket_exists: exists
|
||||
do
|
||||
peek_stream_noexception (1)
|
||||
Result := last_string.count = 1
|
||||
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,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
|
||||
@@ -0,0 +1,149 @@
|
||||
note
|
||||
description: "SSL tcp stream socket."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTPD_STREAM_SSL_SOCKET
|
||||
|
||||
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
|
||||
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, 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 {SSL_NETWORK_STREAM_SOCKET}
|
||||
make_from_descriptor_and_address
|
||||
|
||||
feature -- Input
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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!
|
||||
local
|
||||
l_read: INTEGER
|
||||
l_last_read: INTEGER
|
||||
do
|
||||
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_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
|
||||
Precursor {HTTPD_STREAM_SOCKET} (p, 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!
|
||||
local
|
||||
l_bytes_sent: INTEGER
|
||||
do
|
||||
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-2013, Javier Velilla, Jocelyn Fiat and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
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
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user