Compare commits
238 Commits
WGI_2011_1
...
2012-03-14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25218996e0 | ||
|
|
68dbbdea9f | ||
|
|
5abc79b7c3 | ||
|
|
c5fe539acb | ||
|
|
ac3e969b3c | ||
|
|
98f2efbd68 | ||
|
|
7314e92fe6 | ||
|
|
468b2851be | ||
|
|
f1fe5464c6 | ||
|
|
d621987020 | ||
|
|
e541fdcb0c | ||
|
|
5950d768c9 | ||
|
|
413fdaf6cd | ||
|
|
9138ffedfb | ||
|
|
72cc05532c | ||
|
|
145b129b28 | ||
|
|
fbec89f354 | ||
|
|
f59d5cac32 | ||
|
|
4bb8a71c1b | ||
|
|
dd6b74326e | ||
|
|
e52cd6b352 | ||
|
|
537bd8241f | ||
|
|
040c1d1c10 | ||
|
|
f3c779cf6e | ||
|
|
6cf35e90c6 | ||
|
|
497fe03d38 | ||
|
|
ca3a520bb9 | ||
|
|
3c755019aa | ||
|
|
3a9b67c8ad | ||
|
|
e21da4a591 | ||
|
|
69bc4d568c | ||
|
|
cf8d25c4e5 | ||
|
|
2b9ca86501 | ||
|
|
2f43660628 | ||
|
|
d8476edf36 | ||
|
|
67e6b460b3 | ||
|
|
962154fc81 | ||
|
|
645b35590b | ||
|
|
a1354136fa | ||
|
|
945ef79857 | ||
|
|
2c4df29877 | ||
|
|
e6687c7791 | ||
|
|
754d3f670c | ||
|
|
8e420de8ec | ||
|
|
6dc1c0d2b0 | ||
|
|
80d68699b1 | ||
|
|
fcdf4e456e | ||
|
|
c92c2a91b4 | ||
|
|
da9fa4ecc2 | ||
|
|
abdd68863d | ||
|
|
83a8ad3879 | ||
|
|
1b55b09b64 | ||
|
|
4cf3393a13 | ||
|
|
4486df14cc | ||
|
|
60574ee85f | ||
|
|
7a6c51e47e | ||
|
|
d8c420c4b7 | ||
|
|
790aa40591 | ||
|
|
e506397406 | ||
|
|
434f031680 | ||
|
|
e36533bc99 | ||
|
|
d90ecbd5fe | ||
|
|
20281bc922 | ||
|
|
6b3a2d3b43 | ||
|
|
83346c92a7 | ||
|
|
6b50ab8c55 | ||
|
|
c8efa04147 | ||
|
|
37860f43b5 | ||
|
|
65a998cec3 | ||
|
|
7207a021be | ||
|
|
32373addfa | ||
|
|
e16f03b1c2 | ||
|
|
1698a06ea0 | ||
|
|
da3594db50 | ||
|
|
bfa620eee3 | ||
|
|
1423412f31 | ||
|
|
0f51925ec1 | ||
|
|
b6784ee35c | ||
|
|
ab5b43d8ef | ||
|
|
c7366615cf | ||
|
|
b60c41ee1b | ||
|
|
f9dfeb0034 | ||
|
|
5e35bc59a9 | ||
|
|
2ed6d92e53 | ||
|
|
33d3071cad | ||
|
|
35dde23976 | ||
|
|
390c05b056 | ||
|
|
011f8746d6 | ||
|
|
0335226e8b | ||
|
|
68e4ac9a8f | ||
|
|
f6b293d4ae | ||
|
|
89572b4f33 | ||
|
|
52e6944f37 | ||
|
|
bf056154d8 | ||
|
|
a3c50956f1 | ||
|
|
0d67533c83 | ||
|
|
c0c206e9ae | ||
|
|
36601fd3a4 | ||
|
|
9a85c24c0d | ||
|
|
5ef19021eb | ||
|
|
7495d0e6a7 | ||
|
|
f27c1f97a3 | ||
|
|
b96029a750 | ||
|
|
9ef10c749a | ||
|
|
0aa3d81b22 | ||
|
|
5d17b0dd29 | ||
|
|
5e2c2af18a | ||
|
|
de157be6f1 | ||
|
|
f601ae1c8b | ||
|
|
f6f94add80 | ||
|
|
a70e75f729 | ||
|
|
2dd43ad829 | ||
|
|
108396bd91 | ||
|
|
e9b7fc4c93 | ||
|
|
0dd2812574 | ||
|
|
d961544b8b | ||
|
|
3313e9cf81 | ||
|
|
39b5a70979 | ||
|
|
379e806166 | ||
|
|
c1e08a1bdc | ||
|
|
af21520e5d | ||
|
|
effc6ba81d | ||
|
|
019fb539ae | ||
|
|
03938b43c3 | ||
|
|
e70d67aed5 | ||
|
|
de38f46d1d | ||
|
|
8c79a64f0c | ||
|
|
fff7a5c96d | ||
|
|
1b92403045 | ||
|
|
8ae4a30ee8 | ||
|
|
8ffe2a8f73 | ||
|
|
769f2bb5a8 | ||
|
|
483f065ef1 | ||
|
|
8ff055803d | ||
|
|
3b30f4b994 | ||
|
|
f71bbc07e8 | ||
|
|
9b9bc1f190 | ||
|
|
6feaf5757f | ||
|
|
6f4ec89404 | ||
|
|
cdfc6851e7 | ||
|
|
e0ec84611e | ||
|
|
2234d3712b | ||
|
|
c89ccfa768 | ||
|
|
1a88388ffe | ||
|
|
5eab38778a | ||
|
|
9d457bb978 | ||
|
|
42be0b2a4e | ||
|
|
48d4d26cda | ||
|
|
182749d010 | ||
|
|
fd0912904c | ||
|
|
3032b91ff7 | ||
|
|
772b88f257 | ||
|
|
a1cc2d1d1a | ||
|
|
9f90bf56a5 | ||
|
|
dbea0e509b | ||
|
|
a3f28e3945 | ||
|
|
379a6193e9 | ||
|
|
03d9c3785c | ||
|
|
612915c918 | ||
|
|
ff967d6332 | ||
|
|
8d75a04068 | ||
|
|
202ad2861b | ||
|
|
44857d28ec | ||
|
|
e3597c0f3b | ||
|
|
0cce4d8244 | ||
|
|
aab910ab64 | ||
|
|
257ede7586 | ||
|
|
b58e4e19e1 | ||
|
|
6ec37c90a2 | ||
|
|
49c3e8e789 | ||
|
|
cc11debf08 | ||
|
|
b71a22d040 | ||
|
|
7022206a73 | ||
|
|
b715d674ca | ||
|
|
02f5bdd801 | ||
|
|
203d51a97e | ||
|
|
733296e71e | ||
|
|
0a497b9a4d | ||
|
|
4ed91a91a2 | ||
|
|
a76eb75267 | ||
|
|
2c94a98730 | ||
|
|
cc960310e9 | ||
|
|
d9daac67d9 | ||
|
|
955f73dee9 | ||
|
|
137ed3888c | ||
|
|
8382e8f134 | ||
|
|
0b7ea3c427 | ||
|
|
1e7b370859 | ||
|
|
8c02b0d546 | ||
|
|
13b09adc8c | ||
|
|
bc2e8b8ee2 | ||
|
|
36493b4324 | ||
|
|
a09908c048 | ||
|
|
d96ee66a32 | ||
|
|
7669ccfc1d | ||
|
|
3a6e3592ae | ||
|
|
07f9a8cec7 | ||
|
|
16cab53fb4 | ||
|
|
a2bf68e18a | ||
|
|
214255c4b9 | ||
|
|
082b8902ea | ||
|
|
ee9722fa18 | ||
|
|
4a81d02d12 | ||
|
|
0f5ae7e153 | ||
|
|
179dbceaba | ||
|
|
45292e0248 | ||
|
|
a38fca267b | ||
|
|
d4266a83ec | ||
|
|
83a181ebf1 | ||
|
|
54ecd2b1e8 | ||
|
|
da8a216448 | ||
|
|
085b520879 | ||
|
|
c115a40922 | ||
|
|
6f600362e3 | ||
|
|
bd36aa8b04 | ||
|
|
812f521c88 | ||
|
|
beb1bd1599 | ||
|
|
9bbcdc9927 | ||
|
|
0d637d478a | ||
|
|
8e4e7a5084 | ||
|
|
95d44890d9 | ||
|
|
161a5c720b | ||
|
|
35a4cd7df9 | ||
|
|
70ee7ff47a | ||
|
|
c9343688f3 | ||
|
|
f804a705d5 | ||
|
|
926c0a79b7 | ||
|
|
fb7854fbcc | ||
|
|
663a39d2ec | ||
|
|
6fb36da9ac | ||
|
|
3fbd81aeb1 | ||
|
|
6344f964fa | ||
|
|
14a2c01f41 | ||
|
|
79e12b8d04 | ||
|
|
aec0136739 | ||
|
|
9f53287226 | ||
|
|
8255dfd996 | ||
|
|
fcdc164214 |
18
.gitmodules
vendored
18
.gitmodules
vendored
@@ -1,12 +1,12 @@
|
||||
[submodule "doc/wiki"]
|
||||
path = doc/wiki
|
||||
url = https://github.com/Eiffel-World/Eiffel-Web-Framework.wiki.git
|
||||
[submodule "ext/server/nino"]
|
||||
path = ext/server/nino
|
||||
url = http://github.com/Eiffel-World/EiffelWebNino.git
|
||||
[submodule "ext/text/json"]
|
||||
path = ext/text/json
|
||||
url = http://github.com/Eiffel-World/ejson-svn.git
|
||||
[submodule "ext/ise_library/curl"]
|
||||
path = ext/ise_library/curl
|
||||
url = http://github.com/EiffelSoftware/mirror-Eiffel-cURL.git
|
||||
[submodule "contrib/library/server/nino"]
|
||||
path = contrib/library/server/nino
|
||||
url = https://github.com/Eiffel-World/EiffelWebNino.git
|
||||
[submodule "contrib/library/text/parser/json"]
|
||||
path = contrib/library/text/parser/json
|
||||
url = https://github.com/Eiffel-World/ejson-svn.git
|
||||
[submodule "contrib/ise_library/cURL"]
|
||||
path = contrib/ise_library/cURL
|
||||
url = https://github.com/EiffelSoftware/mirror-Eiffel-cURL.git
|
||||
|
||||
77
README.md
77
README.md
@@ -1,37 +1,80 @@
|
||||
# Eiffel Web Framework
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Official project site for Eiffel Web Framework:
|
||||
|
||||
* http://eiffel-world.github.com/Eiffel-Web-Framework/
|
||||
|
||||
For more information please have a look at the related wiki:
|
||||
|
||||
* https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
|
||||
|
||||
How to get the source code?
|
||||
---------------------------
|
||||
## Requirements
|
||||
|
||||
* Developped using EiffelStudio 7.0 (on Windows, Linux)
|
||||
* Tested using EiffelStudio 7.0 with "jenkins" CI server (and v6.8 for time to time)
|
||||
* The code have to allow __void-safe__ compilation and non void-safe system (see [more about void-safety](http://docs.eiffel.com/book/method/void-safe-programming-eiffel) )
|
||||
|
||||
## How to get the source code?
|
||||
|
||||
Using git version >= 1.6.5
|
||||
* git clone --recursive https://github.com/Eiffel-World/Eiffel-Web-Framework.git
|
||||
|
||||
Otherwise, try
|
||||
* git clone https://github.com/Eiffel-World/Eiffel-Web-Framework.git
|
||||
* cd Eiffel-Web-Framework
|
||||
* git submodule update --init
|
||||
* git submodule foreach git pull origin master
|
||||
* git submodule foreach git checkout master
|
||||
* git submodule foreach --recursive git checkout master
|
||||
|
||||
An alternative to the last 2 instructions is to use the script from tools folder:
|
||||
* cd tools
|
||||
* update_git_working_copy
|
||||
|
||||
* And to build the required and related Clibs
|
||||
** cd ext/ise_library/curl
|
||||
** geant compile
|
||||
* cd contrib/ise_library/cURL
|
||||
* geant compile
|
||||
|
||||
Overview
|
||||
--------
|
||||
## Libraries under 'library'
|
||||
|
||||
* library/server/ewsgi: Eiffel Web Server Gateway Interface
|
||||
* library/server/ewsgi/connectors: various web server connectors for EWSGI
|
||||
* library/server/libfcgi: Wrapper for libfcgi SDK
|
||||
### server
|
||||
* __ewsgi__: Eiffel Web Server Gateway Interface [read more](library/server/ewsgi)
|
||||
* connectors: various web server connectors for EWSGI
|
||||
* libfcgi: Wrapper for libfcgi SDK
|
||||
* __wsf__: Web Server Framework [read more](library/server/wsf)
|
||||
* __router__: URL dispatching/routing based on uri, uri_template, or custom [read more](library/server/wsf/router)
|
||||
|
||||
* library/server/request/router: URL dispatching/routing based on uri, uri_template, or custom.
|
||||
* library/server/request/rest: experimental: RESTful library to help building RESTful services
|
||||
### protocol
|
||||
* __http__: HTTP related classes, constants for status code, content types, ... [read more](library/protocol/http)
|
||||
* __uri_template__: URI Template library (parsing and expander) [read more](library/protocol/uri_template)
|
||||
* __CONNEG__: CONNEG library (Content-type Negociation) [read more](library/protocol/CONNEG)
|
||||
|
||||
* library/protocol/http: HTTP related classes, constants for status code, content types, ...
|
||||
* library/protocol/uri_template: URI Template library (parsing and expander)
|
||||
### client
|
||||
* __http_client__: simple HTTP client based on cURL [read more](library/client/http_client)
|
||||
|
||||
### text
|
||||
* __encoder__: Various simpler encoders: base64, url-encoder, xml entities, html entities [read more](library/text/encoder)
|
||||
|
||||
### crypto
|
||||
* eel
|
||||
* eapml
|
||||
|
||||
### Others
|
||||
* error: very simple/basic library to handle error
|
||||
|
||||
## External libraries under 'contrib'
|
||||
* [Eiffel Web Nino](contrib/library/server/nino)
|
||||
* ..
|
||||
|
||||
## Draft folder = call for contribution ##
|
||||
### library/server/request ###
|
||||
* request
|
||||
* rest: (experimental) "a" RESTful library to help building RESTful services
|
||||
|
||||
## Examples
|
||||
..
|
||||
|
||||
* library/error: very simple/basic library to handle error
|
||||
* library/text/encoder: Various simpler encoder: base64, url-encoder, xml entities, html entities
|
||||
|
||||
For more information please have a look at the related wiki:
|
||||
* https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
|
||||
|
||||
1
contrib/ise_library/cURL
Submodule
1
contrib/ise_library/cURL
Submodule
Submodule contrib/ise_library/cURL added at ad2a498fc0
1
contrib/library/server/nino
Submodule
1
contrib/library/server/nino
Submodule
Submodule contrib/library/server/nino added at e85213689e
1
contrib/library/text/parser/json
Submodule
1
contrib/library/text/parser/json
Submodule
Submodule contrib/library/text/parser/json added at 769bb7d161
2
doc/wiki
2
doc/wiki
Submodule doc/wiki updated: 2b112da43d...51b912c4f8
25
draft/README.md
Normal file
25
draft/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
This "draft" folder contains potential addition to EWF
|
||||
|
||||
Anyone wanting to contribute is welcome to the listed libraries, or by suggesting/contributing with extra libraries
|
||||
|
||||
## Current suggestions ##
|
||||
|
||||
### protocol ###
|
||||
* web syndication [__Atom__](library/protocol/syndication/atom)
|
||||
* web syndication [__RSS__](library/protocol/syndication/rss)
|
||||
* [__Twitter__](library/protocol/twitter)
|
||||
* [__XMPP__](library/protocol/xmpp) (also known as Jabber)
|
||||
|
||||
### Security ###
|
||||
* [__OAuth__](library/security/oauth)
|
||||
* [__OpenID__](library/security/openid)
|
||||
|
||||
### Text ###
|
||||
* [__Filters__](library/text/filter) : Wiki markup, Markdown, ...
|
||||
* [__Templates__](library/text/template) : Web template engine ...
|
||||
|
||||
|
||||
### ... ###
|
||||
|
||||
Any contribution is welcome, help us make Eiffel Web Framework bigger, richer and better.
|
||||
|
||||
9
draft/library/protocol/syndication/README.md
Normal file
9
draft/library/protocol/syndication/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
Web Syndication
|
||||
|
||||
http://en.wikipedia.org/wiki/Web_syndication
|
||||
|
||||
* [Atom Pub](atom)
|
||||
* [RSS](rss)
|
||||
* ...
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
10
draft/library/protocol/syndication/atom/README.md
Normal file
10
draft/library/protocol/syndication/atom/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Atom protocol
|
||||
|
||||
http://en.wikipedia.org/wiki/Atom_(standard)
|
||||
|
||||
Atom standard
|
||||
* [RFC 4287](http://tools.ietf.org/html/rfc4287) – "The Atom Syndication Format"
|
||||
* [RFC 5023](http://tools.ietf.org/html/rfc5023) – "The Atom Publishing Protocol"
|
||||
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
15
draft/library/protocol/syndication/atom/atom-safe.ecf
Normal file
15
draft/library/protocol/syndication/atom/atom-safe.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="atom" uuid="076DEABB-20DA-43E9-A4C7-F3FAEDF5B1FC" library_target="atom">
|
||||
<target name="atom">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
15
draft/library/protocol/syndication/atom/atom.ecf
Normal file
15
draft/library/protocol/syndication/atom/atom.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="atom" uuid="076DEABB-20DA-43E9-A4C7-F3FAEDF5B1FC" library_target="atom">
|
||||
<target name="atom">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
22
draft/library/protocol/syndication/atom/src/atom.e
Normal file
22
draft/library/protocol/syndication/atom/src/atom.e
Normal file
@@ -0,0 +1,22 @@
|
||||
note
|
||||
description: "[
|
||||
Main interface for ATOM interface
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ATOM
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Instantiate Current object
|
||||
do
|
||||
check not_yet_implemented: False end
|
||||
end
|
||||
|
||||
end
|
||||
7
draft/library/protocol/syndication/rss/README.md
Normal file
7
draft/library/protocol/syndication/rss/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
RSS protocol
|
||||
|
||||
http://en.wikipedia.org/wiki/RSS
|
||||
|
||||
* [RSS specification](http://www.rssboard.org/rss-specification)
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
15
draft/library/protocol/syndication/rss/rss-safe.ecf
Normal file
15
draft/library/protocol/syndication/rss/rss-safe.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="rss" uuid="8D8E3E5A-2685-40AF-9EF9-E3113B3C62AA" library_target="rss">
|
||||
<target name="rss">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
15
draft/library/protocol/syndication/rss/rss.ecf
Normal file
15
draft/library/protocol/syndication/rss/rss.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="rss" uuid="8D8E3E5A-2685-40AF-9EF9-E3113B3C62AA" library_target="rss">
|
||||
<target name="rss">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
22
draft/library/protocol/syndication/rss/src/rss.e
Normal file
22
draft/library/protocol/syndication/rss/src/rss.e
Normal file
@@ -0,0 +1,22 @@
|
||||
note
|
||||
description: "[
|
||||
Main interface for RSS interface
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
RSS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Instantiate Current object
|
||||
do
|
||||
check not_yet_implemented: False end
|
||||
end
|
||||
|
||||
end
|
||||
6
draft/library/protocol/twitter/README.md
Normal file
6
draft/library/protocol/twitter/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
Twitter protocol
|
||||
|
||||
http://en.wikipedia.org/wiki/Twitter
|
||||
|
||||
Eventually move http://bricabrac.origo.ethz.ch/wiki/Eiffel_Twitter here
|
||||
Anyone wanting to contribute is welcome
|
||||
6
draft/library/protocol/xmpp/README.md
Normal file
6
draft/library/protocol/xmpp/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
XMPP/Jabber protocol
|
||||
|
||||
http://en.wikipedia.org/wiki/Xmpp
|
||||
|
||||
Eventually move http://bricabrac.origo.ethz.ch/wiki/Eiffel_XMPP here
|
||||
Anyone wanting to contribute is welcome
|
||||
7
draft/library/security/oauth/README.md
Normal file
7
draft/library/security/oauth/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
OAuth
|
||||
|
||||
http://en.wikipedia.org/wiki/Oauth
|
||||
|
||||
* [RFC5849](http://tools.ietf.org/html/rfc5849)
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
15
draft/library/security/oauth/oauth-safe.ecf
Normal file
15
draft/library/security/oauth/oauth-safe.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="oauth" uuid="F8B4DF74-C71B-45A3-9B9A-F6141C4D3C56" library_target="oauth">
|
||||
<target name="oauth">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
15
draft/library/security/oauth/oauth.ecf
Normal file
15
draft/library/security/oauth/oauth.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="oauth" uuid="F8B4DF74-C71B-45A3-9B9A-F6141C4D3C56" library_target="oauth">
|
||||
<target name="oauth">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
22
draft/library/security/oauth/src/oauth.e
Normal file
22
draft/library/security/oauth/src/oauth.e
Normal file
@@ -0,0 +1,22 @@
|
||||
note
|
||||
description: "[
|
||||
Main interface for OAUTH interface
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
OAUTH
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Instantiate Current object
|
||||
do
|
||||
check not_yet_implemented: False end
|
||||
end
|
||||
|
||||
end
|
||||
5
draft/library/security/openid/README.md
Normal file
5
draft/library/security/openid/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
OpenID
|
||||
|
||||
http://en.wikipedia.org/wiki/Openid
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
15
draft/library/security/openid/openid-safe.ecf
Normal file
15
draft/library/security/openid/openid-safe.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="openid" uuid="E6B80EAB-AC99-46F5-9896-4892D3477A9A" library_target="openid">
|
||||
<target name="openid">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
15
draft/library/security/openid/openid.ecf
Normal file
15
draft/library/security/openid/openid.ecf
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="openid" uuid="E6B80EAB-AC99-46F5-9896-4892D3477A9A" library_target="openid">
|
||||
<target name="openid">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
22
draft/library/security/openid/src/openid.e
Normal file
22
draft/library/security/openid/src/openid.e
Normal file
@@ -0,0 +1,22 @@
|
||||
note
|
||||
description: "[
|
||||
Main interface for OPENID interface
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
OPENID
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Instantiate Current object
|
||||
do
|
||||
check not_yet_implemented: False end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -7,12 +7,12 @@
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all"/>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf"/>
|
||||
<library name="http" location="..\..\..\protocol\http\http-safe.ecf"/>
|
||||
<library name="router" location="..\..\request\router\router-safe.ecf" readonly="false"/>
|
||||
<library name="uri_template" location="..\..\..\protocol\uri_template\uri_template-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\..\..\library\protocol\http\http-safe.ecf"/>
|
||||
<library name="uri_template" location="..\..\..\..\..\library\protocol\uri_template\uri_template-safe.ecf"/>
|
||||
<cluster name="contrib" location=".\src\contrib\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/html$</exclude>
|
||||
@@ -9,10 +9,9 @@
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="ewsgi" location="..\..\ewsgi\ewsgi.ecf"/>
|
||||
<library name="http" location="..\..\..\protocol\http\http.ecf"/>
|
||||
<library name="router" location="..\..\request\router\router.ecf" readonly="false"/>
|
||||
<library name="uri_template" location="..\..\..\protocol\uri_template\uri_template.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\..\library\server\wsf\wsf.ecf"/>
|
||||
<library name="http" location="..\..\..\..\..\library\protocol\http\http.ecf"/>
|
||||
<library name="uri_template" location="..\..\..\..\..\library\protocol\uri_template\uri_template.ecf"/>
|
||||
<cluster name="contrib" location=".\src\contrib\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/html$</exclude>
|
||||
@@ -31,7 +31,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
headers: EWF_HEADER
|
||||
headers: HTTP_HEADER
|
||||
|
||||
feature -- Recycle
|
||||
|
||||
@@ -155,11 +155,11 @@ feature -- Output
|
||||
Result := o
|
||||
end
|
||||
|
||||
send (buf: WGI_RESPONSE_BUFFER)
|
||||
send (buf: WSF_RESPONSE)
|
||||
do
|
||||
buf.set_status_code (200)
|
||||
buf.write_headers_string (header_string)
|
||||
buf.write_string (message_string)
|
||||
buf.put_header_text (header_string)
|
||||
buf.put_string (message_string)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation: output
|
||||
@@ -30,13 +30,13 @@ feature {NONE} -- Access: Implementation
|
||||
|
||||
feature -- Access
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_application (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
rep: like new_html_page
|
||||
s: STRING
|
||||
@@ -50,7 +50,7 @@ feature -- Execution
|
||||
create s.make_empty
|
||||
|
||||
if
|
||||
attached {WGI_STRING_VALUE} ctx.path_parameter ("resource") as l_resource_value and then
|
||||
attached {WSF_STRING} ctx.path_parameter ("resource") as l_resource_value and then
|
||||
attached l_resource_value.string as l_resource
|
||||
then
|
||||
from
|
||||
@@ -114,7 +114,7 @@ feature -- Execution
|
||||
rep.recycle
|
||||
end
|
||||
|
||||
process_request_handler_doc (rq: REST_REQUEST_HANDLER [C]; a_resource: STRING; buf: STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_dft_format: detachable STRING)
|
||||
process_request_handler_doc (rq: REST_REQUEST_HANDLER [C]; a_resource: STRING; buf: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; a_dft_format: detachable STRING)
|
||||
local
|
||||
l_dft_format_name: detachable STRING
|
||||
s: STRING
|
||||
@@ -0,0 +1,56 @@
|
||||
note
|
||||
description: "Summary description for {REST_RESPONSE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_RESPONSE
|
||||
|
||||
inherit
|
||||
WSF_PAGE_RESPONSE
|
||||
rename
|
||||
header as headers,
|
||||
body as message,
|
||||
set_body as set_message,
|
||||
put_string as append_message,
|
||||
make as page_make,
|
||||
send_to as send
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: like api)
|
||||
do
|
||||
api := a_api
|
||||
page_make
|
||||
end
|
||||
|
||||
feature -- Recycle
|
||||
|
||||
recycle
|
||||
do
|
||||
headers.recycle
|
||||
message := Void
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
api: STRING
|
||||
-- Associated api query string.
|
||||
|
||||
invariant
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
@@ -23,7 +23,7 @@ create
|
||||
|
||||
feature -- status
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := internal_authentication_required
|
||||
end
|
||||
@@ -9,13 +9,10 @@ deferred class
|
||||
|
||||
inherit
|
||||
REQUEST_HANDLER [C]
|
||||
redefine
|
||||
execute
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
-- Is authentication required
|
||||
-- might depend on the request environment
|
||||
-- or the associated resources
|
||||
@@ -35,53 +32,47 @@ feature -- Element change
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
local
|
||||
rescued: BOOLEAN
|
||||
do
|
||||
if not rescued then
|
||||
if request_method_name_supported (req.request_method) then
|
||||
if authentication_required (req) and then not authenticated (ctx) then
|
||||
execute_unauthorized (ctx, req, res)
|
||||
else
|
||||
pre_execute (ctx, req, res)
|
||||
execute_application (ctx, req, res)
|
||||
post_execute (ctx, req, res)
|
||||
end
|
||||
if request_method_name_supported (req.request_method) then
|
||||
if authentication_required (req) and then not authenticated (ctx) then
|
||||
execute_unauthorized (ctx, req, res)
|
||||
else
|
||||
execute_request_method_not_allowed (req, res, supported_request_method_names)
|
||||
pre_execute (ctx, req, res)
|
||||
execute_application (ctx, req, res)
|
||||
post_execute (ctx, req, res)
|
||||
end
|
||||
else
|
||||
rescue_execute (ctx, req, res)
|
||||
execute_request_method_not_allowed (req, res, supported_request_method_names)
|
||||
end
|
||||
rescue
|
||||
rescued := True
|
||||
retry
|
||||
execute_rescue (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
deferred
|
||||
end
|
||||
|
||||
pre_execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
pre_execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
end
|
||||
|
||||
post_execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
post_execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
end
|
||||
|
||||
rescue_execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_rescue (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
post_execute (ctx, req, res)
|
||||
rescue
|
||||
--| Just in case, the rescue is raising other exceptions ...
|
||||
end
|
||||
|
||||
execute_unauthorized (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_unauthorized (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.unauthorized)
|
||||
res.write_header ({HTTP_STATUS_CODE}.unauthorized, Void)
|
||||
res.write_string ("Unauthorized")
|
||||
res.put_header ({HTTP_STATUS_CODE}.unauthorized, Void)
|
||||
res.put_string ("Unauthorized")
|
||||
end
|
||||
|
||||
feature -- Auth
|
||||
@@ -241,6 +232,9 @@ feature -- Status report
|
||||
if method_put_supported then
|
||||
Result.extend (request_method_constants.method_put)
|
||||
end
|
||||
if method_patch_supported then
|
||||
Result.extend (request_method_constants.method_patch)
|
||||
end
|
||||
if method_delete_supported then
|
||||
Result.extend (request_method_constants.method_delete)
|
||||
end
|
||||
@@ -264,6 +258,11 @@ feature -- Status report
|
||||
Result := request_method_id_supported ({HTTP_REQUEST_METHOD_CONSTANTS}.put)
|
||||
end
|
||||
|
||||
method_patch_supported: BOOLEAN
|
||||
do
|
||||
Result := request_method_id_supported ({HTTP_REQUEST_METHOD_CONSTANTS}.patch)
|
||||
end
|
||||
|
||||
method_delete_supported: BOOLEAN
|
||||
do
|
||||
Result := request_method_id_supported ({HTTP_REQUEST_METHOD_CONSTANTS}.delete)
|
||||
@@ -296,6 +295,11 @@ feature -- Element change: request methods
|
||||
enable_request_method ({HTTP_REQUEST_METHOD_CONSTANTS}.put)
|
||||
end
|
||||
|
||||
enable_request_method_patch
|
||||
do
|
||||
enable_request_method ({HTTP_REQUEST_METHOD_CONSTANTS}.patch)
|
||||
end
|
||||
|
||||
enable_request_method_delete
|
||||
do
|
||||
enable_request_method ({HTTP_REQUEST_METHOD_CONSTANTS}.delete)
|
||||
@@ -314,7 +318,7 @@ feature -- Element change: request methods
|
||||
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
@@ -0,0 +1,131 @@
|
||||
note
|
||||
description: "Summary description for {REST_REQUEST_HANDLER_CONTEXT}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
REQUEST_HANDLER_CONTEXT
|
||||
|
||||
feature -- Accept: Content-Type
|
||||
|
||||
accepted_content_type: detachable READABLE_STRING_8
|
||||
do
|
||||
if internal_accepted_content_type = Void then
|
||||
get_accepted_content_type (Void)
|
||||
end
|
||||
Result := internal_accepted_content_type
|
||||
end
|
||||
|
||||
get_accepted_content_type (a_supported_content_types: detachable ARRAY [STRING_8])
|
||||
do
|
||||
if internal_accepted_content_type = Void then
|
||||
internal_accepted_content_type := request_accepted_content_type (a_supported_content_types)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Format name
|
||||
|
||||
accepted_format_name: detachable READABLE_STRING_8
|
||||
do
|
||||
if internal_accepted_format_name = Void then
|
||||
get_accepted_format_name (Void, Void)
|
||||
end
|
||||
Result := internal_accepted_format_name
|
||||
end
|
||||
|
||||
get_accepted_format_name (a_format_variable_name: detachable READABLE_STRING_8; a_supported_content_types: detachable ARRAY [STRING_8])
|
||||
do
|
||||
if internal_accepted_format_name = Void then
|
||||
internal_accepted_format_name := request_accepted_format (a_format_variable_name, a_supported_content_types)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Format id
|
||||
|
||||
accepted_format_id: INTEGER
|
||||
do
|
||||
if internal_accepted_format_id = 0 then
|
||||
get_accepted_format_id (Void, Void)
|
||||
end
|
||||
Result := internal_accepted_format_id
|
||||
end
|
||||
|
||||
get_accepted_format_id (a_format_variable_name: detachable READABLE_STRING_8; a_supported_content_types: detachable ARRAY [STRING_8])
|
||||
do
|
||||
if internal_accepted_format_id = 0 then
|
||||
internal_accepted_format_id := request_accepted_format_id (a_format_variable_name, a_supported_content_types)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Constants
|
||||
|
||||
Format_constants: HTTP_FORMAT_CONSTANTS
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
feature -- Format
|
||||
|
||||
request_accepted_format (a_format_variable_name: detachable READABLE_STRING_8; a_supported_content_types: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8
|
||||
-- Format id for the request based on {HTTP_FORMAT_CONSTANTS}
|
||||
do
|
||||
if a_format_variable_name /= Void and then attached string_parameter (a_format_variable_name) as ctx_format then
|
||||
Result := ctx_format.as_string_8
|
||||
else
|
||||
Result := request_format_from_content_type (request_accepted_content_type (a_supported_content_types))
|
||||
end
|
||||
end
|
||||
|
||||
request_accepted_format_id (a_format_variable_name: detachable READABLE_STRING_8; a_supported_content_types: detachable ARRAY [READABLE_STRING_8]): INTEGER
|
||||
-- Format id for the request based on {HTTP_FORMAT_CONSTANTS}
|
||||
do
|
||||
if attached request_accepted_format (a_format_variable_name, a_supported_content_types) as l_format then
|
||||
Result := Format_constants.format_id (l_format)
|
||||
else
|
||||
Result := 0
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Format/Content type implementation
|
||||
|
||||
request_format_from_content_type (a_content_type: detachable READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- `a_content_type' converted into a request format name
|
||||
do
|
||||
if a_content_type /= Void then
|
||||
if a_content_type.same_string ({HTTP_MIME_TYPES}.text_json) then
|
||||
Result := {HTTP_FORMAT_CONSTANTS}.json_name
|
||||
elseif a_content_type.same_string ({HTTP_MIME_TYPES}.application_json) then
|
||||
Result := {HTTP_FORMAT_CONSTANTS}.json_name
|
||||
elseif a_content_type.same_string ({HTTP_MIME_TYPES}.text_xml) then
|
||||
Result := {HTTP_FORMAT_CONSTANTS}.xml_name
|
||||
elseif a_content_type.same_string ({HTTP_MIME_TYPES}.text_html) then
|
||||
Result := {HTTP_FORMAT_CONSTANTS}.html_name
|
||||
elseif a_content_type.same_string ({HTTP_MIME_TYPES}.text_plain) then
|
||||
Result := {HTTP_FORMAT_CONSTANTS}.text_name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Internal
|
||||
|
||||
internal_accepted_content_type: like accepted_content_type
|
||||
|
||||
internal_accepted_format_id: like accepted_format_id
|
||||
|
||||
internal_accepted_format_name: like accepted_format_name
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
@@ -1,14 +1,14 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_APPLICATION}."
|
||||
description: "Summary description for {DEFAULT_REST_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_APPLICATION
|
||||
REST_SERVICE
|
||||
|
||||
inherit
|
||||
REST_APPLICATION_I [REST_REQUEST_HANDLER [REST_REQUEST_HANDLER_CONTEXT], REST_REQUEST_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I [REST_REQUEST_HANDLER [REST_REQUEST_HANDLER_CONTEXT], REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
@@ -1,14 +1,14 @@
|
||||
note
|
||||
description: "Summary description for {REST_APPLICATION}."
|
||||
description: "Summary description for {REST_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_APPLICATION_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
ROUTED_APPLICATION_I [H, C]
|
||||
ROUTED_SERVICE_I [H, C]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
@@ -18,7 +18,7 @@ create
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REST_REQUEST_URI_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]];
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REST_REQUEST_URI_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
local
|
||||
h: REST_REQUEST_AGENT_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
@@ -25,7 +25,7 @@ create
|
||||
|
||||
feature -- Status report
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := internal_authentication_required
|
||||
end
|
||||
@@ -36,12 +36,12 @@ feature {NONE} -- Implementation
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
Precursor {REQUEST_URI_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
check should_not_occur: False end
|
||||
end
|
||||
@@ -1,14 +1,14 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_URI_APPLICATION}."
|
||||
description: "Summary description for {DEFAULT_REST_URI_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_URI_APPLICATION
|
||||
REST_URI_SERVICE
|
||||
|
||||
inherit
|
||||
REST_APPLICATION_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT], REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT], REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
@@ -14,11 +14,12 @@ inherit
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]];
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
local
|
||||
h: REST_REQUEST_AGENT_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
@@ -28,7 +29,7 @@ feature -- Mapping
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
@@ -13,10 +13,11 @@ inherit
|
||||
REST_REQUEST_ROUTER [H, C]
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
@@ -14,14 +14,15 @@ inherit
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: REST_REQUEST_URI_TEMPLATE_ROUTER
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
@@ -21,11 +21,12 @@ inherit
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Status report
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := internal_authentication_required
|
||||
end
|
||||
@@ -36,14 +37,14 @@ feature {NONE} -- Implementation
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
pre_execute (ctx, req, res)
|
||||
Precursor {REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
post_execute (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
check should_not_occur: False end
|
||||
end
|
||||
@@ -53,7 +54,7 @@ feature {NONE} -- Routing
|
||||
router: REST_REQUEST_URI_TEMPLATE_ROUTER_I [H, C]
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
@@ -1,14 +1,14 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_URI_TEMPLATE_REST_APPLICATION}."
|
||||
description: "Summary description for {DEFAULT_URI_TEMPLATE_REST_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_URI_TEMPLATE_APPLICATION
|
||||
REST_URI_TEMPLATE_SERVICE
|
||||
|
||||
inherit
|
||||
REST_APPLICATION_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT], REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT], REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
@@ -12,13 +12,13 @@
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="rest" location="..\rest-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi" location="..\..\..\ewsgi\ewsgi-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\..\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\..\..\..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\..\..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
</target>
|
||||
<target name="sample_fcgi" extends="common">
|
||||
<root class="APP_SERVER" feature="make"/>
|
||||
<setting name="executable_name" value="sample"/>
|
||||
<library name="ewsgi_fcgi" location="..\..\..\ewsgi/connectors\libfcgi\libfcgi-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi_fcgi" location="..\..\..\..\..\..\library\server\ewsgi\connectors\libfcgi\libfcgi-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/gateway$</exclude>
|
||||
@@ -29,7 +29,7 @@
|
||||
<target name="sample_cgi" extends="common">
|
||||
<root class="APP_SERVER" feature="make"/>
|
||||
<setting name="executable_name" value="sample"/>
|
||||
<library name="ewsgi_cgi" location="..\..\..\ewsgi/connectors\cgi\cgi-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi_cgi" location="..\..\..\..\..\..\library\server\ewsgi\connectors\cgi\cgi-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/gateway$</exclude>
|
||||
@@ -41,8 +41,8 @@
|
||||
<target name="sample_nino" extends="common">
|
||||
<root class="APP_SERVER" feature="make"/>
|
||||
<setting name="executable_name" value="sample"/>
|
||||
<library name="ewsgi_nino" location="..\..\..\ewsgi/connectors\nino\nino-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi_default_nino" location="..\..\..\ewsgi/default\ewsgi_nino-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi_nino" location="..\..\..\..\..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
|
||||
<library name="default_nino" location="..\..\..\..\..\..\library\server\wsf\default\nino-safe.ecf" readonly="false"/>
|
||||
|
||||
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
@@ -35,34 +35,34 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_unauthorized (a_hdl_context: APP_REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_unauthorized (a_hdl_context: APP_REQUEST_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
s: STRING
|
||||
lst: LIST [STRING]
|
||||
do
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.unauthorized)
|
||||
res.write_header ({HTTP_STATUS_CODE}.unauthorized, <<["WWW-Authenticate", "Basic realm=%"My Silly demo auth, password must be the same as login such as foo:foo%""]>>)
|
||||
res.write_string ("Unauthorized")
|
||||
res.put_header ({HTTP_STATUS_CODE}.unauthorized, <<["WWW-Authenticate", "Basic realm=%"My Silly demo auth, password must be the same as login such as foo:foo%""]>>)
|
||||
res.put_string ("Unauthorized")
|
||||
end
|
||||
|
||||
execute_application (ctx: APP_REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_application (ctx: APP_REQUEST_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
l_full: BOOLEAN
|
||||
h: EWF_HEADER
|
||||
h: HTTP_HEADER
|
||||
l_login: STRING_8
|
||||
s: STRING
|
||||
content_type_supported: ARRAY [STRING]
|
||||
l_format_id: INTEGER
|
||||
do
|
||||
content_type_supported := <<{HTTP_CONSTANTS}.json_app, {HTTP_CONSTANTS}.xml_text, {HTTP_CONSTANTS}.plain_text>>
|
||||
l_format_id := ctx.request_format_id ("format", content_type_supported)
|
||||
content_type_supported := <<{HTTP_CONSTANTS}.application_json, {HTTP_CONSTANTS}.text_xml, {HTTP_CONSTANTS}.text_plain>>
|
||||
l_format_id := ctx.request_accepted_format_id ("format", content_type_supported)
|
||||
if authenticated (ctx) then
|
||||
l_full := attached ctx.query_parameter ("details") as v and then v.is_case_insensitive_equal ("true")
|
||||
if attached authenticated_identifier (ctx) as log then
|
||||
@@ -88,8 +88,8 @@ feature -- Execution
|
||||
end
|
||||
if not s.is_empty then
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (s)
|
||||
res.put_header_text (h.string)
|
||||
res.put_string (s)
|
||||
end
|
||||
else
|
||||
send_error (ctx.path, 0, "User/password unknown", Void, ctx, req, res)
|
||||
@@ -32,30 +32,30 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
authentication_required (req: WGI_REQUEST): BOOLEAN
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_application (ctx: APP_REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_application (ctx: APP_REQUEST_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
local
|
||||
s: STRING
|
||||
h: EWF_HEADER
|
||||
h: HTTP_HEADER
|
||||
do
|
||||
create h.make
|
||||
h.put_content_type_text_plain
|
||||
|
||||
create s.make_empty
|
||||
s.append_string ("test")
|
||||
if attached req.meta_variable ("REQUEST_COUNT") as l_request_count_val then
|
||||
s.append_string ("(request_count="+ l_request_count_val.as_string +")%N")
|
||||
if attached {WSF_STRING} req.meta_variable ("REQUEST_COUNT") as l_request_count_val then
|
||||
s.append_string ("(request_count="+ l_request_count_val.string +")%N")
|
||||
end
|
||||
|
||||
-- ctx.request_format_id ("format", Void)
|
||||
|
||||
if attached ctx.request_format ("format", Void) as l_format then
|
||||
if attached ctx.request_accepted_format ("format", Void) as l_format then
|
||||
s.append_string (" format=" + l_format + "%N")
|
||||
end
|
||||
|
||||
@@ -80,8 +80,8 @@ feature -- Execution
|
||||
end
|
||||
|
||||
res.set_status_code (200)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (s)
|
||||
res.put_header_text (h.string)
|
||||
res.put_string (s)
|
||||
end
|
||||
|
||||
note
|
||||
@@ -8,12 +8,12 @@ class
|
||||
APP_SERVER
|
||||
|
||||
inherit
|
||||
APP_APPLICATION
|
||||
APP_SERVICE
|
||||
redefine
|
||||
execute
|
||||
end
|
||||
|
||||
REST_APPLICATION_GATEWAY
|
||||
REST_SERVICE_GATEWAY
|
||||
|
||||
create
|
||||
make
|
||||
@@ -68,17 +68,17 @@ feature {NONE} -- Handlers
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
request_count := request_count + 1
|
||||
Precursor (req, res)
|
||||
end
|
||||
|
||||
execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
rqst_uri: detachable STRING
|
||||
l_path_info: detachable STRING
|
||||
h: EWF_HEADER
|
||||
h: HTTP_HEADER
|
||||
s: STRING
|
||||
l_redir_url: STRING
|
||||
do
|
||||
@@ -92,10 +92,12 @@ feature -- Execution
|
||||
s.append ("You are being redirected to <a href=%"" + l_redir_url + "%">/doc</a> in 2 seconds ...%N")
|
||||
h.put_content_length (s.count)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.temp_redirect)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (s)
|
||||
res.put_header_text (h.string)
|
||||
res.put_string (s)
|
||||
end
|
||||
|
||||
request_count: INTEGER
|
||||
|
||||
-- execute_rescue (ctx: like new_request_context)
|
||||
-- -- Execute the default rescue behavior
|
||||
-- do
|
||||
@@ -106,7 +108,7 @@ feature -- Implementation
|
||||
|
||||
-- execute_exception_trace (ctx: like new_request_context)
|
||||
-- local
|
||||
-- h: EWF_HEADER
|
||||
-- h: HTTP_HEADER
|
||||
-- s: STRING
|
||||
-- do
|
||||
-- create h.make
|
||||
@@ -121,17 +123,17 @@ feature -- Implementation
|
||||
-- exit_with_code (-1)
|
||||
-- end
|
||||
|
||||
execute_exit_application (ctx: APP_REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
execute_exit_application (ctx: APP_REQUEST_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
res.set_status_code (200)
|
||||
res.write_header (200, <<["Content-Type", "text/html"]>>)
|
||||
res.put_header (200, <<["Content-Type", "text/html"]>>)
|
||||
|
||||
create s.make_empty
|
||||
s.append_string ("Exited")
|
||||
s.append_string (" <a href=%"" + ctx.script_url ("/") + "%">start again</a>%N")
|
||||
res.write_string (s)
|
||||
res.put_string (s)
|
||||
exit_with_code (0)
|
||||
end
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
deferred class
|
||||
REST_APPLICATION_GATEWAY
|
||||
REST_SERVICE_GATEWAY
|
||||
|
||||
inherit
|
||||
WGI_APPLICATION
|
||||
WSF_SERVICE
|
||||
|
||||
feature -- Access
|
||||
|
||||
build_gateway_and_launch
|
||||
local
|
||||
cgi: EWF_CGI_CONNECTOR
|
||||
cgi: WGI_CGI_CONNECTOR
|
||||
do
|
||||
create cgi.make (Current)
|
||||
cgi.launch
|
||||
end
|
||||
end
|
||||
|
||||
gateway_name: STRING = "CGI"
|
||||
|
||||
@@ -20,5 +20,5 @@ feature -- Access
|
||||
do
|
||||
(create {EXCEPTIONS}).die (a_code)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -1,14 +1,14 @@
|
||||
deferred class
|
||||
REST_APPLICATION_GATEWAY
|
||||
REST_SERVICE_GATEWAY
|
||||
|
||||
inherit
|
||||
WGI_APPLICATION
|
||||
WSF_SERVICE
|
||||
|
||||
feature -- Access
|
||||
|
||||
build_gateway_and_launch
|
||||
local
|
||||
libfcgi: EWF_LIBFCGI_CONNECTOR
|
||||
libfcgi: WGI_LIBFCGI_CONNECTOR
|
||||
do
|
||||
create libfcgi.make (Current)
|
||||
libfcgi.launch
|
||||
@@ -1,14 +1,14 @@
|
||||
deferred class
|
||||
REST_APPLICATION_GATEWAY
|
||||
REST_SERVICE_GATEWAY
|
||||
|
||||
inherit
|
||||
WGI_APPLICATION
|
||||
WSF_SERVICE
|
||||
|
||||
feature -- Access
|
||||
|
||||
build_gateway_and_launch
|
||||
local
|
||||
app: NINO_APPLICATION
|
||||
app: NINO_SERVICE
|
||||
port_number: INTEGER
|
||||
base_url: STRING
|
||||
do
|
||||
@@ -18,7 +18,7 @@ feature -- Access
|
||||
print ("Example: start a Nino web server on port " + port_number.out +
|
||||
", %Nand reply Hello World for any request such as http://localhost:" + port_number.out + "/" + base_url + "%N")
|
||||
end
|
||||
create app.make_custom (agent execute, base_url)
|
||||
create app.make_custom (agent wgi_execute, base_url)
|
||||
app.force_single_threaded
|
||||
|
||||
app.listen (port_number)
|
||||
@@ -23,7 +23,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
wgi_value_iteration_to_string (v: ITERABLE [WGI_VALUE]; using_pre: BOOLEAN): STRING_8
|
||||
wgi_value_iteration_to_string (v: ITERABLE [WSF_VALUE]; using_pre: BOOLEAN): STRING_8
|
||||
do
|
||||
create Result.make (100)
|
||||
if using_pre then
|
||||
@@ -32,7 +32,7 @@ feature {NONE} -- Implementation
|
||||
across
|
||||
v as cur
|
||||
loop
|
||||
Result.append_string (cur.item.name.as_string_8 + " = " + cur.item.as_string.as_string_8 + "%N")
|
||||
Result.append_string (cur.item.name.as_string_8 + " = " + cur.item.string_representation.as_string_8 + "%N")
|
||||
end
|
||||
if using_pre then
|
||||
Result.append ("</pre>")
|
||||
@@ -0,0 +1,26 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APP_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
@@ -9,7 +9,7 @@ deferred class
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
send_error (a_path: STRING; a_error_id: INTEGER; a_error_name: STRING; a_error_message: detachable STRING; ctx: APP_REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
send_error (a_path: STRING; a_error_id: INTEGER; a_error_name: STRING; a_error_message: detachable STRING; ctx: APP_REQUEST_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
s: STRING
|
||||
i,nb: INTEGER
|
||||
@@ -20,7 +20,7 @@ feature -- Helpers
|
||||
rep_data.headers.put_content_type_text_plain
|
||||
|
||||
create s.make_empty
|
||||
inspect ctx.format_id
|
||||
inspect ctx.accepted_format_id
|
||||
when {HTTP_FORMAT_CONSTANTS}.json then
|
||||
rep_data.headers.put_content_type_text_plain
|
||||
s := "{%"application%": %"" + a_path + "%""
|
||||
@@ -11,7 +11,8 @@ inherit
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTER_I [APP_REQUEST_HANDLER, APP_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
@@ -1,14 +1,14 @@
|
||||
note
|
||||
description: "Summary description for {APP_APPLICATION}."
|
||||
description: "Summary description for {APP_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
APP_APPLICATION
|
||||
APP_SERVICE
|
||||
|
||||
inherit
|
||||
REST_APPLICATION_I [APP_REQUEST_HANDLER, APP_REQUEST_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I [APP_REQUEST_HANDLER, APP_REQUEST_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
7
draft/library/text/filter/README.md
Normal file
7
draft/library/text/filter/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Support for various text filters such as
|
||||
|
||||
* [wikitext](http://en.wikipedia.org/wiki/Wiki_markup)
|
||||
* [Markdown](http://en.wikipedia.org/wiki/Markdown)
|
||||
* ...
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
7
draft/library/text/template/README.md
Normal file
7
draft/library/text/template/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
We could add libraries for template engines such as
|
||||
|
||||
* [Velocity](http://en.wikipedia.org/wiki/Apache_Velocity)
|
||||
* [Smarty](http://en.wikipedia.org/wiki/Smarty)
|
||||
* ...
|
||||
|
||||
Anyone wanting to contribute is welcome
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="hello_routed_world" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
||||
<target name="hello_routed_world">
|
||||
<root class="HELLO_ROUTED_WORLD" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
|
||||
<library name="default_nino" location="..\..\library\server\ewsgi\default\ewsgi_nino-safe.ecf" readonly="false"/>
|
||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
|
||||
<library name="uri_template" location="..\..\library\protocol\uri_template\uri_template-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,72 +0,0 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
RESTBUCK_CLIENT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
local
|
||||
h: LIBCURL_HTTP_CLIENT
|
||||
sess: HTTP_CLIENT_SESSION
|
||||
s: READABLE_STRING_8
|
||||
j: JSON_PARSER
|
||||
id: detachable STRING
|
||||
do
|
||||
create h.make
|
||||
sess := h.new_session ("http://127.0.0.1")
|
||||
s := "[
|
||||
{
|
||||
"location":"takeAway",
|
||||
"items":[
|
||||
{
|
||||
"name":"Late",
|
||||
"option":"skim",
|
||||
"size":"Small",
|
||||
"quantity":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]"
|
||||
|
||||
if attached sess.post ("/order", Void, s) as r then
|
||||
if attached r.body as m then
|
||||
create j.make_parser (m)
|
||||
|
||||
if j.is_parsed and attached j.parse_object as j_o then
|
||||
if attached {JSON_STRING} j_o.item ("id") as l_id then
|
||||
id := l_id.item
|
||||
end
|
||||
print (m)
|
||||
io.put_new_line
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if id /= Void and then attached sess.get ("/order/" + id, Void) as r then
|
||||
print (r.body)
|
||||
io.put_new_line
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
feature -- Access
|
||||
|
||||
feature -- Change
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
invariant
|
||||
-- invariant_clause: True
|
||||
|
||||
end
|
||||
@@ -1,51 +0,0 @@
|
||||
Restbuck Eiffel Implementation based on the book of REST in Practice
|
||||
|
||||
|
||||
Verb URI or template Use
|
||||
POST /order Create a new order, and upon success, receive a Locationheader specifying the new order<65>s URI.
|
||||
GET /order/{orderId} Request the current state of the order specified by the URI.
|
||||
PUT /order/{orderId} Update an order at the given URI with new information, providing the full representation.
|
||||
DELETE /order/{orderId} Logically remove the order identified by the given URI.
|
||||
|
||||
|
||||
How to Create an order
|
||||
|
||||
* Uri: http://localhost:8080/order
|
||||
* Method: POST
|
||||
* Note: you will get in the response the "location" of the new your order.
|
||||
* HEADERS:
|
||||
|
||||
Content-Type: application/json
|
||||
|
||||
* Example CONTENT
|
||||
|
||||
{
|
||||
"location":"takeAway",
|
||||
"items":[
|
||||
{
|
||||
"name":"Late",
|
||||
"option":"skim",
|
||||
"size":"Small",
|
||||
"quantity":1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
How to Read an order
|
||||
* Uri: http://localhost:8080/order/{order_id}
|
||||
* Method: GET
|
||||
|
||||
|
||||
|
||||
|
||||
How to Update an order
|
||||
* Uri: http://localhost:8080/order/{order_id}
|
||||
* Method: PUT
|
||||
|
||||
|
||||
How to Delete an order
|
||||
* Uri: http://localhost:8080/order/{order_id}
|
||||
* Method: DELETE
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {ORDER_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ORDER_HANDLER [C -> REQUEST_HANDLER_CONTEXT]
|
||||
inherit
|
||||
REQUEST_HANDLER [C]
|
||||
REQUEST_RESOURCE_HANDLER_HELPER [C]
|
||||
redefine
|
||||
do_get,
|
||||
do_post,
|
||||
do_put,
|
||||
do_delete
|
||||
end
|
||||
SHARED_DATABASE_API
|
||||
SHARED_EJSON
|
||||
REFACTORING_HELPER
|
||||
SHARED_ORDER_VALIDATION
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- API DOC
|
||||
|
||||
api_doc : STRING = "URI:/order METHOD: POST%N URI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
-- Using GET to retrieve resource information.
|
||||
-- If the GET request is SUCCESS, we response with
|
||||
-- 200 OK, and a representation of the order
|
||||
-- If the GET request is not SUCCESS, we response with
|
||||
-- 404 Resource not found
|
||||
local
|
||||
id : STRING
|
||||
do
|
||||
if attached req.orig_path_info as orig_path then
|
||||
id := get_order_id_from_path (orig_path)
|
||||
if attached retrieve_order (id) as l_order then
|
||||
compute_response_get (ctx, req, res, l_order)
|
||||
else
|
||||
handle_resource_not_found_response ("The following resource" + orig_path + " is not found ", ctx, req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
compute_response_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER)
|
||||
local
|
||||
h: EWF_HEADER
|
||||
l_msg : STRING
|
||||
do
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.ok)
|
||||
h.put_content_type_application_json
|
||||
if attached {JSON_VALUE} json.value (l_order) as jv then
|
||||
l_msg := jv.representation
|
||||
h.put_content_length (l_msg.count)
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" + time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
end
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (l_msg)
|
||||
end
|
||||
end
|
||||
|
||||
do_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
local
|
||||
l_post: STRING
|
||||
l_location : STRING
|
||||
l_order : detachable ORDER
|
||||
h : EWF_HEADER
|
||||
do
|
||||
fixme ("TODO handle an Internal Server Error")
|
||||
fixme ("Refactor the code, create new abstractions")
|
||||
fixme ("Add Header Date to the response")
|
||||
fixme ("Put implementation is wrong!!!!")
|
||||
req.input.read_stream (req.content_length_value.as_integer_32)
|
||||
l_post := req.input.last_string
|
||||
l_order := extract_order_request(l_post)
|
||||
fixme ("TODO move to a service method")
|
||||
if l_order /= Void and then db_access.orders.has_key (l_order.id) then
|
||||
update_order( l_order)
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.ok)
|
||||
h.put_content_type ("application/json")
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
end
|
||||
if attached req.http_host as host then
|
||||
l_location := "http://"+host +req.request_uri+"/" + l_order.id
|
||||
h.add_header ("Location:"+ l_location)
|
||||
end
|
||||
if attached {JSON_VALUE} json.value (l_order) as jv then
|
||||
h.put_content_length (jv.representation.count)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (jv.representation)
|
||||
end
|
||||
else
|
||||
handle_bad_request_response (l_post +"%N is not a valid ORDER, maybe the order does not exist in the system", ctx, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
do_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
local
|
||||
id: STRING
|
||||
h : EWF_HEADER
|
||||
do
|
||||
fixme ("TODO handle an Internal Server Error")
|
||||
fixme ("Refactor the code, create new abstractions")
|
||||
if attached req.orig_path_info as orig_path then
|
||||
id := get_order_id_from_path (orig_path)
|
||||
if db_access.orders.has_key (id) then
|
||||
delete_order( id)
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.no_content)
|
||||
h.put_content_type ("application/json")
|
||||
if attached req.request_time as time then
|
||||
h.put_utc_date (time)
|
||||
end
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.no_content)
|
||||
res.write_headers_string (h.string)
|
||||
else
|
||||
handle_resource_not_found_response (orig_path + " not found in this server", ctx, req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
-- Here the convention is the following.
|
||||
-- POST is used for creation and the server determines the URI
|
||||
-- of the created resource.
|
||||
-- If the request post is SUCCESS, the server will create the order and will response with
|
||||
-- HTTP_RESPONSE 201 CREATED, the Location header will contains the newly created order's URI
|
||||
-- if the request post is not SUCCESS, the server will response with
|
||||
-- HTTP_RESPONSE 400 BAD REQUEST, the client send a bad request
|
||||
-- HTTP_RESPONSE 500 INTERNAL_SERVER_ERROR, when the server can deliver the request
|
||||
local
|
||||
l_post: STRING
|
||||
do
|
||||
req.input.read_stream (req.content_length_value.as_integer_32)
|
||||
l_post := req.input.last_string
|
||||
if attached extract_order_request (l_post) as l_order then
|
||||
save_order (l_order)
|
||||
compute_response_post (ctx, req, res, l_order)
|
||||
else
|
||||
handle_bad_request_response (l_post +"%N is not a valid ORDER", ctx, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
compute_response_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER)
|
||||
local
|
||||
h: EWF_HEADER
|
||||
l_msg : STRING
|
||||
l_location : STRING
|
||||
joc : JSON_ORDER_CONVERTER
|
||||
do
|
||||
create h.make
|
||||
|
||||
create joc.make
|
||||
json.add_converter(joc)
|
||||
|
||||
h.put_status ({HTTP_STATUS_CODE}.created)
|
||||
h.put_content_type_application_json
|
||||
if attached {JSON_VALUE} json.value (l_order) as jv then
|
||||
l_msg := jv.representation
|
||||
h.put_content_length (l_msg.count)
|
||||
if attached req.http_host as host then
|
||||
l_location := "http://" + host + req.request_uri + "/" + l_order.id
|
||||
h.put_location (l_location)
|
||||
end
|
||||
if attached req.request_time as time then
|
||||
h.put_utc_date (time)
|
||||
end
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.created)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (l_msg)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- URI helper methods
|
||||
|
||||
get_order_id_from_path (a_path: READABLE_STRING_32) : STRING
|
||||
do
|
||||
Result := a_path.split ('/').at (3)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation Repository Layer
|
||||
|
||||
retrieve_order ( id : STRING) : detachable ORDER
|
||||
-- get the order by id if it exist, in other case, Void
|
||||
do
|
||||
Result := db_access.orders.item (id)
|
||||
end
|
||||
|
||||
save_order (an_order: ORDER)
|
||||
-- save the order to the repository
|
||||
local
|
||||
i : INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
not db_access.orders.has_key ((db_access.orders.count + i).out)
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
an_order.set_id ((db_access.orders.count + i).out)
|
||||
an_order.set_status ("submitted")
|
||||
an_order.add_revision
|
||||
db_access.orders.force (an_order, an_order.id)
|
||||
end
|
||||
|
||||
update_order (an_order: ORDER)
|
||||
-- update the order to the repository
|
||||
do
|
||||
an_order.add_revision
|
||||
db_access.orders.force (an_order, an_order.id)
|
||||
end
|
||||
|
||||
delete_order (an_order: STRING)
|
||||
-- update the order to the repository
|
||||
do
|
||||
db_access.orders.remove (an_order)
|
||||
end
|
||||
|
||||
extract_order_request (l_post : STRING) : detachable ORDER
|
||||
-- extract an object Order from the request, or Void
|
||||
-- if the request is invalid
|
||||
local
|
||||
parser : JSON_PARSER
|
||||
joc : JSON_ORDER_CONVERTER
|
||||
do
|
||||
create joc.make
|
||||
json.add_converter(joc)
|
||||
create parser.make_parser (l_post)
|
||||
if attached parser.parse as jv and parser.is_parsed then
|
||||
Result ?= json.object (jv, "ORDER")
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
11
examples/restbucksCRUD/client/README.txt
Normal file
11
examples/restbucksCRUD/client/README.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Make sure to have the Clib generated in the related cURL library
|
||||
|
||||
- if you use EiffelStudio >= 7.0
|
||||
check %ISE_LIBRARY%\library\cURL\spec\%ISE_C_COMPILER%\$ISE_PLATFORM
|
||||
or $ISE_LIBRARY/library/cURL/spec/$ISE_PLATFORM
|
||||
|
||||
- otherwise if you use earlier version
|
||||
check under ext/ise_library/curl/spec/...
|
||||
|
||||
And on Windows, be sure to get the libcurl.dll from %ISE_LIBRARY%\studio\spec\%ISE_PLATFORM%\bin\libcurl.dll
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="http_client" location="..\..\..\library\client\http_client\http_client-safe.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\..\ext\text\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
@@ -11,7 +11,7 @@
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="http_client" location="..\..\..\library\client\http_client\http_client.ecf"/>
|
||||
<library name="json" location="..\..\..\ext\text\json\library\json.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\..\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<library name="thread" location="$ISE_LIBRARY/library/thread/thread.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
152
examples/restbucksCRUD/client/src/restbuck_client.e
Normal file
152
examples/restbucksCRUD/client/src/restbuck_client.e
Normal file
@@ -0,0 +1,152 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
RESTBUCK_CLIENT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
local
|
||||
h: LIBCURL_HTTP_CLIENT
|
||||
sess: HTTP_CLIENT_SESSION
|
||||
resp : HTTP_CLIENT_RESPONSE
|
||||
l_location : detachable READABLE_STRING_8
|
||||
body : STRING
|
||||
do
|
||||
create h.make
|
||||
sess := h.new_session ("http://127.0.0.1:9090")
|
||||
|
||||
-- Create Order
|
||||
print ("%N Create Order %N")
|
||||
resp := create_order (sess)
|
||||
|
||||
|
||||
-- Read the Order
|
||||
print ("%N Read Order %N")
|
||||
l_location := resp.header ("Location")
|
||||
resp := read_order (sess, l_location)
|
||||
|
||||
|
||||
-- Update the Order
|
||||
if attached resp.body as l_body then
|
||||
body := l_body.as_string_8
|
||||
body.replace_substring_all ("takeAway", "in Shop")
|
||||
print ("%N Update Order %N")
|
||||
resp := update_order (sess, l_location, body)
|
||||
end
|
||||
end
|
||||
|
||||
update_order ( sess: HTTP_CLIENT_SESSION; uri : detachable READABLE_STRING_8; a_body : STRING) : HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
context : HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
create Result.make
|
||||
if attached uri as l_uri then
|
||||
sess.set_base_url (l_uri)
|
||||
create context.make
|
||||
context.headers.put ("application/json", "Content-Type")
|
||||
Result := sess.put ("", context, a_body )
|
||||
-- Show headers
|
||||
across
|
||||
Result.headers as l_headers
|
||||
loop
|
||||
print (l_headers.item.name)
|
||||
print (":")
|
||||
print (l_headers.item.value)
|
||||
io.put_new_line
|
||||
end
|
||||
|
||||
-- Show body
|
||||
print (Result.body)
|
||||
io.put_new_line
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
read_order ( sess: HTTP_CLIENT_SESSION; uri : detachable READABLE_STRING_8) : HTTP_CLIENT_RESPONSE
|
||||
do
|
||||
create Result.make
|
||||
if attached uri as l_uri then
|
||||
sess.set_base_url (l_uri)
|
||||
Result := sess.get ("", Void)
|
||||
-- Show headers
|
||||
across
|
||||
Result.headers as l_headers
|
||||
loop
|
||||
print (l_headers.item.name)
|
||||
print (":")
|
||||
print (l_headers.item.value)
|
||||
io.put_new_line
|
||||
end
|
||||
|
||||
-- Show body
|
||||
print (Result.body)
|
||||
io.put_new_line
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
create_order (sess: HTTP_CLIENT_SESSION) : HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
s: READABLE_STRING_8
|
||||
j: JSON_PARSER
|
||||
id: detachable STRING
|
||||
context : HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
s := "[
|
||||
{
|
||||
"location":"takeAway",
|
||||
"items":[
|
||||
{
|
||||
"name":"Late",
|
||||
"option":"skim",
|
||||
"size":"Small",
|
||||
"quantity":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]"
|
||||
|
||||
create context.make
|
||||
context.headers.put ("application/json", "Content-Type")
|
||||
Result := sess.post ("/order", context, s)
|
||||
-- Show the Headers
|
||||
across
|
||||
Result.headers as l_headers
|
||||
loop
|
||||
print (l_headers.item.name)
|
||||
print (":")
|
||||
print (l_headers.item.value)
|
||||
io.put_new_line
|
||||
end
|
||||
|
||||
|
||||
-- Show the Response body
|
||||
if attached Result.body as m then
|
||||
create j.make_parser (m)
|
||||
if j.is_parsed and attached j.parse_object as j_o then
|
||||
if attached {JSON_STRING} j_o.item ("id") as l_id then
|
||||
id := l_id.item
|
||||
end
|
||||
print (m)
|
||||
io.put_new_line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
invariant
|
||||
-- invariant_clause: True
|
||||
|
||||
end
|
||||
293
examples/restbucksCRUD/readme.md
Normal file
293
examples/restbucksCRUD/readme.md
Normal file
@@ -0,0 +1,293 @@
|
||||
Restbuck Eiffel Implementation based on the book of REST in Practice
|
||||
====================================================================
|
||||
This is an implementation of CRUD pattern for manipulate resources, this is the first step to use
|
||||
the HTTP protocol as an application protocol instead of a transport protocol.
|
||||
|
||||
Restbuck Protocol
|
||||
-----------------
|
||||
|
||||
<table>
|
||||
<TR><TH>Verb</TH> <TH>URI or template</TH> <TH>Use</TH></TR>
|
||||
<TR><TD>POST</TD> <TD>/order</TD> <TD>Create a new order, and upon success, receive a Locationheader specifying the new order's URI.</TD></TR>
|
||||
<TR><TD>GET</TD> <TD>/order/{orderId}</TD> <TD>Request the current state of the order specified by the URI.</TD></TR>
|
||||
<TR><TD>PUT</TD> <TD>/order/{orderId}</TD> <TD>Update an order at the given URI with new information, providing the full representation.</TD></TR>
|
||||
<TR><TD>DELETE</TD> <TD>/order/{orderId}</TD> <TD>Logically remove the order identified by the given URI.</TD></TR>
|
||||
</table>
|
||||
|
||||
Resource Represenation
|
||||
----------------------
|
||||
The previous tables shows a contrat, the URI or URI template, allows us to indentify resources, now we will chose a
|
||||
representacion, for this particular case we will use JSON.
|
||||
|
||||
Note: <br/>
|
||||
1. *A resource can have multiple URIs*.<br/>
|
||||
2. *A resource can have multiple Representations*.<br/>
|
||||
|
||||
RESTBUCKS_SERVER
|
||||
----------------
|
||||
This class implement the main entry of our REST CRUD service, we are using a default connector (Nino Connector,
|
||||
using a WebServer written in Eiffel).
|
||||
We are inheriting from URI_TEMPLATE_ROUTED_SERVICE, this allows us to map our service contrat, as is shown in the previous
|
||||
table, the mapping is defined in the feature setup_router, this also show that the class ORDER_HANDLER will be encharge
|
||||
of to handle different type of request to the ORDER resource.
|
||||
|
||||
|
||||
class
|
||||
RESTBUCKS_SERVER
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
URI_TEMPLATE_ROUTED_SERVICE
|
||||
|
||||
DEFAULT_SERVICE
|
||||
-- Here we are using a default connector using the default Nino Connector,
|
||||
-- but it's possible to use other connector (CGI or FCGI).
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize the router (this will have the request handler and
|
||||
-- their context).
|
||||
do
|
||||
initialize_router
|
||||
make_and_launch
|
||||
end
|
||||
|
||||
create_router
|
||||
do
|
||||
create router.make (2)
|
||||
end
|
||||
|
||||
setup_router
|
||||
local
|
||||
order_handler: ORDER_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
do
|
||||
create order_handler
|
||||
router.map_with_request_methods ("/order", order_handler, <<"POST">>)
|
||||
router.map_with_request_methods ("/order/{orderid}", order_handler, <<"GET", "DELETE", "PUT">>)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- I'm using this method to handle the method not allowed response
|
||||
-- in the case that the given uri does not have a corresponding http method
|
||||
-- to handle it.
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
l_description : STRING
|
||||
l_api_doc : STRING
|
||||
do
|
||||
if req.content_length_value > 0 then
|
||||
req.input.read_string (req.content_length_value.as_integer_32)
|
||||
end
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.method_not_allowed)
|
||||
h.put_content_type_text_plain
|
||||
l_api_doc := "%NPlease check the API%NURI:/order METHOD: POST%NURI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
|
||||
l_description := req.request_method + req.request_uri + " is not allowed" + "%N" + l_api_doc
|
||||
h.put_content_length (l_description.count)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed)
|
||||
res.write_header_text (h.string)
|
||||
res.write_string (l_description)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
How to Create an order with POST
|
||||
--------------------------------
|
||||
|
||||
Here is the convention that we are using:
|
||||
POST is used for creation and the server determines the URI of the created resource.
|
||||
If the request POST is SUCCESS, the server will create the order and will response with
|
||||
201 CREATED, the Location header will contains the newly created order's URI,
|
||||
if the request POST is not SUCCESS, the server will response with
|
||||
400 BAD REQUEST, the client send a bad request or
|
||||
500 INTERNAL_SERVER_ERROR, when the server can deliver the request.
|
||||
|
||||
POST /order HTTP/1.1
|
||||
Host: 127.0.0.1:8080
|
||||
Connection: keep-alive
|
||||
Content-Length: 196
|
||||
Origin: chrome-extension://fhjcajmcbmldlhcimfajhfbgofnpcjmb
|
||||
Content-Type: application/json
|
||||
Accept: */*
|
||||
Accept-Encoding: gzip,deflate,sdch
|
||||
Accept-Language: es-419,es;q=0.8,en;q=0.6
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
|
||||
|
||||
{
|
||||
"location":"takeAway",
|
||||
"items":[
|
||||
{
|
||||
"name":"Late",
|
||||
"option":"skim",
|
||||
"size":"Small",
|
||||
"quantity":1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Response success
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Status 201 Created
|
||||
Content-Type application/json
|
||||
Content-Length 123
|
||||
Location http://localhost:8080/order/1
|
||||
Date FRI,09 DEC 2011 20:34:20.00 GMT
|
||||
|
||||
{
|
||||
"location" : "takeAway",
|
||||
"status" : "submitted",
|
||||
"items" : [ {
|
||||
"name" : "late",
|
||||
"size" : "small",
|
||||
"quantity" : 1,
|
||||
"option" : "skim"
|
||||
} ]
|
||||
}
|
||||
|
||||
|
||||
How to Read an order with GET
|
||||
-----------------------------
|
||||
Using GET to retrieve resource information.
|
||||
If the GET request is SUCCESS, we response with 200 OK, and a representation of the order
|
||||
If the GET request is not SUCCESS, we response with 404 Resource not found
|
||||
If is a Conditional GET and the resource does not change we send a 304, Resource not modifed
|
||||
|
||||
GET /order/1 HTTP/1.1
|
||||
Host: 127.0.0.1:8080
|
||||
Connection: keep-alive
|
||||
Accept: */*
|
||||
Accept-Encoding: gzip,deflate,sdch
|
||||
Accept-Language: es-419,es;q=0.8,en;q=0.6
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
|
||||
If-None-Match: 6542EF270D91D3EAF39CFB382E4CEBA7
|
||||
|
||||
Response
|
||||
HTTP/1.1 200 OK
|
||||
|
||||
Status 200 OK
|
||||
Content-Type application/json
|
||||
Content-Length 123
|
||||
Date FRI,09 DEC 2011 20:53:46.00 GMT
|
||||
etag 2ED3A40954A95D766FC155682DC8BB52
|
||||
|
||||
{
|
||||
"location" : "takeAway",
|
||||
"status" : "submitted",
|
||||
"items" : [ {
|
||||
"name" : "late",
|
||||
"size" : "small",
|
||||
"quantity" : 1,
|
||||
"option" : "skim"
|
||||
} ]
|
||||
}
|
||||
|
||||
|
||||
|
||||
How to Update an order with PUT
|
||||
-------------------------------
|
||||
A successful PUT request will not create a new resource, instead it will change the state of the resource identified by the current uri.
|
||||
If success we response with 200 and the updated order.
|
||||
404 if the order is not found
|
||||
400 in case of a bad request
|
||||
500 internal server error
|
||||
If the request is a Conditional PUT, and it does not mat we response 415, precondition failed.
|
||||
|
||||
Suposse that we had created an Order with the values shown in the _How to create an order with POST_
|
||||
But we change our decision and we want to stay in the shop.
|
||||
|
||||
|
||||
|
||||
PUT /order/1 HTTP/1.1
|
||||
Content-Length: 122
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
Host: localhost:8080
|
||||
Connection: Keep-Alive
|
||||
Expect: 100-Continue
|
||||
|
||||
{
|
||||
"location" : "in shop",
|
||||
"status" : "submitted",
|
||||
"items" : [ {
|
||||
"name" : "late",
|
||||
"size" : "small",
|
||||
"quantity" : 1,
|
||||
"option" : "skim"
|
||||
} ]
|
||||
}
|
||||
|
||||
|
||||
Response success
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Status 200 OK
|
||||
Content-Type application/json
|
||||
Date FRI,09 DEC 2011 21:06:26.00 GMT
|
||||
etag 8767F900674B843E1F3F70BCF3E62403
|
||||
Content-Length 122
|
||||
|
||||
{
|
||||
"location" : "in shop",
|
||||
"status" : "submitted",
|
||||
"items" : [ {
|
||||
"name" : "late",
|
||||
"size" : "small",
|
||||
"quantity" : 1,
|
||||
"option" : "skim"
|
||||
} ]
|
||||
}
|
||||
|
||||
How to Delete an order with DELETE
|
||||
----------------------------------
|
||||
Here we use DELETE to cancel an order, if that order is in state where it can still be canceled.
|
||||
204 if is ok
|
||||
404 Resource not found
|
||||
405 if consumer and service's view of the resouce state is inconsisent
|
||||
500 if we have an internal server error
|
||||
|
||||
|
||||
DELETE /order/1 HTTP/1.1
|
||||
Host: localhost:8080
|
||||
Connection: Keep-Alive
|
||||
|
||||
Response success
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
|
||||
Status 204 No Content
|
||||
Content-Type application/json
|
||||
Date FRI,09 DEC 2011 21:10:51.00 GMT
|
||||
|
||||
If we want to check that the resource does not exist anymore we can try to retrieve a GET /order/1 and we will receive a
|
||||
404 No Found
|
||||
|
||||
GET /order/1 HTTP/1.1
|
||||
Host: localhost:8080
|
||||
Connection: Keep-Alive
|
||||
|
||||
Response
|
||||
|
||||
HTTP/1.1 404 Not Found
|
||||
|
||||
Status 404 Not Found
|
||||
Content-Type application/json
|
||||
Content-Length 44
|
||||
Date FRI,09 DEC 2011 21:14:17.79 GMT
|
||||
|
||||
The following resource/order/1 is not found
|
||||
|
||||
|
||||
References
|
||||
----------
|
||||
1. [How to get a cup of coffe](http://www.infoq.com/articles/webber-rest-workflow)
|
||||
2. [Rest in Practice] (http://restinpractice.com/default.aspx)
|
||||
0
examples/restbucksCRUD/readme.txt
Normal file
0
examples/restbucksCRUD/readme.txt
Normal file
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
||||
<target name="restbucks">
|
||||
<root class="RESTBUCKS_SERVER" feature="make"/>
|
||||
<file_rule>
|
||||
@@ -7,19 +7,24 @@
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<debug name="nino" enabled="true"/>
|
||||
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
|
||||
<library name="default_nino" location="..\..\library\server\ewsgi\default\ewsgi_nino-safe.ecf" readonly="false"/>
|
||||
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false">
|
||||
<option debug="true">
|
||||
<debug name="nino" enabled="true"/>
|
||||
</option>
|
||||
</library>
|
||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="false"/>
|
||||
<library name="eel" location="..\..\library\crypto\eel\eel-safe.ecf" readonly="false"/>
|
||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\ext\text\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="uri_template" location="..\..\library\protocol\uri_template\uri_template-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -38,7 +38,7 @@ feature -- Conversion
|
||||
s_location ?= json.object (j.item (location_key), Void)
|
||||
s_status ?= json.object (j.item (status_key), Void)
|
||||
|
||||
create o.make (s_id, s_location, s_status)
|
||||
create o.make ("", s_location, s_status)
|
||||
|
||||
if attached {JSON_ARRAY} j.item (items_key) as l_val then
|
||||
l_array := l_val.array_representation
|
||||
@@ -87,7 +87,7 @@ feature -- Conversion
|
||||
jv: JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.id), id_key)
|
||||
-- Result.put (json.value (o.id), id_key)
|
||||
Result.put (json.value (o.location), location_key)
|
||||
Result.put (json.value (o.status), status_key)
|
||||
from
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user