diff --git a/library/server/wsf/router/filter/wsf_routing_filter.e b/library/server/wsf/router/filter/wsf_routing_filter.e index d1018610..7f398ef4 100644 --- a/library/server/wsf/router/filter/wsf_routing_filter.e +++ b/library/server/wsf/router/filter/wsf_routing_filter.e @@ -44,10 +44,12 @@ feature -- Basic operations execute (req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute the filter + local + sess: WSF_ROUTER_SESSION do - if attached router.dispatch_and_return_handler (req, res) then - check router.is_dispatched end - else + create sess + router.dispatch (req, res, sess) + if not sess.dispatched then execute_default (req, res) end execute_next (req, res) @@ -63,7 +65,7 @@ feature -- Basic operations end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e b/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e index 7618171c..63774e5f 100644 --- a/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e +++ b/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e @@ -58,7 +58,7 @@ feature -- Status Result := p.starts_with (s) end - routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER + try (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION; a_router: WSF_ROUTER) -- Return the handler if Current matches the request `req'. local p: READABLE_STRING_8 @@ -67,7 +67,7 @@ feature -- Status p := path_from_request (req) s := based_uri (uri, a_router) if p.starts_with (s) then - Result := handler + sess.set_dispatched_handler (handler) a_router.execute_before (Current) execute_handler (handler, s, req, res) a_router.execute_after (Current) @@ -113,7 +113,7 @@ invariant uri_attached: uri /= Void note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/support/uri/wsf_uri_mapping_i.e b/library/server/wsf/router/support/uri/wsf_uri_mapping_i.e index cac518fd..aa69a860 100644 --- a/library/server/wsf/router/support/uri/wsf_uri_mapping_i.e +++ b/library/server/wsf/router/support/uri/wsf_uri_mapping_i.e @@ -72,10 +72,10 @@ feature -- Status end end - routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER + try (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION; a_router: WSF_ROUTER) do if is_mapping (req, a_router) then - Result := handler + sess.set_dispatched_handler (handler) a_router.execute_before (Current) execute_handler (handler, req, res) a_router.execute_after (Current) @@ -105,7 +105,7 @@ feature {NONE} -- Implementation end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e b/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e index 0a047949..f1430fa0 100644 --- a/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e +++ b/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e @@ -24,7 +24,7 @@ feature {NONE} -- Initialization -- Create with `h' as the handler for resources matching `tpl' require tpl_attached: tpl /= Void - h_attached: h /= Void + h_attached: h /= Void do template := tpl set_handler (h) @@ -68,7 +68,7 @@ feature -- Status Result := tpl.match (p) /= Void end - routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER + try (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION; a_router: WSF_ROUTER) -- local tpl: URI_TEMPLATE @@ -78,7 +78,7 @@ feature -- Status p := path_from_request (req) tpl := based_uri_template (template, a_router) if attached tpl.match (p) as tpl_res then - Result := handler + sess.set_dispatched_handler (handler) a_router.execute_before (Current) --| Applied the context to the request --| in practice, this will fill the {WSF_REQUEST}.path_parameters @@ -126,7 +126,7 @@ feature {NONE} -- Implementation end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/router/wsf_routed_service.e b/library/server/wsf/router/wsf_routed_service.e index 5f2c3499..06cd6a9e 100644 --- a/library/server/wsf/router/wsf_routed_service.e +++ b/library/server/wsf/router/wsf_routed_service.e @@ -40,10 +40,12 @@ feature -- Execution require req_attached: req /= Void res_attached: res /= Void + local + sess: WSF_ROUTER_SESSION do - if attached router.dispatch_and_return_handler (req, res) as p then - -- executed - else + create sess + router.dispatch (req, res, sess) + if not sess.dispatched then execute_default (req, res) end end diff --git a/library/server/wsf/router/wsf_router.e b/library/server/wsf/router/wsf_router.e index 08a9c965..095a9b9b 100644 --- a/library/server/wsf/router/wsf_router.e +++ b/library/server/wsf/router/wsf_router.e @@ -112,75 +112,84 @@ feature -- Mapping handler map_with_request_methods (f.new_mapping (a_resource), rqst_methods) end -feature -- Access - - is_dispatched: BOOLEAN - -- `dispatch' set `is_dispatched' to True - -- if mapping was found, and associated handler executed - feature -- Basic operations - dispatch (req: WSF_REQUEST; res: WSF_RESPONSE) + dispatch (req: WSF_REQUEST; res: WSF_RESPONSE; sess: detachable WSF_ROUTER_SESSION) -- Dispatch request `req' among the `mappings'. - -- Set `is_dispatched' if the request were dispatched. + -- Set `sess' if the request were dispatched and `sess' attached. require req_attached: req /= Void res_attached: res /= Void + local + l_sess: detachable WSF_ROUTER_SESSION do - if attached dispatch_and_return_handler (req, res) then - check is_dispatched: is_dispatched end + l_sess := sess + if l_sess = Void then + create l_sess end + router_dispatch (req, res, l_sess) end dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable WSF_HANDLER -- Dispatch request `req' among the `mappings' -- And return the associated handler if mapping found and handler executed. --| Violates CQS + obsolete + "Use `dispatch' [2013-mar-21]" require req_attached: req /= Void res_attached: res /= Void + local + sess: WSF_ROUTER_SESSION + do + create sess + router_dispatch (req, res, sess) + Result := sess.dispatched_handler + end + +feature {NONE} -- Dispatch implementation + + router_dispatch (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION) + require + req_attached: req /= Void + res_attached: res /= Void + sess_attached: sess /= Void + sess_not_dispatched: not sess.dispatched local l_req_method: READABLE_STRING_8 head_res: WSF_HEAD_RESPONSE_WRAPPER do l_req_method := request_method (req) - is_dispatched := False - Result := dispatch_and_return_handler_for_request_method (req, res, l_req_method) - if Result = Void and l_req_method = {HTTP_REQUEST_METHODS}.method_head then - check is_not_dispatched: not is_dispatched end + router_dispatch_for_request_method (req, res, sess, l_req_method) + if not sess.dispatched and l_req_method = {HTTP_REQUEST_METHODS}.method_head then create head_res.make_from_response (res) req.set_request_method ({HTTP_REQUEST_METHODS}.method_GET) - Result := dispatch_and_return_handler_for_request_method (req, head_res, {HTTP_REQUEST_METHODS}.method_GET) + router_dispatch_for_request_method (req, head_res, sess, {HTTP_REQUEST_METHODS}.method_GET) end end -feature {NONE} -- Dispatch implementation - - dispatch_and_return_handler_for_request_method (req: WSF_REQUEST; res: WSF_RESPONSE; a_request_method: READABLE_STRING_8): detachable WSF_HANDLER + router_dispatch_for_request_method (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION; a_request_method: READABLE_STRING_8) -- Dispatch request `req' among the `mappings' -- And return the associated handler if mapping found and handler executed. --| Violates CQS require req_attached: req /= Void res_attached: res /= Void + sess_attached: sess /= Void + sess_not_dispatched: not sess.dispatched a_request_method_attached: a_request_method /= Void local m: WSF_ROUTER_MAPPING do - is_dispatched := False - across mappings as c until - Result /= Void + sess.dispatched loop if attached c.item as l_info then if is_matching_request_methods (a_request_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 + m.try (req, res, sess, Current) end end end diff --git a/library/server/wsf/router/wsf_router_mapping.e b/library/server/wsf/router/wsf_router_mapping.e index 89f53303..6f7b4605 100644 --- a/library/server/wsf/router/wsf_router_mapping.e +++ b/library/server/wsf/router/wsf_router_mapping.e @@ -1,6 +1,7 @@ note - description: "Summary description for {WSF_ROUTER_MAPPING}." - author: "" + description: "[ + Describes a route or mapping for the WSF_ROUTER + ]" date: "$Date$" revision: "$Revision$" @@ -23,14 +24,14 @@ feature {NONE} -- Initialization feature -- Access associated_resource: READABLE_STRING_8 - -- Name (URI, or URI template or regular expression or ...) of handled resource + -- Name (URI, or URI template or regular expression or ...) of handled resource. deferred ensure assciated_resource_not_void: Result /= Void end handler: WSF_HANDLER - -- Handler associated with `Current' mapping + -- Handler associated with `Current' mapping. deferred ensure handler_attached: Result /= Void @@ -39,7 +40,7 @@ feature -- Access feature -- Documentation description: READABLE_STRING_32 - -- Short description of associated mapping + -- Short description of associated mapping. deferred ensure description_attached: Result /= Void @@ -63,11 +64,13 @@ feature -- Status deferred end - routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER - -- Handler when `Current' matches the request `req' + try (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION; a_router: WSF_ROUTER) + -- Try using `Current' mapping and if it matches request `req' + -- execute associated handler and set this handler in session `sess'. require req_attached: req /= Void res_attached: res /= Void + sess_attached: sess /= Void a_router_attached: a_router /= Void deferred end @@ -75,7 +78,7 @@ feature -- Status feature -- Helper path_from_request (req: WSF_REQUEST): READABLE_STRING_32 - -- Path used by `Current' to check that mapping matches request `req' + -- Path used by `Current' to check that mapping matches request `req'. require req_attached: req /= Void do diff --git a/library/server/wsf/router/wsf_router_session.e b/library/server/wsf/router/wsf_router_session.e new file mode 100644 index 00000000..e5af83d0 --- /dev/null +++ b/library/server/wsf/router/wsf_router_session.e @@ -0,0 +1,46 @@ +note + description: "[ + This class represents the processing of a request via a WSF_ROUTER. + + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_ROUTER_SESSION + +feature -- Status report + + dispatched: BOOLEAN + -- Handler dispatched? + do + Result := dispatched_handler /= Void + ensure + Result implies dispatched_handler /= Void + end + +feature -- Access + + dispatched_handler: detachable WSF_HANDLER + -- Handler dispatched + +feature -- Change + + set_dispatched_handler (h: like dispatched_handler) + do + dispatched_handler := h + ensure + h_set: dispatched_handler = h + end + +note + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, 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_routing_handler.e b/library/server/wsf/router/wsf_routing_handler.e index 94b97fed..5aa855e5 100644 --- a/library/server/wsf/router/wsf_routing_handler.e +++ b/library/server/wsf/router/wsf_routing_handler.e @@ -54,16 +54,18 @@ feature -- Execution execute (req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute request handler + local + sess: WSF_ROUTER_SESSION do - if attached router.dispatch_and_return_handler (req, res) as h then - check is_dispatched: router.is_dispatched end - else + create sess + router.dispatch (req, res, sess) + if not sess.dispatched then res.put_header ({HTTP_STATUS_CODE}.not_found, <<[{HTTP_HEADER_NAMES}.header_content_length, "0"]>>) end end note - copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software