Added WSF_ROUTER.has_item_associated_with_resource and item_associated_with_resource
Added WSF_ROUTER_MAPPING.associated_resource Added WSF_ROUTER_SELF_DOCUMENTATION_HANDLER and WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE to provide a self documentation for WSF_ROUTER (for now, only HTML)
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
Handler based on a STARTS_WITH handler to respond a
|
||||||
|
WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE message
|
||||||
|
|
||||||
|
This is a self documentation for WSF_ROUTER.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_ROUTER_SELF_DOCUMENTATION_HANDLER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_STARTS_WITH_HANDLER
|
||||||
|
redefine
|
||||||
|
on_mapped
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_router: WSF_ROUTER)
|
||||||
|
do
|
||||||
|
router := a_router
|
||||||
|
end
|
||||||
|
|
||||||
|
router: WSF_ROUTER
|
||||||
|
|
||||||
|
resource: detachable STRING
|
||||||
|
|
||||||
|
feature {WSF_ROUTER} -- Mapping
|
||||||
|
|
||||||
|
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
|
||||||
|
if attached {WSF_STARTS_WITH_MAPPING} a_mapping as m then
|
||||||
|
resource := m.uri
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Execution
|
||||||
|
|
||||||
|
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
m: WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE
|
||||||
|
do
|
||||||
|
if attached resource as l_resource then
|
||||||
|
create m.make (req, router, l_resource)
|
||||||
|
else
|
||||||
|
create m.make (req, router, Void)
|
||||||
|
end
|
||||||
|
res.send (m)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
Response message to send a self documentation of the WSF_ROUTER
|
||||||
|
This is using in addition WSF_SELF_DOCUMENTED_ROUTER_MAPPING and WSF_SELF_DOCUMENTED_HANDLER
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (req: WSF_REQUEST; a_router: WSF_ROUTER; a_resource: detachable STRING)
|
||||||
|
local
|
||||||
|
|
||||||
|
do
|
||||||
|
request := req
|
||||||
|
router := a_router
|
||||||
|
if attached a_router.base_url as l_base_url then
|
||||||
|
resource := l_base_url.twin
|
||||||
|
else
|
||||||
|
create resource.make_empty
|
||||||
|
end
|
||||||
|
if a_resource /= Void then
|
||||||
|
resource.append (a_resource)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
request: WSF_REQUEST
|
||||||
|
|
||||||
|
router: WSF_ROUTER
|
||||||
|
|
||||||
|
resource: STRING_8
|
||||||
|
|
||||||
|
feature {WSF_RESPONSE} -- Output
|
||||||
|
|
||||||
|
send_to (res: WSF_RESPONSE)
|
||||||
|
-- Send Current message to `res'
|
||||||
|
--
|
||||||
|
-- This feature should be called via `{WSF_RESPONSE}.send (obj)'
|
||||||
|
-- where `obj' is the current object
|
||||||
|
local
|
||||||
|
h: HTTP_HEADER
|
||||||
|
l_description: STRING_8
|
||||||
|
l_base_url: STRING_8
|
||||||
|
l_api_resource: detachable STRING_8
|
||||||
|
do
|
||||||
|
create h.make
|
||||||
|
h.put_content_type_text_html
|
||||||
|
create l_description.make (1024)
|
||||||
|
l_description.append ("<html>")
|
||||||
|
l_description.append ("<head>")
|
||||||
|
l_description.append ("<title>Documentation</title>")
|
||||||
|
l_description.append ("[
|
||||||
|
<style type="text/css">
|
||||||
|
.mappingresource { color: #00f; }
|
||||||
|
.mappingdoc { color: #900; }
|
||||||
|
.handlerdoc { white-space: pre; }
|
||||||
|
div#footer { padding: 10px; width: 100%; margin-top: 20px; border-top: 1px dotted #999; color: #999; text-align: center; }
|
||||||
|
</style>
|
||||||
|
]")
|
||||||
|
|
||||||
|
l_description.append ("</head><body>")
|
||||||
|
|
||||||
|
l_description.append ("<h1>Documentation</h1>%N")
|
||||||
|
|
||||||
|
if attached router.base_url as u then
|
||||||
|
l_base_url := u
|
||||||
|
else
|
||||||
|
create l_base_url.make_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
debug
|
||||||
|
l_description.append ("<h2>Meta</h2><ul>")
|
||||||
|
l_description.append ("<li>PATH_INFO=" + request.path_info + "</li>")
|
||||||
|
l_description.append ("<li>QUERY_STRING=" + request.query_string + "</li>")
|
||||||
|
l_description.append ("<li>REQUEST_URI=" + request.request_uri + "</li>")
|
||||||
|
l_description.append ("<li>SCRIPT_NAME=" + request.script_name + "</li>")
|
||||||
|
l_description.append ("<li>HOME=" + request.script_url ("/") + "</li>")
|
||||||
|
if not l_base_url.is_empty then
|
||||||
|
l_description.append ("<li>Base URL=" + l_base_url + "</li>")
|
||||||
|
end
|
||||||
|
l_description.append ("</ul>")
|
||||||
|
end
|
||||||
|
|
||||||
|
if attached request.path_info as l_path then
|
||||||
|
if l_path.starts_with (resource) then
|
||||||
|
l_api_resource := l_path.substring (resource.count + 1, l_path.count)
|
||||||
|
if l_api_resource.is_empty then
|
||||||
|
l_api_resource := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if l_api_resource /= Void then
|
||||||
|
l_description.append ("<a href=%""+ doc_url ("") +"%">Index</a><br/>")
|
||||||
|
if attached router.item_associated_with_resource (l_api_resource, Void) as l_api_item then
|
||||||
|
l_description.append ("<h2>Information related to %"" + l_api_resource + "%"</h2><ul>")
|
||||||
|
append_documentation_to (l_description, l_api_item.mapping, l_api_item.request_methods)
|
||||||
|
l_description.append ("</ul>")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
l_description.append ("<h2>Router</h2><ul>")
|
||||||
|
across
|
||||||
|
router as c
|
||||||
|
loop
|
||||||
|
append_documentation_to (l_description, c.item.mapping, c.item.request_methods)
|
||||||
|
end
|
||||||
|
l_description.append ("</ul>")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
l_description.append ("<div id=%"footer%">-- Self generated documentation --</div>%N")
|
||||||
|
l_description.append ("</body></html>")
|
||||||
|
|
||||||
|
h.put_content_length (l_description.count)
|
||||||
|
h.put_current_date
|
||||||
|
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
|
res.put_header_text (h.string)
|
||||||
|
res.put_string (l_description)
|
||||||
|
end
|
||||||
|
|
||||||
|
append_documentation_to (s: STRING_8; m: WSF_ROUTER_MAPPING; meths: detachable WSF_ROUTER_METHODS)
|
||||||
|
local
|
||||||
|
l_url: detachable STRING_8
|
||||||
|
l_base_url: detachable READABLE_STRING_8
|
||||||
|
hdl: WSF_HANDLER
|
||||||
|
do
|
||||||
|
l_base_url := router.base_url
|
||||||
|
if l_base_url = Void then
|
||||||
|
l_base_url := ""
|
||||||
|
end
|
||||||
|
|
||||||
|
l_url := Void
|
||||||
|
s.append ("<li>")
|
||||||
|
s.append ("<code>")
|
||||||
|
s.append ("<a class=%"mappingresource%" href=%"")
|
||||||
|
s.append (doc_url (m.associated_resource))
|
||||||
|
s.append ("%">")
|
||||||
|
s.append (m.associated_resource)
|
||||||
|
s.append ("</a></code>")
|
||||||
|
|
||||||
|
if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} m as l_doc_mapping then
|
||||||
|
s.append (" <em class=%"mappingdoc%">" + html_encoder.encoded_string (l_doc_mapping.documentation) + "</em> ")
|
||||||
|
else
|
||||||
|
debug
|
||||||
|
s.append (" <em class=%"mappingdoc%">" + m.generating_type.out + "</em> ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if meths /= Void then
|
||||||
|
s.append (" [ ")
|
||||||
|
across
|
||||||
|
meths as rq
|
||||||
|
loop
|
||||||
|
if l_url /= Void and then rq.item.is_case_insensitive_equal ("GET") then
|
||||||
|
s.append ("<a href=%"" + l_base_url + l_url + "%">" + rq.item + "</a>")
|
||||||
|
else
|
||||||
|
s.append (rq.item)
|
||||||
|
end
|
||||||
|
if not rq.is_last then
|
||||||
|
s.append (",")
|
||||||
|
end
|
||||||
|
s.append (" ")
|
||||||
|
end
|
||||||
|
s.append ("]")
|
||||||
|
end
|
||||||
|
|
||||||
|
hdl := m.handler
|
||||||
|
if attached {WSF_SELF_DOCUMENTED_HANDLER} hdl as l_doc_handler and then attached l_doc_handler.documentation as l_doc then
|
||||||
|
s.append ("%N<ul class=%"handlerdoc%">")
|
||||||
|
s.append (html_encoder.encoded_string (l_doc))
|
||||||
|
s.append ("%N</ul>%N")
|
||||||
|
else
|
||||||
|
debug
|
||||||
|
s.append ("%N<ul class=%"handlerdoc%">")
|
||||||
|
s.append (hdl.generating_type.out)
|
||||||
|
s.append ("%N</ul>%N")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if attached {WSF_ROUTING_HANDLER} hdl as l_routing_hdl then
|
||||||
|
s.append ("%N<ul>%N")
|
||||||
|
across
|
||||||
|
l_routing_hdl.router as c
|
||||||
|
loop
|
||||||
|
append_documentation_to (s, c.item.mapping, c.item.request_methods)
|
||||||
|
end
|
||||||
|
s.append ("%N</ul>%N")
|
||||||
|
end
|
||||||
|
s.append ("</li>%N")
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
doc_url (a_api: STRING_8): STRING_8
|
||||||
|
do
|
||||||
|
Result := request.script_url (resource + url_encoder.encoded_string (a_api))
|
||||||
|
end
|
||||||
|
|
||||||
|
html_encoder: HTML_ENCODER
|
||||||
|
once
|
||||||
|
create Result
|
||||||
|
end
|
||||||
|
|
||||||
|
url_encoder: URL_ENCODER
|
||||||
|
once
|
||||||
|
create Result
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_SELF_DOCUMENTED_HANDLER}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_SELF_DOCUMENTED_HANDLER
|
||||||
|
|
||||||
|
feature -- Documentation
|
||||||
|
|
||||||
|
documentation: detachable READABLE_STRING_32
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_SELF_DOCUMENTED_ROUTER_MAPPING}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_SELF_DOCUMENTED_ROUTER_MAPPING
|
||||||
|
|
||||||
|
feature -- Documentation
|
||||||
|
|
||||||
|
documentation: READABLE_STRING_32
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -23,10 +23,20 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
|
associated_resource: READABLE_STRING_8
|
||||||
|
-- Associated resource
|
||||||
|
do
|
||||||
|
Result := uri
|
||||||
|
end
|
||||||
|
|
||||||
handler: WSF_STARTS_WITH_HANDLER
|
handler: WSF_STARTS_WITH_HANDLER
|
||||||
|
|
||||||
uri: READABLE_STRING_8
|
uri: READABLE_STRING_8
|
||||||
|
|
||||||
|
feature -- Documentation
|
||||||
|
|
||||||
|
documentation: STRING_32 = "Starts-With-URI"
|
||||||
|
|
||||||
feature -- Status
|
feature -- Status
|
||||||
|
|
||||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class
|
|||||||
inherit
|
inherit
|
||||||
WSF_ROUTER_MAPPING
|
WSF_ROUTER_MAPPING
|
||||||
|
|
||||||
|
WSF_SELF_DOCUMENTED_ROUTER_MAPPING
|
||||||
|
|
||||||
create
|
create
|
||||||
make,
|
make,
|
||||||
make_trailing_slash_ignored
|
make_trailing_slash_ignored
|
||||||
@@ -30,12 +32,22 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
|
associated_resource: READABLE_STRING_8
|
||||||
|
-- Associated resource
|
||||||
|
do
|
||||||
|
Result := uri
|
||||||
|
end
|
||||||
|
|
||||||
handler: WSF_URI_HANDLER
|
handler: WSF_URI_HANDLER
|
||||||
|
|
||||||
uri: READABLE_STRING_8
|
uri: READABLE_STRING_8
|
||||||
|
|
||||||
trailing_slash_ignored: BOOLEAN
|
trailing_slash_ignored: BOOLEAN
|
||||||
|
|
||||||
|
feature -- Documentation
|
||||||
|
|
||||||
|
documentation: STRING_32 = "Is-URI"
|
||||||
|
|
||||||
feature -- Status
|
feature -- Status
|
||||||
|
|
||||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ class
|
|||||||
inherit
|
inherit
|
||||||
WSF_ROUTER_MAPPING
|
WSF_ROUTER_MAPPING
|
||||||
|
|
||||||
|
WSF_SELF_DOCUMENTED_ROUTER_MAPPING
|
||||||
|
|
||||||
|
DEBUG_OUTPUT
|
||||||
|
|
||||||
create
|
create
|
||||||
make,
|
make,
|
||||||
make_from_template
|
make_from_template
|
||||||
@@ -29,10 +33,28 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
|
associated_resource: READABLE_STRING_8
|
||||||
|
-- Associated resource
|
||||||
|
do
|
||||||
|
Result := template.template
|
||||||
|
end
|
||||||
|
|
||||||
handler: WSF_URI_TEMPLATE_HANDLER
|
handler: WSF_URI_TEMPLATE_HANDLER
|
||||||
|
|
||||||
template: URI_TEMPLATE
|
template: URI_TEMPLATE
|
||||||
|
|
||||||
|
feature -- Documentation
|
||||||
|
|
||||||
|
documentation: STRING_32 = "Match-URI-Template"
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
debug_output: STRING
|
||||||
|
-- String that should be displayed in debugger to represent `Current'.
|
||||||
|
do
|
||||||
|
Result := "URI-template: " + template.template
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Element change
|
feature -- Element change
|
||||||
|
|
||||||
set_handler (h: like handler)
|
set_handler (h: like handler)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class
|
|||||||
inherit
|
inherit
|
||||||
WSF_ROUTER_CONTEXT_MAPPING [C]
|
WSF_ROUTER_CONTEXT_MAPPING [C]
|
||||||
|
|
||||||
|
WSF_SELF_DOCUMENTED_ROUTER_MAPPING
|
||||||
|
|
||||||
DEBUG_OUTPUT
|
DEBUG_OUTPUT
|
||||||
|
|
||||||
create
|
create
|
||||||
@@ -31,10 +33,20 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
|
associated_resource: READABLE_STRING_8
|
||||||
|
-- Associated resource
|
||||||
|
do
|
||||||
|
Result := template.template
|
||||||
|
end
|
||||||
|
|
||||||
handler: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]
|
handler: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]
|
||||||
|
|
||||||
template: URI_TEMPLATE
|
template: URI_TEMPLATE
|
||||||
|
|
||||||
|
feature -- Documentation
|
||||||
|
|
||||||
|
documentation: STRING_32 = "Is-URI"
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
|
|
||||||
debug_output: STRING
|
debug_output: STRING
|
||||||
|
|||||||
@@ -114,6 +114,64 @@ feature -- Access
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
has_item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): BOOLEAN
|
||||||
|
local
|
||||||
|
m: WSF_ROUTER_MAPPING
|
||||||
|
ok: BOOLEAN
|
||||||
|
do
|
||||||
|
across
|
||||||
|
mappings as c
|
||||||
|
loop
|
||||||
|
m := c.item.mapping
|
||||||
|
ok := True
|
||||||
|
if rqst_methods /= Void then
|
||||||
|
if attached c.item.request_methods as l_item_rqst_methods then
|
||||||
|
ok := across rqst_methods as mtd some is_matching_request_methods (mtd.item, l_item_rqst_methods) end
|
||||||
|
else
|
||||||
|
ok := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
if attached {WSF_ROUTING_HANDLER} m.handler as l_routing then
|
||||||
|
Result := l_routing.router.has_item_associated_with_resource (a_resource, rqst_methods)
|
||||||
|
elseif m.associated_resource.same_string (a_resource) then
|
||||||
|
Result := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable WSF_ROUTER_ITEM
|
||||||
|
local
|
||||||
|
m: WSF_ROUTER_MAPPING
|
||||||
|
ok: BOOLEAN
|
||||||
|
do
|
||||||
|
across
|
||||||
|
mappings as c
|
||||||
|
until
|
||||||
|
Result /= Void
|
||||||
|
loop
|
||||||
|
m := c.item.mapping
|
||||||
|
ok := True
|
||||||
|
if rqst_methods /= Void then
|
||||||
|
if attached c.item.request_methods as l_item_rqst_methods then
|
||||||
|
ok := across rqst_methods as mtd some is_matching_request_methods (mtd.item, l_item_rqst_methods) end
|
||||||
|
else
|
||||||
|
ok := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
if attached {WSF_ROUTING_HANDLER} m.handler as l_routing then
|
||||||
|
Result := l_routing.router.item_associated_with_resource (a_resource, rqst_methods)
|
||||||
|
elseif m.associated_resource.same_string (a_resource) then
|
||||||
|
Result := c.item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Hook
|
feature -- Hook
|
||||||
|
|
||||||
execute_before (a_mapping: WSF_ROUTER_MAPPING)
|
execute_before (a_mapping: WSF_ROUTER_MAPPING)
|
||||||
|
|||||||
@@ -13,7 +13,12 @@ feature {NONE} -- Initialization
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
|
associated_resource: READABLE_STRING_8
|
||||||
|
-- Associated resource
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
handler: WSF_HANDLER
|
handler: WSF_HANDLER
|
||||||
-- Handler associated with Current mapping.
|
-- Handler associated with Current mapping.
|
||||||
|
|||||||
Reference in New Issue
Block a user