Introduced WSF_ROUTER_SESSION
This fixes CQS violation from WSF_ROUTER.dispatch_and_return_handler (...): ? WSF_HANDLER and related code, and this is more compliant with concurrency. In addition, the WSF_ROUTER_SESSION can be enhanced in the future to answer more advanced needs.
This commit is contained in:
@@ -44,10 +44,12 @@ feature -- Basic operations
|
|||||||
|
|
||||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Execute the filter
|
-- Execute the filter
|
||||||
|
local
|
||||||
|
sess: WSF_ROUTER_SESSION
|
||||||
do
|
do
|
||||||
if attached router.dispatch_and_return_handler (req, res) then
|
create sess
|
||||||
check router.is_dispatched end
|
router.dispatch (req, res, sess)
|
||||||
else
|
if not sess.dispatched then
|
||||||
execute_default (req, res)
|
execute_default (req, res)
|
||||||
end
|
end
|
||||||
execute_next (req, res)
|
execute_next (req, res)
|
||||||
@@ -63,7 +65,7 @@ feature -- Basic operations
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ feature -- Status
|
|||||||
Result := p.starts_with (s)
|
Result := p.starts_with (s)
|
||||||
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)
|
||||||
-- Return the handler if Current matches the request `req'.
|
-- Return the handler if Current matches the request `req'.
|
||||||
local
|
local
|
||||||
p: READABLE_STRING_8
|
p: READABLE_STRING_8
|
||||||
@@ -67,7 +67,7 @@ feature -- Status
|
|||||||
p := path_from_request (req)
|
p := path_from_request (req)
|
||||||
s := based_uri (uri, a_router)
|
s := based_uri (uri, a_router)
|
||||||
if p.starts_with (s) then
|
if p.starts_with (s) then
|
||||||
Result := handler
|
sess.set_dispatched_handler (handler)
|
||||||
a_router.execute_before (Current)
|
a_router.execute_before (Current)
|
||||||
execute_handler (handler, s, req, res)
|
execute_handler (handler, s, req, res)
|
||||||
a_router.execute_after (Current)
|
a_router.execute_after (Current)
|
||||||
@@ -113,7 +113,7 @@ invariant
|
|||||||
uri_attached: uri /= Void
|
uri_attached: uri /= Void
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ feature -- Status
|
|||||||
end
|
end
|
||||||
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
|
do
|
||||||
if is_mapping (req, a_router) then
|
if is_mapping (req, a_router) then
|
||||||
Result := handler
|
sess.set_dispatched_handler (handler)
|
||||||
a_router.execute_before (Current)
|
a_router.execute_before (Current)
|
||||||
execute_handler (handler, req, res)
|
execute_handler (handler, req, res)
|
||||||
a_router.execute_after (Current)
|
a_router.execute_after (Current)
|
||||||
@@ -105,7 +105,7 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ feature -- Status
|
|||||||
Result := tpl.match (p) /= Void
|
Result := tpl.match (p) /= Void
|
||||||
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)
|
||||||
-- <Precursor>
|
-- <Precursor>
|
||||||
local
|
local
|
||||||
tpl: URI_TEMPLATE
|
tpl: URI_TEMPLATE
|
||||||
@@ -78,7 +78,7 @@ feature -- Status
|
|||||||
p := path_from_request (req)
|
p := path_from_request (req)
|
||||||
tpl := based_uri_template (template, a_router)
|
tpl := based_uri_template (template, a_router)
|
||||||
if attached tpl.match (p) as tpl_res then
|
if attached tpl.match (p) as tpl_res then
|
||||||
Result := handler
|
sess.set_dispatched_handler (handler)
|
||||||
a_router.execute_before (Current)
|
a_router.execute_before (Current)
|
||||||
--| Applied the context to the request
|
--| Applied the context to the request
|
||||||
--| in practice, this will fill the {WSF_REQUEST}.path_parameters
|
--| in practice, this will fill the {WSF_REQUEST}.path_parameters
|
||||||
@@ -126,7 +126,7 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -40,10 +40,12 @@ feature -- Execution
|
|||||||
require
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= Void
|
res_attached: res /= Void
|
||||||
|
local
|
||||||
|
sess: WSF_ROUTER_SESSION
|
||||||
do
|
do
|
||||||
if attached router.dispatch_and_return_handler (req, res) as p then
|
create sess
|
||||||
-- executed
|
router.dispatch (req, res, sess)
|
||||||
else
|
if not sess.dispatched then
|
||||||
execute_default (req, res)
|
execute_default (req, res)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -112,75 +112,84 @@ feature -- Mapping handler
|
|||||||
map_with_request_methods (f.new_mapping (a_resource), rqst_methods)
|
map_with_request_methods (f.new_mapping (a_resource), rqst_methods)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
|
||||||
|
|
||||||
is_dispatched: BOOLEAN
|
|
||||||
-- `dispatch' set `is_dispatched' to True
|
|
||||||
-- if mapping was found, and associated handler executed
|
|
||||||
|
|
||||||
feature -- Basic operations
|
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'.
|
-- 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
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= Void
|
res_attached: res /= Void
|
||||||
|
local
|
||||||
|
l_sess: detachable WSF_ROUTER_SESSION
|
||||||
do
|
do
|
||||||
if attached dispatch_and_return_handler (req, res) then
|
l_sess := sess
|
||||||
check is_dispatched: is_dispatched end
|
if l_sess = Void then
|
||||||
|
create l_sess
|
||||||
end
|
end
|
||||||
|
router_dispatch (req, res, l_sess)
|
||||||
end
|
end
|
||||||
|
|
||||||
dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable WSF_HANDLER
|
dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable WSF_HANDLER
|
||||||
-- Dispatch request `req' among the `mappings'
|
-- Dispatch request `req' among the `mappings'
|
||||||
-- And return the associated handler if mapping found and handler executed.
|
-- And return the associated handler if mapping found and handler executed.
|
||||||
--| Violates CQS
|
--| Violates CQS
|
||||||
|
obsolete
|
||||||
|
"Use `dispatch' [2013-mar-21]"
|
||||||
require
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= 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
|
local
|
||||||
l_req_method: READABLE_STRING_8
|
l_req_method: READABLE_STRING_8
|
||||||
head_res: WSF_HEAD_RESPONSE_WRAPPER
|
head_res: WSF_HEAD_RESPONSE_WRAPPER
|
||||||
do
|
do
|
||||||
l_req_method := request_method (req)
|
l_req_method := request_method (req)
|
||||||
is_dispatched := False
|
router_dispatch_for_request_method (req, res, sess, l_req_method)
|
||||||
Result := dispatch_and_return_handler_for_request_method (req, res, l_req_method)
|
if not sess.dispatched and l_req_method = {HTTP_REQUEST_METHODS}.method_head then
|
||||||
if Result = Void and l_req_method = {HTTP_REQUEST_METHODS}.method_head then
|
|
||||||
check is_not_dispatched: not is_dispatched end
|
|
||||||
create head_res.make_from_response (res)
|
create head_res.make_from_response (res)
|
||||||
req.set_request_method ({HTTP_REQUEST_METHODS}.method_GET)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Dispatch implementation
|
router_dispatch_for_request_method (req: WSF_REQUEST; res: WSF_RESPONSE; sess: WSF_ROUTER_SESSION; a_request_method: READABLE_STRING_8)
|
||||||
|
|
||||||
dispatch_and_return_handler_for_request_method (req: WSF_REQUEST; res: WSF_RESPONSE; a_request_method: READABLE_STRING_8): detachable WSF_HANDLER
|
|
||||||
-- Dispatch request `req' among the `mappings'
|
-- Dispatch request `req' among the `mappings'
|
||||||
-- And return the associated handler if mapping found and handler executed.
|
-- And return the associated handler if mapping found and handler executed.
|
||||||
--| Violates CQS
|
--| Violates CQS
|
||||||
require
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= Void
|
res_attached: res /= Void
|
||||||
|
sess_attached: sess /= Void
|
||||||
|
sess_not_dispatched: not sess.dispatched
|
||||||
a_request_method_attached: a_request_method /= Void
|
a_request_method_attached: a_request_method /= Void
|
||||||
local
|
local
|
||||||
m: WSF_ROUTER_MAPPING
|
m: WSF_ROUTER_MAPPING
|
||||||
do
|
do
|
||||||
is_dispatched := False
|
|
||||||
|
|
||||||
across
|
across
|
||||||
mappings as c
|
mappings as c
|
||||||
until
|
until
|
||||||
Result /= Void
|
sess.dispatched
|
||||||
loop
|
loop
|
||||||
if attached c.item as l_info then
|
if attached c.item as l_info then
|
||||||
if is_matching_request_methods (a_request_method, l_info.request_methods) then
|
if is_matching_request_methods (a_request_method, l_info.request_methods) then
|
||||||
m := l_info.mapping
|
m := l_info.mapping
|
||||||
if attached m.routed_handler (req, res, Current) as r then
|
m.try (req, res, sess, Current)
|
||||||
is_dispatched := True
|
|
||||||
Result := r
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
note
|
note
|
||||||
description: "Summary description for {WSF_ROUTER_MAPPING}."
|
description: "[
|
||||||
author: ""
|
Describes a route or mapping for the WSF_ROUTER
|
||||||
|
]"
|
||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
@@ -23,14 +24,14 @@ feature {NONE} -- Initialization
|
|||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
associated_resource: READABLE_STRING_8
|
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
|
deferred
|
||||||
ensure
|
ensure
|
||||||
assciated_resource_not_void: Result /= Void
|
assciated_resource_not_void: Result /= Void
|
||||||
end
|
end
|
||||||
|
|
||||||
handler: WSF_HANDLER
|
handler: WSF_HANDLER
|
||||||
-- Handler associated with `Current' mapping
|
-- Handler associated with `Current' mapping.
|
||||||
deferred
|
deferred
|
||||||
ensure
|
ensure
|
||||||
handler_attached: Result /= Void
|
handler_attached: Result /= Void
|
||||||
@@ -39,7 +40,7 @@ feature -- Access
|
|||||||
feature -- Documentation
|
feature -- Documentation
|
||||||
|
|
||||||
description: READABLE_STRING_32
|
description: READABLE_STRING_32
|
||||||
-- Short description of associated mapping
|
-- Short description of associated mapping.
|
||||||
deferred
|
deferred
|
||||||
ensure
|
ensure
|
||||||
description_attached: Result /= Void
|
description_attached: Result /= Void
|
||||||
@@ -63,11 +64,13 @@ feature -- Status
|
|||||||
deferred
|
deferred
|
||||||
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)
|
||||||
-- Handler when `Current' matches the request `req'
|
-- Try using `Current' mapping and if it matches request `req'
|
||||||
|
-- execute associated handler and set this handler in session `sess'.
|
||||||
require
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= Void
|
res_attached: res /= Void
|
||||||
|
sess_attached: sess /= Void
|
||||||
a_router_attached: a_router /= Void
|
a_router_attached: a_router /= Void
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
@@ -75,7 +78,7 @@ feature -- Status
|
|||||||
feature -- Helper
|
feature -- Helper
|
||||||
|
|
||||||
path_from_request (req: WSF_REQUEST): READABLE_STRING_32
|
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
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
do
|
do
|
||||||
|
|||||||
46
library/server/wsf/router/wsf_router_session.e
Normal file
46
library/server/wsf/router/wsf_router_session.e
Normal file
@@ -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
|
||||||
@@ -54,16 +54,18 @@ feature -- Execution
|
|||||||
|
|
||||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Execute request handler
|
-- Execute request handler
|
||||||
|
local
|
||||||
|
sess: WSF_ROUTER_SESSION
|
||||||
do
|
do
|
||||||
if attached router.dispatch_and_return_handler (req, res) as h then
|
create sess
|
||||||
check is_dispatched: router.is_dispatched end
|
router.dispatch (req, res, sess)
|
||||||
else
|
if not sess.dispatched then
|
||||||
res.put_header ({HTTP_STATUS_CODE}.not_found, <<[{HTTP_HEADER_NAMES}.header_content_length, "0"]>>)
|
res.put_header ({HTTP_STATUS_CODE}.not_found, <<[{HTTP_HEADER_NAMES}.header_content_length, "0"]>>)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
Reference in New Issue
Block a user