diff --git a/examples/tutorial/step_4/hello/src/hello_application.e b/examples/tutorial/step_4/hello/src/hello_application.e
index 83dbc7bc..38d09ced 100644
--- a/examples/tutorial/step_4/hello/src/hello_application.e
+++ b/examples/tutorial/step_4/hello/src/hello_application.e
@@ -13,7 +13,7 @@ class
HELLO_APPLICATION
inherit
- WSF_URI_TEMPLATE_ROUTED_SERVICE
+ WSF_ROUTED_SERVICE
WSF_DEFAULT_SERVICE
redefine
@@ -27,12 +27,34 @@ feature {NONE} -- Initialization
setup_router
do
- router.map_agent ("/hello", agent execute_hello)
+-- router.map (create {WSF_URI_MAPPING}.make ("/hello", create {WSF_AGENT_URI_HANDLER}.make (agent execute_hello)))
+ map_agent_uri ("/hello", agent execute_hello, Void)
- router.map_with_request_methods ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, router.methods_HEAD_GET_POST)
- router.map_with_request_methods ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, router.methods_GET_POST)
+-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}), router.methods_HEAD_GET_POST)
+ map_uri_template ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, router.methods_HEAD_GET_POST)
- router.map_agent_response_with_request_methods ("/users/{user}/{?op}", agent response_user, router.methods_GET)
+-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}), router.methods_GET_POST)
+ map_uri_template ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, router.methods_GET_POST)
+
+-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/{?op}", create {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}.make (agent response_user)), router.methods_GET)
+ map_agent_uri_template_response ("/users/{user}/{?op}", agent response_user, router.methods_GET)
+ end
+
+feature -- Helper: mapping
+
+ map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_AGENT_URI_HANDLER}.action; rqst_methods: detachable WSF_ROUTER_METHODS)
+ do
+ router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_AGENT_URI_HANDLER}.make (a_action)), rqst_methods)
+ end
+
+ map_uri_template (a_tpl: READABLE_STRING_8; a_handler: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS)
+ do
+ router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, a_handler), rqst_methods)
+ end
+
+ map_agent_uri_template_response (a_tpl: READABLE_STRING_8; a_action: like {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}.action; rqst_methods: detachable WSF_ROUTER_METHODS)
+ do
+ router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, create {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}.make (a_action)), rqst_methods)
end
feature -- Execution
@@ -43,7 +65,7 @@ feature -- Execution
res.redirect_now_with_content (req.script_url ("/hello"), "Redirection to " + req.script_url ("/hello"), "text/html")
end
- execute_hello (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
+ execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Computed response message.
local
mesg: WSF_HTML_PAGE_RESPONSE
@@ -107,8 +129,9 @@ feature -- Execution
then
if l_op.is_case_insensitive_equal ("quit") then
create redir.make (req.script_url ("/hello"), 3)
- redir.set_title ("Bye " + u.url_encoded_value)
- redir.set_body ("Bye " + u.url_encoded_value + ",
see you soon.
You will be redirected to " +
+ create html.make
+ redir.set_title ("Bye " + html.html_encoded_string (l_username))
+ redir.set_body ("Bye " + html.html_encoded_string (l_username) + ",
see you soon.
You will be redirected to " +
redir.url_location + " in " + redir.delay.out + " second(s) ...
"
)
Result := redir
diff --git a/examples/tutorial/step_4/hello/src/user_message_handler.e b/examples/tutorial/step_4/hello/src/user_message_handler.e
index 616cd337..cbc95f17 100644
--- a/examples/tutorial/step_4/hello/src/user_message_handler.e
+++ b/examples/tutorial/step_4/hello/src/user_message_handler.e
@@ -9,7 +9,7 @@ class
USER_MESSAGE_HANDLER
inherit
- WSF_RESPONSE_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
+ WSF_URI_TEMPLATE_RESPONSE_HANDLER
feature -- Access
diff --git a/library/server/wsf/router/README.md b/library/server/wsf/router/README.md
index 80233fc4..abd12c96 100644
--- a/library/server/wsf/router/README.md
+++ b/library/server/wsf/router/README.md
@@ -1,7 +1,7 @@
# Router
## Requirements
-* [URI Template](../../../protocol/rui_template)
+* [URI Template](../../../protocol/uri_template)
## Overview
diff --git a/library/server/wsf/router/default/wsf_routed_service.e b/library/server/wsf/router/default/wsf_routed_service.e
deleted file mode 100644
index b2634211..00000000
--- a/library/server/wsf/router/default/wsf_routed_service.e
+++ /dev/null
@@ -1,23 +0,0 @@
-note
- description: "Summary description for {DEFAULT_ROUTED_SERVICE}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-deferred class
- WSF_ROUTED_SERVICE
-
-inherit
- WSF_ROUTED_SERVICE_I [WSF_HANDLER [WSF_HANDLER_CONTEXT], WSF_HANDLER_CONTEXT]
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/wsf_routed_service_i.e b/library/server/wsf/router/service/wsf_routed_service.e
similarity index 78%
rename from library/server/wsf/router/wsf_routed_service_i.e
rename to library/server/wsf/router/service/wsf_routed_service.e
index fa82da2a..11c09ba1 100644
--- a/library/server/wsf/router/wsf_routed_service_i.e
+++ b/library/server/wsf/router/service/wsf_routed_service.e
@@ -5,12 +5,11 @@ note
revision: "$Revision$"
deferred class
- WSF_ROUTED_SERVICE_I [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
+ WSF_ROUTED_SERVICE
-feature -- Setup
+feature -- Initialization
initialize_router
- -- Initialize `router'
do
create_router
setup_router
@@ -18,7 +17,8 @@ feature -- Setup
create_router
-- Create `router'
- deferred
+ do
+ create router.make (10)
ensure
router_created: router /= Void
end
@@ -30,15 +30,12 @@ feature -- Setup
deferred
end
- router: WSF_ROUTER [H, C]
- -- Request router
-
feature -- Execution
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
do
- if attached router.route (req) as r then
- router.execute_route (r, req, res)
+ if attached router.dispatch_and_return_handler (req, res) as p then
+ -- executed
else
execute_default (req, res)
end
@@ -48,7 +45,11 @@ feature -- Execution
deferred
end
-note
+feature -- Access
+
+ router: WSF_ROUTER
+
+;note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
diff --git a/library/server/wsf/router/starts_with/wsf_starts_with_handler.e b/library/server/wsf/router/starts_with/wsf_starts_with_handler.e
new file mode 100644
index 00000000..19c3a037
--- /dev/null
+++ b/library/server/wsf/router/starts_with/wsf_starts_with_handler.e
@@ -0,0 +1,19 @@
+note
+ description: "Summary description for {WSF_STARTS_WITH_HANDLER}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_STARTS_WITH_HANDLER
+
+inherit
+ WSF_HANDLER
+
+feature -- Execution
+
+ execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
+ deferred
+ end
+
+end
diff --git a/library/server/wsf/router/starts_with/wsf_starts_with_mapping.e b/library/server/wsf/router/starts_with/wsf_starts_with_mapping.e
new file mode 100644
index 00000000..fed15b87
--- /dev/null
+++ b/library/server/wsf/router/starts_with/wsf_starts_with_mapping.e
@@ -0,0 +1,62 @@
+note
+ description: "Summary description for EWF_URI_PATH."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WSF_STARTS_WITH_MAPPING
+
+inherit
+ WSF_ROUTER_MAPPING
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_uri: READABLE_STRING_8; h: like handler)
+ do
+ handler := h
+ uri := a_uri
+ end
+
+feature -- Access
+
+ handler: WSF_STARTS_WITH_HANDLER
+
+ uri: READABLE_STRING_8
+
+feature -- Status
+
+ routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
+ local
+ p: READABLE_STRING_8
+ s: like based_uri
+ do
+ p := source_uri (req)
+ s := based_uri (uri, a_router)
+ if p.starts_with (s) then
+ Result := handler
+ a_router.execute_before (Current)
+ handler.execute (s, req, res)
+ a_router.execute_after (Current)
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ based_uri (a_uri: like uri; a_router: WSF_ROUTER): like uri
+ local
+ s: STRING_8
+ do
+ if attached a_router.base_url as l_base_url then
+ create s.make_from_string (l_base_url)
+ s.append_string (a_uri)
+ Result := s
+ else
+ Result := a_uri
+ end
+ end
+
+end
diff --git a/library/server/wsf/router/uri/default/wsf_uri_router.e b/library/server/wsf/router/uri/default/wsf_uri_router.e
deleted file mode 100644
index b4305757..00000000
--- a/library/server/wsf/router/uri/default/wsf_uri_router.e
+++ /dev/null
@@ -1,50 +0,0 @@
-note
- description: "[
- Default router based on URI map
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_ROUTER
-
-inherit
- WSF_URI_ROUTER_I [WSF_HANDLER [WSF_URI_HANDLER_CONTEXT], WSF_URI_HANDLER_CONTEXT]
- redefine
- map_agent_with_request_methods, map_agent_response_with_request_methods
- end
-
-create
- make
-
-feature -- Mapping agent
-
- map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: WSF_URI_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- local
- h: WSF_AGENT_HANDLER [WSF_URI_HANDLER_CONTEXT]
- do
- create h.make (a_action)
- map_with_request_methods (a_id, h, rqst_methods)
- end
-
- map_agent_response_with_request_methods (a_id: READABLE_STRING_8; a_action: FUNCTION [ANY, TUPLE [ctx: WSF_URI_HANDLER_CONTEXT; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- local
- h: WSF_AGENT_RESPONSE_HANDLER [WSF_URI_HANDLER_CONTEXT]
- do
- create h.make (a_action)
- map_with_request_methods (a_id, h, rqst_methods)
- end
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/uri/default/wsf_uri_routing_handler.e b/library/server/wsf/router/uri/default/wsf_uri_routing_handler.e
deleted file mode 100644
index 0d06d477..00000000
--- a/library/server/wsf/router/uri/default/wsf_uri_routing_handler.e
+++ /dev/null
@@ -1,35 +0,0 @@
-note
- description: "[
- WSF_URI_ROUTING_HANDLER is a default descendant of WSF_URI_ROUTING_HANDLER_I
- for WSF_URI_ROUTER
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_ROUTING_HANDLER
-
-inherit
- WSF_URI_ROUTING_HANDLER_I [WSF_HANDLER [WSF_URI_HANDLER_CONTEXT], WSF_URI_HANDLER_CONTEXT]
- redefine
- router
- end
-
-create
- make
-
-feature {NONE} -- Routing
-
- router: WSF_URI_ROUTER
-
-;note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/uri/wsf_uri_routing_handler_i.e b/library/server/wsf/router/uri/wsf_agent_uri_handler.e
similarity index 59%
rename from library/server/wsf/router/uri/wsf_uri_routing_handler_i.e
rename to library/server/wsf/router/uri/wsf_agent_uri_handler.e
index 81a048ae..8fda84fa 100644
--- a/library/server/wsf/router/uri/wsf_uri_routing_handler_i.e
+++ b/library/server/wsf/router/uri/wsf_agent_uri_handler.e
@@ -1,33 +1,35 @@
note
- description: "[
- This class helps to build Routing handler based for WSF_URI_ROUTER
- ]"
+ description: "Summary description for {WSF_AGENT_HANDLER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
- WSF_URI_ROUTING_HANDLER_I [H -> WSF_HANDLER [C],
- C -> WSF_URI_HANDLER_CONTEXT create make end]
+ WSF_AGENT_URI_HANDLER
inherit
- WSF_ROUTING_HANDLER [H, C]
+ WSF_URI_HANDLER
create
make
feature {NONE} -- Initialization
- make (n: INTEGER)
+ make (a_action: like action)
do
- create router.make (n)
+ action := a_action
end
-feature {NONE} -- Routing
+ action: PROCEDURE [ANY, TUPLE [request: WSF_REQUEST; response: WSF_RESPONSE]]
- router: WSF_URI_ROUTER_I [H, C]
+feature -- Execution
-;note
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ do
+ action.call ([req, res])
+ end
+
+note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
diff --git a/library/server/wsf/router/wsf_agent_response_handler.e b/library/server/wsf/router/uri/wsf_agent_uri_template_response_handler.e
similarity index 62%
rename from library/server/wsf/router/wsf_agent_response_handler.e
rename to library/server/wsf/router/uri/wsf_agent_uri_template_response_handler.e
index 56277e51..e178ccf4 100644
--- a/library/server/wsf/router/wsf_agent_response_handler.e
+++ b/library/server/wsf/router/uri/wsf_agent_uri_template_response_handler.e
@@ -1,13 +1,14 @@
note
- description: "Summary description for WSF_AGENT_RESPONSE_HANDLER."
+ description: "Summary description for {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
class
- WSF_AGENT_RESPONSE_HANDLER [C -> WSF_HANDLER_CONTEXT]
+ WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER
inherit
- WSF_RESPONSE_HANDLER [C]
+ WSF_URI_TEMPLATE_RESPONSE_HANDLER
create
make
@@ -21,11 +22,11 @@ feature -- Initialization
feature -- Access
- action: FUNCTION [ANY, TUPLE [ctx: C; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE]
+ action: FUNCTION [ANY, TUPLE [ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE]
feature -- Execution
- response (ctx: C; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
+ response (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
do
Result := action.item ([ctx, req])
end
diff --git a/library/server/wsf/router/uri/wsf_uri_handler.e b/library/server/wsf/router/uri/wsf_uri_handler.e
new file mode 100644
index 00000000..74e63523
--- /dev/null
+++ b/library/server/wsf/router/uri/wsf_uri_handler.e
@@ -0,0 +1,19 @@
+note
+ description: "Summary description for {EWF_ROUTER_URI_PATH_HANDLER}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_URI_HANDLER
+
+inherit
+ WSF_HANDLER
+
+feature -- Execution
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ deferred
+ end
+
+end
diff --git a/library/server/wsf/router/uri/wsf_uri_handler_context.e b/library/server/wsf/router/uri/wsf_uri_handler_context.e
deleted file mode 100644
index dfd880ca..00000000
--- a/library/server/wsf/router/uri/wsf_uri_handler_context.e
+++ /dev/null
@@ -1,60 +0,0 @@
-note
- description: "[
- Context for the handler execution
-
- It does not provide additional information compared to {WSF_HANDLER_CONTEXT}
- - request: WSF_REQUEST -- Associated request
- - path: READABLE_STRING_8 -- Associated path
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_HANDLER_CONTEXT
-
-inherit
- WSF_HANDLER_CONTEXT
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make (req: WSF_REQUEST; p: like path)
- do
- request := req
- path := p
- end
-
-feature -- Request data
-
- apply (req: WSF_REQUEST)
- --
- do
- end
-
- revert (req: WSF_REQUEST)
- --
- do
- end
-
-feature -- Item
-
- item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
- -- Variable value for parameter or variable `a_name'
- -- See `{WSF_REQUEST}.item(s)'
- do
- Result := request.item (a_name)
- end
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/uri/wsf_uri_mapping.e b/library/server/wsf/router/uri/wsf_uri_mapping.e
new file mode 100644
index 00000000..fcc33642
--- /dev/null
+++ b/library/server/wsf/router/uri/wsf_uri_mapping.e
@@ -0,0 +1,80 @@
+note
+ description: "Summary description for EWF_URI_PATH."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WSF_URI_MAPPING
+
+inherit
+ WSF_ROUTER_MAPPING
+
+create
+ make,
+ make_trailing_slash_ignored
+
+feature {NONE} -- Initialization
+
+ make (a_uri: READABLE_STRING_8; h: like handler)
+ do
+ handler := h
+ uri := a_uri
+ end
+
+ make_trailing_slash_ignored (a_uri: READABLE_STRING_8; h: like handler)
+ do
+ make (a_uri, h)
+ trailing_slash_ignored := True
+ end
+
+feature -- Access
+
+ handler: WSF_URI_HANDLER
+
+ uri: READABLE_STRING_8
+
+ trailing_slash_ignored: BOOLEAN
+
+feature -- Status
+
+ routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
+ local
+ p: READABLE_STRING_8
+ l_uri: like uri
+ do
+ p := source_uri (req)
+ l_uri := based_uri (uri, a_router)
+ if l_uri.ends_with ("/") then
+ if not p.ends_with ("/") then
+ p := p + "/"
+ end
+ else
+ if p.ends_with ("/") then
+ p := p.substring (1, p.count - 1)
+ end
+ end
+ if p.same_string (l_uri) then
+ Result := handler
+ a_router.execute_before (Current)
+ handler.execute (req, res)
+ a_router.execute_after (Current)
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ based_uri (a_uri: like uri; a_router: WSF_ROUTER): like uri
+ local
+ s: STRING_8
+ do
+ if attached a_router.base_url as l_base_url then
+ create s.make_from_string (l_base_url)
+ s.append_string (a_uri)
+ Result := s
+ else
+ Result := a_uri
+ end
+ end
+
+end
diff --git a/library/server/wsf/router/uri/wsf_uri_response_handler.e b/library/server/wsf/router/uri/wsf_uri_response_handler.e
new file mode 100644
index 00000000..e956fe92
--- /dev/null
+++ b/library/server/wsf/router/uri/wsf_uri_response_handler.e
@@ -0,0 +1,41 @@
+note
+ description: "Summary description for {WSF_URI_RESPONSE_HANDLER}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_URI_RESPONSE_HANDLER
+
+inherit
+ WSF_URI_HANDLER
+
+feature -- Response
+
+ response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
+ require
+ is_valid_context: is_valid_context (req)
+ deferred
+ ensure
+ Result_attached: Result /= Void
+ end
+
+feature -- Execution
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute request handler
+ do
+ res.send (response (req))
+ end
+
+note
+ copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/library/server/wsf/router/uri/wsf_uri_router_i.e b/library/server/wsf/router/uri/wsf_uri_router_i.e
deleted file mode 100644
index 3058a73d..00000000
--- a/library/server/wsf/router/uri/wsf_uri_router_i.e
+++ /dev/null
@@ -1,251 +0,0 @@
-note
- description: "[
- URL dispatcher/router based on simple URI mapping and request methods if precised
- The associated context {WSF_URI_HANDLER_CONTEXT} does not contains any additional information.
-
- The matching check if the same path is mapped, or if a substring of the path is mapped
-
- Examples:
-
- map ("/users/", users_handler)
- map_with_request_methods ("/groups/", read_groups_handler, <<"GET">>)
- map_with_request_methods ("/groups/", write_groups_handler, <<"POST", "PUT", "DELETE">>)
- map_agent_with_request_methods ("/order/", agent do_get_order, <<"GET">>)
- map_agent_with_request_methods ("/order/", agent do_post_order, <<"POST">>)
-
-
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_ROUTER_I [H -> WSF_HANDLER [C], C -> WSF_URI_HANDLER_CONTEXT create make end]
-
-inherit
- WSF_ROUTER [H, C]
-
-create
- make,
- make_with_base_url
-
-feature -- Initialization
-
- make (n: INTEGER)
- do
- create handlers.make (n)
- handlers.compare_objects
- initialize
- end
-
- make_with_base_url (n: INTEGER; a_base_url: like base_url)
- -- Make router allocated for at least `n' maps,
- -- and use `a_base_url' as base_url
- do
- make (n)
- set_base_url (a_base_url)
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Status report
-
- handlers_matching_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable LIST [H]
- local
- l_res: READABLE_STRING_8
- do
- l_res := based_resource (a_resource)
- across
- handlers as c
- loop
- if c.item.resource.same_string (l_res) then
- if
- rqst_methods = Void or else
- across rqst_methods as rq some is_matching_request_methods (rq.item, c.item.request_methods) end
- then
- if Result = Void then
- create {ARRAYED_LIST [H]} Result.make (1)
- end
- Result.extend (c.item.handler)
- end
- end
- end
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Default: implementation
-
- default_handler_context (req: WSF_REQUEST): C
- --
- do
- Result := handler_context (Void, req)
- end
-
-feature -- Registration
-
- map_with_request_methods (p: READABLE_STRING_8; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
- local
- l_uri: READABLE_STRING_8
- do
- if attached base_url as l_base_url then
- l_uri := l_base_url + p
- else
- l_uri := p
- end
- handlers.force ([h, l_uri, rqst_methods])
- h.on_handler_mapped (l_uri, rqst_methods)
- end
-
-feature {NONE} -- Implementation
-
- based_resource (a_resource: READABLE_STRING_8): READABLE_STRING_8
- do
- if attached base_url as l_base_url then
- Result := l_base_url + a_resource
- else
- Result := a_resource
- end
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Handler
-
- matching_route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
- local
- h: detachable H
- ctx: detachable C
- rq_method: READABLE_STRING_8
- do
- rq_method := request_method (req)
-
- h := handler_by_path (source_uri (req), rq_method)
- if h = Void then
- if attached smart_handler_by_path (source_uri (req), rq_method) as info then
- h := info.handler
- ctx := handler_context (info.path, req)
- end
- end
- if h /= Void then
- if h.is_valid_context (req) then
- if ctx = Void then
- ctx := handler_context (Void, req)
- end
- create Result.make (h, ctx)
- else
- Result := Void
- end
- end
- end
-
-feature {NONE} -- Access: Implementation
-
- handler_by_path (a_path: READABLE_STRING_GENERAL; rqst_method: READABLE_STRING_8): detachable H
- require
- a_path_valid: a_path /= Void
- local
- l_handlers: like handlers
- l_item: like handlers.item
- do
- l_handlers := handlers
- from
- l_handlers.start
- until
- l_handlers.after or Result /= Void
- loop
- l_item := l_handlers.item
- if is_matching_request_methods (rqst_method, l_item.request_methods) and a_path.same_string (l_item.resource) then
- Result := l_item.handler
- end
- l_handlers.forth
- end
- ensure
- a_path_unchanged: a_path.same_string (old a_path)
- end
-
- smart_handler_by_path (a_path: READABLE_STRING_8; rqst_method: READABLE_STRING_8): detachable TUPLE [path: READABLE_STRING_8; handler: H]
- require
- a_path_valid: a_path /= Void
- local
- p: INTEGER
- l_context_path, l_path: READABLE_STRING_8
- h: detachable H
- do
- l_context_path := context_path (a_path)
- from
- p := l_context_path.count + 1
- until
- p <= 1 or Result /= Void
- loop
- l_path := l_context_path.substring (1, p - 1)
- h := handler_by_path (l_path, rqst_method)
- if h /= Void then
- Result := [l_path, h]
- else
- p := l_context_path.last_index_of ('/', p - 1)
- end
- variant
- p
- end
- ensure
- a_path_unchanged: a_path.same_string (old a_path)
- end
-
-feature {NONE} -- Context factory
-
- handler_context (p: detachable STRING; req: WSF_REQUEST): C
- local
- ctx: C
- do
- if p /= Void then
- create ctx.make (req, p)
- else
- create ctx.make (req, source_uri (req))
- end
- Result := ctx
- end
-
-feature -- Access
-
- new_cursor: ITERATION_CURSOR [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
- -- Fresh cursor associated with current structure
- do
- Result := handlers.new_cursor
- end
-
-feature {NONE} -- Implementation
-
- handlers: ARRAYED_LIST [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
- -- Handlers indexed by the template expression
- -- see `templates'
-
- context_path (a_path: READABLE_STRING_8): READABLE_STRING_8
- -- Prepared path from context which match requirement
- -- i.e: not empty, starting with '/'
- local
- p: INTEGER
- s: STRING_8
- do
- Result := a_path
- if Result.is_empty then
- Result := "/"
- else
- if Result[1] /= '/' then
- create s.make_from_string (Result)
- s.prepend_character ('/')
- Result := s
- end
- p := Result.index_of ('.', 1)
- if p > 0 then
- Result := Result.substring (1, p - 1)
- end
- end
- ensure
- result_not_empty: not Result.is_empty
- end
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/wsf_response_handler.e b/library/server/wsf/router/uri/wsf_uri_template_response_handler.e
similarity index 59%
rename from library/server/wsf/router/wsf_response_handler.e
rename to library/server/wsf/router/uri/wsf_uri_template_response_handler.e
index 15f60f76..fa8493c0 100644
--- a/library/server/wsf/router/wsf_response_handler.e
+++ b/library/server/wsf/router/uri/wsf_uri_template_response_handler.e
@@ -1,25 +1,18 @@
note
- description: "[
- Request handler object which is called by a WSF_ROUTER
- A response handler should implement the method
-
- response (ctx: C; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
-
-
- The class is generic, this way one can use a custom WSF_HANDLER_CONTEXT if needed
- ]"
+ description: "Summary description for {WSF_URI_TEMPLATE_RESPONSE_HANDLER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
- WSF_RESPONSE_HANDLER [C -> WSF_HANDLER_CONTEXT]
+ WSF_URI_TEMPLATE_RESPONSE_HANDLER
inherit
- WSF_HANDLER [C]
+ WSF_URI_TEMPLATE_HANDLER
feature -- Response
- response (ctx: C; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
+ response (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
require
is_valid_context: is_valid_context (req)
deferred
@@ -29,7 +22,7 @@ feature -- Response
feature -- Execution
- execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ execute (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
res.send (response (ctx, req))
diff --git a/library/server/wsf/router/uri_template/default/wsf_uri_template_routed_service.e b/library/server/wsf/router/uri_template/default/wsf_uri_template_routed_service.e
deleted file mode 100644
index af11bf51..00000000
--- a/library/server/wsf/router/uri_template/default/wsf_uri_template_routed_service.e
+++ /dev/null
@@ -1,39 +0,0 @@
-note
- description: "Summary description for {DEFAULT_URI_TEMPLATE_ROUTED_SERVICE}."
- author: ""
- date: "$Date$"
- revision: "$Revision$"
-
-deferred class
- WSF_URI_TEMPLATE_ROUTED_SERVICE
-
-inherit
- WSF_ROUTED_SERVICE_I [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
- redefine
- router
- end
-
-feature {NONE} -- Initialization
-
- create_router
- -- Create router
- --| it can be redefine to create with precise count if needed.
- do
- create router.make (0)
- end
-
-feature -- Router
-
- router: WSF_URI_TEMPLATE_ROUTER
-
-;note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/uri_template/default/wsf_uri_template_router.e b/library/server/wsf/router/uri_template/default/wsf_uri_template_router.e
deleted file mode 100644
index e537d0bd..00000000
--- a/library/server/wsf/router/uri_template/default/wsf_uri_template_router.e
+++ /dev/null
@@ -1,52 +0,0 @@
-note
- description: "[
- Default router based on URI Template map
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_TEMPLATE_ROUTER
-
-inherit
- WSF_URI_TEMPLATE_ROUTER_I [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
- redefine
- map_agent_with_request_methods,
- map_agent_response_with_request_methods
- end
-
-create
- make,
- make_with_base_url
-
-feature -- Mapping agent
-
- map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- local
- h: WSF_AGENT_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
- do
- create h.make (a_action)
- map_with_request_methods (a_id, h, rqst_methods)
- end
-
- map_agent_response_with_request_methods (a_id: READABLE_STRING_8; a_action: FUNCTION [ANY, TUPLE [ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- local
- h: WSF_AGENT_RESPONSE_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
- do
- create h.make (a_action)
- map_with_request_methods (a_id, h, rqst_methods)
- end
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/uri_template/default/wsf_uri_template_routing_handler.e b/library/server/wsf/router/uri_template/default/wsf_uri_template_routing_handler.e
deleted file mode 100644
index f51843a7..00000000
--- a/library/server/wsf/router/uri_template/default/wsf_uri_template_routing_handler.e
+++ /dev/null
@@ -1,35 +0,0 @@
-note
- description: "[
- WSF_URI_TEMPLATE_ROUTING_HANDLER is a default descendant of WSF_URI_ROUTING_HANDLER_I
- for WSF_URI_TEMPLATE_ROUTER
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_TEMPLATE_ROUTING_HANDLER
-
-inherit
- WSF_URI_TEMPLATE_ROUTING_HANDLER_I [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
- redefine
- router
- end
-
-create
- make
-
-feature {NONE} -- Routing
-
- router: WSF_URI_TEMPLATE_ROUTER
-
-;note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/wsf_agent_handler.e b/library/server/wsf/router/uri_template/wsf_agent_uri_template_handler.e
similarity index 55%
rename from library/server/wsf/router/wsf_agent_handler.e
rename to library/server/wsf/router/uri_template/wsf_agent_uri_template_handler.e
index a8afaf5a..99950925 100644
--- a/library/server/wsf/router/wsf_agent_handler.e
+++ b/library/server/wsf/router/uri_template/wsf_agent_uri_template_handler.e
@@ -1,31 +1,30 @@
note
- description: "Summary description for WSF_AGENT_HANDLER."
+ description: "Summary description for {WSF_AGENT_URI_TEMPLATE_HANDLER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
class
- WSF_AGENT_HANDLER [C -> WSF_HANDLER_CONTEXT]
+ WSF_AGENT_URI_TEMPLATE_HANDLER
inherit
- WSF_HANDLER [C]
+ WSF_URI_TEMPLATE_HANDLER
create
make
-feature -- Initialization
+feature {NONE} -- Initialization
- make (act: like action)
+ make (a_action: like action)
do
- action := act
+ action := a_action
end
-feature -- Access
-
- action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]
+ action: PROCEDURE [ANY, TUPLE [context: WSF_URI_TEMPLATE_HANDLER_CONTEXT; request: WSF_REQUEST; response: WSF_RESPONSE]]
feature -- Execution
- execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ execute (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
action.call ([ctx, req, res])
end
diff --git a/library/server/wsf/router/uri_template/wsf_uri_template_handler.e b/library/server/wsf/router/uri_template/wsf_uri_template_handler.e
new file mode 100644
index 00000000..3f5d8f96
--- /dev/null
+++ b/library/server/wsf/router/uri_template/wsf_uri_template_handler.e
@@ -0,0 +1,19 @@
+note
+ description: "Summary description for EWF_URI_TEMPLATE_HANDLER."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_URI_TEMPLATE_HANDLER
+
+inherit
+ WSF_HANDLER
+
+feature -- Execution
+
+ execute (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
+ deferred
+ end
+
+end
diff --git a/library/server/wsf/router/uri_template/wsf_uri_template_mapping.e b/library/server/wsf/router/uri_template/wsf_uri_template_mapping.e
new file mode 100644
index 00000000..2623af3f
--- /dev/null
+++ b/library/server/wsf/router/uri_template/wsf_uri_template_mapping.e
@@ -0,0 +1,81 @@
+note
+ description: "Summary description for {EWF_ROUTER_URI_TEMPLATE_PATH}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WSF_URI_TEMPLATE_MAPPING
+
+inherit
+ WSF_ROUTER_MAPPING
+
+create
+ make,
+ make_from_string
+
+feature {NONE} -- Initialization
+
+ make_from_string (s: READABLE_STRING_8; h: like handler)
+ do
+ make (create {URI_TEMPLATE}.make (s), h)
+ end
+
+ make (tpl: URI_TEMPLATE; h: like handler)
+ do
+ template := tpl
+ handler := h
+ end
+
+feature -- Access
+
+ handler: WSF_URI_TEMPLATE_HANDLER
+
+ template: URI_TEMPLATE
+
+feature -- Element change
+
+ set_handler (h: like handler)
+ do
+ handler := h
+ end
+
+feature -- Status
+
+ routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
+ local
+ tpl: URI_TEMPLATE
+ p: READABLE_STRING_32
+ ctx: detachable WSF_URI_TEMPLATE_HANDLER_CONTEXT
+ do
+ p := source_uri (req)
+ tpl := based_uri_template (template, a_router)
+ if attached tpl.match (p) as tpl_res then
+ Result := handler
+ create ctx.make (req, tpl, tpl_res, source_uri (req))
+ a_router.execute_before (Current)
+ ctx.apply (req)
+ handler.execute (ctx, req, res)
+ ctx.revert (req)
+ a_router.execute_after (Current)
+ end
+ rescue
+ if ctx /= Void then
+ ctx.revert (req)
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ based_uri_template (a_tpl: like template; a_router: WSF_ROUTER): like template
+ do
+ if attached a_router.base_url as l_base_url then
+ Result := a_tpl.duplicate
+ Result.set_template (l_base_url + a_tpl.template)
+ else
+ Result := a_tpl
+ end
+ end
+
+
+end
diff --git a/library/server/wsf/router/uri_template/wsf_uri_template_router_i.e b/library/server/wsf/router/uri_template/wsf_uri_template_router_i.e
deleted file mode 100644
index 24ac6ea3..00000000
--- a/library/server/wsf/router/uri_template/wsf_uri_template_router_i.e
+++ /dev/null
@@ -1,228 +0,0 @@
-note
- description: "[
- URL dispatcher/router based on URI Template mapping and request methods if precised
- The associated context {WSF_URI_TEMPLATE_HANDLER_CONTEXT} contains information about the matched map.
-
- Examples:
-
- map ("/users/", users_handler)
- map_with_request_methods ("/order/{order-id}", order_handler, <<"GET", "POST">>)
- map_agent_with_request_methods ("/order/{order-id}", agent do_get_order, <<"GET">>)
- map_agent_with_request_methods ("/order/{order-id}", agent do_post_order, <<"POST">>)
-
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_TEMPLATE_ROUTER_I [H -> WSF_HANDLER [C], C -> WSF_URI_TEMPLATE_HANDLER_CONTEXT create make end]
-
-inherit
- WSF_ROUTER [H, C]
-
-create
- make,
- make_with_base_url
-
-feature -- Initialization
-
- make (n: INTEGER)
- do
- create handlers.make (n)
- create templates.make (n)
- handlers.compare_objects
- initialize
- end
-
- make_with_base_url (n: INTEGER; a_base_url: like base_url)
- -- Make router allocated for at least `n' maps,
- -- and use `a_base_url' as base_url
- do
- make (n)
- set_base_url (a_base_url)
- end
-
-feature -- Status report
-
- handlers_matching_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable LIST [H]
- local
- l_res: READABLE_STRING_8
- do
- l_res := based_resource (a_resource)
- across
- handlers as c
- loop
- if c.item.resource.same_string (l_res) then
- if
- rqst_methods = Void or else
- across rqst_methods as rq some is_matching_request_methods (rq.item, c.item.request_methods) end
- then
- if Result = Void then
- create {ARRAYED_LIST [H]} Result.make (1)
- end
- Result.extend (c.item.handler)
- end
- end
- end
- end
-
-feature -- Registration
-
- map_with_uri_template (uri: URI_TEMPLATE; h: H)
- require
- has_not_such_map: not has_map (uri.template, Void, h)
- do
- map_with_uri_template_and_request_methods (uri, h, Void)
- end
-
- map_with_uri_template_and_request_methods (uri: URI_TEMPLATE; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
- require
- uri_is_valid: uri.is_valid
- has_not_such_map: not has_map (uri.template, rqst_methods, h)
- local
- l_tpl: like {URI_TEMPLATE}.template
- l_uri: URI_TEMPLATE
- do
- l_uri := based_uri (uri)
- l_tpl := l_uri.template
-
- handlers.force ([h, l_tpl, rqst_methods])
- templates.force (l_uri, l_tpl)
- h.on_handler_mapped (l_tpl, rqst_methods)
- end
-
- map_with_request_methods (tpl: READABLE_STRING_8; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
- do
- map_with_uri_template_and_request_methods (create {URI_TEMPLATE}.make (tpl), h, rqst_methods)
- end
-
-feature {NONE} -- Implementation
-
- based_uri (uri: URI_TEMPLATE): URI_TEMPLATE
- do
- if attached base_url as l_base_url then
- Result := uri.duplicate
- Result.set_template (l_base_url + uri.template)
- else
- Result := uri
- end
- end
-
- based_resource (a_resource: READABLE_STRING_8): READABLE_STRING_8
- do
- if attached base_url as l_base_url then
- Result := l_base_url + a_resource
- else
- Result := a_resource
- end
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Handler
-
- matching_route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
- local
- l_handlers: like handlers
- t: READABLE_STRING_8
- p: READABLE_STRING_8
- l_req_method: READABLE_STRING_8
- l_res: URI_TEMPLATE_MATCH_RESULT
- do
- p := source_uri (req)
- from
- l_req_method := request_method (req)
- l_handlers := handlers
- l_handlers.start
- until
- l_handlers.after or Result /= Void
- loop
- if attached l_handlers.item as l_info then
- if is_matching_request_methods (l_req_method, l_info.request_methods) then
- t := l_info.resource
- if
- attached {WSF_ROUTING_HANDLER [H, C]} l_info.handler as rah and then
- p.starts_with (t)
- then
- create l_res.make_empty
- l_res.path_variables.force (p.substring (t.count + 1, p.count), "path")
-
- create Result.make (l_info.handler, handler_context (p, req, create {URI_TEMPLATE}.make (t), l_res))
- elseif attached templates.item (t) as tpl and then
- attached tpl.match (p) as res
- then
- create Result.make (l_info.handler, handler_context (p, req, tpl, res))
- end
- end
- end
- l_handlers.forth
- end
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Default: implementation
-
- default_handler_context (req: WSF_REQUEST): C
- --
- do
- Result := handler_context (Void, req, create {URI_TEMPLATE}.make ("/"), create {URI_TEMPLATE_MATCH_RESULT}.make_empty)
- end
-
-feature {NONE} -- Context factory
-
- handler_context (p: detachable READABLE_STRING_8; req: WSF_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT): C
- do
- if p /= Void then
- create Result.make (req, tpl, tpl_res, p)
- else
- create Result.make (req, tpl, tpl_res, source_uri (req))
- end
- end
-
-feature -- Access: ITERABLE
-
- new_cursor: ITERATION_CURSOR [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
- -- Fresh cursor associated with current structure
- do
- Result := handlers.new_cursor
- end
-
-feature {NONE} -- Implementation
-
- handlers: ARRAYED_LIST [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
- -- Handlers indexed by the template expression
- -- see `templates'
-
- templates: HASH_TABLE [URI_TEMPLATE, READABLE_STRING_8]
- -- URI Template indexed by the template expression
-
- context_path (a_path: STRING): STRING
- -- Prepared path from context which match requirement
- -- i.e: not empty, starting with '/'
- local
- p: INTEGER
- do
- Result := a_path
- if Result.is_empty then
- Result := "/"
- else
- if Result[1] /= '/' then
- Result := "/" + Result
- end
- p := Result.index_of ('.', 1)
- if p > 0 then
- Result := Result.substring (1, p - 1)
- end
- end
- ensure
- result_not_empty: not Result.is_empty
- end
-
-;note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/uri_template/wsf_uri_template_routing_handler_i.e b/library/server/wsf/router/uri_template/wsf_uri_template_routing_handler_i.e
deleted file mode 100644
index d6fd3dcf..00000000
--- a/library/server/wsf/router/uri_template/wsf_uri_template_routing_handler_i.e
+++ /dev/null
@@ -1,47 +0,0 @@
-note
- description: "[
- This class helps to build Routing handler based for WSF_URI_TEMPLATE_ROUTER
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_URI_TEMPLATE_ROUTING_HANDLER_I [H -> WSF_HANDLER [C],
- C -> WSF_URI_TEMPLATE_HANDLER_CONTEXT create make end]
-
-inherit
- WSF_ROUTING_HANDLER [H, C]
-
-create
- make,
- make_with_base_url
-
-feature {NONE} -- Initialization
-
- make (n: INTEGER)
- do
- create router.make (n)
- end
-
- make_with_base_url (n: INTEGER; a_base_url: like base_url)
- -- Make allocated for at least `n' maps,
- -- and use `a_base_url' as base_url
- do
- create router.make_with_base_url (n, a_base_url)
- end
-
-feature {NONE} -- Routing
-
- router: WSF_URI_TEMPLATE_ROUTER_I [H, C]
-
-;note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/wsf_file_system_handler.e b/library/server/wsf/router/wsf_file_system_handler.e
index fc18bedb..01626c60 100644
--- a/library/server/wsf/router/wsf_file_system_handler.e
+++ b/library/server/wsf/router/wsf_file_system_handler.e
@@ -1,43 +1,69 @@
note
- description: "[
- Request handler used to respond file system request.
- ]"
+ description: "Summary description for {WSF_FILE_SYSTEM_HANDLER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
class
- WSF_FILE_SYSTEM_HANDLER [C -> WSF_HANDLER_CONTEXT]
+ WSF_FILE_SYSTEM_HANDLER
inherit
- WSF_HANDLER [C]
+ WSF_STARTS_WITH_HANDLER
+ rename
+ execute as execute_starts_with
+ end
create
make
feature {NONE} -- Initialization
- make (a_root: READABLE_STRING_8)
+ make (d: like document_root)
require
- a_root_exists: node_exists (a_root)
+ valid_d: (d /= Void and then not d.is_empty) implies d.ends_with ("/")
+ local
+ e: EXECUTION_ENVIRONMENT
do
- document_root := a_root
+ if d.is_empty then
+ create e
+ document_root := e.current_working_directory
+ else
+ document_root := d
+ end
end
-feature -- Access
+feature -- Access
- document_root: READABLE_STRING_8
- -- Document root for the file system
+ document_root: STRING
+ max_age: INTEGER
+
+ index_disabled: BOOLEAN
+ -- Index disabled?
directory_index: detachable ARRAY [READABLE_STRING_8]
-- File serve if a directory index is requested
- not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]
-
- access_denied_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]
+ not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE]]
+ access_denied_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE]]
feature -- Element change
+ enable_index
+ do
+ index_disabled := False
+ end
+
+ disable_index
+ do
+ index_disabled := True
+ end
+
+ set_max_age (a_seconds: like max_age)
+ do
+ max_age := a_seconds
+ end
+
set_directory_index (idx: like directory_index)
-- Set `directory_index' as `idx'
do
@@ -62,38 +88,25 @@ feature -- Element change
feature -- Execution
- requested_path (ctx: C): detachable READABLE_STRING_8
- -- Path associated with the request
- -- i.e: path of the file system resource if any
- do
- if attached {WSF_STRING} ctx.item ("path") as v_path then
- Result := v_path.value.as_string_8
- end
- end
-
- execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Execute request handler
+ execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
- h: HTTP_HEADER
- s: STRING
+ p: STRING
do
- if attached requested_path (ctx) as uri then
- process_uri (uri, ctx, req, res)
+ p := req.path_info
+ if p.starts_with (a_start_path) then
+ p.remove_head (a_start_path.count)
else
- s := "Hello " + ctx.path + "%N"
- s.append ("root=" + document_root)
-
- create h.make
- h.put_content_type_text_html
- h.put_content_length (s.count)
-
- res.set_status_code ({HTTP_STATUS_CODE}.ok)
- res.put_header_text (h.string)
- res.put_string (s)
+ check starts_with_base: False end
end
+ process_uri (p, req, res)
end
- process_uri (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ execute_starts_with (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
+ do
+ execute (a_start_path,req, res)
+ end
+
+ process_uri (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
f: RAW_FILE
fn: READABLE_STRING_8
@@ -103,19 +116,23 @@ feature -- Execution
if f.exists then
if f.is_readable then
if f.is_directory then
- respond_index (req.request_uri, fn, ctx, req, res)
+ if index_disabled then
+ process_directory_index_disabled (uri, req, res)
+ else
+ process_index (req.request_uri, fn, req, res)
+ end
else
- respond_file (f, ctx, req, res)
+ process_file (f, req, res)
end
else
- respond_access_denied (uri, ctx, req, res)
+ process_access_denied (uri, req, res)
end
else
- respond_not_found (uri, ctx, req, res)
+ process_not_found (uri, req, res)
end
end
- respond_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ process_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
h: HTTP_HEADER
uri, s: STRING_8
@@ -124,7 +141,7 @@ feature -- Execution
do
create d.make_open_read (dn)
if attached directory_index_file (d) as f then
- respond_file (f, ctx, req, res)
+ process_file (f, req, res)
else
uri := a_uri
if not uri.is_empty and then uri [uri.count] /= '/' then
@@ -170,31 +187,72 @@ feature -- Execution
d.close
end
- respond_file (f: FILE; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ process_file (f: FILE; req: WSF_REQUEST; res: WSF_RESPONSE)
local
ext: READABLE_STRING_8
ct: detachable READABLE_STRING_8
fres: WSF_FILE_RESPONSE
+ dt: DATE_TIME
do
ext := extension (f.name)
ct := extension_mime_mapping.mime_type (ext)
if ct = Void then
ct := {HTTP_MIME_TYPES}.application_force_download
end
- create fres.make_with_content_type (ct, f.name)
- fres.set_status_code ({HTTP_STATUS_CODE}.ok)
- fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head))
+ if
+ attached req.meta_string_variable ("HTTP_IF_MODIFIED_SINCE") as s_if_modified_since and then
+ attached file_date (f) as f_date and then (f_date >= rfc1123_http_date_format_to_date (s_if_modified_since))
+ then
+ process_not_modified (f_date, req, res)
+ else
+ create fres.make_with_content_type (ct, f.name)
+ fres.set_status_code ({HTTP_STATUS_CODE}.ok)
- res.send (fres)
+ -- cache control
+ create dt.make_now_utc
+ fres.header.put_cache_control ("private, max-age=" + max_age.out)
+ fres.header.put_utc_date (dt)
+ if max_age > 0 then
+ dt := dt.twin
+ dt.second_add (max_age)
+ end
+ fres.header.put_expires_date (dt)
+
+ fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head))
+ res.send (fres)
+ end
end
- respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ process_not_modified (a_utc_date: detachable DATE_TIME; req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ h: HTTP_HEADER
+ dt: DATE_TIME
+ do
+ create dt.make_now_utc
+ create h.make
+ h.put_cache_control ("private, max-age=" + max_age.out)
+ h.put_utc_date (dt)
+ if max_age > 0 then
+ dt := dt.twin
+ dt.second_add (max_age)
+ end
+ h.put_expires_date (dt)
+
+ if a_utc_date /= Void then
+ h.put_last_modified (a_utc_date)
+ end
+ res.set_status_code ({HTTP_STATUS_CODE}.not_modified)
+ res.put_header_text (h.string)
+ res.flush
+ end
+
+ process_not_found (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
h: HTTP_HEADER
s: STRING_8
do
if attached not_found_handler as hdl then
- hdl.call ([uri, ctx, req, res])
+ hdl.call ([uri, req, res])
else
create h.make
h.put_content_type_text_plain
@@ -208,13 +266,13 @@ feature -- Execution
end
end
- respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
+ process_access_denied (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
h: HTTP_HEADER
s: STRING_8
do
if attached access_denied_handler as hdl then
- hdl.call ([uri, ctx, req, res])
+ hdl.call ([uri, req, res])
else
create h.make
h.put_content_type_text_plain
@@ -228,6 +286,26 @@ feature -- Execution
end
end
+ process_directory_index_disabled (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ h: HTTP_HEADER
+ s: STRING_8
+ do
+ if attached access_denied_handler as hdl then
+ hdl.call ([uri, req, res])
+ else
+ create h.make
+ h.put_content_type_text_plain
+ create s.make_empty
+ s.append ("Directory index: Access denied%N")
+ res.set_status_code ({HTTP_STATUS_CODE}.forbidden)
+ h.put_content_length (s.count)
+ res.put_header_text (h.string)
+ res.put_string (s)
+ res.flush
+ end
+ end
+
feature {NONE} -- Implementation
directory_index_file (d: DIRECTORY): detachable FILE
@@ -343,14 +421,33 @@ feature {NONE} -- Implementation
end
end
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
+feature {NONE} -- implementation: date time
+
+ date_time_utility: HTTP_DATE_TIME_UTILITIES
+ once
+ create Result
+ end
+
+ file_date (f: FILE): DATE_TIME
+ do
+ Result := timestamp_to_date (f.date)
+ end
+
+ rfc1123_http_date_format_to_date (s: STRING): DATE_TIME
+ -- String representation of `dt' using the RFC 1123
+ local
+ t: STRING
+ do
+ t := s
+ if t.ends_with ("GMT") then
+ t := t.substring (1, t.count - 4)
+ end
+ create Result.make_from_string (t, "ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2")
+ end
+
+ timestamp_to_date (n: INTEGER): DATE_TIME
+ do
+ Result := date_time_utility.unix_time_stamp_to_date_time (n)
+ end
+
end
diff --git a/library/server/wsf/router/wsf_handler.e b/library/server/wsf/router/wsf_handler.e
index 0bdf431d..17d8d161 100644
--- a/library/server/wsf/router/wsf_handler.e
+++ b/library/server/wsf/router/wsf_handler.e
@@ -1,20 +1,11 @@
note
- description: "[
- Request handler object which is called by a WSF_ROUTER
- An handler should implement the method
-
- execute (ctx, req, res)
-
- The class is generic, this way one can use a custom WSF_HANDLER_CONTEXT if needed
- ]"
+ description: "Summary description for {WSF_HANDLER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
- WSF_HANDLER [C -> WSF_HANDLER_CONTEXT]
-
-inherit
- ANY
+ WSF_HANDLER
feature -- Status report
@@ -23,60 +14,10 @@ feature -- Status report
do
Result := True
end
+
+feature {WSF_ROUTER} -- Mapping change
-feature -- Execution
-
- execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Execute request handler
- --
- -- `ctx': contains advanced data related to request_uri
- -- in the case of URI_TEMPLATE, it add support for "path_parameter"
- -- `req': request data
- -- `res': reponse stream
- --| note `ctx' can also provide data coming from `req'
- require
- is_valid_context: is_valid_context (req)
- deferred
- ensure
- response_status_set: res.status_is_set
- end
-
-feature -- Execution: report
-
- url (req: WSF_REQUEST; a_base: detachable READABLE_STRING_8; args: detachable STRING; abs: BOOLEAN): STRING
- -- Associated url based on `a_base' and `args'
- -- if `abs' then return absolute url
- local
- s: detachable STRING
- l_base: STRING
- do
- if a_base /= Void then
- l_base := a_base
- else
- l_base := req.request_uri
- end
- s := args
- if s /= Void and then s.count > 0 then
- if s[1] /= '/' then
- s := l_base + "/" + s
- else
- s := l_base + s
- end
- else
- s := l_base
- end
- if abs then
- Result := req.absolute_script_url (s)
- else
- Result := req.script_url (s)
- end
- ensure
- result_attached: Result /= Void
- end
-
-feature {WSF_ROUTER} -- Routes change
-
- on_handler_mapped (a_resource: READABLE_STRING_8; a_rqst_methods: detachable WSF_ROUTER_METHODS)
+ on_mapped (a_mapping: WSF_ROUTER_MAPPING; a_rqst_methods: detachable WSF_ROUTER_METHODS)
-- Callback called when a router map a route to Current handler
do
end
diff --git a/library/server/wsf/router/wsf_route.e b/library/server/wsf/router/wsf_route.e
deleted file mode 100644
index 57afda65..00000000
--- a/library/server/wsf/router/wsf_route.e
+++ /dev/null
@@ -1,45 +0,0 @@
-note
- description: "[
- a WSF_ROUTE object associates a handler and the associated context at runtime
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-class
- WSF_ROUTE [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make (h: H; c: C)
- -- Instantiate Current with `h' and `c'
- do
- handler := h
- context := c
- end
-
-feature -- Access
-
- handler: H
- -- Handler
-
- context: C
- -- Context associated to `handler' for execution
-
-invariant
- handler /= Void
- context /= Void
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end
diff --git a/library/server/wsf/router/wsf_router.e b/library/server/wsf/router/wsf_router.e
index 0171b1d4..c1403d0b 100644
--- a/library/server/wsf/router/wsf_router.e
+++ b/library/server/wsf/router/wsf_router.e
@@ -1,111 +1,120 @@
note
- description: "[
- URL dispatcher/router based on deferred mapping (to be defined in descendant)
- The associated context {WSF_HANDLER_CONTEXT} does contains information related to the matching at runtime.
- ]"
+ description: "Summary description for {EWF_ROUTER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
-deferred class
- WSF_ROUTER [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
+class
+ WSF_ROUTER
inherit
- ITERABLE [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
+ ITERABLE [TUPLE [mapping: WSF_ROUTER_MAPPING; request_methods: detachable WSF_ROUTER_METHODS]]
+
+create
+ make,
+ make_with_base_url
feature {NONE} -- Initialization
+ make (n: INTEGER)
+ do
+ create mappings.make (n)
+ initialize
+ end
+
+ make_with_base_url (n: INTEGER; a_base_url: like base_url)
+ -- Make router allocated for at least `n' maps,
+ -- and use `a_base_url' as base_url
+ do
+ make (n)
+ set_base_url (a_base_url)
+ end
+
initialize
-- Initialize router
do
- create pre_route_execution_actions
+ create mappings.make (10)
+ create pre_execution_actions
end
-feature -- Status report
-
- has_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS; a_handler: detachable H): BOOLEAN
- -- Has a map corresponding to `a_resource' and `rqst_methods' other than `a_handler'?
- do
- if attached handlers_matching_map (a_resource, rqst_methods) as lst then
- Result := a_handler = Void or else not lst.has (a_handler)
- end
- end
-
- handlers_matching_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable LIST [H]
- -- Existing handlers matching map with `a_resource' and `rqst_methods'
- deferred
- end
+ mappings: ARRAYED_LIST [TUPLE [mapping: WSF_ROUTER_MAPPING; request_methods: detachable WSF_ROUTER_METHODS]]
+ -- Existing mappings
feature -- Mapping
- map (a_resource: READABLE_STRING_8; h: H)
- -- Map handler `h' with `a_resource'
- require
- has_not_such_map: not has_map (a_resource, Void, h)
+ map (a_mapping: WSF_ROUTER_MAPPING)
+ -- Map `a_mapping'
do
- map_with_request_methods (a_resource, h, Void)
+ map_with_request_methods (a_mapping, Void)
end
- map_routing (a_resource: READABLE_STRING_8; h: H)
- -- Map handler `h' with `a_resource'
- require
- has_not_such_map: not has_map (a_resource, Void, h)
+ map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_ROUTER_METHODS)
+ -- Map `a_mapping' for request methods `rqst_methods'
do
- map (a_resource, h)
+ mappings.extend ([a_mapping, rqst_methods])
+ a_mapping.handler.on_mapped (a_mapping, rqst_methods)
end
- map_with_request_methods (a_resource: READABLE_STRING_8; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
- -- Map handler `h' with `a_resource' and `rqst_methods'
- require
- has_not_such_map: not has_map (a_resource, rqst_methods, h)
- deferred
- end
+feature -- Access
-feature -- Mapping agent
+ is_dispatched: BOOLEAN
+ -- `dispatch' set `is_dispatched' to True
+ -- if handler was found and executed
- map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]])
- -- Map `a_action' as an handler with `a_resource'
+ dispatch (req: WSF_REQUEST; res: WSF_RESPONSE)
do
- map_agent_with_request_methods (a_resource, a_action, Void)
- end
-
- map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- -- Map `a_action' as an handler with `a_resource' and `rqst_methods'
- local
- rah: WSF_AGENT_HANDLER [C]
- do
- create rah.make (a_action)
- if attached {H} rah as h then
- map_with_request_methods (a_resource, h, rqst_methods)
- else
- check valid_agent_handler: False end
+ if attached dispatch_and_return_handler (req, res) then
+ check is_dispatched: is_dispatched end
end
end
-feature -- Mapping response agent
-
- map_agent_response (a_resource: READABLE_STRING_8; a_function: FUNCTION [ANY, TUPLE [ctx: C; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE])
- -- Map response as Result `a_function' as an handler with `a_resource'
- do
- map_agent_response_with_request_methods (a_resource, a_function, Void)
- end
-
- map_agent_response_with_request_methods (a_resource: READABLE_STRING_8; a_function: FUNCTION [ANY, TUPLE [ctx: C; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- -- Map response as Result `a_function' as an handler with `a_resource' and `rqst_methods'
+ dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable WSF_HANDLER
local
- rah: WSF_AGENT_RESPONSE_HANDLER [C]
+ l_req_method: READABLE_STRING_8
+ m: WSF_ROUTER_MAPPING
do
- create rah.make (a_function)
- if attached {H} rah as h then
- map_with_request_methods (a_resource, h, rqst_methods)
- else
- check valid_agent_handler: False end
+ is_dispatched := False
+ l_req_method := request_method (req)
+
+ across
+ mappings as c
+ until
+ Result /= Void
+ loop
+ if attached c.item as l_info then
+ if is_matching_request_methods (l_req_method, l_info.request_methods) then
+ m := l_info.mapping
+ if attached m.routed_handler (req, res, Current) as r then
+ is_dispatched := True
+ Result := r
+ end
+ end
+ end
end
end
+feature -- Hook
+
+ execute_before (a_mapping: WSF_ROUTER_MAPPING)
+ do
+ pre_execution_actions.call ([a_mapping])
+ end
+
+ execute_after (a_mapping: WSF_ROUTER_MAPPING)
+ do
+ end
+
+ pre_execution_actions: ACTION_SEQUENCE [TUPLE [WSF_ROUTER_MAPPING]]
+ -- Action triggered before a route is execute
+ --| Could be used for tracing, logging
+
feature -- Base url
+ count: INTEGER
+ do
+ Result := mappings.count
+ end
+
base_url: detachable READABLE_STRING_8
-- Common start of any route url
@@ -115,6 +124,7 @@ feature -- Element change
-- Set `base_url' to `a_base_url'
-- make sure no map is already added (i.e: count = 0)
require
+ a_valid_base_url: (a_base_url /= Void and then a_base_url.is_empty) implies (a_base_url.starts_with ("/") and not a_base_url.ends_with ("/"))
no_handler_set: count = 0
do
if a_base_url = Void or else a_base_url.is_empty then
@@ -124,105 +134,12 @@ feature -- Element change
end
end
-feature -- Hook
-
- pre_route_execution_actions: ACTION_SEQUENCE [TUPLE [like route]]
- -- Action triggered before a route is execute
- --| Could be used for tracing, logging
-
-feature -- Routing
-
- route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
- -- Route matching `req'.
- do
- Result := matching_route (req)
- end
-
-feature -- Execution
-
- execute_route (a_route: WSF_ROUTE [H,C]; req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Process route `a_route'
- require
- a_route_attached: a_route /= Void
- local
- ctx: C
- do
- pre_route_execution_actions.call ([a_route])
- ctx := a_route.context
- ctx.apply (req)
- a_route.handler.execute (ctx, req, res)
- ctx.revert (req)
- rescue
- a_route.context.revert (req)
- end
-
- dispatch (req: WSF_REQUEST; res: WSF_RESPONSE): BOOLEAN
- -- Dispatch `req, res' to the associated handler
- -- And return True is handled, otherwise False
- do
- if attached route (req) as r then
- Result := True
- execute_route (r, req, res)
- end
- end
-
- dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable H
- -- Dispatch `req, res' to the associated handler
- -- And return this handler
- -- If Result is Void, this means no handler was found.
- do
- if attached route (req) as r then
- Result := r.handler
- execute_route (r, req, res)
- end
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Implementation
-
- default_handler_context (req: WSF_REQUEST): C
- -- Default handler context associated with `req'.
- --| It can be used to build a context if needed.
- deferred
- end
-
-feature -- status report
-
- count: INTEGER
- -- Count of maps handled by current
- do
- across
- Current as curs
- loop
- if attached {WSF_ROUTING_HANDLER [H, C]} curs.item.handler as rh then
- Result := Result + rh.count + 1 --| +1 for the handler itself
- else
- Result := Result + 1
- end
- end
- end
-
feature -- Traversing
- new_cursor: ITERATION_CURSOR [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
+ new_cursor: ITERATION_CURSOR [TUPLE [mapping: WSF_ROUTER_MAPPING; request_methods: detachable WSF_ROUTER_METHODS]]
-- Fresh cursor associated with current structure
- deferred
- end
-
-feature {WSF_ROUTED_SERVICE_I} -- Handler
-
- source_uri (req: WSF_REQUEST): READABLE_STRING_32
- -- URI to use to find handler.
do
- Result := req.path_info
- end
-
- matching_route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
- -- Handler whose map matched with `req' with associated Context
- require
- req_valid: source_uri (req) /= Void
- deferred
- ensure
- source_uri_unchanged: source_uri (req).same_string (old source_uri (req))
+ Result := mappings.new_cursor
end
feature -- Request methods helper
@@ -343,14 +260,4 @@ feature {NONE} -- Access: Implementation
end
end
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
end
diff --git a/library/server/wsf/router/uri/default/wsf_uri_routed_service.e b/library/server/wsf/router/wsf_router_mapping.e
similarity index 53%
rename from library/server/wsf/router/uri/default/wsf_uri_routed_service.e
rename to library/server/wsf/router/wsf_router_mapping.e
index f5ff1015..0fcf66da 100644
--- a/library/server/wsf/router/uri/default/wsf_uri_routed_service.e
+++ b/library/server/wsf/router/wsf_router_mapping.e
@@ -1,31 +1,33 @@
note
- description: "Summary description for WSF_URI_ROUTED_SERVICE."
+ description: "Summary description for {WSF_ROUTER_MAPPING}."
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
- WSF_URI_ROUTED_SERVICE
+ WSF_ROUTER_MAPPING
-inherit
- WSF_ROUTED_SERVICE_I [WSF_HANDLER [WSF_URI_HANDLER_CONTEXT], WSF_URI_HANDLER_CONTEXT]
- redefine
- router
+feature -- Access
+
+ handler: WSF_HANDLER
+ deferred
end
-feature {NONE} -- Initialization
+feature -- Status
- create_router
- -- Create router
- --| it can be redefine to create with precise count if needed.
+ routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
+ deferred
+ end
+
+feature -- Helper
+
+ source_uri (req: WSF_REQUEST): READABLE_STRING_32
+ -- URI to use to find handler.
do
- create router.make (0)
+ Result := req.path_info
end
-feature -- Router
- router: WSF_URI_ROUTER
-
-;note
+note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
diff --git a/library/server/wsf/router/wsf_routing_handler.e b/library/server/wsf/router/wsf_routing_handler.e
deleted file mode 100644
index 384dfa4f..00000000
--- a/library/server/wsf/router/wsf_routing_handler.e
+++ /dev/null
@@ -1,113 +0,0 @@
-note
- description: "[
- WSF_ROUTING_HANDLER is mainly to group a set of handler having the same base
- such as /users for
- /users/by/id/{id}
- /users/by/name/name}
-
- It can be used to optimize the router, where the router checks only the base path before checking each entries
- Then for
- /a/a1
- /a/a2
- /a/a3
- /a/a4
- /b/b1
- /b/b2
- /b/b3
- 2 routing handlers could be used "/a" and "/b"
- then to find the /b/b2 match, the router has to do only
- /a /b /b/b1 and /b/b2 i.e: 4 checks
- instead of /a/a1 /a/a2 /a/a3 /a/a4 /b/b1 /b/b2: i.e: 6 checks
- On router with deep arborescence this could be significant
- ]"
- date: "$Date$"
- revision: "$Revision$"
-
-deferred class
- WSF_ROUTING_HANDLER [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
-
-inherit
- WSF_HANDLER [C]
-
-feature -- Access
-
- count: INTEGER
- -- Count of maps handled by current
- do
- Result := router.count
- end
-
- base_url: detachable READABLE_STRING_8
- do
- Result := router.base_url
- end
-
-feature -- Element change
-
- set_base_url (a_base_url: like base_url)
- -- Set `base_url' to `a_base_url'
- -- make sure no map is already added (i.e: count = 0)
- require
- no_handler_set: count = 0
- do
- router.set_base_url (a_base_url)
- end
-
-feature -- Execution
-
- execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Execute request handler
- local
- r: detachable WSF_ROUTE [H, C]
- do
- r := router.route (req)
- if r = Void then
- res.put_header ({HTTP_STATUS_CODE}.not_found, <<[{HTTP_HEADER_NAMES}.header_content_length, "0"]>>)
- else
- router.execute_route (r, req, res)
- end
- end
-
-feature {NONE} -- Routing
-
- router: WSF_ROUTER [H, C]
- deferred
- end
-
-feature -- Mapping
-
- map (a_resource: READABLE_STRING_8; h: H)
- -- Map handler `h' with `a_resource'
- do
- router.map (a_resource, h)
- end
-
- map_with_request_methods (a_resource: READABLE_STRING_8; h: H;
- rqst_methods: detachable WSF_ROUTER_METHODS)
- -- Map handler `h' with `a_resource' and `rqst_methods'
- do
- router.map_with_request_methods (a_resource, h, rqst_methods)
- end
-
- map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]])
- do
- router.map_agent (a_resource, a_action)
- end
-
- map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]];
- rqst_methods: detachable WSF_ROUTER_METHODS)
- do
- router.map_agent_with_request_methods (a_resource, a_action, rqst_methods)
- end
-
-note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
- license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
- source: "[
- Eiffel Software
- 5949 Hollister Ave., Goleta, CA 93117 USA
- Telephone 805-685-1006, Fax 805-685-6869
- Website http://www.eiffel.com
- Customer support http://support.eiffel.com
- ]"
-end