diff --git a/examples/obsolete/README.md b/examples/obsolete/README.md
deleted file mode 100644
index 9b612771..00000000
--- a/examples/obsolete/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Obsolete example based on EWF v0
-================================
-
-Those examples are using the old EWF v0 interface, including use of deprecated "nino" connector.
-They serves as example for existing project based on EWF v0, but willing to use latest EiffelStudio, and latest EWF repository.
-
diff --git a/examples/obsolete/v0/filter/filter.ecf b/examples/obsolete/v0/filter/filter.ecf
deleted file mode 100644
index 5b26d48d..00000000
--- a/examples/obsolete/v0/filter/filter.ecf
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- /EIFGENs$
- /\.git$
- /\.svn$
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/obsolete/v0/filter/license.lic b/examples/obsolete/v0/filter/license.lic
deleted file mode 100644
index 73a78070..00000000
--- a/examples/obsolete/v0/filter/license.lic
+++ /dev/null
@@ -1,4 +0,0 @@
-${NOTE_KEYWORD}
- copyright: "2011-${YEAR}, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-
diff --git a/examples/obsolete/v0/filter/readme.md b/examples/obsolete/v0/filter/readme.md
deleted file mode 100644
index b1a43c03..00000000
--- a/examples/obsolete/v0/filter/readme.md
+++ /dev/null
@@ -1,4 +0,0 @@
-Filter example
-
-To test the example, you can just run in a terminal:
-> curl -u foo:bar http://localhost:9090/user/1 -v
diff --git a/examples/obsolete/v0/filter/src/database/database_api.e b/examples/obsolete/v0/filter/src/database/database_api.e
deleted file mode 100644
index 4c0024c0..00000000
--- a/examples/obsolete/v0/filter/src/database/database_api.e
+++ /dev/null
@@ -1,57 +0,0 @@
-note
- description: "Summary description for {DATABASE_API}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- DATABASE_API
-create
- make
-
-feature -- Initialization
-
- make
- local
- l_user: USER
- do
- create users.make (10)
- create l_user.make (1, "foo", "bar")
- users.put (l_user, l_user.id)
- create l_user.make (2, "demo", "demo")
- users.put (l_user, l_user.id)
- end
-
-feature -- Access
-
- user (a_id: INTEGER; a_name: detachable READABLE_STRING_GENERAL): detachable USER
- -- User with id `a_id' or name `a_name'.
- require
- a_id > 0 xor a_name /= Void
- local
- n: like {USER}.name
- do
- if a_id > 0 then
- Result := users.item (a_id)
- elseif a_name /= Void then
- n := a_name.as_string_8
- across
- users as c
- until
- Result /= Void
- loop
- if attached c.item as u and then u.name.same_string (n) then
- Result := u
- end
- end
- end
- ensure
- Result /= Void implies ((a_id > 0 and then Result.id = a_id) xor (a_name /= Void and then Result.name.same_string_general (a_name)))
- end
-
- users: HASH_TABLE [USER, INTEGER]
-
-;note
- copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/filter/src/database/shared_database_api.e b/examples/obsolete/v0/filter/src/database/shared_database_api.e
deleted file mode 100644
index 10ad5dff..00000000
--- a/examples/obsolete/v0/filter/src/database/shared_database_api.e
+++ /dev/null
@@ -1,20 +0,0 @@
-note
- description: "Summary description for {SHARED_DATABASE_API}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- SHARED_DATABASE_API
-
-feature -- Access
-
- db_access: DATABASE_API
- once
- create Result.make
- end
-
-note
- copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/filter/src/domain/json_user_converter.e b/examples/obsolete/v0/filter/src/domain/json_user_converter.e
deleted file mode 100644
index 34800625..00000000
--- a/examples/obsolete/v0/filter/src/domain/json_user_converter.e
+++ /dev/null
@@ -1,52 +0,0 @@
-note
- description: "JSON user converter."
- author: "Olivier Ligot"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- JSON_USER_CONVERTER
-
-inherit
- JSON_CONVERTER
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make
- do
- create object.make (0, "", "")
- end
-
-feature -- Access
-
- object: USER
-
- value: detachable JSON_OBJECT
-
-feature -- Conversion
-
- from_json (j: attached like value): detachable like object
- -- Convert from JSON value.
- do
- end
-
- to_json (o: like object): like value
- -- Convert to JSON value.
- do
- create Result.make
- Result.put (json.value (o.id), id_key)
- Result.put (json.value (o.name), name_key)
- end
-
- feature {NONE} -- Implementation
-
- id_key: STRING = "id"
- name_key: STRING = "name"
-
-note
- copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/filter/src/domain/user.e b/examples/obsolete/v0/filter/src/domain/user.e
deleted file mode 100644
index 0ad70f2c..00000000
--- a/examples/obsolete/v0/filter/src/domain/user.e
+++ /dev/null
@@ -1,59 +0,0 @@
-note
- description: "User."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- USER
-
-inherit
- ANY
- redefine
- is_equal
- end
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make (an_id: INTEGER; a_name, a_password: STRING)
- do
- id := an_id
- name := a_name
- password := a_password
- ensure
- id_set: id = an_id
- name_set: name = a_name
- password_set: password = a_password
- end
-
-feature -- Access
-
- id: INTEGER
- -- Identifier
-
- name: STRING
- -- Name
-
- password: STRING
- -- Password
-
-feature -- Comparison
-
- is_equal (other: like Current): BOOLEAN
- -- Is `other' attached to an object considered
- -- equal to current object?
- do
- if Current = other then
- Result := True
- else
- Result := (id = other.id) and (name = other.name) and (password = other.password)
- end
- end
-
-;note
- copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/filter/src/filter/authentication_filter.e b/examples/obsolete/v0/filter/src/filter/authentication_filter.e
deleted file mode 100644
index c3bf8ae3..00000000
--- a/examples/obsolete/v0/filter/src/filter/authentication_filter.e
+++ /dev/null
@@ -1,65 +0,0 @@
-note
- description: "Authentication filter."
- author: "Olivier Ligot"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- AUTHENTICATION_FILTER
-
-inherit
- WSF_FILTER
-
- WSF_URI_TEMPLATE_HANDLER
-
- SHARED_DATABASE_API
-
- SHARED_EJSON
-
-feature -- Basic operations
-
- execute (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Execute the filter
- local
- l_auth: detachable HTTP_AUTHORIZATION
- do
- if attached req.http_authorization as l_http_authorization then
- create l_auth.make (l_http_authorization)
- end
- if
- l_auth /= Void and then
- l_auth.is_basic and then
- attached l_auth.login as l_auth_login and then
- attached Db_access.user (0, l_auth_login) as l_user and then
- l_auth_login.same_string (l_user.name) and then
- attached l_auth.password as l_auth_password and then
- l_auth_password.same_string (l_user.password)
- then
- req.set_execution_variable ("user", l_user)
- execute_next (req, res)
- else
- handle_unauthorized ("Unauthorized", req, res)
- end
- end
-
-feature {NONE} -- Implementation
-
- handle_unauthorized (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Handle forbidden.
- local
- h: HTTP_HEADER
- do
- create h.make
- h.put_content_type_text_plain
- h.put_content_length (a_description.count)
- h.put_current_date
- h.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, "Basic realm=%"User%"")
- res.set_status_code ({HTTP_STATUS_CODE}.unauthorized)
- res.put_header_text (h.string)
- res.put_string (a_description)
- end
-
-note
- copyright: "2011-2014, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/filter/src/filter/filter_handler_context.e b/examples/obsolete/v0/filter/src/filter/filter_handler_context.e
deleted file mode 100644
index a4f5a448..00000000
--- a/examples/obsolete/v0/filter/src/filter/filter_handler_context.e
+++ /dev/null
@@ -1,34 +0,0 @@
-note
- description: "Summary description for {FILTER_HANDLER_CONTEXT}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- FILTER_HANDLER_CONTEXT
-
-inherit
- WSF_HANDLER_CONTEXT
-
-create
- make
-
-feature -- Access
-
- user: detachable USER
- -- Authenticated user
-
-feature -- Element change
-
- set_user (a_user: USER)
- -- Set `user' to `a_user'
- do
- user := a_user
- ensure
- user_set: user = a_user
- end
-
-note
- copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/filter/src/filter_server.e b/examples/obsolete/v0/filter/src/filter_server.e
deleted file mode 100644
index 3c7de0a3..00000000
--- a/examples/obsolete/v0/filter/src/filter_server.e
+++ /dev/null
@@ -1,111 +0,0 @@
-note
- description : "Filter example."
- author : "Olivier Ligot"
- date : "$Date$"
- revision : "$Revision$"
-
-class
- FILTER_SERVER
-
-inherit
- ANY
-
- WSF_DEFAULT_SERVICE
-
- WSF_ROUTED_SERVICE
- undefine
- execute
- end
-
- WSF_FILTERED_SERVICE
-
- SHARED_EJSON
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make
- local
- l_message: STRING
- l_factory: INET_ADDRESS_FACTORY
- do
- initialize_router
- initialize_filter
- initialize_json
- set_service_option ("port", port)
- create l_message.make_empty
- l_message.append_string ("Launching filter server at ")
- create l_factory
- l_message.append_string (l_factory.create_localhost.host_name)
- l_message.append_string (" port ")
- l_message.append_integer (port)
- io.put_string (l_message)
- io.put_new_line
- make_and_launch
- end
-
- create_filter
- -- Create `filter'
- do
- create {WSF_CORS_FILTER} filter
- end
-
- setup_filter
- -- Setup `filter'
- local
- l_routing_filter: WSF_ROUTING_FILTER
- l_logging_filter: WSF_LOGGING_FILTER
- do
- create l_routing_filter.make (router)
- l_routing_filter.set_execute_default_action (agent execute_default)
- filter.set_next (l_routing_filter)
-
- create l_logging_filter
- l_routing_filter.set_next (l_logging_filter)
- end
-
- setup_router
- -- Setup `router'
- local
- l_options_filter: WSF_CORS_OPTIONS_FILTER
- l_authentication_filter: AUTHENTICATION_FILTER
- l_user_filter: USER_HANDLER
- l_methods: WSF_REQUEST_METHODS
- do
- create l_options_filter.make (router)
- create l_authentication_filter
- create l_user_filter
-
- l_options_filter.set_next (l_authentication_filter)
- l_authentication_filter.set_next (l_user_filter)
-
- create l_methods
- l_methods.enable_options
- l_methods.enable_get
- router.handle ("/user/{userid}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent l_options_filter.execute), l_methods)
- end
-
- initialize_json
- -- Initialize `json'.
- do
- json.add_converter (create {JSON_USER_CONVERTER}.make)
- end
-
-feature {NONE} -- Implementation
-
- port: INTEGER = 9090
- -- Port number
-
-note
- copyright: "2011-2017, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/examples/obsolete/v0/filter/src/resource/user_handler.e b/examples/obsolete/v0/filter/src/resource/user_handler.e
deleted file mode 100644
index bf20bec3..00000000
--- a/examples/obsolete/v0/filter/src/resource/user_handler.e
+++ /dev/null
@@ -1,97 +0,0 @@
-note
- description: "User handler."
- author: "Olivier Ligot"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- USER_HANDLER
-
-inherit
- WSF_FILTER
-
- WSF_URI_TEMPLATE_HANDLER
-
- WSF_RESOURCE_HANDLER_HELPER
- redefine
- do_get
- end
-
- SHARED_DATABASE_API
-
- SHARED_EJSON
-
-feature -- Basic operations
-
- execute (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Execute request handler
- do
- execute_methods (req, res)
- execute_next (req, res)
- end
-
- do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Using GET to retrieve resource information.
- -- If the GET request is SUCCESS, we response with
- -- 200 OK, and a representation of the user
- -- If the GET request is not SUCCESS, we response with
- -- 404 Resource not found
- require else
- authenticated_user_attached: attached {USER} req.execution_variable ("user")
- local
- id : STRING
- do
- if attached req.orig_path_info as orig_path then
- id := get_user_id_from_path (orig_path.as_string_32)
- if attached retrieve_user (id) as l_user then
- if l_user ~ req.execution_variable ("user") then
- compute_response_get (req, res, l_user)
- elseif attached {USER} req.execution_variable ("user") as l_auth_user then
- -- Trying to access another user that the authenticated one,
- -- which is forbidden in this example...
- handle_forbidden ("You try to access the user " + id.out + " while authenticating with the user " + l_auth_user.id.out, req, res)
- end
- else
- handle_resource_not_found_response ("The following resource " + orig_path + " is not found ", req, res)
- end
- end
- end
-
-feature {NONE} -- Implementation
-
- compute_response_get (req: WSF_REQUEST; res: WSF_RESPONSE; l_user : USER)
- local
- h: HTTP_HEADER
- l_msg : STRING
- do
- create h.make
- h.put_content_type_application_json
- if attached {JSON_VALUE} json.value (l_user) as jv then
- l_msg := jv.representation
- h.put_content_length (l_msg.count)
- if attached req.request_time as time then
- h.put_utc_date (time)
- end
- res.set_status_code ({HTTP_STATUS_CODE}.ok)
- res.put_header_text (h.string)
- res.put_string (l_msg)
- end
- end
-
- get_user_id_from_path (a_path: READABLE_STRING_32): STRING
- do
- Result := a_path.split ('/').at (3)
- end
-
- retrieve_user (id: STRING) : detachable USER
- -- Retrieve the user by id if it exist, in other case, Void
- do
- if id.is_integer and then Db_access.users.has (id.to_integer) then
- Result := db_access.users.item (id.to_integer)
- end
- end
-
-note
- copyright: "2011-2017, Olivier Ligot, Jocelyn Fiat and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/README-compilation.txt b/examples/obsolete/v0/restbucksCRUD/README-compilation.txt
deleted file mode 100644
index 6e3dfa50..00000000
--- a/examples/obsolete/v0/restbucksCRUD/README-compilation.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-The current example has a main target for the server: "restbucks"
-But we also provide "policy_driven_restbucks" target which is using the
-policy-driven framework than help coder fulfill HTTP expectations.
diff --git a/examples/obsolete/v0/restbucksCRUD/client/README.txt b/examples/obsolete/v0/restbucksCRUD/client/README.txt
deleted file mode 100644
index 033eaaf4..00000000
--- a/examples/obsolete/v0/restbucksCRUD/client/README.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-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
-
diff --git a/examples/obsolete/v0/restbucksCRUD/client/client.ecf b/examples/obsolete/v0/restbucksCRUD/client/client.ecf
deleted file mode 100644
index f60278f9..00000000
--- a/examples/obsolete/v0/restbucksCRUD/client/client.ecf
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
- /\.git$
- /\.svn$
- /EIFGENs$
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/obsolete/v0/restbucksCRUD/client/src/restbuck_client.e b/examples/obsolete/v0/restbucksCRUD/client/src/restbuck_client.e
deleted file mode 100644
index 56a82390..00000000
--- a/examples/obsolete/v0/restbucksCRUD/client/src/restbuck_client.e
+++ /dev/null
@@ -1,154 +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
- resp : detachable 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")
--- Uncomment the following 2 lines, if you use fiddler2 web debugging tool
--- sess.set_is_debug (True)
--- sess.set_proxy ("127.0.0.1", 8888)
-
- -- 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 resp /= Void and then 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): detachable HTTP_CLIENT_RESPONSE
- local
- context : HTTP_CLIENT_REQUEST_CONTEXT
- do
- 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): detachable HTTP_CLIENT_RESPONSE
- do
- 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_with_string (m)
- j.parse_content
- if j.is_valid and then attached j.parsed_json_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
diff --git a/examples/obsolete/v0/restbucksCRUD/license.lic b/examples/obsolete/v0/restbucksCRUD/license.lic
deleted file mode 100644
index 6928e20b..00000000
--- a/examples/obsolete/v0/restbucksCRUD/license.lic
+++ /dev/null
@@ -1,4 +0,0 @@
-${NOTE_KEYWORD}
- copyright: "2011-${YEAR}, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-
diff --git a/examples/obsolete/v0/restbucksCRUD/readme.md b/examples/obsolete/v0/restbucksCRUD/readme.md
deleted file mode 100644
index 6b85f132..00000000
--- a/examples/obsolete/v0/restbucksCRUD/readme.md
+++ /dev/null
@@ -1,297 +0,0 @@
-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
------------------
-
-
-
Verb
URI or template
Use
-
POST
/order
Create a new order, and upon success, receive a Locationheader specifying the new order'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.
-
-
-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:
-1. *A resource can have multiple URIs*.
-2. *A resource can have multiple Representations*.
-
-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"
- } ]
- }
-
-note:
- curl -vv http://localhost:9090/order -H "Content-Type: application/json" -d "{\"location\":\"takeAway\",\"items\":[{\"name\":\"Late\",\"option\":\"skim\",\"size\":\"Small\",\"quantity\":1}]}" -X POST
-
-
-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"
- } ]
- }
-
-note:
- curl -vv http://localhost:9090/order/1
-
-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)
diff --git a/examples/obsolete/v0/restbucksCRUD/readme.txt b/examples/obsolete/v0/restbucksCRUD/readme.txt
deleted file mode 100644
index e69de29b..00000000
diff --git a/examples/obsolete/v0/restbucksCRUD/restbucks.ecf b/examples/obsolete/v0/restbucksCRUD/restbucks.ecf
deleted file mode 100644
index 486593f8..00000000
--- a/examples/obsolete/v0/restbucksCRUD/restbucks.ecf
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
- /EIFGENs$
- /\.git$
- /\.svn$
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /policy_driven_resource$
-
-
-
-
-
-
-
-
-
- /resource$
-
-
-
-
diff --git a/examples/obsolete/v0/restbucksCRUD/src/database/database_api.e b/examples/obsolete/v0/restbucksCRUD/src/database/database_api.e
deleted file mode 100644
index efc0bf20..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/database/database_api.e
+++ /dev/null
@@ -1,26 +0,0 @@
-note
- description: "Summary description for {DATABASE_API}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- DATABASE_API
-create
- make
-
-feature -- Initialization
-
- make
- do
- create orders.make (10)
- end
-
-feature -- Access
-
- orders: HASH_TABLE [ORDER, STRING]
-
-;note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/database/shared_database_api.e b/examples/obsolete/v0/restbucksCRUD/src/database/shared_database_api.e
deleted file mode 100644
index de4c9a22..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/database/shared_database_api.e
+++ /dev/null
@@ -1,19 +0,0 @@
-note
- description: "Summary description for {SHARED_DATABASE_API}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- SHARED_DATABASE_API
-
-feature -- Access
-
- db_access: DATABASE_API
- once
- create Result.make
- end
-note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/domain/item.e b/examples/obsolete/v0/restbucksCRUD/src/domain/item.e
deleted file mode 100644
index 2e27cf5a..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/domain/item.e
+++ /dev/null
@@ -1,90 +0,0 @@
-note
- description: "Summary description for {ITEM}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- ITEM
-inherit
- ITEM_CONSTANTS
-create
- make
-feature -- Initialization
- make ( a_name : STRING_32 ; a_size:STRING_32; a_option: STRING_32; a_quantity:INTEGER_8)
- do
- set_name (a_name)
- set_size (a_size)
- set_option (a_option)
- set_quantity (a_quantity)
- end
-
-feature -- Access
- name : STRING
- -- product name type of Coffee(Late, Cappuccino, Expresso)
-
- option : STRING
- -- customization option Milk (skim, semi, whole)
-
- size : STRING
- -- small, mediumm large
-
- quantity :INTEGER
-
-
-
-
-feature -- Element Change
- set_name (a_name: STRING)
- require
- valid_name: is_valid_coffee_type (a_name)
- do
- name := a_name
- ensure
- name_assigned : name.same_string(a_name)
- end
-
- set_size (a_size: STRING)
- require
- valid_size : is_valid_size_option (a_size)
- do
- size := a_size
- ensure
- size_assigned : size.same_string(a_size)
- end
-
- set_option (an_option: STRING)
- require
- valid_option : is_valid_milk_type (an_option)
- do
- option := an_option
- ensure
- option_assigned : option.same_string (an_option)
- end
-
- set_quantity (a_quantity: INTEGER)
- require
- valid_quantity : a_quantity > 0
- do
- quantity := a_quantity
- ensure
- quantity_assigned : quantity = a_quantity
- end
-
-feature -- Report
- hash_code: INTEGER
- --Hash code value
- do
- Result := option.hash_code + name.hash_code + size.hash_code + quantity.hash_code
- end
-
-
-invariant
- valid_size : is_valid_size_option (size)
- valid_coffe : is_valid_coffee_type (name)
- valid_customization : is_valid_milk_type (option)
- valid_quantity : quantity > 0
-note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/domain/item_constants.e b/examples/obsolete/v0/restbucksCRUD/src/domain/item_constants.e
deleted file mode 100644
index ecea445d..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/domain/item_constants.e
+++ /dev/null
@@ -1,54 +0,0 @@
-note
- description: "Summary description for {ITEM_CONSTANTS}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- ITEM_CONSTANTS
-feature -- Access
- is_valid_coffee_type (a_type: STRING) : BOOLEAN
- --is `a_type' a valid coffee type
- do
- a_type.to_lower
- coffe_types.compare_objects
- Result := coffe_types.has (a_type)
- end
-
- Coffe_types : ARRAY[STRING]
- -- List of valid Coffee types
- once
- Result := <<"late","cappuccino", "expresso">>
- end
-
- is_valid_milk_type (a_type: STRING) : BOOLEAN
- --is `a_type' a valid milk type
- do
- a_type.to_lower
- milk_types.compare_objects
- Result := milk_types.has (a_type)
- end
-
- Milk_types : ARRAY[STRING]
- -- List of valid Milk types
- once
- Result := <<"skim","semi", "whole">>
- end
-
- is_valid_size_option (an_option: STRING) : BOOLEAN
- --is `an_option' a valid size option
- do
- an_option.to_lower
- size_options.compare_objects
- Result := size_options.has (an_option)
- end
-
- Size_options : ARRAY[STRING]
- -- List of valid Size_options
- once
- Result := <<"small","mediumn", "large">>
- end
-note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/domain/json_order_converter.e b/examples/obsolete/v0/restbucksCRUD/src/domain/json_order_converter.e
deleted file mode 100644
index 1d022062..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/domain/json_order_converter.e
+++ /dev/null
@@ -1,176 +0,0 @@
-note
- description: "Summary description for {JSON_ORDER_CONVERTER}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- JSON_ORDER_CONVERTER
-inherit
- JSON_CONVERTER
-create
- make
-feature -- Initialization
- make
- do
- create object.make ("","","")
- end
-feature -- Access
- object : ORDER
-
-
- value : detachable JSON_OBJECT
-feature -- Conversion
-
- from_json (j: attached like value): detachable like object
- -- Convert from JSON value. Returns Void if unable to convert
- local
- s_id, s_location, s_status: detachable STRING_32
- q: INTEGER_8
- o: ORDER
- i : ITEM
- l_array : detachable ARRAYED_LIST [JSON_VALUE]
- is_valid_from_json : BOOLEAN
- do
- is_valid_from_json := True
-
- if attached {STRING_32} json.object (j.item (id_key), Void) as l_id then
- s_id := s_id
- end
- if attached {STRING_32} json.object (j.item (location_key), Void) as l_location then
- s_location := l_location
- end
- if attached {STRING_32} json.object (j.item (status_key), Void) as l_status then
- s_status := l_status
- end
-
- 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
- from
- l_array.start
- until
- l_array.after
- loop
- if attached {JSON_OBJECT} l_array.item_for_iteration as jv then
- if attached {INTEGER_8} json.object (jv.item (quantity_key), Void) as l_integer then
- q := l_integer
- else
- q := 0
- end
- if
- attached {STRING_32} json.object (jv.item (name_key), Void) as s_name and then
- attached {STRING_32} json.object (jv.item (size_key), Void) as s_key and then
- attached {STRING_32} json.object (jv.item (option_key), Void) as s_option
- then
- if is_valid_item_customization (s_name, s_key, s_option,q) then
- create i.make (s_name, s_key, s_option, q)
- o.add_item (i)
- else
- is_valid_from_json := False
- end
- else
- is_valid_from_json := False
- end
- end
-
- l_array.forth
- end
- end
- if not is_valid_from_json or o.items.is_empty then
- Result := Void
- else
- Result := o
- end
- end
-
- to_json (o: like object): like value
- -- Convert to JSON value
- local
- ja : JSON_ARRAY
- i : ITEM
- jv: JSON_OBJECT
- do
- create Result.make
--- 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
- create ja.make_empty
- o.items.start
- until
- o.items.after
- loop
- i := o.items.item_for_iteration
- create jv.make
- jv.put (json.value (i.name), name_key)
- jv.put (json.value (i.size),size_key)
- jv.put (json.value (i.quantity), quantity_key)
- jv.put (json.value (i.option), option_key)
- ja.add (jv)
- o.items.forth
- end
- Result.put (ja, items_key)
- end
-
- feature {NONE} -- Implementation
- id_key: JSON_STRING
- once
- create Result.make_from_string ("id")
- end
-
- location_key: JSON_STRING
- once
- create Result.make_from_string ("location")
- end
-
- status_key: JSON_STRING
- once
- create Result.make_from_string ("status")
- end
-
- items_key : JSON_STRING
- once
- create Result.make_from_string ("items")
- end
-
-
- name_key : JSON_STRING
-
- once
- create Result.make_from_string ("name")
- end
-
- size_key : JSON_STRING
-
- once
- create Result.make_from_string ("size")
- end
-
- quantity_key : JSON_STRING
-
- once
- create Result.make_from_string ("quantity")
- end
-
-
- option_key : JSON_STRING
-
- once
- create Result.make_from_string ("option")
- end
-feature -- Validation
-
- is_valid_item_customization ( name : STRING_32; size: STRING_32; option : STRING_32; quantity : INTEGER_8 ) : BOOLEAN
- local
- ic : ITEM_CONSTANTS
- do
- create ic
- Result := ic.is_valid_coffee_type (name) and ic.is_valid_milk_type (option) and ic.is_valid_size_option (size) and quantity > 0
- end
-
-note
- copyright: "2011-2015, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/domain/order.e b/examples/obsolete/v0/restbucksCRUD/src/domain/order.e
deleted file mode 100644
index 721d2256..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/domain/order.e
+++ /dev/null
@@ -1,114 +0,0 @@
-note
- description: "Summary description for {ORDER}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- ORDER
-create
- make
-feature -- Initialization
-
- make ( an_id : detachable STRING_32; a_location: detachable STRING_32; a_status: detachable STRING_32)
- do
- create {ARRAYED_LIST [ITEM]} items.make (10)
- if an_id /= Void then
- set_id (an_id)
- else
- set_id ("")
- end
- if a_location /= Void then
- set_location (a_location)
- else
- set_location ("")
- end
- if a_status /= Void then
- set_status (a_status)
- else
- set_status ("")
- end
- revision := 0
- end
-
-feature -- Access
-
- id : STRING_32
- location : STRING_32
- items: LIST[ITEM]
- status : STRING_32
- revision : INTEGER
-
-feature -- element change
-
- set_id (an_id : STRING_32)
- do
- id := an_id
- ensure
- id_assigned : id.same_string (an_id)
- end
-
- set_location (a_location : STRING_32)
- do
- location := a_location
- ensure
- location_assigned : location.same_string (a_location)
- end
-
- set_status (a_status : STRING_32)
- do
- status := a_status
- ensure
- status_asigned : status.same_string (a_status)
- end
-
- add_item (a_item : ITEM)
- require
- valid_item: a_item /= Void
- do
- items.force (a_item)
- ensure
- has_item : items.has (a_item)
- end
-
- add_revision
- do
- revision := revision + 1
- ensure
- revision_incremented : old revision + 1 = revision
- end
-
-feature -- Etag
-
- etag : STRING_32
- -- Etag generation for Order objects
- do
- Result := hash_code.out + revision.out
- end
-
-
-feature -- Output
-
-feature -- Report
-
- hash_code: INTEGER_32
- -- Hash code value
- do
- from
- items.start
- Result := items.item.hash_code
- until
- items.off
- loop
- Result:= ((Result \\ 8388593) |<< 8) + items.item.hash_code
- items.forth
- end
- if items.count > 1 then
- Result := Result \\ items.count
- end
- end
-
-note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/domain/order_validation.e b/examples/obsolete/v0/restbucksCRUD/src/domain/order_validation.e
deleted file mode 100644
index 5583a318..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/domain/order_validation.e
+++ /dev/null
@@ -1,56 +0,0 @@
-note
- description: "Summary description for {ORDER_TRANSITIONS}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- ORDER_VALIDATION
-feature -- Access
-
- is_valid_status_state (a_status: STRING) : BOOLEAN
- --is `a_status' a valid coffee order state
- do
- a_status.to_lower
- Order_states.compare_objects
- Result := Order_states.has (a_status)
- end
-
- Order_states : ARRAY[STRING]
- -- List of valid status states
- once
- Result := <<"submitted","pay","payed", "cancel","canceled","prepare","prepared","deliver","completed">>
- end
-
-
- is_valid_transition (order:ORDER a_status : STRING) :BOOLEAN
- -- Given the current order state, determine if the transition is valid
- do
- a_status.to_lower
- if order.status.same_string ("submitted") then
- Result := a_status.same_string ("pay") or a_status.same_string ("cancel") or order.status.same_string (a_status)
- elseif order.status.same_string ("pay") then
- Result := a_status.same_string ("payed") or order.status.same_string (a_status)
- elseif order.status.same_string ("cancel") then
- Result := a_status.same_string ("canceled") or order.status.same_string (a_status)
- elseif order.status.same_string ("payed") then
- Result := a_status.same_string ("prepared") or order.status.same_string (a_status)
- elseif order.status.same_string ("prepared") then
- Result := a_status.same_string ("deliver") or order.status.same_string (a_status)
- elseif order.status.same_string ("deliver") then
- Result := a_status.same_string ("completed") or order.status.same_string (a_status)
- end
- end
-
- is_state_valid_to_update ( a_status : STRING) : BOOLEAN
- -- Given the current state `a_status' of an order, is possible to update the order?
- do
- if a_status.same_string ("submitted") or else a_status.same_string ("pay") or else a_status.same_string ("payed") then
- Result := true
- end
- end
-
-note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/domain/shared_order_validation.e b/examples/obsolete/v0/restbucksCRUD/src/domain/shared_order_validation.e
deleted file mode 100644
index 4e3a1d33..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/domain/shared_order_validation.e
+++ /dev/null
@@ -1,19 +0,0 @@
-note
- description: "Summary description for {SHARED_ORDER_VALIDATION}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class
- SHARED_ORDER_VALIDATION
-
-feature
- order_validation : ORDER_VALIDATION
- once
- create Result
- end
-
-note
- copyright: "2011-2012, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/policy_driven_resource/order_handler.e b/examples/obsolete/v0/restbucksCRUD/src/policy_driven_resource/order_handler.e
deleted file mode 100644
index 31410477..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/policy_driven_resource/order_handler.e
+++ /dev/null
@@ -1,574 +0,0 @@
-note
- description: "{ORDER_HANDLER} handle the resources that we want to expose"
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class ORDER_HANDLER
-
-inherit
-
- WSF_SKELETON_HANDLER
-
- SHARED_DATABASE_API
-
- SHARED_EJSON
-
- REFACTORING_HELPER
-
- SHARED_ORDER_VALIDATION
-
- WSF_RESOURCE_HANDLER_HELPER
- rename
- execute_options as helper_execute_options,
- handle_internal_server_error as helper_handle_internal_server_error
- end
-
-create
-
- make_with_router
-
-
-feature -- Execution variables
-
- Order_execution_variable: STRING = "ORDER"
- -- Execution variable used by application
-
- Generated_content_execution_variable: STRING = "GENERATED_CONTENT"
- -- Execution variable used by application
-
- Extracted_order_execution_variable: STRING = "EXTRACTED_ORDER"
- -- Execution variable used by application
-
-feature -- Documentation
-
- description: READABLE_STRING_GENERAL
- -- General description for self-generated documentation;
- -- The specific URI templates supported will be described automatically
- do
- Result := "Create, Read, Update or Delete an ORDER."
- end
-
-feature -- Access
-
- is_chunking (req: WSF_REQUEST): BOOLEAN
- -- Will the response to `req' using chunked transfer encoding?
- do
- -- No.
- end
-
- includes_response_entity (req: WSF_REQUEST): BOOLEAN
- -- Does the response to `req' include an entity?
- -- Method will be DELETE, POST, PUT or an extension method.
- do
- Result := False
- -- At present, there is no support for this except for DELETE.
- end
-
- conneg (req: WSF_REQUEST): SERVER_CONTENT_NEGOTIATION
- -- Content negotiatior for all requests
- once
- create Result.make ({HTTP_MIME_TYPES}.application_json, "en", "UTF-8", "identity")
- end
-
- mime_types_supported (req: WSF_REQUEST): LIST [STRING]
- -- All values for Accept header that `Current' can serve
- do
- create {ARRAYED_LIST [STRING]} Result.make_from_array (<<{HTTP_MIME_TYPES}.application_json>>)
- Result.compare_objects
- end
-
- languages_supported (req: WSF_REQUEST): LIST [STRING]
- -- All values for Accept-Language header that `Current' can serve
- do
- create {ARRAYED_LIST [STRING]} Result.make_from_array (<<"en">>)
- Result.compare_objects
- end
-
- charsets_supported (req: WSF_REQUEST): LIST [STRING]
- -- All values for Accept-Charset header that `Current' can serve
- do
- create {ARRAYED_LIST [STRING]} Result.make_from_array (<<"UTF-8">>)
- Result.compare_objects
- end
-
- encodings_supported (req: WSF_REQUEST): LIST [STRING]
- -- All values for Accept-Encoding header that `Current' can serve
- do
- create {ARRAYED_LIST [STRING]} Result.make_from_array (<<"identity">>)
- Result.compare_objects
- end
-
- max_age (req: WSF_REQUEST): NATURAL
- -- Maximum age in seconds before response to `req` is considered stale;
- -- This is used to generate a Cache-Control: max-age header.
- -- Return 0 to indicate already expired.
- -- Return Never_expires to indicate never expires.
- do
- -- All our responses are considered stale.
- end
-
- is_freely_cacheable (req: WSF_REQUEST): BOOLEAN
- -- Should the response to `req' be freely cachable in shared caches?
- -- If `True', then a Cache-Control: public header will be generated.
- do
- -- definitely not!
- end
-
- private_headers (req: WSF_REQUEST): detachable LIST [READABLE_STRING_8]
- -- Header names intended for a single user.
- -- If non-Void, then a Cache-Control: private header will be generated.
- -- Returning an empty list prevents the entire response from being served from a shared cache.
- do
- create {ARRAYED_LIST [READABLE_STRING_8]} Result.make (0)
- end
-
- non_cacheable_headers (req: WSF_REQUEST): detachable LIST [READABLE_STRING_8]
- -- Header names that will not be sent from a cache without revalidation;
- -- If non-Void, then a Cache-Control: no-cache header will be generated.
- -- Returning an empty list prevents the response being served from a cache
- -- without revalidation.
- do
- create {ARRAYED_LIST [READABLE_STRING_8]} Result.make (0)
- end
-
- is_sensitive (req: WSF_REQUEST): BOOLEAN
- -- Is the response to `req' of a sensitive nature?
- -- If `True' then a Cache-Control: no-store header will be generated.
- do
- Result := True
- -- since it's commercial data.
- end
-
- allowed_cross_origins (req: WSF_REQUEST): detachable STRING
- -- Value for Access-Control-Allow-Origin header;
- -- If supplied, should be a single URI, or the values "*" or "null".
- -- This is currently supported only for GET requests, and POSTs that functions as GET.
- do
- if req.is_get_head_request_method then
- Result := "*"
- end
- end
-
- matching_etag (req: WSF_REQUEST; a_etag: READABLE_STRING_32; a_strong: BOOLEAN): BOOLEAN
- -- Is `a_etag' a match for resource requested in `req'?
- -- If `a_strong' then the strong comparison function must be used.
- local
- l_id: STRING
- l_etag_util: ETAG_UTILS
- do
- l_id := order_id_from_request (req)
- if db_access.orders.has_key (l_id) then
- check attached db_access.orders.item (l_id) as l_order then
- -- postcondition of `has_key'
- create l_etag_util
- Result := a_etag.same_string (l_etag_util.md5_digest (l_order.out).as_string_32)
- end
- end
- end
-
- etag (req: WSF_REQUEST): detachable READABLE_STRING_8
- -- Optional Etag for `req' in the requested variant
- local
- l_etag_utils: ETAG_UTILS
- do
- create l_etag_utils
- if attached {ORDER} req.execution_variable (Order_execution_variable) as l_order then
- Result := l_etag_utils.md5_digest (l_order.out)
- end
- end
-
- last_modified (req: WSF_REQUEST): detachable DATE_TIME
- -- When representation of resource selected in `req' was last modified;
- -- SHOULD be set whenever it can reasonably be determined.
- do
- end
-
- modified_since (req: WSF_REQUEST; a_date_time: DATE_TIME): BOOLEAN
- -- Has resource requested in `req' been modified since `a_date_time' (UTC)?
- do
- -- We don't track this information. It is safe to always say yes.
- Result := True
- end
-
-feature -- Measurement
-
- content_length (req: WSF_REQUEST): NATURAL
- -- Length of entity-body of the response to `req'
- do
- check attached {READABLE_STRING_8} req.execution_variable (Generated_content_execution_variable) as l_response then
- -- postcondition generated_content_set_for_get_head of `ensure_content_available'
- -- We only call this for GET/HEAD in this example.
- Result := l_response.count.as_natural_32
- end
- end
-
- allow_post_to_missing_resource (req: WSF_REQUEST): BOOLEAN
- -- The resource named in `req' does not exist, and this is a POST. Do we allow it?
- do
- -- No.
- end
-
-feature -- Status report
-
- finished (req: WSF_REQUEST): BOOLEAN
- -- Has the last chunk been generated for `req'?
- do
- -- precondition is never met
- end
-
-feature -- Execution
-
- check_resource_exists (req: WSF_REQUEST; a_helper: WSF_METHOD_HELPER)
- -- Call `a_helper.set_resource_exists' to indicate that `req.path_translated'
- -- is the name of an existing resource.
- -- We also put the order into `req.execution_variable (Order_execution_variable)' for GET or HEAD responses.
- local
- l_id: STRING
- do
- if req.is_post_request_method then
- a_helper.set_resource_exists
- -- because only /order is defined to this handler for POST
- else
- -- the request is of the form /order/{orderid}
- l_id := order_id_from_request (req)
- if db_access.orders.has_key (l_id) then
- a_helper.set_resource_exists
- if req.is_get_head_request_method then
- check attached db_access.orders.item (l_id) as l_order then
- -- postcondition `item_if_found' of `has_key'
- req.set_execution_variable (Order_execution_variable, l_order)
- end
- end
- end
- end
- ensure then
- order_saved_only_for_get_head: attached {ORDER} req.execution_variable (Order_execution_variable) implies req.is_get_head_request_method
- end
-
-feature -- GET/HEAD content
-
- ensure_content_available (req: WSF_REQUEST)
- -- Commence generation of response text (entity-body).
- -- If not chunked, then this will create the entire entity-body so as to be available
- -- for a subsequent call to `content'.
- -- If chunked, only the first chunk will be made available to `next_chunk'. If chunk extensions
- -- are used, then this will also generate the chunk extension for the first chunk.
- -- We save the text in `req.execution_variable (Generated_content_execution_variable)'
- -- We ignore the results of content negotiation, as there is only one possible combination.
- do
- check attached {ORDER} req.execution_variable (Order_execution_variable) as l_order then
- -- precondition get_or_head and postcondition order_saved_only_for_get_head of `check_resource_exists' and
- if attached {JSON_VALUE} json.value (l_order) as jv then
- req.set_execution_variable (Generated_content_execution_variable, jv.representation)
- else
- req.set_execution_variable (Generated_content_execution_variable, "")
- end
- end
- ensure then
- generated_content_set_for_get_head: req.is_get_head_request_method implies
- attached {READABLE_STRING_8} req.execution_variable (Generated_content_execution_variable)
- end
-
- content (req: WSF_REQUEST): READABLE_STRING_8
- -- Non-chunked entity body in response to `req';
- -- We only call this for GET/HEAD in this example.
- do
- check attached {READABLE_STRING_8} req.execution_variable (Generated_content_execution_variable) as l_response then
- -- postcondition generated_content_set_for_get_head of `ensure_content_available'
- Result := l_response
- end
- end
-
- next_chunk (req: WSF_REQUEST): TUPLE [a_chunk: READABLE_STRING_8; a_extension: detachable READABLE_STRING_8]
- -- Next chunk of entity body in response to `req';
- -- The second field of the result is an optional chunk extension.
- do
- -- precondition `is_chunking' is never met, but we need a dummy `Result'
- -- to satisfy the compiler in void-safe mode
- Result := ["", Void]
- end
-
- generate_next_chunk (req: WSF_REQUEST)
- -- Prepare next chunk (including optional chunk extension) of entity body in response to `req'.
- -- This is not called for the first chunk.
- do
- -- precondition `is_chunking' is never met
- end
-
-feature -- DELETE
-
- delete (req: WSF_REQUEST)
- -- Delete resource named in `req' or set an error on `req.error_handler'.
- local
- l_id: STRING
- do
- l_id := order_id_from_request (req)
- if db_access.orders.has_key (l_id) then
- if is_valid_to_delete (l_id) then
- delete_order (l_id)
- else
- req.error_handler.add_custom_error ({HTTP_STATUS_CODE}.method_not_allowed, "DELETE not valid",
- "There is conflict while trying to delete the order, the order could not be deleted in the current state")
- end
- else
- req.error_handler.add_custom_error ({HTTP_STATUS_CODE}.not_found, "DELETE not valid",
- "There is no such order to delete")
- end
- end
-
- delete_queued (req: WSF_REQUEST): BOOLEAN
- -- Has resource named by `req' been queued for deletion?
- do
- -- No
- end
-
-
-feature -- PUT/POST
-
- is_entity_too_large (req: WSF_REQUEST): BOOLEAN
- -- Is the entity stored in `req.execution_variable (Request_entity_execution_variable)' too large for the application?
- do
- -- No. We don't care for this example.
- end
-
- check_content_headers (req: WSF_REQUEST)
- -- Check we can support all content headers on request entity.
- -- Set `req.execution_variable (Content_check_code_execution_variable)' to {NATURAL} zero if OK, or 415 or 501 if not.
- do
- -- We don't bother for this example. Note that this is equivalent to setting zero.
- end
-
- create_resource (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Create new resource in response to a PUT request when `check_resource_exists' returns `False'.
- -- Implementor must set error code of 200 OK or 500 Server Error.
- do
- -- We don't support creating a new resource with PUT. But this can't happen
- -- with our router mappings, so we don't bother to set a 500 response.
- end
-
- append_resource (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Create new resource in response to a POST request.
- -- Implementor must set error code of 200 OK or 204 No Content or 303 See Other or 500 Server Error.
- do
- if attached {ORDER} req.execution_variable (Extracted_order_execution_variable) as l_order then
- save_order (l_order)
- compute_response_post (req, res, l_order)
- else
- handle_bad_request_response ("Not a valid order", req, res)
- end
- end
-
- check_conflict (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Check we can support all content headers on request entity.
- -- Set `req.execution_variable (Conflict_check_code_execution_variable)' to {NATURAL} zero if OK, or 409 if not.
- -- In the latter case, write the full error response to `res'.
- do
- if attached {ORDER} req.execution_variable (Extracted_order_execution_variable) as l_order then
- if not is_valid_to_update (l_order) then
- req.set_execution_variable (Conflict_check_code_execution_variable, {NATURAL} 409)
- handle_resource_conflict_response (l_order.out +"%N There is conflict while trying to update the order, the order could not be update in the current state", req, res)
- end
- else
- req.set_execution_variable (Conflict_check_code_execution_variable, {NATURAL} 409)
- --| This ought to be a 500, as if attached should probably be check attached. But as yet I lack a proof.
- handle_resource_conflict_response ("There is conflict while trying to update the order, the order could not be update in the current state", req, res)
- end
- end
-
- check_request (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Check that the request entity is a valid request.
- -- The entity is available as `req.execution_variable (Conflict_check_code_execution_variable)'.
- -- Set `req.execution_variable (Request_check_code_execution_variable)' to {NATURAL} zero if OK, or 400 if not.
- -- In the latter case, write the full error response to `res'.
- local
- l_order: detachable ORDER
- l_id: STRING
- do
- if attached {READABLE_STRING_8} req.execution_variable (Request_entity_execution_variable) as l_request then
- l_order := extract_order_request (l_request)
- if req.is_put_request_method then
- l_id := order_id_from_request (req)
- if l_order /= Void and then db_access.orders.has_key (l_id) then
- l_order.set_id (l_id)
- req.set_execution_variable (Request_check_code_execution_variable, {NATURAL} 0)
- req.set_execution_variable (Extracted_order_execution_variable, l_order)
- else
- req.set_execution_variable (Request_check_code_execution_variable, {NATURAL} 400)
- handle_bad_request_response (l_request +"%N is not a valid ORDER, maybe the order does not exist in the system", req, res)
- end
- else
- req.set_execution_variable (Request_check_code_execution_variable, {NATURAL} 0)
- req.set_execution_variable (Extracted_order_execution_variable, l_order)
- end
- else
- req.set_execution_variable (Request_check_code_execution_variable, {NATURAL} 400)
- handle_bad_request_response ("Request is not a valid ORDER", req, res)
- end
- end
-
- update_resource (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Perform the update requested in `req'.
- -- Write a response to `res' with a code of 204 or 500.
- do
- if attached {ORDER} req.execution_variable (Extracted_order_execution_variable) as l_order then
- update_order (l_order)
- compute_response_put (req, res, l_order)
- else
- handle_internal_server_error (res)
- end
- end
-
-feature -- HTTP Methods
-
- compute_response_put (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
- local
- h: HTTP_HEADER
- joc : JSON_ORDER_CONVERTER
- etag_utils : ETAG_UTILS
- do
- create h.make
- create joc.make
- create etag_utils
- json.add_converter(joc)
-
- create h.make
- 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
- h.add_header ("etag:" + etag_utils.md5_digest (l_order.out))
- 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.put_header_text (h.string)
- res.put_string (jv.representation)
- end
- end
-
- compute_response_post (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
- local
- h: HTTP_HEADER
- l_msg : STRING
- l_location : STRING
- joc : JSON_ORDER_CONVERTER
- do
- create h.make
-
- create joc.make
- json.add_converter(joc)
-
- 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.put_header_text (h.string)
- res.put_string (l_msg)
- end
- end
-
-feature {NONE} -- URI helper methods
-
- order_id_from_request (req: WSF_REQUEST): STRING
- -- Value of "orderid" template URI variable in `req'
- require
- req_attached: req /= Void
- do
- if attached {WSF_VALUE} req.path_parameter ("orderid") as l_value then
- Result := l_value.as_string.value.as_string_8
- else
- Result := ""
- end
- 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
-
-
- is_valid_to_delete ( an_id : STRING) : BOOLEAN
- -- Is the order identified by `an_id' in a state whre it can still be deleted?
- do
- if attached retrieve_order (an_id) as l_order then
- if order_validation.is_state_valid_to_update (l_order.status) then
- Result := True
- end
- end
- end
-
- is_valid_to_update (an_order: ORDER) : BOOLEAN
- -- Check if there is a conflict while trying to update the order
- do
- if attached retrieve_order (an_order.id) as l_order then
- if order_validation.is_state_valid_to_update (l_order.status) and then order_validation.is_valid_status_state (an_order.status) and then
- order_validation.is_valid_transition (l_order, an_order.status) then
- Result := True
- end
- end
- 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_with_string (l_post)
- parser.parse_content
- if parser.is_valid and then attached parser.parsed_json_value as jv then
- if attached {like extract_order_request} json.object (jv, "ORDER") as res then
- Result := res
- end
- end
- end
-
-note
- copyright: "2011-2015, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/resource/order_handler.e b/examples/obsolete/v0/restbucksCRUD/src/resource/order_handler.e
deleted file mode 100644
index 4088494e..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/resource/order_handler.e
+++ /dev/null
@@ -1,403 +0,0 @@
-note
- description: "{ORDER_HANDLER} handle the resources that we want to expose"
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-class ORDER_HANDLER
-inherit
-
- WSF_URI_TEMPLATE_HANDLER
-
- WSF_RESOURCE_HANDLER_HELPER
- redefine
- do_get,
- do_post,
- do_put,
- do_delete
- end
-
- SHARED_DATABASE_API
-
- SHARED_EJSON
-
- REFACTORING_HELPER
-
- SHARED_ORDER_VALIDATION
-
- WSF_SELF_DOCUMENTED_HANDLER
-
-create
- make_with_router
-
-feature {NONE} -- Initialization
-
- make_with_router (a_router: WSF_ROUTER)
- -- Initialize `router'.
- require
- a_router_attached: a_router /= Void
- do
- router := a_router
- ensure
- router_aliased: router = a_router
- end
-
-feature -- Router
-
- router: WSF_ROUTER
- -- Associated router that could be used for advanced strategy
-
-feature -- Execute
-
- execute (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Execute request handler
- do
- execute_methods (req, res)
- end
-
-feature -- API DOC
-
- api_doc : STRING = "URI:/order METHOD: POST%N URI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
-
-
-feature -- Documentation
-
- mapping_documentation (m: WSF_ROUTER_MAPPING; a_request_methods: detachable WSF_REQUEST_METHODS): WSF_ROUTER_MAPPING_DOCUMENTATION
- do
- create Result.make (m)
- if a_request_methods /= Void then
- if a_request_methods.has_method_post then
- Result.add_description ("URI:/order METHOD: POST")
- elseif
- a_request_methods.has_method_get
- or a_request_methods.has_method_put
- or a_request_methods.has_method_delete
- then
- Result.add_description ("URI:/order/{orderid} METHOD: GET, PUT, DELETE")
- end
- end
- end
-
-feature -- HTTP Methods
-
- do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
- --
- local
- id: STRING
- do
- if attached req.path_info as l_path_info then
- id := get_order_id_from_path (l_path_info)
- if attached retrieve_order (id) as l_order then
- if is_conditional_get (req, l_order) then
- handle_resource_not_modified_response ("The resource" + l_path_info + "does not change", req, res)
- else
- compute_response_get (req, res, l_order)
- end
- else
- handle_resource_not_found_response ("The following resource" + l_path_info + " is not found ", req, res)
- end
- end
- end
-
- is_conditional_get (req : WSF_REQUEST; l_order : ORDER) : BOOLEAN
- -- Check if If-None-Match is present and then if there is a representation that has that etag
- -- if the representation hasn't changed, we return TRUE
- -- then the response is a 304 with no entity body returned.
- local
- etag_util : ETAG_UTILS
- do
- if attached req.meta_string_variable ("HTTP_IF_NONE_MATCH") as if_none_match then
- create etag_util
- if if_none_match.same_string (etag_util.md5_digest (l_order.out).as_string_32) then
- Result := True
- end
- end
- end
-
- compute_response_get (req: WSF_REQUEST; res: WSF_RESPONSE; l_order: ORDER)
- local
- h: HTTP_HEADER
- l_msg : STRING
- etag_utils : ETAG_UTILS
- do
- create h.make
- create etag_utils
- 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
- h.add_header ("etag:" + etag_utils.md5_digest (l_order.out))
- res.set_status_code ({HTTP_STATUS_CODE}.ok)
- res.put_header_text (h.string)
- res.put_string (l_msg)
- end
- end
-
- do_put (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Updating a resource 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.
- local
- l_put: STRING
- l_order : detachable ORDER
- id : STRING
- do
- if attached req.path_info as l_path_info then
- id := get_order_id_from_path (l_path_info)
- l_put := retrieve_data (req)
- l_order := extract_order_request(l_put)
- if l_order /= Void and then db_access.orders.has_key (id) then
- l_order.set_id (id)
- if is_valid_to_update(l_order) then
- if is_conditional_put (req, l_order) then
- update_order( l_order)
- compute_response_put (req, res, l_order)
- else
- handle_precondition_fail_response ("", req, res)
- end
- else
- --| FIXME: Here we need to define the Allow methods
- handle_resource_conflict_response (l_put +"%N There is conflict while trying to update the order, the order could not be update in the current state", req, res)
- end
- else
- handle_bad_request_response (l_put +"%N is not a valid ORDER, maybe the order does not exist in the system", req, res)
- end
- end
- end
-
- is_conditional_put (req : WSF_REQUEST; order : ORDER) : BOOLEAN
- -- Check if If-Match is present and then if there is a representation that has that etag
- -- if the representation hasn't changed, we return TRUE
- local
- etag_util : ETAG_UTILS
- do
- if attached retrieve_order (order.id) as l_order then
- if attached req.meta_string_variable ("HTTP_IF_MATCH") as if_match then
- create etag_util
- if if_match.same_string (etag_util.md5_digest (l_order.out).as_string_32) then
- Result := True
- end
- else
- Result := True
- end
- end
- end
-
-
- compute_response_put (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
- local
- h: HTTP_HEADER
- joc : JSON_ORDER_CONVERTER
- etag_utils : ETAG_UTILS
- do
- create h.make
- create joc.make
- create etag_utils
- json.add_converter(joc)
-
- create h.make
- 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
- h.add_header ("etag:" + etag_utils.md5_digest (l_order.out))
- 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.put_header_text (h.string)
- res.put_string (jv.representation)
- end
- end
-
-
- do_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Here we use DELETE to cancel an order, if that order is in state where
- -- it can still be canceled.
- -- 200 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
- local
- id: STRING
- do
- if attached req.path_info as l_path_info then
- id := get_order_id_from_path (l_path_info)
- if db_access.orders.has_key (id) then
- if is_valid_to_delete (id) then
- delete_order( id)
- compute_response_delete (req, res)
- else
- --| FIXME: Here we need to define the Allow methods
- handle_method_not_allowed_response (l_path_info + "%N There is conflict while trying to delete the order, the order could not be deleted in the current state", req, res)
- end
- else
- handle_resource_not_found_response (l_path_info + " not found in this server", req, res)
- end
- end
- end
-
- compute_response_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
- local
- h : HTTP_HEADER
- do
- create h.make
- 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.put_header_text (h.string)
- end
-
- do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- 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
- l_post := retrieve_data (req)
- if attached extract_order_request (l_post) as l_order then
- save_order (l_order)
- compute_response_post (req, res, l_order)
- else
- handle_bad_request_response (l_post +"%N is not a valid ORDER", req, res)
- end
- end
-
- compute_response_post (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
- local
- h: HTTP_HEADER
- l_msg : STRING
- l_location : STRING
- joc : JSON_ORDER_CONVERTER
- do
- create h.make
-
- create joc.make
- json.add_converter(joc)
-
- 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.put_header_text (h.string)
- res.put_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
-
-
- is_valid_to_delete ( an_id : STRING) : BOOLEAN
- -- Is the order identified by `an_id' in a state whre it can still be deleted?
- do
- if attached retrieve_order (an_id) as l_order then
- if order_validation.is_state_valid_to_update (l_order.status) then
- Result := True
- end
- end
- end
-
- is_valid_to_update (an_order: ORDER) : BOOLEAN
- -- Check if there is a conflict while trying to update the order
- do
- if attached retrieve_order (an_order.id) as l_order then
- if order_validation.is_state_valid_to_update (l_order.status) and then order_validation.is_valid_status_state (an_order.status) and then
- order_validation.is_valid_transition (l_order, an_order.status) then
- Result := True
- end
- end
- 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_with_string (l_post)
- parser.parse_content
- if
- parser.is_valid and then
- attached parser.parsed_json_value as jv
- then
- if attached {like extract_order_request} json.object (jv, "ORDER") as res then
- Result := res
- end
- end
- end
-
-note
- copyright: "2011-2015, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/examples/obsolete/v0/restbucksCRUD/src/restbucks_server.e b/examples/obsolete/v0/restbucksCRUD/src/restbucks_server.e
deleted file mode 100644
index 588b2057..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/restbucks_server.e
+++ /dev/null
@@ -1,58 +0,0 @@
-note
- description : "REST Buck server"
- date : "$Date$"
- revision : "$Revision$"
-
-class RESTBUCKS_SERVER
-
-inherit
-
- WSF_ROUTED_SKELETON_SERVICE
- undefine
- requires_proxy
- end
-
- WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE
-
- WSF_HANDLER_HELPER
-
- WSF_DEFAULT_SERVICE
-
- WSF_NO_PROXY_POLICY
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make
- do
- initialize_router
- set_service_option ("port", 9090)
- make_and_launch
- end
-
- setup_router
- local
- order_handler: ORDER_HANDLER
- doc: WSF_ROUTER_SELF_DOCUMENTATION_HANDLER
- do
- create order_handler.make_with_router (router)
- router.handle_with_request_methods ("/order", order_handler, router.methods_POST)
- router.handle_with_request_methods ("/order/{orderid}", order_handler, router.methods_GET + router.methods_DELETE + router.methods_PUT)
- create doc.make_hidden (router)
- router.handle_with_request_methods ("/api/doc", doc, router.methods_GET)
- end
-
-
-note
- copyright: "2011-2013, Javier Velilla 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
diff --git a/examples/obsolete/v0/restbucksCRUD/src/utils/etag_utils.e b/examples/obsolete/v0/restbucksCRUD/src/utils/etag_utils.e
deleted file mode 100644
index 9aed6c1d..00000000
--- a/examples/obsolete/v0/restbucksCRUD/src/utils/etag_utils.e
+++ /dev/null
@@ -1,24 +0,0 @@
-note
- description: "Summary description for {ETAG_UTILS}."
- date: "$Date$"
- revision: "$Revision$"
-
-class
- ETAG_UTILS
-
-feature -- Access
-
- md5_digest (a_string: STRING): STRING
- -- Cryptographic hash function that produces a 128-bit (16-byte) hash value, based on `a_string'
- local
- md5: MD5
- do
- create md5.make
- md5.update_from_string (a_string)
- Result := md5.digest_as_string
- end
-
-note
- copyright: "2011-2014, Javier Velilla and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
-end
diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf
deleted file mode 100644
index fcb6d042..00000000
--- a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi-safe.ecf
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf
deleted file mode 100644
index 59057676..00000000
--- a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/libfcgi.ecf
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
- /EIFGENs$
- /\.git$
- /\.svn$
-
-
-
-
-
-
-
-
- /wgi_.*_connector.e$
-
-
-
-
-
diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic
deleted file mode 100644
index cf2d1ed9..00000000
--- a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/license.lic
+++ /dev/null
@@ -1,10 +0,0 @@
-${NOTE_KEYWORD}
- copyright: "2011-${YEAR}, 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
- ]"
diff --git a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e b/library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e
deleted file mode 100644
index 97051098..00000000
--- a/library/server/obsolete/v0/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e
+++ /dev/null
@@ -1,119 +0,0 @@
-note
- description: "Summary description for {WGI_LIBFCGI_CONNECTOR}."
- legal: "See notice at end of class."
- status: "See notice at end of class."
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WGI_LIBFCGI_CONNECTOR
-
-inherit
- WGI_CONNECTOR
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make (a_service: like service)
- do
- service := a_service
- create fcgi.make
- create input.make (fcgi)
- create output.make (fcgi)
- end
-
-feature -- Access
-
- Name: STRING_8 = "libFCGI"
- -- Name of Current connector
-
- Version: STRING_8 = "0.1"
- -- Version of Current connector
-
-feature {NONE} -- Access
-
- service: WGI_SERVICE
- -- Gateway Service
-
-feature -- Server
-
- launch
- local
- res: INTEGER
- do
- from
- res := fcgi.fcgi_listen
- until
- res < 0
- loop
- process_fcgi_request (fcgi.updated_environ_variables, input, output)
- res := fcgi.fcgi_listen
- end
- end
-
-feature -- Execution
-
- process_fcgi_request (vars: STRING_TABLE [READABLE_STRING_8]; a_input: like input; a_output: like output)
- local
- req: WGI_REQUEST_FROM_TABLE
- res: detachable WGI_RESPONSE_STREAM
- rescued: BOOLEAN
- utf: UTF_CONVERTER
- do
- if not rescued then
- a_input.reset
- create req.make (vars, a_input, Current)
- create res.make (a_output, a_output)
- service.execute (req, res)
- res.push
- else
- if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then
- if res /= Void then
- if not res.status_is_set then
- res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
- end
- if res.message_writable then
- res.put_string ("