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