Moved EWF workbook from ewf_example to EWF main repository.
This commit is contained in:
BIN
doc/workbook/SERVICE_TEMPLATE.png
Normal file
BIN
doc/workbook/SERVICE_TEMPLATE.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
211
doc/workbook/basics/basics.md
Normal file
211
doc/workbook/basics/basics.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
Nav: [Workbook](../workbook.md) | [Handling Requests: Form/Query Parameter](/workbook/handling_request/form.md)
|
||||||
|
|
||||||
|
|
||||||
|
## EWF basic service
|
||||||
|
|
||||||
|
##### Table of Contents
|
||||||
|
- [Basic Structure](#structure)
|
||||||
|
- [Service to Generate Plain Text](#text)
|
||||||
|
- [Source code](#source_1)
|
||||||
|
- [Service to Generate HTML](#html)
|
||||||
|
- [Source code](#source_2)
|
||||||
|
|
||||||
|
|
||||||
|
<a name="structure"/>
|
||||||
|
## EWF service structure
|
||||||
|
|
||||||
|
The following code describes the basic structure of an EWF basic service that handles HTTP requests.
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
class
|
||||||
|
SERVICE_TEMPLATE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE -- Todo explain this, and the concept of launchers and connectors ()
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
do
|
||||||
|
-- To read incoming HTTP request, we need to use `req'
|
||||||
|
|
||||||
|
-- May require talking to databases or other services.
|
||||||
|
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers and the content we want to send out our client
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
When using the "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).
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
class
|
||||||
|
SERVICE_TEMPLATE
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
-- on port 9090
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incoming request.
|
||||||
|
do
|
||||||
|
-- To read incoming HTTP requires, we need to use `req'
|
||||||
|
|
||||||
|
-- May require talking to databases or other services.
|
||||||
|
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers and the content we want to send out client
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
The **WSF_REQUEST** gives access to the incoming data; the class provides features to get information such as request method, form data, query parameters, uploaded files, HTTP request headers, and hostname of the client among others.
|
||||||
|
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.
|
||||||
|
|
||||||
|
**SERVICE_TEMPLATE** 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 or nino. For development is recommended to use Nino, 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.
|
||||||
|
|
||||||
|
The **SERVICE_TEMPLATE** class inherits from _WSF_DEFAULT_SERVICE_ class, and this one also inherits from other interfaces. Let’s describe them in a few words.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**WS_LAUNCHABLE_SERVICE** inherit from **WS_SERVICE** class, which is the low level entry point in EWF, handling each incoming request with a single procedure ```execute (req: WSF_REQUEST; res: WSF_RESPONSE) ...```. And also provides a way to launch our application using different kind of connectors. Below a [BON diagram] (http://www.bon-method.com/index_normal.htm) showing the different kind of connectors.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A basic EWF service inherits from **WSF_DEFAULT_SERVICE** (for other options see [?]).
|
||||||
|
And then you only need to implement the **execute** feature, get data from the request *req* and write the response in *res*.
|
||||||
|
|
||||||
|
<a name="text"/>
|
||||||
|
## A simple Service to Generate Plain Text.
|
||||||
|
|
||||||
|
Before to continue, it is recommended to review the getting started guided.
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/plain"], ["Content-Length", "11"]>>)
|
||||||
|
res.put_string ("Hello World")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
```
|
||||||
|
<a name="source_1"></a>
|
||||||
|
##### Source code
|
||||||
|
The source code is available on Github. You can get it by running the command:
|
||||||
|
|
||||||
|
```git clone https://github.com/EiffelWebFramework/ewf_examples.git```
|
||||||
|
|
||||||
|
The example of simple service that generate plain text response is located in the directory $PATH/ewf_examples/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:
|
||||||
|
|
||||||
|
```estudio -config simple.ecf -target simple_nino```
|
||||||
|
|
||||||
|
<a name="html"></a>
|
||||||
|
## A Service to Generate HTML.
|
||||||
|
To generate HTML, it's needed
|
||||||
|
|
||||||
|
1. Change the Content-Type : "text/html"
|
||||||
|
2. Build an HTML page
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", web_page.count.out]>>)
|
||||||
|
res.put_string (web_page)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Resume</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Hello World
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
end
|
||||||
|
```
|
||||||
|
##### Source code
|
||||||
|
The source code is available on Github. You can get it by running the command:
|
||||||
|
|
||||||
|
```git clone https://github.com/EiffelWebFramework/ewf_examples.git```
|
||||||
|
|
||||||
|
The example of the service that generates HTML is located in the directory $PATH/ewf_examples/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:
|
||||||
|
|
||||||
|
```estudio -config simple_html.ecf -target simple_html_nino```
|
||||||
|
|
||||||
|
Nav: [Workbook](../workbook.md) | [Handling Requests: Form/Query Parameter](/workbook/handling_request/form.md)
|
||||||
|
|
||||||
0
doc/workbook/basics/reading_request_data.md
Normal file
0
doc/workbook/basics/reading_request_data.md
Normal file
37
doc/workbook/basics/simple/application.e
Normal file
37
doc/workbook/basics/simple/application.e
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that Generates Plain Text"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/plain"], ["Content-Length", "11"]>>)
|
||||||
|
res.put_string ("Hello World")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/basics/simple/simple.ecf
Normal file
42
doc/workbook/basics/simple/simple.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?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">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="simple" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="simple_libfcgi" 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_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
|
||||||
|
<cluster name="simple" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="simple" extends="simple_nino">
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
52
doc/workbook/basics/simple_html/apache_config/Readme.md
Normal file
52
doc/workbook/basics/simple_html/apache_config/Readme.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
##Run simple_html example on Apache with FCGI on Windows.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####Prerequisites
|
||||||
|
|
||||||
|
* This tutorial was written for people working under Windows environment, and using Apache Server with FCGI connector
|
||||||
|
* Compile the ewf application from command line.
|
||||||
|
* Assuming you have installed Apache Server under C:/home/server/Apache24.
|
||||||
|
* Assuming you have placed your current project under C:/home/server/Apache24/fcgi-bin.
|
||||||
|
* Assuming you have setted the Listen to 8888, the defautl value is 80 .
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####FCGI module
|
||||||
|
If you don't have the FCGI module installed, you can get it from https://www.apachelounge.com/download/, download the module based on your platform [modules-2.4-win64-VC11.zip](https://www.apachelounge.com/download/VC11/modules/modules-2.4-win64-VC11.zip) or [modules-2.4-win32-VC11.zip](https://www.apachelounge.com/download/VC11/modules/modules-2.4-win32-VC11.zip), uncompress it
|
||||||
|
and copy the _mod_fcgid.so_ to C:/home/server/Apache24/modules
|
||||||
|
|
||||||
|
####Compile the project simple_html using the fcgi connector.
|
||||||
|
|
||||||
|
ec -config simple_html.ecf -target simple_html_fcgi -finalize -c_compile -project_path .
|
||||||
|
|
||||||
|
Copy the genereted exe to C:/home/server/Apache24/fcgi-bin folder.
|
||||||
|
|
||||||
|
Check if you have _libfcgi.dll_ in your PATH.
|
||||||
|
|
||||||
|
|
||||||
|
####Apache configuration
|
||||||
|
Add to httpd.conf the content, you can get the configuration file [here](config.conf)
|
||||||
|
|
||||||
|
```
|
||||||
|
LoadModule fcgid_module modules/mod_fcgid.so
|
||||||
|
|
||||||
|
<IfModule mod_fcgid.c>
|
||||||
|
<Directory "C:/home/server/Apache24/fcgi-bin">
|
||||||
|
SetHandler fcgid-script
|
||||||
|
Options +ExecCGI +Includes +FollowSymLinks -Indexes
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
ScriptAlias /simple "C:/home/server/Apache24/fcgi-bin/simple_html.exe"
|
||||||
|
</IfModule>
|
||||||
|
```
|
||||||
|
|
||||||
|
Test if your httpd.conf is ok
|
||||||
|
>httpd -t
|
||||||
|
|
||||||
|
Luanch the server
|
||||||
|
>httpd
|
||||||
|
|
||||||
|
Check the application
|
||||||
|
>http://localhost:8888/simple
|
||||||
12
doc/workbook/basics/simple_html/apache_config/config.conf
Normal file
12
doc/workbook/basics/simple_html/apache_config/config.conf
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
LoadModule fcgid_module modules/mod_fcgid.so
|
||||||
|
|
||||||
|
<IfModule mod_fcgid.c>
|
||||||
|
<Directory "C:/home/server/Apache24/fcgi-bin">
|
||||||
|
SetHandler fcgid-script
|
||||||
|
Options +ExecCGI +Includes +FollowSymLinks -Indexes
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
ScriptAlias /simple "C:/home/server/Apache24/fcgi-bin/simple_html.exe"
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
77
doc/workbook/basics/simple_html/application.e
Normal file
77
doc/workbook/basics/simple_html/application.e
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that Generate HTML"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", web_page.count.out]>>)
|
||||||
|
res.put_string (web_page)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Resume</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<p id="name">Your Name Here</p>
|
||||||
|
<a href="mailto:you@yourdomain.com"><p id="email">you@yourdomain.com</p></a>
|
||||||
|
</div>
|
||||||
|
<div class="left"></div>
|
||||||
|
<div class="right">
|
||||||
|
<h4>Objective</h4>
|
||||||
|
<p>To take a position as a software engineer.</p>
|
||||||
|
<h4>Experience</h4>
|
||||||
|
<p>Junior Developer, Software Company (2010 - Present)</p>
|
||||||
|
<ul>
|
||||||
|
<li>Designed and implemented end-user features for Flagship Product</li>
|
||||||
|
<li>Wrote third-party JavaScript and Eiffel libraries</li>
|
||||||
|
</ul>
|
||||||
|
<h4>Skills</h4>
|
||||||
|
<p>Languages: C#, JavaScript, Python, Ruby, Eiffel</p>
|
||||||
|
<p>Frameworks: .NET, Node.js, Django, Ruby on Rails, EWF</p>
|
||||||
|
<h4>Education</h4>
|
||||||
|
<p>BS, Economics, My University</p>
|
||||||
|
<ul>
|
||||||
|
<li>Award for best senior thesis</li>
|
||||||
|
<li>GPA: 3.8</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>123 Your Street, Anytown, State 12345-6789 | Tel: (555) 555-5555</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/basics/simple_html/simple_html.ecf
Normal file
42
doc/workbook/basics/simple_html/simple_html.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="simple_html" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="simple_html">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="simple_html" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="simple_html_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="simple_html" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="simple_html_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
6
doc/workbook/basics/simple_html/simple_html.rc
Normal file
6
doc/workbook/basics/simple_html/simple_html.rc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
1 "This Program was made using EiffelStudio using Visual Studio C++"
|
||||||
|
END
|
||||||
47
doc/workbook/generating_response/exel/application.e
Normal file
47
doc/workbook/generating_response/exel/application.e
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that show how to use common Status Code"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/csv"],["Content-Disposition","attachment;filename=Report.xls"],["Content-Length", sheet.count.out]>>)
|
||||||
|
res.put_string (sheet)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ,["Content-Disposition","attachment;filename=Report.xls"]
|
||||||
|
|
||||||
|
|
||||||
|
sheet: STRING ="[
|
||||||
|
Q1 Q2 Q3 Q4 Total
|
||||||
|
Cherries 78 87 92 29 =SUM(B2:E2)
|
||||||
|
Grapes 77 86 93 30 =SUM(B3:E3)
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/generating_response/exel/exel.ecf
Normal file
42
doc/workbook/generating_response/exel/exel.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="exel" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="exel">l
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="exel" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="exel_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="exel" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="exel_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
1021
doc/workbook/generating_response/generating_response.md
Normal file
1021
doc/workbook/generating_response/generating_response.md
Normal file
File diff suppressed because it is too large
Load Diff
68
doc/workbook/generating_response/headers/application.e
Normal file
68
doc/workbook/generating_response/headers/application.e
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that build a generic front end for the most used search engines."
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
-- (1) To send a response we need to setup, the status code and the response headers.
|
||||||
|
-- res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", web_page.count.out]>>)
|
||||||
|
-- res.put_string (web_page)
|
||||||
|
|
||||||
|
-- (2) Using put_header_line
|
||||||
|
-- res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
|
-- res.put_header_line ("Content-Type:text/html")
|
||||||
|
res.put_header_line ("Content-Length:"+ web_page.count.out)
|
||||||
|
res.put_header_line ("Content-Type:text/plain")
|
||||||
|
|
||||||
|
res.put_string (web_page)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Home Page
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Headers Responses</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="right">
|
||||||
|
<h2>Example Header Response</h2>
|
||||||
|
<p>Response headers</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>EWF Response Header</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
end
|
||||||
42
doc/workbook/generating_response/headers/headers.ecf
Normal file
42
doc/workbook/generating_response/headers/headers.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="headers" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="headers_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="headers" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="headers_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
183
doc/workbook/generating_response/search/application.e
Normal file
183
doc/workbook/generating_response/search/application.e
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that build a generic front end for the most used search engines."
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
if req.is_get_request_method then
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", web_page.count.out]>>)
|
||||||
|
res.put_string (web_page)
|
||||||
|
else
|
||||||
|
send_resouce_not_found (req, res)
|
||||||
|
end
|
||||||
|
elseif req.is_post_request_method then
|
||||||
|
if req.path_info.same_string ("/search") then
|
||||||
|
if attached {WSF_STRING} req.form_parameter ("query") as l_query then
|
||||||
|
if attached {WSF_STRING} req.form_parameter ("engine") as l_engine then
|
||||||
|
if attached {STRING} map.at (l_engine.value) as l_engine_url then
|
||||||
|
l_engine_url.append (l_query.value)
|
||||||
|
send_redirect (req, res, l_engine_url)
|
||||||
|
-- res.redirect_now (l_engine_url)
|
||||||
|
else
|
||||||
|
send_bad_request (req, res, " <strong>search engine: " + l_engine.value + "</strong> not supported,<br> try with Google or Bing")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_bad_request (req, res, " <strong>search engine</strong> not selected")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_bad_request (req, res, " form_parameter <strong>query</strong> is not present")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_resouce_not_found (req, res)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Method Not Allowed")
|
||||||
|
l_message.replace_substring_all ("$status", "Method Not Allowed 405")
|
||||||
|
-- Method not allowed
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.method_not_allowed, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Engine Map
|
||||||
|
|
||||||
|
map : STRING_TABLE[STRING]
|
||||||
|
do
|
||||||
|
create Result.make (2)
|
||||||
|
Result.put ("http://www.google.com/search?q=", "Google")
|
||||||
|
Result.put ("http://www.bing.com/search?q=", "Bing")
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Redirect
|
||||||
|
|
||||||
|
send_redirect (req: WSF_REQUEST; res: WSF_RESPONSE; a_location: READABLE_STRING_32)
|
||||||
|
-- Redirect to `a_location'
|
||||||
|
local
|
||||||
|
h: HTTP_HEADER
|
||||||
|
do
|
||||||
|
create h.make
|
||||||
|
h.put_content_type_text_html
|
||||||
|
h.put_current_date
|
||||||
|
h.put_location (a_location)
|
||||||
|
res.set_status_code ({HTTP_STATUS_CODE}.see_other)
|
||||||
|
res.put_header_text (h.string)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Bad Request
|
||||||
|
|
||||||
|
send_bad_request (req: WSF_REQUEST; res: WSF_RESPONSE; description: STRING)
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Bad Request")
|
||||||
|
l_message.replace_substring_all ("$status", "Bad Request" + description)
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.bad_request, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Resource not found
|
||||||
|
|
||||||
|
send_resouce_not_found (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Resource not found")
|
||||||
|
l_message.replace_substring_all ("$status", "Resource " + req.request_uri + " not found 404")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.not_found, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Home Page
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Generic Search Engine</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="right">
|
||||||
|
<h2>Generic Search Engine</h2>
|
||||||
|
<form method="POST" action="/search" target="_blank">
|
||||||
|
<fieldset>
|
||||||
|
Search: <input type="search" name="query" placeholder="EWF framework"><br>
|
||||||
|
<div>
|
||||||
|
<input type="radio" name="engine" value="Google" checked><img src="http://ebizmba.ebizmbainc.netdna-cdn.com/images/logos/google.gif" height="24" width="42">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input type="radio" name="engine" value="Bing"><img src="http://ebizmba.ebizmbainc.netdna-cdn.com/images/logos/bing.gif" height="24" width="42">
|
||||||
|
</div><br>
|
||||||
|
</fieldset>
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p><a href="http://www.ebizmba.com/articles/search-engines">Top 15 Most Popular Search Engines | March 2015</a></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
feature -- Generic Message
|
||||||
|
|
||||||
|
message_template: STRING="[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>$title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<p id="name">Use a tool to see the request and header details, for example (Developers tools in Chrome or Firebugs in Firefox)</p>
|
||||||
|
</div>
|
||||||
|
<div class="left"></div>
|
||||||
|
<div class="right">
|
||||||
|
<h4>This page is an example of $status</h4>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<p><a href="/">Back Home</a></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/generating_response/search/search.ecf
Normal file
42
doc/workbook/generating_response/search/search.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="search" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="search">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="search" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="search_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="search" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="search_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
149
doc/workbook/generating_response/status/application.e
Normal file
149
doc/workbook/generating_response/status/application.e
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that a simple web page to show the most common status codes"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
if req.is_get_request_method then
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", web_page.count.out]>>)
|
||||||
|
res.put_string (web_page)
|
||||||
|
elseif req.path_info.same_string ("/redirect") then
|
||||||
|
send_redirect (req, res, "https://httpwg.github.io/")
|
||||||
|
elseif req.path_info.same_string ("/bad_request") then
|
||||||
|
-- Here you can do some logic for example log, send emails to register the error, before to send the response.
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Bad Request")
|
||||||
|
l_message.replace_substring_all ("$status", "Bad Request 400")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.bad_request, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
elseif req.path_info.same_string ("/internal_error") then
|
||||||
|
-- Here you can do some logic for example log, send emails to register the error, before to send the response.
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Internal Server Error")
|
||||||
|
l_message.replace_substring_all ("$status", "Internal Server Error 500")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.internal_server_error, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
else
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Resource not found")
|
||||||
|
l_message.replace_substring_all ("$status", "Resource not found 400")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.not_found, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
create l_message.make_from_string (message_template)
|
||||||
|
l_message.replace_substring_all ("$title", "Method Not Allowed")
|
||||||
|
l_message.replace_substring_all ("$status", "Method Not Allowed 405")
|
||||||
|
-- Method not allowed
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.method_not_allowed, <<["Content-Type", "text/html"], ["Content-Length", l_message.count.out]>>)
|
||||||
|
res.put_string (l_message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Home Page
|
||||||
|
|
||||||
|
send_redirect (req: WSF_REQUEST; res: WSF_RESPONSE; a_location: READABLE_STRING_32)
|
||||||
|
-- Redirect to `a_location'
|
||||||
|
local
|
||||||
|
h: HTTP_HEADER
|
||||||
|
do
|
||||||
|
create h.make
|
||||||
|
h.put_content_type_text_html
|
||||||
|
h.put_current_date
|
||||||
|
h.put_location (a_location)
|
||||||
|
res.set_status_code ({HTTP_STATUS_CODE}.see_other)
|
||||||
|
res.put_header_text (h.string)
|
||||||
|
end
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Example showing common status codes</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<p id="name">Use a tool to see the request and header details, for example (Developers tools in Chrome or Firebugs in Firefox)</p>
|
||||||
|
</div>
|
||||||
|
<div class="left"></div>
|
||||||
|
<div class="right">
|
||||||
|
<h4>This page is an example of Status Code 200</h4>
|
||||||
|
|
||||||
|
<h4> Redirect Example </h4>
|
||||||
|
<p> Click on the following link will redirect you to the HTTP Specifcation, we can do the redirect from the HTML directly but
|
||||||
|
here we want to show you an exmaple, where you can do something before to send a redirect <a href="/redirect">Redirect</a></p>
|
||||||
|
|
||||||
|
<h4> Bad Request </h4>
|
||||||
|
<p> Click on the following link, the server will answer with a 400 error, check the status code <a href="/bad_request">Bad Request</a></p>
|
||||||
|
|
||||||
|
<h4> Internal Server Error </h4>
|
||||||
|
<p> Click on the following link, the server will answer with a 500 error, check the status code <a href="/internal_error">Internal Error</a></p>
|
||||||
|
|
||||||
|
<h4> Resource not found </h4>
|
||||||
|
<p> Click on the following link or add to the end of the url something like /1030303 the server will answer with a 404 error, check the status code <a href="/not_foundd">Not found</a></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>Useful links for status codes <a href="httpstat.us">httpstat.us</a> and <a href="httpbing.org">httpbin.org</a></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
feature -- Generic Message
|
||||||
|
|
||||||
|
message_template: STRING="[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>$title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<p id="name">Use a tool to see the request and header details, for example (Developers tools in Chrome or Firebugs in Firefox)</p>
|
||||||
|
</div>
|
||||||
|
<div class="left"></div>
|
||||||
|
<div class="right">
|
||||||
|
<h4>This page is an example of $status</h4>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<p><a href="/">Back Home</a></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/generating_response/status/status.ecf
Normal file
42
doc/workbook/generating_response/status/status.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="status" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="status">l
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="status" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="status_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="status" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="status_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
153
doc/workbook/handling_cookies/example/application.e
Normal file
153
doc/workbook/handling_cookies/example/application.e
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that build a generic front to demonstrate the use of Cookies"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose",True)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
l_header: HTTP_HEADER
|
||||||
|
l_time: HTTP_DATE
|
||||||
|
l_cookies: STRING
|
||||||
|
l_answer: STRING
|
||||||
|
do
|
||||||
|
-- all the cookies
|
||||||
|
create l_cookies.make_empty
|
||||||
|
across req.cookies as ic loop
|
||||||
|
l_cookies.append (ic.item.name)
|
||||||
|
l_cookies.append("<br>")
|
||||||
|
end
|
||||||
|
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
create l_header.make
|
||||||
|
create l_answer.make_from_string (web_page)
|
||||||
|
if req.cookie ("_EWF_Cookie") = Void then
|
||||||
|
-- First access the the home page, find a cookie with specific name `_EWF_Cookie'
|
||||||
|
l_answer.replace_substring_all ("$header_title", "Hey, thanks for access our cool site, this is your first acess")
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_header.put_cookie_with_expiration_date ("_EWF_Cookie", "EXAMPLE",l_time.date_time, "", Void, False, True)
|
||||||
|
else
|
||||||
|
-- No a new access
|
||||||
|
l_answer.replace_substring_all ("$header_title", "Welcome back, please check all the new things we have!!!")
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
end
|
||||||
|
l_header.put_content_type_text_html
|
||||||
|
l_header.put_content_length (l_answer.count)
|
||||||
|
res.put_header_text (l_header.string)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
|
||||||
|
elseif req.path_info.same_string ("/visitors") then
|
||||||
|
create l_header.make
|
||||||
|
create l_answer.make_from_string (visit_page)
|
||||||
|
if req.cookie ("_visits") = Void then
|
||||||
|
-- First access the the visit page, find a cookie with specific name `_visits'
|
||||||
|
l_answer.replace_substring_all ("$visit", "1")
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_header.put_cookie_with_expiration_date ("_visits", "1",l_time.date_time, "/visitors", Void, False, True)
|
||||||
|
|
||||||
|
else
|
||||||
|
if attached {WSF_STRING} req.cookie ("_visits") as l_visit then
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_answer.replace_substring_all ("$visit", (l_visit.value.to_integer + 1).out )
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
l_header.put_cookie_with_expiration_date ("_visits", (l_visit.value.to_integer + 1).out,l_time.date_time, "/visitors", Void, False, True)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.second_add (120)
|
||||||
|
l_header.put_content_type_text_html
|
||||||
|
-- This cookie expires in 120 seconds, its valid for 120 seconds
|
||||||
|
l_header.put_cookie_with_expiration_date ("_Framework", "EWF",l_time.date_time, "/", Void, False, True)
|
||||||
|
-- This is a session cookie, valid only to the current browsing session.
|
||||||
|
l_header.put_cookie ("Session", "Cookie",Void, "/", Void, False, True)
|
||||||
|
l_header.put_content_length (l_answer.count)
|
||||||
|
res.add_header_text (l_header.string)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Home Page
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Cookies</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="right">
|
||||||
|
<h2>$header_title</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<a href="/visitors">Visitors</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Cookies for the home page</h3>
|
||||||
|
$cookies
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
visit_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Visit Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="right">
|
||||||
|
<h2>The number of visits is $visit</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Cookies for the Visit page</h3>
|
||||||
|
$cookies
|
||||||
|
</div>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Back to <a href="/"> Home </a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<p>EWF Example Cookies</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/handling_cookies/example/example.ecf
Normal file
42
doc/workbook/handling_cookies/example/example.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?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="example" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="example">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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="example" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="example_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="example" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="example_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
300
doc/workbook/handling_cookies/handling_cookies.md
Normal file
300
doc/workbook/handling_cookies/handling_cookies.md
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
Nav: [Workbook](../workbook.md) | [Generating Responses](/workbook/generating_response/generating_response.md)
|
||||||
|
|
||||||
|
# Handling Cookies
|
||||||
|
|
||||||
|
- [Cookie](#cookie)
|
||||||
|
- [Cookie Porperties](#properties)
|
||||||
|
- [Write and Read Cookies](#set_get)
|
||||||
|
- [How to set a cookie](#set_cookie)
|
||||||
|
- [How to read a cookie](#read_cookie)
|
||||||
|
- [Examples](#examples)
|
||||||
|
|
||||||
|
<a name="cookie"/>
|
||||||
|
## [Cookie](http://httpwg.github.io/specs/rfc6265.html)
|
||||||
|
A cookie is a piece of data that can be stored in a browser's cache. If you visit a web site and then revisit it, the cookie data can be used to identify you as a return visitor. Cookies enable state information, such as an online shopping cart, to be remembered. A cookie can be short term, holding data for a single web session, that is, until you close the browser, or a cookie can be longer term, holding data for a week or a year.
|
||||||
|
|
||||||
|
Cookies are used a lot in web client-server communication.
|
||||||
|
|
||||||
|
- HTTP State Management With Cookies
|
||||||
|
|
||||||
|
- Personalized response to the client based on their preference, for example we can set background color as cookie in client browser and then use it to customize response background color, image etc.
|
||||||
|
|
||||||
|
Server send cookies to the client
|
||||||
|
|
||||||
|
>Set-Cookie: _Framework=EWF; Path=/; Expires=Tue, 10 Mar 2015 13:28:10 GMT; HttpOnly%R
|
||||||
|
|
||||||
|
|
||||||
|
Client send cookies to server
|
||||||
|
|
||||||
|
>Cookie: _Framework=EWF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="properties"/>
|
||||||
|
### Cookie properties
|
||||||
|
|
||||||
|
- Comment: describe the purpose of the cookie. Note that server doesn’t receive this information when client sends cookie in request header.
|
||||||
|
- Domain: domain name for the cookie.
|
||||||
|
- Expiration/MaxAge: Expiration time of the cookie, we could also set it in seconds. (At the moment Max-Age attribute is not supported)
|
||||||
|
- Name: name of the cookie.
|
||||||
|
- Path: path on the server to which the browser returns this cookie. Path instruct the browser to send cookie to a particular resource.
|
||||||
|
- Secure: True, if the browser is sending cookies only over a secure protocol, False in other case.
|
||||||
|
- Value: Value of th cookie as string.
|
||||||
|
- HttpOnly: Checks whether this Cookie has been marked as HttpOnly.
|
||||||
|
- Version:
|
||||||
|
|
||||||
|
<a name="set_get"/>
|
||||||
|
## Write and Read Cookies.
|
||||||
|
|
||||||
|
To send a cookie to the client we should use the [HTTP_HEADER] class, and call ```h.put_cookie``` feature or
|
||||||
|
```h.put_cookie_with_expiration_date``` feature, see [How to set Cookies]() to learn the details, and the set it to response object [WSF_RESPONSE] as we saw previously.
|
||||||
|
|
||||||
|
We will show an example.
|
||||||
|
|
||||||
|
To Read incomming cookies we can read all the cookies with
|
||||||
|
|
||||||
|
```
|
||||||
|
cookies: ITERABLE [WSF_VALUE]
|
||||||
|
-- All cookies.
|
||||||
|
```
|
||||||
|
which return an interable of WSF_VALUE objects corresponding to the cookies the browser has associated with the web site.
|
||||||
|
We can also check if a particular cookie by name using
|
||||||
|
|
||||||
|
```
|
||||||
|
WSF_REQUEST.cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||||
|
-- Field for name `a_name'.
|
||||||
|
```
|
||||||
|
feature.
|
||||||
|
|
||||||
|
|
||||||
|
<a name="set_cookie"/>
|
||||||
|
### How to set Cookies
|
||||||
|
Here we have the feature definitions to set cookies
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
deferred class interface
|
||||||
|
HTTP_HEADER_MODIFIER
|
||||||
|
|
||||||
|
feature -- Cookie
|
||||||
|
|
||||||
|
put_cookie (key, value: READABLE_STRING_8; expiration, path, domain: detachable READABLE_STRING_8; secure, http_only: BOOLEAN)
|
||||||
|
-- Set a cookie on the client's machine
|
||||||
|
-- with key 'key' and value 'value'.
|
||||||
|
-- Note: you should avoid using "localhost" as `domain' for local cookies
|
||||||
|
-- since they are not always handled by browser (for instance Chrome)
|
||||||
|
require
|
||||||
|
make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty)
|
||||||
|
domain_without_port_info: domain /= Void implies domain.index_of (':', 1) = 0
|
||||||
|
|
||||||
|
put_cookie_with_expiration_date (key, value: READABLE_STRING_8; expiration: DATE_TIME; path, domain: detachable READABLE_STRING_8; secure, http_only: BOOLEAN)
|
||||||
|
-- Set a cookie on the client's machine
|
||||||
|
-- with key 'key' and value 'value'.
|
||||||
|
require
|
||||||
|
make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example of use:
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
response_with_cookies (res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
l_header: HTTP_HEADER
|
||||||
|
l_time: HTTP_DATE
|
||||||
|
do
|
||||||
|
create l_header.make
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_header.put_content_type_text_html
|
||||||
|
l_header.put_cookie_with_expiration_date ("EWFCookie", "EXAMPLE",l_time.date_time, "/", Void, False, True)
|
||||||
|
res.put_header_text (l_header.string)
|
||||||
|
res.put_string (web_page)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
<a name="read_cookie"/>
|
||||||
|
### How to read Cookies
|
||||||
|
|
||||||
|
Reading a particular cookie
|
||||||
|
```eiffel
|
||||||
|
if req.cookie ("EWFCookie") = Void then
|
||||||
|
do_something
|
||||||
|
end
|
||||||
|
````
|
||||||
|
|
||||||
|
Reading all the cookies
|
||||||
|
|
||||||
|
```Eiffel
|
||||||
|
across req.cookies as ic loop
|
||||||
|
print (ic.item.name)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
<a name="examples"/>
|
||||||
|
### Example
|
||||||
|
The following EWF service shows a basic use of cookies.
|
||||||
|
1. It display a message to first-time visitors.
|
||||||
|
2. Display a welcome back message if a visitor return.
|
||||||
|
3. A visitor page, counting the number of visits to the page (track user access counts).
|
||||||
|
4. A cookie with an expiration of 120 seconds.
|
||||||
|
5. A cookie with an session level, valid in browser session.
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
note
|
||||||
|
description : "Basic Service that build a generic front to demonstrate the use of Cookies"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose",True)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
l_header: HTTP_HEADER
|
||||||
|
l_time: HTTP_DATE
|
||||||
|
l_cookies: STRING
|
||||||
|
l_answer: STRING
|
||||||
|
do
|
||||||
|
-- all the cookies
|
||||||
|
create l_cookies.make_empty
|
||||||
|
across req.cookies as ic loop
|
||||||
|
l_cookies.append (ic.item.name)
|
||||||
|
l_cookies.append("<br>")
|
||||||
|
end
|
||||||
|
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
create l_header.make
|
||||||
|
create l_answer.make_from_string (web_page)
|
||||||
|
if req.cookie ("_EWF_Cookie") = Void then
|
||||||
|
-- First access the the home page, find a cookie with specific name `_EWF_Cookie'
|
||||||
|
l_answer.replace_substring_all ("$header_title", "Hey, thanks for access our cool site, this is your first acess")
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_header.put_cookie_with_expiration_date ("_EWF_Cookie", "EXAMPLE",l_time.date_time, "", Void, False, True)
|
||||||
|
else
|
||||||
|
-- No a new access
|
||||||
|
l_answer.replace_substring_all ("$header_title", "Welcome back, please check all the new things we have!!!")
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
end
|
||||||
|
l_header.put_content_type_text_html
|
||||||
|
l_header.put_content_length (l_answer.count)
|
||||||
|
res.put_header_text (l_header.string)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
|
||||||
|
elseif req.path_info.same_string ("/visitors") then
|
||||||
|
create l_header.make
|
||||||
|
create l_answer.make_from_string (visit_page)
|
||||||
|
if req.cookie ("_visits") = Void then
|
||||||
|
-- First access the the visit page, find a cookie with specific name `_visits'
|
||||||
|
l_answer.replace_substring_all ("$visit", "1")
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_header.put_cookie_with_expiration_date ("_visits", "1",l_time.date_time, "/visitors", Void, False, True)
|
||||||
|
|
||||||
|
else
|
||||||
|
if attached {WSF_STRING} req.cookie ("_visits") as l_visit then
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.day_add (40)
|
||||||
|
l_answer.replace_substring_all ("$visit", (l_visit.value.to_integer + 1).out )
|
||||||
|
l_answer.replace_substring_all ("$cookies", l_cookies)
|
||||||
|
l_header.put_cookie_with_expiration_date ("_visits", (l_visit.value.to_integer + 1).out,l_time.date_time, "/visitors", Void, False, True)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
create l_time.make_now_utc
|
||||||
|
l_time.date_time.second_add (120)
|
||||||
|
l_header.put_content_type_text_html
|
||||||
|
-- This cookie expires in 120 seconds, its valid for 120 seconds
|
||||||
|
l_header.put_cookie_with_expiration_date ("_Framework", "EWF",l_time.date_time, "/", Void, False, True)
|
||||||
|
-- This is a session cookie, valid only to the current browsing session.
|
||||||
|
l_header.put_cookie ("Session", "Cookie",Void, "/", Void, False, True)
|
||||||
|
l_header.put_content_length (l_answer.count)
|
||||||
|
res.add_header_text (l_header.string)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Home Page
|
||||||
|
|
||||||
|
web_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Cookies</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="right">
|
||||||
|
<h2>$header_title</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<a href="/visitors">Visitors</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Cookies for the home page</h3>
|
||||||
|
$cookies
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
visit_page: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Visit Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="right">
|
||||||
|
<h2>The number of visits is $visit</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Cookies for the Visit page</h3>
|
||||||
|
$cookies
|
||||||
|
</div>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Back to <a href="/"> Home </a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<p>EWF Example Cookies</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Nav: [Workbook](../workbook.md) | [Generating Responses](/workbook/generating_response/generating_response.md)
|
||||||
309
doc/workbook/handling_request/form.md
Normal file
309
doc/workbook/handling_request/form.md
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
Nav: [Workbook](../workbook.md) | [Basic Concepts] (/workbook/basics/basics.md) | [Handling Requests: Header Fields](/workbook/handling_request/headers.md)
|
||||||
|
|
||||||
|
|
||||||
|
#Handling Requests: Form/Query Data
|
||||||
|
|
||||||
|
|
||||||
|
##### Table of Contents
|
||||||
|
- [Reading Form Data](#read)
|
||||||
|
- [Query Parameters](#query)
|
||||||
|
- [Form Parameters](#form)
|
||||||
|
- [Uniform Read](#uniform)
|
||||||
|
- [Reading Parameters and Values](#reading_pv)
|
||||||
|
- [How to read all parameters names](#all_names)
|
||||||
|
- [How to read single values](#single_values)
|
||||||
|
- [How to read multiple values](#multiple_values)
|
||||||
|
- [How to read table values](#table_values)
|
||||||
|
- [Reading raw data](#raw_data)
|
||||||
|
- [Upload Files](#upload)
|
||||||
|
- [Examples](#examples)
|
||||||
|
|
||||||
|
|
||||||
|
An HTML Form can handle GET and POST requests.
|
||||||
|
When we use a form with method GET, the data is attached at the end of the url for example:
|
||||||
|
|
||||||
|
>http://wwww.example.com?key1=value1&...keyn=valuen
|
||||||
|
|
||||||
|
If we use the method POST, the data is sent to the server in a different line.
|
||||||
|
|
||||||
|
Extracting form data from the server side is one of the most tedious parts. If you do it by hand, you will need
|
||||||
|
to parse the input, you'll have to URL-decode the value.
|
||||||
|
|
||||||
|
Here we will show you how to read input submitted by a user using a Form (GET and POST).
|
||||||
|
* How to handle missing values:
|
||||||
|
* client side validattion, server side validations, set default if it's a valid option.
|
||||||
|
* How to populate Eiffel objects from the request data.
|
||||||
|
|
||||||
|
<a name="read"/>
|
||||||
|
## Reading Form Data
|
||||||
|
EWF [WSF_REQUEST]() class, provides features to handling this form parsing automatically.
|
||||||
|
|
||||||
|
<a name="query"/>
|
||||||
|
### Query Parameters
|
||||||
|
|
||||||
|
WSF_REQUEST.query_parameters: ITERABLE [WSF_VALUE]
|
||||||
|
-- All query parameters
|
||||||
|
|
||||||
|
WSF_REQUEST.query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||||
|
-- Query parameter for name `a_name'.
|
||||||
|
<a name="form"/>
|
||||||
|
### Form Parameters
|
||||||
|
|
||||||
|
WSF_REQUEST.form_parameters: ITERABLE [WSF_VALUE]
|
||||||
|
-- All form parameters sent by a POST
|
||||||
|
|
||||||
|
WSF_REQUEST.form_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||||
|
-- Field for name `a_name'.
|
||||||
|
|
||||||
|
The values supplied to form_parameter and query_parameter are case sensitive.
|
||||||
|
|
||||||
|
<a name="uniform"/>
|
||||||
|
### Read Data
|
||||||
|
The previous features, let you read the data one way for GET request and a different way for POST request. WSF_REQUEST provide a feature to read all the data in a uniform way.
|
||||||
|
|
||||||
|
WSF_REQUEST.item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||||
|
-- Variable named `a_name' from any of the variables container
|
||||||
|
-- and following a specific order: form_, query_ and path_ parameters
|
||||||
|
|
||||||
|
So, you use **WSF_REQUEST.item** feature exactly the same way for GET and POST request.
|
||||||
|
|
||||||
|
>Note: if a query parameter has the same name as a form paramenter req.item will retrieve the form paramenter. Remember the precedence: form > query > path
|
||||||
|
|
||||||
|
|
||||||
|
<a name="reading_pv">
|
||||||
|
## Reading Parameters and Values
|
||||||
|
|
||||||
|
Suppose we have the following HTML5 form using Method POST. This HTML5 form has client side form validation using the new HTML5 attribute, you can do the same using Javascript. So in this case if the user does not fill the fields as expected the form will not be submitted to the server.
|
||||||
|
|
||||||
|
>Note: You want to validate on the server side because you can protect against the malicious user, who can easily bypass your JavaScript and submit dangerous input to the server.
|
||||||
|
|
||||||
|
```
|
||||||
|
<h1> EWF Handling Client Request: Form example </h1>
|
||||||
|
<form action="/" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Personal details</legend>
|
||||||
|
<div>
|
||||||
|
<label>First Name
|
||||||
|
<input id="given-name" name="given-name" type="text" placeholder="First name only" required autofocus>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Last Name
|
||||||
|
<input id="family-name" name="family-name" type="text" placeholder="Last name only" required autofocus>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Email
|
||||||
|
<input id="email" name="email" type="email" placeholder="example@domain.com" required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Languages
|
||||||
|
<input type="checkbox" name="languages" value="Spanish"> Spanish
|
||||||
|
<input type="checkbox" name="languages" value="English"> English
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<button type=submit>Submit Form</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
```
|
||||||
|
<a name="all_names">
|
||||||
|
### How to read all parameter names
|
||||||
|
To read all the parameters names we simple call WSF_REQUEST.form_parameters.
|
||||||
|
|
||||||
|
```
|
||||||
|
req: WSF_REQUEST
|
||||||
|
across req.form_parameters as ic loop show_parameter_name (ic.item.key) end
|
||||||
|
```
|
||||||
|
<a name="single_values">
|
||||||
|
### How to read single values
|
||||||
|
To read a particular parameter, a single value, for example `given-name', we simple call WSF_REQUEST.form_parameter (a_name) and we check if it's attached to WSF_STRING (represents a String parameter)
|
||||||
|
```
|
||||||
|
req: WSF_REQUEST
|
||||||
|
if attached {WSF_STRING} req.form_paramenter ('given-name') as l_given_name then
|
||||||
|
-- Work with the given parameter, for example populate an USER object
|
||||||
|
-- the argument is case sensitive
|
||||||
|
else
|
||||||
|
-- Value missing, check the name against the HTML form
|
||||||
|
end
|
||||||
|
```
|
||||||
|
<a name="multiple_values">
|
||||||
|
### How to read multiple values
|
||||||
|
|
||||||
|
To read multiple values, for example in the case of `languages', we simple call WSF_REQUEST.form_parameter (a_name) and we check if it's attached to WSF_MULTIPLE_STRING (represents a String parameter)
|
||||||
|
|
||||||
|
```
|
||||||
|
req: WSF_REQUEST
|
||||||
|
idioms: LIST[STRING]
|
||||||
|
-- the argument is case sensitive
|
||||||
|
if attached {WSF_MULTIPLE_STRING} req.form_paramenter ('languages') as l_languages then
|
||||||
|
-- Work with the given parameter, for example populate an USER object
|
||||||
|
-- Get all the associated values
|
||||||
|
create {ARRAYED_LIST[STRING]} idioms.make (2)
|
||||||
|
across l_languages as ic loop idioms.force (ic.item.value) end
|
||||||
|
elseif attached {WSF_STRING} req.form_paramenter ('languages') as l_language then
|
||||||
|
-- Value missing, check the name against the HTML form
|
||||||
|
create {ARRAYED_LIST[STRING]} idioms.make (1)
|
||||||
|
idioms.force (l_language.value)
|
||||||
|
else
|
||||||
|
-- Value missing
|
||||||
|
end
|
||||||
|
```
|
||||||
|
In this case we are handling strings values, but in some cases you will need to do a conversion, betweend the strings that came from the request to map them to your domain model.
|
||||||
|
|
||||||
|
<a name="table_values">
|
||||||
|
### How to read table values
|
||||||
|
This is particularly useful when you have a request with the following format
|
||||||
|
|
||||||
|
``` <a href="/link?tab[a]=1&tab[b]=2&tab[c]=foo"> ```
|
||||||
|
|
||||||
|
To read table values, for example in the case of `tab', we simple call WSF_REQUEST.form_parameter (a_name) and we check if it's attached to WSF_TABLE.
|
||||||
|
|
||||||
|
```
|
||||||
|
if attached {WSF_TABLE} req.query_parameter ("tab") as l_tab then
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append (l_tab.name)
|
||||||
|
from
|
||||||
|
l_tab.values.start
|
||||||
|
until
|
||||||
|
l_tab.values.after
|
||||||
|
loop
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append (l_tab.values.key_for_iteration)
|
||||||
|
if attached {WSF_STRING} l_tab.value (l_tab.values.key_for_iteration) as l_value then
|
||||||
|
l_parameter_names.append ("=")
|
||||||
|
l_parameter_names.append (l_value.value)
|
||||||
|
end
|
||||||
|
l_tab.values.forth
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="raw_data">
|
||||||
|
## Reading Raw Data
|
||||||
|
You can also access the data in raw format, it means you will need to parse and url-decode it, and also you will not be able to use the previous features, by default, to enable that you need to call `req.set_raw_input_data_recorded (True)'. This feature (reading raw data) is useful if you are reading POST data with JSON or XML formats, but it's not convinient for HTML forms.
|
||||||
|
|
||||||
|
To read raw data you need to do this
|
||||||
|
|
||||||
|
```
|
||||||
|
l_raw_data:STRING
|
||||||
|
|
||||||
|
req.set_raw_input_data_recorded (True) --
|
||||||
|
create l_raw_data.make_empty
|
||||||
|
req.read_input_data_into (l_raw_data)
|
||||||
|
```
|
||||||
|
|
||||||
|
> given-name=testr&family-name=test&dob=1976-08-26&email=test%40gmail.com&url=http%3A%2F%2Fwww.eiffelroom.com&phone=455555555555&languages=Spanish&languages=English
|
||||||
|
|
||||||
|
<a name=upload></a>
|
||||||
|
## Upload Files
|
||||||
|
How can we read data when the date come from an uploaded file/s?.
|
||||||
|
HTML supports a form element ```<input type="File" ... > ``` to upload a single file and ```<input type="File" ... multiplr> ``` to upload multiple files.
|
||||||
|
|
||||||
|
So supose we have the following form
|
||||||
|
|
||||||
|
```
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Client Request: File Upload Example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1> EWF Handling Client Request: File Upload Example</h1>
|
||||||
|
<form action="/upload" enctype="multipart/form-data" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Upload file/s</legend>
|
||||||
|
<div>
|
||||||
|
<label>File
|
||||||
|
<input name="file-name[]" type="file" multiple>
|
||||||
|
</label>
|
||||||
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<button type=submit>Send</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
The class WSF_REQUEST has defines mechanism to work with uploaded files. We can call the query
|
||||||
|
|
||||||
|
```
|
||||||
|
WSF_REQUEST.has_uploaded_file: BOOLEAN
|
||||||
|
-- Has any uploaded file?
|
||||||
|
```
|
||||||
|
|
||||||
|
to check if the request form parameters has any uploaded file, and we can call the feature
|
||||||
|
|
||||||
|
```
|
||||||
|
WSF_REQUEST.uploaded_files: ITERABLE [WSF_UPLOADED_FILE]
|
||||||
|
-- uploaded files values
|
||||||
|
--| filename: original path from the user
|
||||||
|
--| type: content type
|
||||||
|
--| tmp_name: path to temp file that resides on server
|
||||||
|
--| tmp_base_name: basename of `tmp_name'
|
||||||
|
--| error: if /= 0 , there was an error : TODO ...
|
||||||
|
--| size: size of the file given by the http request
|
||||||
|
```
|
||||||
|
to iterate over the uploaded files if any, and the details in the class [WSF_UPLOADED_FILE].
|
||||||
|
|
||||||
|
The following snipet code show how to work with Uploaded files using EWF [WSF_REQUEST] class, in the example
|
||||||
|
we build a simple html answer with basic information, if there is not uploaded files, we send a 400 status code
|
||||||
|
and a simple message.
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
|
||||||
|
if req.path_info.same_string ("/upload") then
|
||||||
|
-- Check if we have an uploaded file
|
||||||
|
if req.has_uploaded_file then
|
||||||
|
-- iterate over all the uploaded files
|
||||||
|
create l_answer.make_from_string ("<h1>Uploaded File/s</h1><br>")
|
||||||
|
across req.uploaded_files as ic loop
|
||||||
|
l_answer.append ("<strong>FileName:</strong>")
|
||||||
|
l_answer.append (ic.item.filename)
|
||||||
|
l_answer.append ("<br><strong>Size:</strong>")
|
||||||
|
l_answer.append (ic.item.size.out)
|
||||||
|
l_answer.append ("<br>")
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-type","text/html"],["Content-lenght", l_answer.count.out]>>)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
else
|
||||||
|
-- Here we should handle unexpected errors.
|
||||||
|
create l_answer.make_from_string ("<strong>No uploaded files</strong><br>")
|
||||||
|
create l_answer.append ("Back to <a href='/'>Home</a>")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.bad_request, <<["Content-type","text/html"],["Content-lenght", l_answer.count.out]>>)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Handle error
|
||||||
|
end
|
||||||
|
```
|
||||||
|
The source code is available on Github. You can get it by running the command:
|
||||||
|
|
||||||
|
```git clone https://github.com/EiffelWebFramework/ewf_examples.git```
|
||||||
|
|
||||||
|
The example is located in the directory $PATH/ewf_examples/workbook/upload_file where $PATH is where you run git clone.
|
||||||
|
|
||||||
|
|
||||||
|
<a name=examples>
|
||||||
|
## Examples
|
||||||
|
The source code is available on Github. You can get it by running the command:
|
||||||
|
|
||||||
|
```git clone https://github.com/EiffelWebFramework/ewf_examples.git```
|
||||||
|
|
||||||
|
The GET example is located in the directory $PATH/ewf_examples/workbook/form/get, and the post example is located in the directory $PATH/ewf_examples/workbook/form/post where $PATH is where you run git clone . To run open it using Eiffel Studio or just run theg following command
|
||||||
|
|
||||||
|
```estudio -config <ecf_name>.ecf -target <target_name>```
|
||||||
|
|
||||||
|
>Note: replace <ecf_name> and<target_name> with the corresponding values.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Nav: [Workbook](../workbook.md) | [Basic Concepts] (/workbook/basics/basics.md) | [Handling Requests: Header Fields](/workbook/handling_request/headers.md)
|
||||||
|
|
||||||
112
doc/workbook/handling_request/form/get/application.e
Normal file
112
doc/workbook/handling_request/form/get/application.e
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that show how to handle a GET request"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
file: WSF_FILE_RESPONSE
|
||||||
|
l_parameter_names: STRING
|
||||||
|
l_answer: STRING
|
||||||
|
idioms: LIST[STRING]
|
||||||
|
l_raw_data: STRING
|
||||||
|
do
|
||||||
|
if req.is_get_request_method then
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
create file.make_html ("form.html")
|
||||||
|
res.send (file)
|
||||||
|
elseif req.path_info.same_string ("/search") then
|
||||||
|
|
||||||
|
-- (1) the parameter is case sensitive
|
||||||
|
if not (attached req.query_parameter ("GIVEN-NAME")) then
|
||||||
|
-- Wrong `GIVEN-NAME' need to be in lower case.
|
||||||
|
end
|
||||||
|
|
||||||
|
-- (2) Multiple values
|
||||||
|
if attached {WSF_MULTIPLE_STRING} req.query_parameter ("languages") as l_languages then
|
||||||
|
-- Get all the associated values
|
||||||
|
create {ARRAYED_LIST[STRING]} idioms.make (2)
|
||||||
|
across l_languages as ic loop idioms.force (ic.item.value) end
|
||||||
|
elseif attached {WSF_STRING} req.query_parameter ("languages") as l_language then
|
||||||
|
-- Single value
|
||||||
|
print (l_language.value)
|
||||||
|
else
|
||||||
|
-- Value Missing
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read the all parameters names and his values.
|
||||||
|
create l_parameter_names.make_from_string ("<h2>Parameters Names</h2>")
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
create l_answer.make_from_string ("<h2>Parameter Names and Values</h2>")
|
||||||
|
l_answer.append ("<br>")
|
||||||
|
across req.query_parameters as ic loop
|
||||||
|
l_parameter_names.append (ic.item.key)
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
|
||||||
|
l_answer.append (ic.item.key)
|
||||||
|
l_answer.append_character ('=')
|
||||||
|
if attached {WSF_STRING} req.query_parameter (ic.item.key) as l_value then
|
||||||
|
l_answer.append_string (l_value.value)
|
||||||
|
end
|
||||||
|
l_answer.append ("<br>")
|
||||||
|
end
|
||||||
|
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append_string (l_answer)
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_parameter_names.count.out]>>)
|
||||||
|
res.put_string (l_parameter_names)
|
||||||
|
elseif req.path_info.same_string ("/link") then
|
||||||
|
-- WSF_TABLE example
|
||||||
|
create l_parameter_names.make_from_string ("<h2>Parameters Name</h2>")
|
||||||
|
if attached {WSF_TABLE} req.query_parameter ("tab") as l_tab then
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append (l_tab.name)
|
||||||
|
|
||||||
|
from
|
||||||
|
l_tab.values.start
|
||||||
|
until
|
||||||
|
l_tab.values.after
|
||||||
|
loop
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append (l_tab.values.key_for_iteration)
|
||||||
|
if attached {WSF_STRING} l_tab.value (l_tab.values.key_for_iteration) as l_value then
|
||||||
|
l_parameter_names.append ("=")
|
||||||
|
l_parameter_names.append (l_value.value)
|
||||||
|
end
|
||||||
|
l_tab.values.forth
|
||||||
|
end
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_parameter_names.count.out]>>)
|
||||||
|
res.put_string (l_parameter_names)
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Here we should handle unexpected errors.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/handling_request/form/get/form.ecf
Normal file
42
doc/workbook/handling_request/form/get/form.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="form" library_target="form">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="form" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="form_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="form" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="form_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
49
doc/workbook/handling_request/form/get/form.html
Normal file
49
doc/workbook/handling_request/form/get/form.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Client Request: Search Form example </title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1> EWF Handling Search Request: Form example </h1>
|
||||||
|
<form action="/search" method="GET">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Search by</legend>
|
||||||
|
<div>
|
||||||
|
<label>First Name
|
||||||
|
<input id="given-name" name="given-name" type="text" placeholder="First name only" autofocus>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Last Name
|
||||||
|
<input id="family-name" name="family-name" type="text" placeholder="Last name only" autofocus>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Date of Birth
|
||||||
|
<input id="dob" name="dob" type="date">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Email
|
||||||
|
<input id="email" name="email" type="email" placeholder="example@domain.com">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Languages
|
||||||
|
<input type="checkbox" name="languages" value="Spanish"> Spanish
|
||||||
|
<input type="checkbox" name="languages" value="English"> English
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<button type=submit>Submit Form</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<h2> Example link </h2>
|
||||||
|
<div>
|
||||||
|
<a href="/link?tab[a]=1&tab[b]=2&tab[c]=foo">Link</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
94
doc/workbook/handling_request/form/post/application.e
Normal file
94
doc/workbook/handling_request/form/post/application.e
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
note
|
||||||
|
description : "Reading Parameters from a HTML FORM (method POST) "
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
file: WSF_FILE_RESPONSE
|
||||||
|
l_parameter_names: STRING
|
||||||
|
l_answer: STRING
|
||||||
|
idioms: LIST[STRING]
|
||||||
|
l_raw_data: STRING
|
||||||
|
do
|
||||||
|
if req.is_get_request_method then
|
||||||
|
create file.make_html ("form.html")
|
||||||
|
res.send (file)
|
||||||
|
elseif req.is_post_request_method then
|
||||||
|
req.set_raw_input_data_recorded (True)
|
||||||
|
|
||||||
|
-- (3) Read Raw Data
|
||||||
|
create l_raw_data.make_empty
|
||||||
|
req.read_input_data_into (l_raw_data)
|
||||||
|
|
||||||
|
-- (1) the parameter is case sensitive
|
||||||
|
if not (attached req.form_parameter ("GIVEN-NAME")) then
|
||||||
|
-- Wrong `GIVEN-NAME' need to be in lower case.
|
||||||
|
end
|
||||||
|
|
||||||
|
-- (2) Multiple values
|
||||||
|
if attached {WSF_MULTIPLE_STRING} req.form_parameter ("languages") as l_languages then
|
||||||
|
-- Get all the associated values
|
||||||
|
create {ARRAYED_LIST[STRING]} idioms.make (2)
|
||||||
|
across l_languages as ic loop idioms.force (ic.item.value) end
|
||||||
|
elseif attached {WSF_STRING} req.form_parameter ("langauges") as l_language then
|
||||||
|
-- Single value
|
||||||
|
print (l_language.value)
|
||||||
|
else
|
||||||
|
-- Value Missing
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read the all parameters names and his values.
|
||||||
|
create l_parameter_names.make_from_string ("<h2>Parameters Names</h2>")
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
create l_answer.make_from_string ("<h2>Parameter Names and Values</h2>")
|
||||||
|
l_answer.append ("<br>")
|
||||||
|
|
||||||
|
across req.form_parameters as ic loop
|
||||||
|
l_parameter_names.append (ic.item.key)
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
|
||||||
|
l_answer.append (ic.item.key)
|
||||||
|
l_answer.append_character ('=')
|
||||||
|
if attached {WSF_STRING} req.form_parameter (ic.item.key) as l_value then
|
||||||
|
l_answer.append_string (l_value.value)
|
||||||
|
end
|
||||||
|
l_answer.append ("<br>")
|
||||||
|
end
|
||||||
|
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append_string (l_answer)
|
||||||
|
l_parameter_names.append ("<br>")
|
||||||
|
l_parameter_names.append ("<h2>Raw content</h2>")
|
||||||
|
l_parameter_names.append (l_raw_data)
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_parameter_names.count.out]>>)
|
||||||
|
res.put_string (l_parameter_names)
|
||||||
|
else
|
||||||
|
-- Here we should handle unexpected errors.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/handling_request/form/post/form.ecf
Normal file
42
doc/workbook/handling_request/form/post/form.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="form" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486" library_target="form">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="form" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="form_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="form" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="form_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
56
doc/workbook/handling_request/form/post/form.html
Normal file
56
doc/workbook/handling_request/form/post/form.html
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Client Request: Form example </title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1> EWF Handling Client Request: Form example </h1>
|
||||||
|
<form action="/" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Personal details</legend>
|
||||||
|
<div>
|
||||||
|
<label>First Name
|
||||||
|
<input id="given-name" name="given-name" type="text" placeholder="First name only" required autofocus>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Last Name
|
||||||
|
<input id="family-name" name="family-name" type="text" placeholder="Last name only" required autofocus>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Date of Birth
|
||||||
|
<input id="dob" name="dob" type="date" required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Email
|
||||||
|
<input id="email" name="email" type="email" placeholder="example@domain.com" required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>URL
|
||||||
|
<input id="url" name="url" type="url" placeholder="http://mysite.com">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Telephone
|
||||||
|
<input id="phone" name="phone" type="tel" placeholder="Eg. +447000 000000" required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Languages
|
||||||
|
<input type="checkbox" name="languages" value="Spanish"> Spanish
|
||||||
|
<input type="checkbox" name="languages" value="English"> English
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<button type=submit>Submit Form</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
457
doc/workbook/handling_request/headers.md
Normal file
457
doc/workbook/handling_request/headers.md
Normal file
@@ -0,0 +1,457 @@
|
|||||||
|
Nav: [Workbook](../workbook.md) | [Handling Requests: Form/Query parameters] (/workbook/handling_request/form.md) | [Generating Responses](/workbook/generating_response/generating_response.md)
|
||||||
|
|
||||||
|
|
||||||
|
#Handling Requests: Headers
|
||||||
|
|
||||||
|
##### Introduction
|
||||||
|
- The [HTTP request header fields (also known as "headers")](https://httpwg.github.io/specs/rfc7231.html#request.header.fields) are set by the client (usually web browser) and sent in the header of the http request text (see http protocol), as opposed to form or query parameters [Form Data]().
|
||||||
|
- Query parameters are encoded in the URL [GET requests](https://httpwg.github.io/specs/rfc7230.html#http.message).
|
||||||
|
- Form parameters are encoded in the request message for [POST/PUT requests.](https://httpwg.github.io/specs/rfc7230.html#http.message).
|
||||||
|
|
||||||
|
A request usually includes the header fields [Accept, Accept-Encoding, Connection, Cookie, Host, Referer, and User-Agent](https://httpwg.github.io/specs/rfc7231.html#request.header), defining important information about how the server should process the request. And then, the server needs to read the request header fields to use those informations.
|
||||||
|
|
||||||
|
##### Table of Contents
|
||||||
|
- [Reading HTTP Header fields](#read_header)
|
||||||
|
- [Reading HTTP Request line](#read_line)
|
||||||
|
- [Understanding HTTP header fields](#understand)
|
||||||
|
- [Accept](#accept)
|
||||||
|
- [Accept-Charset](#accept_charset)
|
||||||
|
- [Accept-Encoding](#accept_encoding)
|
||||||
|
- [Accept-Language](#accept_language)
|
||||||
|
- [Connection](#connection)
|
||||||
|
- [Authorization](#authorization)
|
||||||
|
- [Content-length](#content-length)
|
||||||
|
- [Cookie](#cookie)
|
||||||
|
- [Host](#host)
|
||||||
|
- [If-Modified-Since](#if-modified-since)
|
||||||
|
- [If-Unmodified-Since](#if-unmodified-since)
|
||||||
|
- [Referer](#referer)
|
||||||
|
- [User-Agent](#user-agent)
|
||||||
|
- [Example: Request Headers](#example)
|
||||||
|
- [Example: How to compress pages](#compress)
|
||||||
|
- [Example: Detecting Browser Types](#browser-types)
|
||||||
|
- [Example: CGI Variables](#cgi-variables)
|
||||||
|
|
||||||
|
|
||||||
|
That section explains how to read HTTP information sent by the browser via the request header fields. Mostly by defining the most important HTTP request header fields, for more information, read [HTTP 1.1 specification](https://httpwg.github.io/specs/).
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
The Eiffel Web Framework is using the traditional Common Gateway Interface (CGI) programming interface to access the header fields, query and form parameters.
|
||||||
|
Among other, this means the header fields are exposed with associated CGI field names:
|
||||||
|
- the header field name are uppercased, and any dash "-" replaced by underscore "_".
|
||||||
|
- and also prefixed by "HTTP_" except for CONTENT_TYPE and CONTENT_LENGTH.
|
||||||
|
- For instance `X-Server` will be known as `HTTP_X_SERVER`.
|
||||||
|
|
||||||
|
<a name="read_header"></a>
|
||||||
|
## Reading HTTP Header fields
|
||||||
|
EWF [WSF_REQUEST]() class provides features to access HTTP headers.
|
||||||
|
|
||||||
|
Reading most headers is straightforward by calling:
|
||||||
|
- the corresponding `http_*` functions such as `http_accept` for header "Accept".
|
||||||
|
- or indirectly using the `meta_string_variable (a_name)` function by passing the associated CGI field name.
|
||||||
|
In both cases, if the related header field is supplied by the request, the result is a string value, otherwise it is Void.
|
||||||
|
|
||||||
|
Note: always check if the result of those functions is non-void before using it.
|
||||||
|
|
||||||
|
* Cookies:
|
||||||
|
- To iterate on all cookies valued, use `cookies: ITERABLE [WSF_VALUE]`
|
||||||
|
- To retrieve a specific cookie value, use `cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE`
|
||||||
|
|
||||||
|
* Authorization
|
||||||
|
- To read the Authorization header, first check its type with: `auth_type: detachable READABLE_STRING_8`
|
||||||
|
- And its value via `http_authorization: detachable READABLE_STRING_8 --Contents of the Authorization: header from the current wgi_request, if there is one.`
|
||||||
|
|
||||||
|
* Content_length
|
||||||
|
- If supplied, get the content length as an string value: `content_length: detachable READABLE_STRING_8`
|
||||||
|
- or directly as a natural value with `content_length_value: NATURAL_64`
|
||||||
|
|
||||||
|
* Content_type
|
||||||
|
- If supplied, get the content type as an string value with `content_type: detachable HTTP_CONTENT_TYPE`
|
||||||
|
|
||||||
|
Due to CGI compliance, the original header names are not available, however the function `raw_header_data` may return the http header data as a string value (warning: this may not be available, depending on the underlying connector). Apart from very specific cases (proxy, debugging, ...), it should not be useful.
|
||||||
|
Note: CGI variables are information about the current request (and also about the server). Some are based on the HTTP request line and headers (e.g., form parameters, query parameters), others are derived from the socket itself (e.g., the name and IP address of the requesting host), and still others are taken from server installation parameters (e.g., the mapping of URLs to actual paths).
|
||||||
|
|
||||||
|
<a name="read_line"></a>
|
||||||
|
####Retrieve information from the Request Line
|
||||||
|
|
||||||
|
For convenience, the following sections refer to a request starting with line:
|
||||||
|
```
|
||||||
|
GET http://eiffel.org/search?q=EiffelBase HTTP/1.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Overview of the features
|
||||||
|
|
||||||
|
* HTTP method
|
||||||
|
- The function `request_method: READABLE_STRING_8` gives access to the HTTP request method, (usually GET or POST in conventional Web Applications), but with the raise of REST APIs other methods are also frequently used such as HEAD, PUT, DELETE, OPTIONS, or TRACE.
|
||||||
|
A few functions helps determining quickly the nature of the request method:
|
||||||
|
- `is_get_request_method: BOOLEAN -- Is Current a GET request method?`
|
||||||
|
- `is_put_request_method: BOOLEAN -- Is Current a PUT request method?`
|
||||||
|
- `is_post_request_method: BOOLEAN -- Is Current a POST request method?`
|
||||||
|
- `is_delete_request_method: BOOLEAN -- Is Current a DELETE request method?`
|
||||||
|
|
||||||
|
In our example the request method is `GET`
|
||||||
|
|
||||||
|
* Query String
|
||||||
|
- The query string for the example is `q=EiffelBase`
|
||||||
|
- `query_string: READABLE_STRING_8`
|
||||||
|
|
||||||
|
* Protocol
|
||||||
|
- The feature return the third part of the request line, which is generally HTTP/1.0 or HTTP/1.1.
|
||||||
|
- `server_protocol: READABLE_STRING_8`
|
||||||
|
In the example the request method is `HTTP/1.1`
|
||||||
|
|
||||||
|
|
||||||
|
<a name="understand"></a>
|
||||||
|
#### Understanding HTTP 1.1 Request Headers
|
||||||
|
Access to the request headers permits the web server applications or APIs to perform optimizations and provide behavior that would not be possible without them for instance such as adapting the response according to the browser preferences.
|
||||||
|
This section summarizes the headers most often used; for more information, see the [HTTP 1.1 specification](https://httpwg.github.io/specs/), note that [RFC 2616 is dead](https://www.mnot.net/blog/2014/06/07/rfc2616_is_dead).
|
||||||
|
|
||||||
|
<a name="accept"></a>
|
||||||
|
* [Accept](https://httpwg.github.io/specs/rfc7231.html#header.accept)
|
||||||
|
- The "Accept" header field can be used by user agents (browser or other clients) to define response media types that are acceptable. Accept header fields can be used to indicate that the request is limited to a small set of desired types, as in the case of a request for an inline image.
|
||||||
|
For example, assume an APIs Learn4Kids can respond with XML or JSON data (JSON format have some advantages over XML, readability, parsing etc...), a client can define its preference using "Accept: application/json" to request data in JSON format, or "Accept: application/xml" to get XML format. In other case the server sends a not acceptable response. Note that the client can define an ordered list of accepted content types, including "*", the client will get the response and know the content type via the response header field "Content-Type". Related [Content-Negotiation]()
|
||||||
|
|
||||||
|
<a name="accept_charset"></a>
|
||||||
|
* [Accept-Charset](https://httpwg.github.io/specs/rfc7231.html#header.accept-charset)
|
||||||
|
- The "Accept-Charset" header field can be sent by a user agent (browser or other clients) to indicate which charsets are acceptable in textual response content (e.g., ISO-8859-1).
|
||||||
|
|
||||||
|
<a name="accept_encoding"></a>
|
||||||
|
* [Accept-Encoding](https://httpwg.github.io/specs/rfc7231.html#header.accept-encoding)
|
||||||
|
- The "Accept-Encoding" header field can be used by user agents (browser or other clients) to indicate which response content-codings (`gzip`, `compress`) are acceptable in the response. An "identity" token is used as a synonym for "no encoding" in order to communicate when no encoding is preferred. If the server receives this header, it is free to encode the page by using one of the content-encodings specified (usually to reduce transmission time), sending the `Content-Encoding` response header to indicate that it has done so.
|
||||||
|
|
||||||
|
<a name="accept_language"></a>
|
||||||
|
* [Accept-Language](https://httpwg.github.io/specs/rfc7231.html#header.accept-language)
|
||||||
|
- The "Accept-Language" header field can be used by user agents (browser or other client) to indicate the set of natural languages that are preferred in the response in case the server can produce representation in more than one language. The value of the header should be one of the standard language codes such as en, en-us, da, etc. See RFC 1766 for details (start at http://www.rfc-editor.org/ to get a current list of the RFC archive sites).
|
||||||
|
|
||||||
|
<a name="connection"></a>
|
||||||
|
* [Connection](https://httpwg.github.io/specs/rfc7230.html#header.connection)
|
||||||
|
- The "Connection" header field allows the sender to indicate desired control options for the current connection, for example if it can hanlde persistent HTTP connections.
|
||||||
|
By default HTTP/1.1 uses "persistent connections", allowing multiple requests and responses to be carried over a single connection. The "close" connection option is used to signal that a connection will not persist after the current request/response.
|
||||||
|
|
||||||
|
<a name="authorization"></a>
|
||||||
|
* [Authorization](https://httpwg.github.io/specs/rfc7235.html#header.authorization)
|
||||||
|
- The header is used by user agents to authenticate themselves when accessing password protected resources.
|
||||||
|
|
||||||
|
<a name="content-length"></a>
|
||||||
|
* [Content-Length](https://httpwg.github.io/specs/rfc7230.html#header.content-length)
|
||||||
|
- For messages that includes a payload body, the Content-Length field-value provides the framing information necessary to determine where the body (and message) ends.
|
||||||
|
|
||||||
|
<a name="cookie"></a>
|
||||||
|
* [Cookie](https://httpwg.github.io/specs/rfc6265.html)
|
||||||
|
- The Cookie header contains cookies received by the user agent in previous Set-Cookie headers. The origin server is free to ignore the Cookie header or use its contents for an application-specific purpose. (Related State Management).
|
||||||
|
|
||||||
|
<a name="host"></a>
|
||||||
|
* [Host](https://httpwg.github.io/specs/rfc7230.html#header.host)
|
||||||
|
- The "Host" header field provides the host and port information from the target URI, enabling the origin server to distinguish among resources while serving requests for multiple host names on a single IP address. In HTTP 1.1, browsers and other clients are required to specify this header, which indicates the host and port as given in the original URL.
|
||||||
|
|
||||||
|
<a name="if-modified-since"></a>
|
||||||
|
* [If-Modified-Since](https://httpwg.github.io/specs/rfc7232.html#header.if-modified-since)
|
||||||
|
- The "If-Modified-Since" header field makes a GET or HEAD request method conditional on the selected representation's modification date being more recent than the date provided in the field-value. Transfering of the selected representation's data is avoided if that data has not changed. So, indicates that the user agents wants the page only if it has been changes after the specified date. The server sends a 304 resource not modified if not has a newer result representation available.
|
||||||
|
|
||||||
|
<a name="if-unmodified-since"></a>
|
||||||
|
* [If-Unmodified-Since](https://httpwg.github.io/specs/rfc7232.html#header.if-unmodified-since)
|
||||||
|
- The "If-Unmodified-Since" header field makes the request method conditional on the selected representation's last modification date being earlier than or equal to the date provided in the field-value. The operation should succeed only if the document is older than the specified date.
|
||||||
|
|
||||||
|
Generally, If-Modified-Since is used for GET requests (“give me the document only if it is newer than my cached version”), whereas If-Unmodified-Since is used for PUT requests (“update this document only if nobody else has changed it since I generated it”).
|
||||||
|
|
||||||
|
<a name="referer"></a>
|
||||||
|
* [Referer](https://httpwg.github.io/specs/rfc7231.html#header.referer)
|
||||||
|
- The "Referer" header field allows the user agent to specify a URI reference for the resource from which the target URI was obtained (i.e., the "referrer", though the field name is misspelled). A user agent MUST NOT include the fragment and userinfo components of the URI reference [RFC3986], if any, when generating the Referer field value. This header indicates the URL of the referring Web page.
|
||||||
|
|
||||||
|
For example, if you are at Web page A and click on a link to Web page B, the URL of Web page A is
|
||||||
|
included in the Referer header when the browser requests Web page B.
|
||||||
|
|
||||||
|
<a name="user-agent"></a>
|
||||||
|
* [User-Agent](https://httpwg.github.io/specs/rfc7231.html#header.user-agent)
|
||||||
|
- The "User-Agent" header field contains information about the user agent of the request, which is often used by servers to help identify the scope of reported interoperability problems, to work around or tailor responses to avoid particular user agent limitations, and for analytics regarding browser or operating system use or device.
|
||||||
|
|
||||||
|
<a name="example"></a>
|
||||||
|
#### Building a Table of All Request Headers
|
||||||
|
|
||||||
|
The following [EWF service](./headers/header_fields/application.e) code simply uses an ```html_template``` to fill a table (names and values) with all the headers fields it receives.
|
||||||
|
The service accomplishes this task by calling ```req.meta_variables``` feature to get an ```ITERABLE [WSF_STRING]```, an structure that can be iterated over using ```across...loop...end```, then it checks if the name has the prefix ```HTTP_``` and if it is true, put the header name and value in a row. (the name in the left cell, the value in the right cell).
|
||||||
|
|
||||||
|
The service also writes three components of the main request line (method, URI, and protocol), and also the raw header.
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_raw_data: STRING
|
||||||
|
l_page_response: STRING
|
||||||
|
l_rows: STRING
|
||||||
|
do
|
||||||
|
create l_page_response.make_from_string (html_template)
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
|
||||||
|
-- HTTP method
|
||||||
|
l_page_response.replace_substring_all ("$http_method", req.request_method)
|
||||||
|
-- URI
|
||||||
|
l_page_response.replace_substring_all ("$uri", req.path_info)
|
||||||
|
-- Protocol
|
||||||
|
l_page_response.replace_substring_all ("$protocol", req.server_protocol)
|
||||||
|
|
||||||
|
-- Fill the table rows with HTTP Headers
|
||||||
|
create l_rows.make_empty
|
||||||
|
across req.meta_variables as ic loop
|
||||||
|
if ic.item.name.starts_with ("HTTP_") then
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (ic.item.name)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (ic.item.value)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
l_page_response.replace_substring_all ("$rows", l_rows)
|
||||||
|
|
||||||
|
-- Reading the raw header
|
||||||
|
if attached req.raw_header_data as l_raw_header then
|
||||||
|
l_page_response.replace_substring_all ("$raw_header", l_raw_header)
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_page_response.count.out]>>)
|
||||||
|
res.put_string (l_page_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
html_template: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
thead {color:green;}
|
||||||
|
tbody {color:blue;}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>EWF service example: Showing Request Headers</h1>
|
||||||
|
|
||||||
|
<strong>HTTP METHOD:</strong>$http_method<br/>
|
||||||
|
<strong>URI:</strong>$uri<br>
|
||||||
|
<strong>PROTOCOL:</strong>$protocol<br/>
|
||||||
|
<strong>REQUEST TIME:</strong>$time<br/>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Header Name</th>
|
||||||
|
<th>Header Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
$rows
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Raw header</h2>
|
||||||
|
|
||||||
|
$raw_header
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="compress"></a>
|
||||||
|
#### How to compress pages
|
||||||
|
To be completed.
|
||||||
|
|
||||||
|
|
||||||
|
<a name="browser-types"></a>
|
||||||
|
|
||||||
|
#### Detecting Browser Types
|
||||||
|
|
||||||
|
The User-Agent header identifies the specific browser/client that is sending the request. The following code shows a [EWF service](./headers/browser_name/application.e) that sends browser-specific responses.
|
||||||
|
The examples uses the ideas based on the [Browser detection using the user agent](https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent) article.
|
||||||
|
Basically the code check if the header user_agent exist and then call the ```browser_name (a_user_agent: READABLE_STRING_8): READABLE_STRING_32```
|
||||||
|
feature to retrieve the current browser name or Unknown in other case.
|
||||||
|
|
||||||
|
```eiffel
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_raw_data: STRING
|
||||||
|
l_page_response: STRING
|
||||||
|
l_rows: STRING
|
||||||
|
do
|
||||||
|
create l_page_response.make_from_string (html_template)
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
|
||||||
|
-- retrieve the user-agent
|
||||||
|
if attached req.http_user_agent as l_user_agent then
|
||||||
|
l_page_response.replace_substring_all ("$user_agent", l_user_agent)
|
||||||
|
l_page_response.replace_substring_all ("$browser", browser_name (l_user_agent))
|
||||||
|
else
|
||||||
|
l_page_response.replace_substring_all ("$user_agent", "[]")
|
||||||
|
l_page_response.replace_substring_all ("$browser", "Unknown, the user-agent was not present.")
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_page_response.count.out]>>)
|
||||||
|
res.put_string (l_page_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Browser utility
|
||||||
|
|
||||||
|
browser_name (a_user_agent: READABLE_STRING_8): READABLE_STRING_32
|
||||||
|
-- Browser name.
|
||||||
|
-- Must contain Must not contain
|
||||||
|
-- Firefox Firefox/xyz Seamonkey/xyz
|
||||||
|
-- Seamonkey Seamonkey/xyz
|
||||||
|
-- Chrome Chrome/xyz Chromium/xyz
|
||||||
|
-- Chromium Chromium/xyz
|
||||||
|
-- Safari Safari/xyz Chrome/xyz
|
||||||
|
-- Chromium/xyz
|
||||||
|
-- Opera OPR/xyz [1]
|
||||||
|
-- Opera/xyz [2]
|
||||||
|
-- Internet Explorer ;MSIE xyz; Internet Explorer doesn't put its name in the BrowserName/VersionNumber format
|
||||||
|
|
||||||
|
do
|
||||||
|
if
|
||||||
|
a_user_agent.has_substring ("Firefox") and then
|
||||||
|
not a_user_agent.has_substring ("Seamonkey")
|
||||||
|
then
|
||||||
|
Result := "Firefox"
|
||||||
|
elseif a_user_agent.has_substring ("Seamonkey") then
|
||||||
|
Result := "Seamonkey"
|
||||||
|
elseif a_user_agent.has_substring ("Chrome") and then not a_user_agent.has_substring ("Chromium")then
|
||||||
|
Result := "Chrome"
|
||||||
|
elseif a_user_agent.has_substring ("Chromium") then
|
||||||
|
Result := "Chromiun"
|
||||||
|
elseif a_user_agent.has_substring ("Safari") and then not (a_user_agent.has_substring ("Chrome") or else a_user_agent.has_substring ("Chromium")) then
|
||||||
|
Result := "Safari"
|
||||||
|
elseif a_user_agent.has_substring ("OPR") or else a_user_agent.has_substring ("Opera") then
|
||||||
|
Result := "Opera"
|
||||||
|
elseif a_user_agent.has_substring ("MSIE") or else a_user_agent.has_substring ("Trident")then
|
||||||
|
Result := "Internet Explorer"
|
||||||
|
else
|
||||||
|
Result := "Unknown"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
html_template: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>EWF service example: Showing Browser Dectection Using User-Agent</h1> <br>
|
||||||
|
|
||||||
|
<strong>User Agent:</strong> $user_agent <br>
|
||||||
|
|
||||||
|
<h2>Enjoy using $browser </h2>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
Let see some results, we will show the html returned
|
||||||
|
|
||||||
|
Internet Explorer
|
||||||
|
---
|
||||||
|
```
|
||||||
|
<h1>EWF service example: Showing Browser Dectection Using User-Agent</h1></br>
|
||||||
|
|
||||||
|
<strong>User Agent:</strong> Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MDDCJS; rv:11.0) like Gecko <br>
|
||||||
|
|
||||||
|
<h2> Enjoy using Internet Explorer </h2>
|
||||||
|
```
|
||||||
|
|
||||||
|
Chrome
|
||||||
|
---
|
||||||
|
```
|
||||||
|
<h1>EWF service example: Showing Browser Dectection Using User-Agent</h1></br>
|
||||||
|
|
||||||
|
<strong>User Agent:</strong> Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36 <br>
|
||||||
|
|
||||||
|
<h2> Enjoy using Chrome </h2>
|
||||||
|
```
|
||||||
|
|
||||||
|
As an exercise, try to write a similar service to retrieve the OS family using the User-Agent information.
|
||||||
|
|
||||||
|
<a name="cgi-variables"></a>
|
||||||
|
|
||||||
|
[Meta-variables](https://tools.ietf.org/html/rfc3875#section-4.1) contains data about the request, they are identified by case-insensitive names. In this section, the purpose is to show a similar example to HEADERS FIELDS, but in this case building a table showing the standard CGI variables.
|
||||||
|
|
||||||
|
|
||||||
|
* [AUTH_TYPE](https://tools.ietf.org/html/rfc3875#section-4.1.1).
|
||||||
|
* [CONTENT_LENGTH](https://tools.ietf.org/html/rfc3875#section-4.1.2)
|
||||||
|
* [CONTENT_TYPE](https://tools.ietf.org/html/rfc3875#section-4.1.3)
|
||||||
|
* [GATEWAY_INTERFACE](https://tools.ietf.org/html/rfc3875#section-4.1.4)
|
||||||
|
* [PATH_INFO](https://tools.ietf.org/html/rfc3875#section-4.1.5)
|
||||||
|
* [PATH_TRANSLATED](https://tools.ietf.org/html/rfc3875#section-4.1.6)
|
||||||
|
* [QUERY_STRING](https://tools.ietf.org/html/rfc3875#section-4.1.7)
|
||||||
|
* [REMOTE_ADDR](https://tools.ietf.org/html/rfc3875#section-4.1.8)
|
||||||
|
* [REMOTE_HOST](https://tools.ietf.org/html/rfc3875#section-4.1.9)
|
||||||
|
* [REMOTE_IDENT](https://tools.ietf.org/html/rfc3875#section-4.1.10)
|
||||||
|
* [REMOTE_USER](https://tools.ietf.org/html/rfc3875#section-4.1.11)
|
||||||
|
* [REQUEST_METHOD](https://tools.ietf.org/html/rfc3875#section-4.1.12)
|
||||||
|
* [SCRIPT_NAME](https://tools.ietf.org/html/rfc3875#section-4.1.13)
|
||||||
|
* [SERVER_NAME](https://tools.ietf.org/html/rfc3875#section-4.1.14)
|
||||||
|
* [SERVER_PROTOCOL](https://tools.ietf.org/html/rfc3875#section-4.1.15)
|
||||||
|
* [SERVER_SOFTWARE](https://tools.ietf.org/html/rfc3875#section-4.1.16)
|
||||||
|
|
||||||
|
An [EWF service](./headers/cgi_variables/application.e) that shows the CGI variables, creates a table showing the values of all the CGI variables.
|
||||||
|
|
||||||
|
|
||||||
|
Nav: [Workbook](../workbook.md) | [Handling Requests: Form/Query parameters] (/workbook/handling_request/form.md) | [Generating Responses](/workbook/generating_response/generating_response.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
109
doc/workbook/handling_request/headers/browser_name/application.e
Normal file
109
doc/workbook/handling_request/headers/browser_name/application.e
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that Read a Request, a "
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
EIS: "name=Browser detection using user agent","src=https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent", "protocol=url"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_raw_data: STRING
|
||||||
|
l_page_response: STRING
|
||||||
|
l_rows: STRING
|
||||||
|
do
|
||||||
|
create l_page_response.make_from_string (html_template)
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
|
||||||
|
-- retrieve the user-agent
|
||||||
|
if attached req.http_user_agent as l_user_agent then
|
||||||
|
l_page_response.replace_substring_all ("$user_agent", l_user_agent)
|
||||||
|
l_page_response.replace_substring_all ("$browser", get_browser_name (l_user_agent))
|
||||||
|
else
|
||||||
|
l_page_response.replace_substring_all ("$user_agent", "[]")
|
||||||
|
l_page_response.replace_substring_all ("$browser", "Unknown, the user-agent was not present.")
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_page_response.count.out]>>)
|
||||||
|
res.put_string (l_page_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Browser utility
|
||||||
|
|
||||||
|
get_browser_name (a_user_agent: READABLE_STRING_8):READABLE_STRING_32
|
||||||
|
-- Must contain Must not contain
|
||||||
|
-- Firefox Firefox/xyz Seamonkey/xyz
|
||||||
|
-- Seamonkey Seamonkey/xyz
|
||||||
|
-- Chrome Chrome/xyz Chromium/xyz
|
||||||
|
-- Chromium Chromium/xyz
|
||||||
|
-- Safari Safari/xyz Chrome/xyz
|
||||||
|
-- Chromium/xyz
|
||||||
|
-- Opera OPR/xyz [1]
|
||||||
|
-- Opera/xyz [2]
|
||||||
|
-- Internet Explorer ;MSIE xyz; Internet Explorer doesn't put its name in the BrowserName/VersionNumber format
|
||||||
|
|
||||||
|
do
|
||||||
|
if
|
||||||
|
a_user_agent.has_substring ("Firefox") and then
|
||||||
|
not a_user_agent.has_substring ("Seamonkey")
|
||||||
|
then
|
||||||
|
Result := "Firefox"
|
||||||
|
elseif a_user_agent.has_substring ("Seamonkey") then
|
||||||
|
Result := "Seamonkey"
|
||||||
|
elseif a_user_agent.has_substring ("Chrome") and then not a_user_agent.has_substring ("Chromium")then
|
||||||
|
Result := "Chrome"
|
||||||
|
elseif a_user_agent.has_substring ("Chromium") then
|
||||||
|
Result := "Chromiun"
|
||||||
|
elseif a_user_agent.has_substring ("Safari") and then not (a_user_agent.has_substring ("Chrome") or else a_user_agent.has_substring ("Chromium")) then
|
||||||
|
Result := "Safari"
|
||||||
|
elseif a_user_agent.has_substring ("OPR") or else a_user_agent.has_substring ("Opera") then
|
||||||
|
Result := "Opera"
|
||||||
|
elseif a_user_agent.has_substring ("MSIE") or else a_user_agent.has_substring ("Trident")then
|
||||||
|
Result := "Internet Explorer"
|
||||||
|
else
|
||||||
|
Result := "Unknown"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
html_template: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>EWF service example: Showing Browser Dectection Using User-Agent</h1> <br>
|
||||||
|
|
||||||
|
<strong>User Agent:</strong> $user_agent <br>
|
||||||
|
|
||||||
|
<h2>Enjoy using $browser </h2>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="browsers" library_target="browsers">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="browsers" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="browsers_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="browsers" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="browsers_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that shows the standard CGI variables"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
EIS: "name=CGI specification","src=(https://tools.ietf.org/html/rfc3875", "protocol=url"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_raw_data: STRING
|
||||||
|
l_page_response: STRING
|
||||||
|
l_rows: STRING
|
||||||
|
do
|
||||||
|
create l_page_response.make_from_string (html_template)
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
|
||||||
|
-- HTTP method
|
||||||
|
l_page_response.replace_substring_all ("$http_method", req.request_method)
|
||||||
|
-- URI
|
||||||
|
l_page_response.replace_substring_all ("$uri", req.path_info)
|
||||||
|
-- Protocol
|
||||||
|
l_page_response.replace_substring_all ("$protocol", req.server_protocol)
|
||||||
|
|
||||||
|
-- Fill the table rows with CGI standard variables
|
||||||
|
create l_rows.make_empty
|
||||||
|
|
||||||
|
-- Auth_type
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("AUTH_TYPE")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.auth_type as l_type then
|
||||||
|
l_rows.append (l_type)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Content length
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("CONTENT_LENGTH")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.content_length as l_content_length then
|
||||||
|
l_rows.append (l_content_length)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Content length
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("CONTENT_TYPE")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.content_type as l_content_type then
|
||||||
|
l_rows.append (l_content_type.string)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Gateway interface
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("GATEWAY_INTERFACE")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.gateway_interface as l_gateway_interface then
|
||||||
|
l_rows.append (l_gateway_interface)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Path info
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("PATH_INFO")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.path_info as l_path_info then
|
||||||
|
l_rows.append (l_path_info)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Path translated
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("PATH_TRANSLATED")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.path_translated as l_path_translated then
|
||||||
|
l_rows.append (l_path_translated)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Query string
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("QUERY_STRING")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.query_string as l_query_string then
|
||||||
|
l_rows.append (l_query_string)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Remote addr
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("REMOTE_ADDR")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (req.remote_addr)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Remote host
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("REMOTE_HOST")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.remote_host as l_remote_host then
|
||||||
|
l_rows.append (l_remote_host)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Remote ident
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("REMOTE_IDENT")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.remote_ident as l_remote_ident then
|
||||||
|
l_rows.append (l_remote_ident)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Remote user
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("REMOTE_USER")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
if attached req.remote_user as l_remote_user then
|
||||||
|
l_rows.append (l_remote_user)
|
||||||
|
else
|
||||||
|
l_rows.append ("Not present")
|
||||||
|
end
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Request method
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("REQUEST_METHOD")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (req.request_method)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
-- Script name
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("SCRIPT_NAME")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (req.script_name)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Server name
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("SERVER_NAME")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (req.server_name)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Server protocol
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("SERVER_PROTOCOL")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (req.server_protocol)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
-- Server software
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append ("SERVER_SOFTWARE")
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (req.server_software)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
|
||||||
|
|
||||||
|
l_page_response.replace_substring_all ("$rows", l_rows)
|
||||||
|
|
||||||
|
-- Reading the raw header
|
||||||
|
if attached req.raw_header_data as l_raw_header then
|
||||||
|
l_page_response.replace_substring_all ("$raw_header", l_raw_header)
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_page_response.count.out]>>)
|
||||||
|
res.put_string (l_page_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
html_template: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
thead {color:green;}
|
||||||
|
tbody {color:blue;}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>EWF service example: Showing Standard CGI Variables</h1>
|
||||||
|
|
||||||
|
<strong>HTTP METHOD:</strong>$http_method<br>
|
||||||
|
<strong>URI:</strong>$uri<br>
|
||||||
|
<strong>PROTOCOL:</strong>$protocol<br>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>CGI Name</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
$rows
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Raw header</h2>
|
||||||
|
|
||||||
|
$raw_header
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="cgi_variables" library_target="cgi_variables">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="cgi_variables" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="cgi_variables_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="cgi_variables" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="cgi_variables_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that Read Request Headers"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
set_service_option ("verbose", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
l_raw_data: STRING
|
||||||
|
l_page_response: STRING
|
||||||
|
l_rows: STRING
|
||||||
|
do
|
||||||
|
create l_page_response.make_from_string (html_template)
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
|
||||||
|
-- HTTP method
|
||||||
|
l_page_response.replace_substring_all ("$http_method", req.request_method)
|
||||||
|
-- URI
|
||||||
|
l_page_response.replace_substring_all ("$uri", req.path_info)
|
||||||
|
-- Protocol
|
||||||
|
l_page_response.replace_substring_all ("$protocol", req.server_protocol)
|
||||||
|
|
||||||
|
-- Fill the table rows with HTTP Headers
|
||||||
|
create l_rows.make_empty
|
||||||
|
across req.meta_variables as ic loop
|
||||||
|
if ic.item.name.starts_with ("HTTP_") then
|
||||||
|
l_rows.append ("<tr>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (ic.item.name)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("<td>")
|
||||||
|
l_rows.append (ic.item.value)
|
||||||
|
l_rows.append ("</td>")
|
||||||
|
l_rows.append ("</tr>")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
l_page_response.replace_substring_all ("$rows", l_rows)
|
||||||
|
|
||||||
|
-- Reading the raw header
|
||||||
|
if attached req.raw_header_data as l_raw_header then
|
||||||
|
l_page_response.replace_substring_all ("$raw_header", l_raw_header)
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_page_response.count.out]>>)
|
||||||
|
res.put_string (l_page_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
html_template: STRING = "[
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
thead {color:green;}
|
||||||
|
tbody {color:blue;}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>EWF service example: Showing Request Headers</h1>
|
||||||
|
|
||||||
|
<strong>HTTP METHOD:</strong>$http_method<br>
|
||||||
|
<strong>URI:</strong>$uri<br>
|
||||||
|
<strong>PROTOCOL:</strong>$protocol<br>
|
||||||
|
<strong>REQUEST TIME:</strong>$time<br>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Header Name</th>
|
||||||
|
<th>Header Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
$rows
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Raw header</h2>
|
||||||
|
|
||||||
|
$raw_header
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="header_fields" library_target="header_fields">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="header_fields" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="header_fields_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="header_fields" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="header_fields_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
69
doc/workbook/handling_request/upload_file/application.e
Normal file
69
doc/workbook/handling_request/upload_file/application.e
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
note
|
||||||
|
description : "Basic Service that show how to Upload a file"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Execute the incomming request
|
||||||
|
local
|
||||||
|
file: WSF_FILE_RESPONSE
|
||||||
|
l_answer: STRING
|
||||||
|
do
|
||||||
|
if req.is_get_request_method then
|
||||||
|
if req.path_info.same_string ("/") then
|
||||||
|
create file.make_html ("upload.html")
|
||||||
|
res.send (file)
|
||||||
|
else
|
||||||
|
-- Here we should handle unexpected errors.
|
||||||
|
end
|
||||||
|
elseif req.is_post_request_method then
|
||||||
|
if req.path_info.same_string ("/upload") then
|
||||||
|
-- Check if we have an uploaded file
|
||||||
|
if req.has_uploaded_file then
|
||||||
|
-- iterate over all the uploaded files
|
||||||
|
create l_answer.make_from_string ("<h1>Uploaded File/s</h1><br>")
|
||||||
|
across req.uploaded_files as ic loop
|
||||||
|
l_answer.append ("<strong>FileName:</strong>")
|
||||||
|
l_answer.append (ic.item.filename)
|
||||||
|
l_answer.append ("<br><strong>Size:</strong>")
|
||||||
|
l_answer.append (ic.item.size.out)
|
||||||
|
l_answer.append ("<br>")
|
||||||
|
end
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-type","text/html"],["Content-lenght", l_answer.count.out]>>)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
else
|
||||||
|
-- Here we should handle unexpected errors.
|
||||||
|
create l_answer.make_from_string ("<strong>No uploaded files</strong><br>")
|
||||||
|
create l_answer.append ("Back to <a href='/'>Home</a>")
|
||||||
|
res.put_header ({HTTP_STATUS_CODE}.bad_request, <<["Content-type","text/html"],["Content-lenght", l_answer.count.out]>>)
|
||||||
|
res.put_string (l_answer)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Handle error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
42
doc/workbook/handling_request/upload_file/upload.ecf
Normal file
42
doc/workbook/handling_request/upload_file/upload.ecf
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="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="upload" library_target="upload">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</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>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<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">
|
||||||
|
<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"/>
|
||||||
|
<cluster name="upload" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="upload_cgi" 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_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||||
|
<cluster name="upload" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
<target name="upload_libfcgi" 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_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>
|
||||||
|
</system>
|
||||||
22
doc/workbook/handling_request/upload_file/upload.html
Normal file
22
doc/workbook/handling_request/upload_file/upload.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EWF Handling Client Request: File Upload Example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1> EWF Handling Client Request: File Upload Example</h1>
|
||||||
|
<form action="/upload" enctype="multipart/form-data" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Upload file/s</legend>
|
||||||
|
<div>
|
||||||
|
<label>File
|
||||||
|
<input name="file-name[]" type="file" multiple>
|
||||||
|
</label>
|
||||||
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<button type=submit>Send</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
doc/workbook/readme.md
Normal file
13
doc/workbook/readme.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Introduction
|
||||||
|
|
||||||
|
Basic Concepts
|
||||||
|
Generating Plain Text
|
||||||
|
Generation HTML
|
||||||
|
|
||||||
|
Handling Client Request:
|
||||||
|
Form Data
|
||||||
|
Request Heders
|
||||||
|
Query Parameters.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
38
doc/workbook/workbook.md
Normal file
38
doc/workbook/workbook.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# EWF Workbook
|
||||||
|
|
||||||
|
##### Table of Contents
|
||||||
|
* [EWF Core](#core)
|
||||||
|
* [EWF Introduction](#introduction)
|
||||||
|
* [Handling Requests: Form/Query Parameter](#form_query_parameters)
|
||||||
|
* [Handling Requests: Header Fields](#header_fields)
|
||||||
|
* [Generating Responses](/workbook/generating_response/generating_response.md)
|
||||||
|
* [Handling Cookies](/workbook/handling_cookies/handling_cookies.md)
|
||||||
|
*
|
||||||
|
|
||||||
|
<a name="core"></a>
|
||||||
|
# EWF Core
|
||||||
|
Before reading (or walking throught) the workbook, to get a quick overview of EWF, it is recommended to read the following articles:
|
||||||
|
* [Getting Started with EWF](http://eiffelwebframework.github.io/EWF/getting-started/)
|
||||||
|
* [EWF Documentation](http://eiffelwebframework.github.io/EWF/wiki/Documentation/)
|
||||||
|
* [EWF Application Lifecyle](https://github.com/EiffelWebFramework/ewf_examples/wiki/Application-Lifecycle)
|
||||||
|
|
||||||
|
|
||||||
|
<a name="introduction"></a>
|
||||||
|
## Introduction
|
||||||
|
[Basic Concepts] (/workbook/basics/basics.md).
|
||||||
|
|
||||||
|
<a name="form_query_parameters"></a>
|
||||||
|
## Handling Requests: Form/Query Parameter
|
||||||
|
[Handling Requests: Form/Query Parameter] (/workbook/handling_request/form.md).
|
||||||
|
|
||||||
|
<a name="header_fields"></a>
|
||||||
|
## Handling Requests: Header Fields
|
||||||
|
[Handling Requests: Header Fields](/workbook/handling_request/headers.md).
|
||||||
|
|
||||||
|
<a name="header_fields"></a>
|
||||||
|
## Generating Response
|
||||||
|
[Generating Responses](/workbook/generating_response/generating_response.md)
|
||||||
|
|
||||||
|
## Handling Cookies
|
||||||
|
[Handling Cookies](/workbook/handling_cookies/handling_cookies.md)
|
||||||
|
|
||||||
Reference in New Issue
Block a user