Added a few example based on the obsolete libraries (v0).
Updated the tutorial example. Added WSF_MESSAGE_EXECUTION.
This commit is contained in:
@@ -8,10 +8,11 @@ To write once and run on any web server, on any platforms thanks to the notion o
|
||||
== What is a connector? ==
|
||||
|
||||
A connector is the layer between the underlying httpd server, and your application based on EWF.
|
||||
Currently, 3 connectors are available within EWF (but others are available outside).
|
||||
Currently, 4 connectors are available within EWF (but others are available outside).
|
||||
* CGI: the common CGI application (apache, iis, ...)
|
||||
* FastCGI: on any server supporting libfcgi handling (apache, iis, ...)
|
||||
* Nino: using the standalone Eiffel Web Nino server, you can run anywhere easily, and debug simply with EiffelStudio's debugger
|
||||
* Standalone: a standalone Eiffel Web server, it can be run anywhere easily, and debug simply with EiffelStudio's debugger. It supports all concurrency modes, and require EiffelStudio >= 15.05.
|
||||
* Nino: similar to the "standalone" connectors, but lack good concurrency support.
|
||||
|
||||
Supporting a new connector is fairly simple, it just has to support the simple EWSGI specification which is really small. Then EWF will bring the power on top of it.
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ or go to [[step_2.wiki|step 2]]
|
||||
|
||||
== Get EWF package ==
|
||||
=== From the archive ===
|
||||
* Get recent archive from https://github.com/EiffelWebFramework/EWF/downloads
|
||||
* Get recent archive of version v1 from https://github.com/EiffelWebFramework/EWF/releases
|
||||
|
||||
=== From the source ===
|
||||
* '''Requirement''': install [http://www.git-scm.org/ git] on your machine
|
||||
|
||||
$ git clone --recursive https://github.com/EiffelWebFramework/EWF.git ewf
|
||||
$ git clone -b v1 --recursive https://github.com/EiffelWebFramework/EWF.git ewf
|
||||
|
||||
== Install EWF ==
|
||||
For now, there is nothing specific to do.
|
||||
|
||||
@@ -13,14 +13,14 @@ or go to [[step_3.wiki|step 3]]
|
||||
== "hello" project ==
|
||||
* using the "wsf" library:
|
||||
** It provides service, request, response, ...
|
||||
* using the "default_nino" library
|
||||
** This is used to build the application in a portable manner, but for this compilation, it uses Eiffel Web Nino as connector.
|
||||
** We use Eiffel Web Nino for this tutorial, because there is no need to configure any apache, iis, and so on. And it is convenient to execute inside EiffelStudio
|
||||
* using the "default_standalone" library
|
||||
** This is used to build the application in a portable manner, but for this compilation, it uses the standalone web server as connector.
|
||||
** We use that standalone connection this tutorial, because there is no need to configure any apache, iis, and so on. And it is convenient to execute with EiffelStudio debugger.
|
||||
|
||||
* To see the result, you should open http://localhost/ on your web browser. Note if the application is using another port such as 9999, you should open http://localhost:9999/
|
||||
|
||||
* You will find inside [[step_2]] the "hello" project
|
||||
** target "hello" provides a very simple implementation (But by default, it is using port 80 with Eiffel Web Nino, which might already be busy by other application)
|
||||
** target "hello" provides a very simple implementation (But by default, it is using port 80 with standalone web server, which might already be busy by other application)
|
||||
** target "hello_custom" which uses almost the same code, but in addition, you can use the ewf.ini file to precise the port number (9999 for this example)
|
||||
|
||||
* To see the result, open http://localhost/ in a web browser.
|
||||
@@ -28,25 +28,38 @@ or go to [[step_3.wiki|step 3]]
|
||||
|
||||
* Eiffel code
|
||||
class
|
||||
HELLO_APPLICATION
|
||||
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_RESPONSE_SERVICE
|
||||
|
||||
WSF_DEFAULT_SERVICE [HELLO_EXECUTION]
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
response (req: WSF_REQUEST): WSF_PAGE_RESPONSE
|
||||
-- Computed response message.
|
||||
do
|
||||
create Result.make
|
||||
Result.put_string ("Hello World")
|
||||
end
|
||||
make_and_launch
|
||||
|
||||
end
|
||||
|
||||
class
|
||||
HELLO_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute
|
||||
local
|
||||
msg: WSF_PAGE_RESPONSE
|
||||
do
|
||||
create msg.make_with_body ("Hello World")
|
||||
response.send (msg)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Note: we could also declare the root class as being "WSF_DEFAULT_SERVICE [HELLO_EXECUTION]" to avoid this HELLO_APPLICATION class.
|
||||
|
||||
----
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
This folder contains 2 alternatives code
|
||||
|
||||
1) "execute" using the WSF_SERVICE interface, i.e
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
1) "message" using the WSF_MESSAGE_EXECUTION interface, i.e
|
||||
message: WSF_RESPONSE_MESSAGE
|
||||
do
|
||||
...
|
||||
end
|
||||
|
||||
|
||||
2) "launcher" using the WSF_RESPONSE_SERVICE interface, but it uses a launcher to start the service, instead of inheriting from WSF_DEFAULT_SERVICE or WSF_DEFAULT_RESPONSE_SERVICE
|
||||
2) "launcher" using the WSF_RESPONSE_SERVICE interface, but it uses a launcher to start the service, instead of inheriting from WSF_DEFAULT_SERVICE
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
APPLICATION implements the `Hello World' service.
|
||||
|
||||
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready
|
||||
only `execute' needs to be implemented.
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed.
|
||||
|
||||
]"
|
||||
|
||||
class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
page: WSF_PAGE_RESPONSE
|
||||
do
|
||||
create page.make
|
||||
page.put_string ("Hello World")
|
||||
res.send (page)
|
||||
|
||||
--| another alternative would have been more low level
|
||||
--| by setting the status code, the content type, and the content length which is 11 for "Hello World"
|
||||
--| res.put_header ({WSF_HEADER}.ok, <<["Content-Type", "text/plain"], ["Content-Length", "11"]>>)
|
||||
--| res.put_string ("Hello World")
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -11,30 +11,31 @@ class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_RESPONSE_SERVICE
|
||||
WSF_LAUNCHABLE_SERVICE
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_and_launch
|
||||
initialize
|
||||
local
|
||||
launcher: WSF_DEFAULT_SERVICE_LAUNCHER
|
||||
opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS
|
||||
do
|
||||
--| Uncomment the following line, to read options from "ewf.ini" configuration file
|
||||
-- create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} opts.make_from_file ("ewf.ini")
|
||||
|
||||
create launcher.make_and_launch (Current, opts)
|
||||
Precursor
|
||||
--| Uncomment the following 2 lines, to read options from "ewf.ini" configuration file
|
||||
-- create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} opts.make_from_file ("ewf.ini")
|
||||
-- import_service_options (opts)
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
response (req: WSF_REQUEST): WSF_PAGE_RESPONSE
|
||||
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
launcher: WSF_DEFAULT_SERVICE_LAUNCHER [HELLO_EXECUTION]
|
||||
do
|
||||
create Result.make
|
||||
Result.put_string ("Hello World")
|
||||
create launcher.make_and_launch (opts)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
note
|
||||
description: "[
|
||||
Request execution for Current application.
|
||||
Implement `execute' based on `request' and `response'.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HELLO_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute
|
||||
local
|
||||
msg: WSF_PAGE_RESPONSE
|
||||
do
|
||||
create msg.make_with_body ("Hello World")
|
||||
response.send (msg)
|
||||
|
||||
--| alternative would have been more low level
|
||||
--| by setting the content type, and the content length which is 11 for "Hello World"
|
||||
-- response.header.put_content_type_text_plain
|
||||
-- response.header.put_content_length (11)
|
||||
-- response.put_string ("Hello World")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
note
|
||||
description: "[
|
||||
APPLICATION implements the `Hello World' service.
|
||||
|
||||
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready
|
||||
only `execute' needs to be implemented.
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed.
|
||||
|
||||
]"
|
||||
|
||||
class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE [HELLO_EXECUTION]
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
note
|
||||
description: "[
|
||||
Request execution for Current application.
|
||||
Implement `message' based on `request' and `response'.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HELLO_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_MESSAGE_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
message: WSF_PAGE_RESPONSE
|
||||
do
|
||||
create Result.make_with_body ("Hello World")
|
||||
response.send (Result)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -11,9 +11,10 @@
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<library name="default_standalone" location="..\..\..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<cluster name="src" location=".\" />
|
||||
</target>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# For nino connector, use port 9999
|
||||
# For standalone connectors, use port 9999
|
||||
port=9999
|
||||
|
||||
#verbose=true
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</option>
|
||||
<precompile name="precomp_wsf" location="..\..\..\..\precomp\wsf-safe.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<library name="default_standalone" location="..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
@@ -29,7 +29,7 @@
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<precompile name="precomp_wsf-mt" location="..\..\..\..\precomp\wsf-mt-safe.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<library name="default_standalone" location="..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
@@ -2,19 +2,17 @@ note
|
||||
description: "[
|
||||
This class implements the `Hello World' service.
|
||||
|
||||
It inherits from WSF_DEFAULT_RESPONSE_SERVICE to get default EWF connector ready
|
||||
only `response' needs to be implemented.
|
||||
In this example, it is redefined and specialized to be WSF_PAGE_RESPONSE
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed.
|
||||
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready
|
||||
only `HELLO_EXECUTION' needs to be implemented.
|
||||
|
||||
`initialize' is redefined to provide custom options if needed.
|
||||
]"
|
||||
|
||||
class
|
||||
CUSTOM_HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_RESPONSE_SERVICE
|
||||
WSF_DEFAULT_SERVICE [HELLO_EXECUTION]
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
@@ -32,7 +30,7 @@ feature {NONE} -- Initialization
|
||||
--| You can also uncomment the following line if you use the Nino connector
|
||||
--| so that the server listens on port 9999
|
||||
--| quite often the port 80 is already busy
|
||||
-- set_service_option ("port", 9999)
|
||||
set_service_option ("port", 9999)
|
||||
|
||||
--| Uncomment next line to have verbose option if available
|
||||
-- set_service_option ("verbose", True)
|
||||
@@ -41,13 +39,4 @@ feature {NONE} -- Initialization
|
||||
Precursor
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
response (req: WSF_REQUEST): WSF_PAGE_RESPONSE
|
||||
-- Computed response message.
|
||||
do
|
||||
create Result.make
|
||||
Result.put_string ("Hello World")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -2,30 +2,20 @@ note
|
||||
description: "[
|
||||
This class implements the `Hello World' service.
|
||||
|
||||
It inherits from WSF_DEFAULT_RESPONSE_SERVICE to get default EWF connector ready
|
||||
only `response' needs to be implemented.
|
||||
In this example, it is redefined and specialized to be WSF_PAGE_RESPONSE
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed.
|
||||
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready.
|
||||
And implement HELLO_EXECUTION.
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed,
|
||||
such as specific port number.
|
||||
]"
|
||||
|
||||
class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_RESPONSE_SERVICE
|
||||
WSF_DEFAULT_SERVICE [HELLO_EXECUTION]
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
response (req: WSF_REQUEST): WSF_PAGE_RESPONSE
|
||||
-- Computed response message.
|
||||
do
|
||||
create Result.make
|
||||
Result.put_string ("Hello World")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
35
examples/tutorial/step_2/hello/src/hello_execution.e
Normal file
35
examples/tutorial/step_2/hello/src/hello_execution.e
Normal file
@@ -0,0 +1,35 @@
|
||||
note
|
||||
description: "[
|
||||
Request execution for Current application.
|
||||
Implement `execute' based on `request' and `response'.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HELLO_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute
|
||||
local
|
||||
msg: WSF_PAGE_RESPONSE
|
||||
do
|
||||
create msg.make_with_body ("Hello World")
|
||||
response.send (msg)
|
||||
|
||||
--| alternative would have been more low level
|
||||
--| by setting the content type, and the content length which is 11 for "Hello World"
|
||||
-- response.header.put_content_type_text_plain
|
||||
-- response.header.put_content_length (11)
|
||||
-- response.put_string ("Hello World")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -11,12 +11,12 @@ or go to [[step_4.wiki|step 4]]
|
||||
|
||||
== "hello" project ==
|
||||
* Let's start from the "hello_custom" project
|
||||
* you will learn how to use the req: WSF_REQUEST argument
|
||||
* you will learn how to use the request: WSF_REQUEST argument
|
||||
* See the hello project from [[step_3|step #3]] folder
|
||||
|
||||
* You can find code in [[step_3]] folder :
|
||||
|
||||
response (req: WSF_REQUEST): WSF_HTML_PAGE_RESPONSE
|
||||
message: WSF_HTML_PAGE_RESPONSE
|
||||
-- Computed response message.
|
||||
do
|
||||
--| It is now returning a WSF_HTML_PAGE_RESPONSE
|
||||
@@ -25,7 +25,7 @@ or go to [[step_4.wiki|step 4]]
|
||||
Result.set_title ("EWF tutorial / Hello World!")
|
||||
--| Check if the request contains a parameter named "user"
|
||||
--| this could be a query, or a form parameter
|
||||
if attached req.string_item ("user") as l_user then
|
||||
if attached request.string_item ("user") as l_user then
|
||||
--| If yes, say hello world #name
|
||||
Result.set_body ("Hello " + l_user + "!")
|
||||
--| We should html encode this name
|
||||
@@ -43,8 +43,8 @@ or go to [[step_4.wiki|step 4]]
|
||||
end
|
||||
--| note:
|
||||
--| 1) Source of the parameter, we could have used
|
||||
--| req.query_parameter ("user") to search only in the query string
|
||||
--| req.form_parameter ("user") to search only in the form parameters
|
||||
--| request.query_parameter ("user") to search only in the query string
|
||||
--| request.form_parameter ("user") to search only in the form parameters
|
||||
--| 2) response type
|
||||
--| it could also have used WSF_PAGE_REPONSE, and build the html in the code
|
||||
--|
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<precompile name="precomp_wsf-mt" location="..\..\..\..\precomp\wsf-mt-safe.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<library name="default_standalone" location="..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<cluster name="src" location=".\src" recursive="true"/>
|
||||
</target>
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
note
|
||||
description: "[
|
||||
This class implements the `Hello World' service.
|
||||
This class launch the HELLO_EXECUTION service.
|
||||
|
||||
It inherits from WSF_DEFAULT_RESPONSE_SERVICE to get default EWF connector ready
|
||||
only `response' needs to be implemented.
|
||||
In this example, it is redefined and specialized to be WSF_PAGE_RESPONSE
|
||||
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready
|
||||
only `HELLO_EXECUTION' needs to be implemented.
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed.
|
||||
|
||||
@@ -14,7 +13,7 @@ class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_RESPONSE_SERVICE
|
||||
WSF_DEFAULT_SERVICE [HELLO_EXECUTION]
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
@@ -22,44 +21,6 @@ inherit
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Execution
|
||||
|
||||
response (req: WSF_REQUEST): WSF_HTML_PAGE_RESPONSE
|
||||
-- Computed response message.
|
||||
do
|
||||
--| It is now returning a WSF_HTML_PAGE_RESPONSE
|
||||
--| Since it is easier for building html page
|
||||
create Result.make
|
||||
Result.set_title ("EWF tutorial / Hello World!")
|
||||
--| Check if the request contains a parameter named "user"
|
||||
--| this could be a query, or a form parameter
|
||||
if attached req.string_item ("user") as l_user then
|
||||
--| If yes, say hello world #name
|
||||
Result.set_body ("Hello " + l_user + "!")
|
||||
--| We should html encode this name
|
||||
--| but to keep the example simple, we don't do that for now.
|
||||
else
|
||||
--| Otherwise, ask for name
|
||||
Result.set_body ("[
|
||||
<form action="/" method="POST">
|
||||
<p>Hello, what is your name?</p>
|
||||
<input type="text" name="user"/>
|
||||
<input type="submit" value="Validate"/>
|
||||
</form>
|
||||
]"
|
||||
)
|
||||
end
|
||||
|
||||
--| note:
|
||||
--| 1) Source of the parameter, we could have used
|
||||
--| req.query_parameter ("user") to search only in the query string
|
||||
--| req.form_parameter ("user") to search only in the form parameters
|
||||
--| 2) response type
|
||||
--| it could also have used WSF_PAGE_REPONSE, and build the html in the code
|
||||
--|
|
||||
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
|
||||
53
examples/tutorial/step_3/hello/src/hello_execution.e
Normal file
53
examples/tutorial/step_3/hello/src/hello_execution.e
Normal file
@@ -0,0 +1,53 @@
|
||||
note
|
||||
description: "Implementation of Hello world with form."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HELLO_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_MESSAGE_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Execution
|
||||
|
||||
message: WSF_HTML_PAGE_RESPONSE
|
||||
-- Computed response message.
|
||||
do
|
||||
--| It is now returning a WSF_HTML_PAGE_RESPONSE
|
||||
--| Since it is easier for building html page
|
||||
create Result.make
|
||||
Result.set_title ("EWF tutorial / Hello World!")
|
||||
--| Check if the request contains a parameter named "user"
|
||||
--| this could be a query, or a form parameter
|
||||
if attached request.string_item ("user") as l_user then
|
||||
--| If yes, say hello world #name
|
||||
Result.set_body ("Hello " + l_user + "!")
|
||||
--| We should html encode this name
|
||||
--| but to keep the example simple, we don't do that for now.
|
||||
else
|
||||
--| Otherwise, ask for name
|
||||
Result.set_body ("[
|
||||
<form action="/" method="POST">
|
||||
<p>Hello, what is your name?</p>
|
||||
<input type="text" name="user"/>
|
||||
<input type="submit" value="Validate"/>
|
||||
</form>
|
||||
]"
|
||||
)
|
||||
end
|
||||
|
||||
--| note:
|
||||
--| 1) Source of the parameter, we could have used
|
||||
--| request.query_parameter ("user") to search only in the query string
|
||||
--| request.form_parameter ("user") to search only in the form parameters
|
||||
--| 2) response type
|
||||
--| it could also have used WSF_PAGE_REPONSE, and build the html in the code
|
||||
--|
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -11,30 +11,30 @@ or go to the [[README.wiki|index]]
|
||||
|
||||
== "hello" project ==
|
||||
* Let's start from the "hello" project
|
||||
* you will learn how to use the req: WSF_ROUTER component
|
||||
* you will learn how to use the WSF_ROUTER component
|
||||
* See the hello project from [[step_4|step #4]] folder
|
||||
|
||||
* You can find code in [[step_4]] folder :
|
||||
|
||||
To get a routed service based on URI Template, your service application class should inherit from WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
then you need to implement "setup_router", the following code is from the step_4 example
|
||||
To get a routed execution based on URI Template, your execution class should inherit from WSF_URI_TEMPLATE_ROUTED_EXECUTION
|
||||
then you need to implement "setup_router". In addition you can inherit from WSF_ROUTED_URI_HELPER and WSF_ROUTED_URI_TEMPLATE_HELPER, in order to call user-friendly routine provided to work easily with uri, or uri-template mapping. the following code is from the step_4 example
|
||||
|
||||
setup_router
|
||||
do
|
||||
router.map_agent ("/hello", agent execute_hello)
|
||||
map_uri_agent ("/hello", agent execute_hello, Void)
|
||||
|
||||
|
||||
router.map_with_request_methods ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, <<"GET", "POST">>)
|
||||
router.map_with_request_methods ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, <<"GET", "POST">>)
|
||||
map_uri_template ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, <<"GET", "POST">>)
|
||||
map_uri_template ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, <<"GET", "POST">>)
|
||||
|
||||
router.map_agent_response_with_request_methods ("/users/{user}/{?op}", agent response_user, <<"GET">>)
|
||||
map_uri_template_response_agent ("/users/{user}/{?op}", agent response_user, <<"GET">>)
|
||||
end
|
||||
|
||||
* map_agent is used to handle the url /hello with the feature "execute_hello"
|
||||
* map_agent_response_with_request_methods is similar but you precise the accepted request methods
|
||||
* map and map_with_request_method are similar to previous "agent" variant, but it is using a descendant of WSF_HANDLER to handle the related url.
|
||||
* map_agent_response is similar but you precise the accepted request methods
|
||||
* map is similar to previous "agent" variant, but it is using a descendant of WSF_HANDLER to handle the related request.
|
||||
|
||||
* In this example, we use the URI Template router, this allows to define the route using resource like /user/{user} , and then you get access to the "user" data from the WSF_REQUEST.path_parameter or using the context argument passed for the execute or response handler.
|
||||
* In this example, we use the URI-Template router, this allows to define the route using resource like /user/{user} , and then you get access to the "user" data from the WSF_REQUEST.path_parameter or using the context argument passed for the execute or response handler.
|
||||
|
||||
* The example also includes basic notions of url, html encoding, check the hello.ecf to see the added libraries (http to get easy access to the http status code, encoder for simple encoding components)
|
||||
----
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<library name="default_standalone" location="..\..\..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||
<library name="encoder" location="..\..\..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="../../../../library/network/protocol/http/http-safe.ecf" readonly="false"/>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
This class implements the `Hello World' service.
|
||||
|
||||
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready
|
||||
And from WSF_URI_TEMPLATE_ROUTED_SERVICE to use the router service
|
||||
|
||||
`initialize' can be redefine to provide custom options if needed.
|
||||
|
||||
@@ -13,9 +12,7 @@ class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
WSF_DEFAULT_SERVICE
|
||||
WSF_DEFAULT_SERVICE [HELLO_EXECUTION]
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
@@ -23,136 +20,6 @@ inherit
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
setup_router
|
||||
do
|
||||
-- router.map (create {WSF_URI_MAPPING}.make ("/hello", create {WSF_AGENT_URI_HANDLER}.make (agent execute_hello)))
|
||||
map_agent_uri ("/hello", agent execute_hello, Void)
|
||||
|
||||
-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}), router.methods_HEAD_GET_POST)
|
||||
map_uri_template ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, router.methods_HEAD_GET_POST)
|
||||
|
||||
-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}), router.methods_GET_POST)
|
||||
map_uri_template ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, router.methods_GET_POST)
|
||||
|
||||
-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/{?op}", create {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}.make (agent response_user)), router.methods_GET)
|
||||
map_agent_uri_template_response ("/users/{user}/{?op}", agent response_user, router.methods_GET)
|
||||
end
|
||||
|
||||
feature -- Helper: mapping
|
||||
|
||||
map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods)
|
||||
end
|
||||
|
||||
map_uri_template (a_tpl: READABLE_STRING_8; a_handler: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, a_handler), rqst_methods)
|
||||
end
|
||||
|
||||
map_agent_uri_template_response (a_tpl: READABLE_STRING_8; a_action: like {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, create {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}.make (a_action)), rqst_methods)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Computed response message.
|
||||
local
|
||||
mesg: WSF_HTML_PAGE_RESPONSE
|
||||
s: STRING_8
|
||||
l_user_name: READABLE_STRING_32
|
||||
do
|
||||
--| It is now returning a WSF_HTML_PAGE_RESPONSE
|
||||
--| Since it is easier for building html page
|
||||
create mesg.make
|
||||
mesg.set_title ("EWF tutorial / Hello World!")
|
||||
--| Check if the request contains a parameter named "user"
|
||||
--| this could be a query, or a form parameter
|
||||
if attached {WSF_STRING} req.item ("user") as u then
|
||||
--| If yes, say hello world #name
|
||||
|
||||
l_user_name := (create {HTML_ENCODER}).decoded_string (u.value)
|
||||
|
||||
s := "<p>Hello " + mesg.html_encoded_string (l_user_name) + "!</p>"
|
||||
s.append ("Display a <a href=%"/users/" + u.url_encoded_value + "/message/%">message</a></p>")
|
||||
s.append ("<p>Click <a href=%"/users/" + u.url_encoded_value + "/?op=quit%">here</a> to quit.</p>")
|
||||
mesg.set_body (s)
|
||||
--| We should html encode this name
|
||||
--| but to keep the example simple, we don't do that for now.
|
||||
else
|
||||
--| Otherwise, ask for name
|
||||
s := (create {HTML_ENCODER}).encoded_string ({STRING_32} "Hello / ahoj / नमस्ते / Ciào / مرحبا / Hola / 你好 / Hallo / Selam / Bonjour ")
|
||||
s.append ("[
|
||||
<form action="/hello" method="GET">
|
||||
What is your name?</p>
|
||||
<input type="text" name="user"/>
|
||||
<input type="submit" value="Validate"/>
|
||||
</form>
|
||||
]"
|
||||
)
|
||||
mesg.set_body (s)
|
||||
end
|
||||
|
||||
--| note:
|
||||
--| 1) Source of the parameter, we could have used
|
||||
--| req.query_parameter ("user") to search only in the query string
|
||||
--| req.form_parameter ("user") to search only in the form parameters
|
||||
--| 2) response type
|
||||
--| it could also have used WSF_PAGE_REPONSE, and build the html in the code
|
||||
--|
|
||||
|
||||
res.send (mesg)
|
||||
end
|
||||
|
||||
response_user (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
-- Computed response message.
|
||||
local
|
||||
html: WSF_HTML_PAGE_RESPONSE
|
||||
redir: WSF_HTML_DELAYED_REDIRECTION_RESPONSE
|
||||
s: STRING_8
|
||||
l_username: STRING_32
|
||||
do
|
||||
if attached {WSF_STRING} req.path_parameter ("user") as u then
|
||||
l_username := (create {HTML_ENCODER}).general_decoded_string (u.value)
|
||||
if
|
||||
attached {WSF_STRING} req.query_parameter ("op") as l_op
|
||||
then
|
||||
if l_op.is_case_insensitive_equal ("quit") then
|
||||
create redir.make (req.script_url ("/hello"), 3)
|
||||
create html.make
|
||||
redir.set_title ("Bye " + html.html_encoded_string (l_username))
|
||||
redir.set_body ("Bye " + html.html_encoded_string (l_username) + ",<br/> see you soon.<p>You will be redirected to " +
|
||||
redir.url_location + " in " + redir.delay.out + " second(s) ...</p>"
|
||||
)
|
||||
Result := redir
|
||||
else
|
||||
create html.make
|
||||
html.set_title ("Bad request")
|
||||
html.set_body ("Bad request: unknown operation '" + l_op.url_encoded_value + "'.")
|
||||
Result := html
|
||||
end
|
||||
else
|
||||
create html.make
|
||||
|
||||
s := "<p>User <em>'" + html.html_encoded_string (l_username) + "'</em>!</p>"
|
||||
s.append ("Display a <a href=%"/users/" + u.url_encoded_value + "/message/%">message</a></p>")
|
||||
s.append ("<p>Click <a href=%"/users/" + u.url_encoded_value + "/?op=quit%">here</a> to quit.</p>")
|
||||
html.set_title ("User '" + u.url_encoded_value + "'")
|
||||
html.set_body (s)
|
||||
Result := html
|
||||
end
|
||||
else
|
||||
create html.make
|
||||
html.set_title ("Bad request")
|
||||
html.set_body ("Bad request: missing user parameter")
|
||||
Result := html
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
@@ -163,8 +30,6 @@ feature {NONE} -- Initialization
|
||||
--| If you don't need any custom options, you are not obliged to redefine `initialize'
|
||||
Precursor
|
||||
|
||||
--| Initialize router
|
||||
initialize_router
|
||||
end
|
||||
|
||||
|
||||
|
||||
135
examples/tutorial/step_4/hello/src/hello_execution.e
Normal file
135
examples/tutorial/step_4/hello/src/hello_execution.e
Normal file
@@ -0,0 +1,135 @@
|
||||
note
|
||||
description: "[
|
||||
This class implements the `Hello World' execution service.
|
||||
|
||||
It inherits from WSF_ROUTED_EXECUTION to use the router service
|
||||
and from WSF_ROUTED_URI_TEMPLATE_HELPER to use help feature to map
|
||||
uri-template routes
|
||||
]"
|
||||
|
||||
class
|
||||
HELLO_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_EXECUTION
|
||||
|
||||
WSF_ROUTED_URI_HELPER
|
||||
WSF_ROUTED_URI_TEMPLATE_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
setup_router
|
||||
do
|
||||
-- router.map (create {WSF_URI_MAPPING}.make ("/hello", create {WSF_AGENT_URI_HANDLER}.make (agent execute_hello)))
|
||||
map_uri_agent ("/hello", agent execute_hello)
|
||||
|
||||
-- router.map (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}), router.methods_HEAD_GET_POST)
|
||||
map_uri_template ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, router.methods_HEAD_GET_POST)
|
||||
|
||||
-- router.map (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}), router.methods_GET_POST)
|
||||
map_uri_template ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, router.methods_GET_POST)
|
||||
|
||||
-- router.map (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/{?op}", create {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}.make (agent response_user)), router.methods_GET)
|
||||
map_uri_template_response_agent ("/users/{user}/{?op}", agent response_user, router.methods_GET)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Computed response message.
|
||||
local
|
||||
mesg: WSF_HTML_PAGE_RESPONSE
|
||||
s: STRING_8
|
||||
l_user_name: READABLE_STRING_32
|
||||
do
|
||||
--| It is now returning a WSF_HTML_PAGE_RESPONSE
|
||||
--| Since it is easier for building html page
|
||||
create mesg.make
|
||||
mesg.set_title ("EWF tutorial / Hello World!")
|
||||
--| Check if the request contains a parameter named "user"
|
||||
--| this could be a query, or a form parameter
|
||||
if attached {WSF_STRING} req.item ("user") as u then
|
||||
--| If yes, say hello world #name
|
||||
|
||||
l_user_name := (create {HTML_ENCODER}).decoded_string (u.value)
|
||||
|
||||
s := "<p>Hello " + mesg.html_encoded_string (l_user_name) + "!</p>"
|
||||
s.append ("Display a <a href=%"/users/" + u.url_encoded_value + "/message/%">message</a></p>")
|
||||
s.append ("<p>Click <a href=%"/users/" + u.url_encoded_value + "/?op=quit%">here</a> to quit.</p>")
|
||||
mesg.set_body (s)
|
||||
--| We should html encode this name
|
||||
--| but to keep the example simple, we don't do that for now.
|
||||
else
|
||||
--| Otherwise, ask for name
|
||||
s := (create {HTML_ENCODER}).encoded_string ({STRING_32} "Hello / ahoj / नमस्ते / Ciào / مرحبا / Hola / 你好 / Hallo / Selam / Bonjour ")
|
||||
s.append ("[
|
||||
<form action="/hello" method="GET">
|
||||
What is your name?</p>
|
||||
<input type="text" name="user"/>
|
||||
<input type="submit" value="Validate"/>
|
||||
</form>
|
||||
]"
|
||||
)
|
||||
mesg.set_body (s)
|
||||
end
|
||||
|
||||
--| note:
|
||||
--| 1) Source of the parameter, we could have used
|
||||
--| req.query_parameter ("user") to search only in the query string
|
||||
--| req.form_parameter ("user") to search only in the form parameters
|
||||
--| 2) response type
|
||||
--| it could also have used WSF_PAGE_REPONSE, and build the html in the code
|
||||
--|
|
||||
|
||||
res.send (mesg)
|
||||
end
|
||||
|
||||
response_user (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
-- Computed response message.
|
||||
local
|
||||
html: WSF_HTML_PAGE_RESPONSE
|
||||
redir: WSF_HTML_DELAYED_REDIRECTION_RESPONSE
|
||||
s: STRING_8
|
||||
l_username: STRING_32
|
||||
do
|
||||
if attached {WSF_STRING} req.path_parameter ("user") as u then
|
||||
l_username := (create {HTML_ENCODER}).general_decoded_string (u.value)
|
||||
if
|
||||
attached {WSF_STRING} req.query_parameter ("op") as l_op
|
||||
then
|
||||
if l_op.is_case_insensitive_equal ("quit") then
|
||||
create redir.make (req.script_url ("/hello"), 3)
|
||||
create html.make
|
||||
redir.set_title ("Bye " + html.html_encoded_string (l_username))
|
||||
redir.set_body ("Bye " + html.html_encoded_string (l_username) + ",<br/> see you soon.<p>You will be redirected to " +
|
||||
redir.url_location + " in " + redir.delay.out + " second(s) ...</p>"
|
||||
)
|
||||
Result := redir
|
||||
else
|
||||
create html.make
|
||||
html.set_title ("Bad request")
|
||||
html.set_body ("Bad request: unknown operation '" + l_op.url_encoded_value + "'.")
|
||||
Result := html
|
||||
end
|
||||
else
|
||||
create html.make
|
||||
|
||||
s := "<p>User <em>'" + html.html_encoded_string (l_username) + "'</em>!</p>"
|
||||
s.append ("Display a <a href=%"/users/" + u.url_encoded_value + "/message/%">message</a></p>")
|
||||
s.append ("<p>Click <a href=%"/users/" + u.url_encoded_value + "/?op=quit%">here</a> to quit.</p>")
|
||||
html.set_title ("User '" + u.url_encoded_value + "'")
|
||||
html.set_body (s)
|
||||
Result := html
|
||||
end
|
||||
else
|
||||
create html.make
|
||||
html.set_title ("Bad request")
|
||||
html.set_body ("Bad request: missing user parameter")
|
||||
Result := html
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user