Breaking changes:
added `a_request_methods' argument to WSF_ROUTER_SELF_DOCUMENTATION_HANDLER.mapping_documentation added similar argument to WSF_ROUTER_SELF_DOCUMENTATION_ROUTER_MAPPING.documentation Renamed WSF_ROUTER_METHODS as WSF_REQUEST_METHODS Enhanced WSF_REQUEST_METHODS with new has_... function Added WSF_ROUTER_VISITOR and WSF_ROUTER_ITERATOR that may be useful to iterate inside the router. we may improve the implementation of the router using those visitors in the future. Improved the WSF_DEFAULT_RESPONSE to embedded suggested items (typically based on pseudo self documented router)
This commit is contained in:
@@ -36,18 +36,26 @@ feature {WSF_RESPONSE} -- Output
|
||||
local
|
||||
msg: WSF_RESPONSE_MESSAGE
|
||||
req: like request
|
||||
not_found: WSF_NOT_FOUND_RESPONSE
|
||||
trace: WSF_TRACE_RESPONSE
|
||||
do
|
||||
req := request
|
||||
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then
|
||||
create trace.make (req)
|
||||
msg := trace
|
||||
msg := trace_message (req)
|
||||
else
|
||||
create not_found.make (req)
|
||||
msg := not_found
|
||||
msg := not_found_message (req)
|
||||
end
|
||||
res.send (msg)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
trace_message (req: WSF_REQUEST): WSF_TRACE_RESPONSE
|
||||
do
|
||||
create Result.make (req)
|
||||
end
|
||||
|
||||
not_found_message (req: WSF_REQUEST): WSF_NOT_FOUND_RESPONSE
|
||||
do
|
||||
create Result.make (req)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,7 +9,8 @@ class
|
||||
inherit
|
||||
WSF_DEFAULT_RESPONSE
|
||||
redefine
|
||||
send_to
|
||||
send_to,
|
||||
not_found_message
|
||||
end
|
||||
|
||||
create
|
||||
@@ -30,6 +31,18 @@ feature -- Access
|
||||
router: WSF_ROUTER
|
||||
-- Associated router.
|
||||
|
||||
feature -- Settings
|
||||
|
||||
documentation_included: BOOLEAN
|
||||
-- Include self-documentation from `router' in the response?
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_documentation_included (b: BOOLEAN)
|
||||
do
|
||||
documentation_included := b
|
||||
end
|
||||
|
||||
feature {WSF_RESPONSE} -- Output
|
||||
|
||||
send_to (res: WSF_RESPONSE)
|
||||
@@ -40,24 +53,100 @@ feature {WSF_RESPONSE} -- Output
|
||||
local
|
||||
msg: WSF_RESPONSE_MESSAGE
|
||||
req: like request
|
||||
not_found: WSF_NOT_FOUND_RESPONSE
|
||||
not_allowed: WSF_METHOD_NOT_ALLOWED_RESPONSE
|
||||
trace: WSF_TRACE_RESPONSE
|
||||
do
|
||||
req := request
|
||||
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then
|
||||
create trace.make (req)
|
||||
msg := trace
|
||||
elseif attached router.allowed_methods_for_request (req) as mtds and then not mtds.is_empty then
|
||||
create not_allowed.make (req)
|
||||
not_allowed.set_suggested_methods (mtds)
|
||||
msg := trace_message (req)
|
||||
elseif attached method_not_allowed_message (req) as not_allowed then
|
||||
msg := not_allowed
|
||||
else
|
||||
create not_found.make (req)
|
||||
|
||||
msg := not_found
|
||||
msg := not_found_message (req)
|
||||
end
|
||||
res.send (msg)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
method_not_allowed_message (req: WSF_REQUEST): detachable WSF_METHOD_NOT_ALLOWED_RESPONSE
|
||||
local
|
||||
vis: WSF_ROUTER_AGENT_ITERATOR
|
||||
do
|
||||
if attached router.allowed_methods_for_request (req) as l_allowed_mtds and then not l_allowed_mtds.is_empty then
|
||||
create Result.make (req)
|
||||
Result.set_suggested_methods (l_allowed_mtds)
|
||||
|
||||
if documentation_included then
|
||||
create vis
|
||||
vis.on_item_actions.extend (agent (i: WSF_ROUTER_ITEM; r: WSF_METHOD_NOT_ALLOWED_RESPONSE)
|
||||
local
|
||||
l_is_hidden: BOOLEAN
|
||||
s: STRING_32
|
||||
do
|
||||
-- Keep only mapping for the request's method
|
||||
if
|
||||
not attached i.request_methods as l_methods or else
|
||||
l_methods.has (request.request_method)
|
||||
then
|
||||
if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} i.mapping as l_doc_mapping then
|
||||
l_is_hidden := l_doc_mapping.documentation (i.request_methods).is_hidden
|
||||
end
|
||||
if not l_is_hidden then
|
||||
create s.make_from_string (i.mapping.associated_resource)
|
||||
if attached i.request_methods as mtds then
|
||||
s.append (" [ ")
|
||||
across
|
||||
mtds as mtds_c
|
||||
loop
|
||||
s.append (mtds_c.item)
|
||||
s.append_character (' ')
|
||||
end
|
||||
s.append ("]")
|
||||
else
|
||||
s.append (" [*]")
|
||||
end
|
||||
r.add_suggested_text (s, Void)
|
||||
end
|
||||
end
|
||||
end (?, Result))
|
||||
vis.process_router (router)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
not_found_message (req: WSF_REQUEST): WSF_NOT_FOUND_RESPONSE
|
||||
local
|
||||
vis: WSF_ROUTER_AGENT_ITERATOR
|
||||
do
|
||||
Result := Precursor (req)
|
||||
if documentation_included then
|
||||
create vis
|
||||
vis.on_item_actions.extend (agent (i: WSF_ROUTER_ITEM; r: WSF_NOT_FOUND_RESPONSE)
|
||||
local
|
||||
l_is_hidden: BOOLEAN
|
||||
s: STRING_32
|
||||
do
|
||||
if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} i.mapping as l_doc_mapping then
|
||||
l_is_hidden := l_doc_mapping.documentation (i.request_methods).is_hidden
|
||||
end
|
||||
if not l_is_hidden then
|
||||
create s.make_from_string (i.mapping.associated_resource)
|
||||
if attached i.request_methods as mtds then
|
||||
s.append (" [ ")
|
||||
across
|
||||
mtds as mtds_c
|
||||
loop
|
||||
s.append (mtds_c.item)
|
||||
s.append_character (' ')
|
||||
end
|
||||
s.append ("]")
|
||||
else
|
||||
s.append (" [*]")
|
||||
end
|
||||
r.add_suggested_text (s, Void)
|
||||
end
|
||||
end (?, Result))
|
||||
vis.process_router (router)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -23,6 +23,7 @@ feature {NONE} -- Initialization
|
||||
request := req
|
||||
create header.make
|
||||
create suggested_methods
|
||||
create suggested_items.make (0)
|
||||
end
|
||||
|
||||
feature -- Header
|
||||
@@ -33,10 +34,18 @@ feature -- Header
|
||||
request: WSF_REQUEST
|
||||
-- Associated request.
|
||||
|
||||
suggested_methods: WSF_ROUTER_METHODS
|
||||
suggested_methods: WSF_REQUEST_METHODS
|
||||
-- Optional suggestions
|
||||
-- First is the default.
|
||||
|
||||
suggested_items: ARRAYED_LIST [TUPLE [location: detachable READABLE_STRING_8; text: detachable READABLE_STRING_GENERAL; description: detachable READABLE_STRING_GENERAL]]
|
||||
-- Optional suggestions
|
||||
-- First is the default.
|
||||
|
||||
body: detachable READABLE_STRING_8
|
||||
-- Optional body
|
||||
-- Displayed as extra content
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_suggested_methods (m: like suggested_methods)
|
||||
@@ -45,11 +54,31 @@ feature -- Element change
|
||||
suggested_methods := m
|
||||
end
|
||||
|
||||
add_suggested_location (a_loc: READABLE_STRING_8; a_title: detachable READABLE_STRING_GENERAL; a_description: detachable READABLE_STRING_GENERAL)
|
||||
-- Add `a_loc' to `suggested_items'
|
||||
do
|
||||
suggested_items.force ([a_loc, a_title, a_description])
|
||||
end
|
||||
|
||||
add_suggested_text (a_text: READABLE_STRING_GENERAL; a_description: detachable READABLE_STRING_GENERAL)
|
||||
-- Add `a_text' to `suggested_items'
|
||||
do
|
||||
suggested_items.force ([Void, a_text, a_description])
|
||||
end
|
||||
|
||||
set_body (b: like body)
|
||||
-- Set `body' to `b'
|
||||
do
|
||||
body := b
|
||||
end
|
||||
|
||||
feature {WSF_RESPONSE} -- Output
|
||||
|
||||
send_to (res: WSF_RESPONSE)
|
||||
local
|
||||
s: STRING
|
||||
l_text: detachable READABLE_STRING_GENERAL
|
||||
l_loc: detachable READABLE_STRING_8
|
||||
h: like header
|
||||
do
|
||||
h := header
|
||||
@@ -62,7 +91,7 @@ feature {WSF_RESPONSE} -- Output
|
||||
s := "Not allowed"
|
||||
|
||||
if request.is_content_type_accepted ({HTTP_MIME_TYPES}.text_html) then
|
||||
s := "<html><head>"
|
||||
s := "<html lang=%"en%"><head>"
|
||||
s.append ("<title>")
|
||||
s.append (html_encoder.encoded_string (request.request_uri))
|
||||
s.append ("Error 405 (Method Not Allowed)!!")
|
||||
@@ -103,6 +132,48 @@ feature {WSF_RESPONSE} -- Output
|
||||
end
|
||||
s.append ("%N")
|
||||
end
|
||||
|
||||
if attached suggested_items as lst and then not lst.is_empty then
|
||||
s.append ("<div id=%"suggestions%"><strong>Perhaps your are looking for:</strong><ul>")
|
||||
from
|
||||
lst.start
|
||||
until
|
||||
lst.after
|
||||
loop
|
||||
l_text := lst.item.text
|
||||
l_loc := lst.item.location
|
||||
if l_loc /= Void then
|
||||
if l_text = Void then
|
||||
l_text := l_loc
|
||||
end
|
||||
s.append ("<li>")
|
||||
s.append ("<a href=%"" + l_loc + "%">" + html_encoder.encoded_string (l_text.to_string_32) + "</a>")
|
||||
elseif l_text /= Void then
|
||||
|
||||
s.append ("<li>")
|
||||
s.append (html_encoder.encoded_string (l_text.to_string_32))
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
if (l_loc /= Void or l_text /= Void) then
|
||||
if attached lst.item.description as l_desc then
|
||||
s.append ("<br/> - ")
|
||||
s.append (html_encoder.encoded_string (l_desc.to_string_32))
|
||||
s.append ("%N")
|
||||
end
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
|
||||
lst.forth
|
||||
end
|
||||
s.append ("</ul></div>%N")
|
||||
end
|
||||
if attached body as b then
|
||||
s.append ("<div>")
|
||||
s.append (b)
|
||||
s.append ("</div>%N")
|
||||
end
|
||||
|
||||
|
||||
s.append ("<div id=%"footer%"></div>")
|
||||
s.append ("</body>%N")
|
||||
s.append ("</html>%N")
|
||||
@@ -122,6 +193,43 @@ feature {WSF_RESPONSE} -- Output
|
||||
end
|
||||
s.append ("%N")
|
||||
end
|
||||
if attached suggested_items as lst and then not lst.is_empty then
|
||||
s.append ("%NPerhaps your are looking for:%N")
|
||||
from
|
||||
lst.start
|
||||
until
|
||||
lst.after
|
||||
loop
|
||||
l_text := lst.item.text
|
||||
l_loc := lst.item.location
|
||||
if l_loc /= Void then
|
||||
s.append (" - ")
|
||||
if l_text = Void then
|
||||
s.append (l_loc)
|
||||
else
|
||||
s.append (" : ")
|
||||
s.append (l_text.to_string_8)
|
||||
end
|
||||
elseif l_text /= Void then
|
||||
s.append (" - ")
|
||||
s.append (l_text.to_string_8)
|
||||
end
|
||||
if (l_loc /= Void or l_text /= Void) then
|
||||
s.append ("%N")
|
||||
if attached lst.item.description as l_desc then
|
||||
s.append (" ")
|
||||
s.append (l_desc.to_string_8)
|
||||
s.append ("%N")
|
||||
end
|
||||
end
|
||||
lst.forth
|
||||
end
|
||||
end
|
||||
if attached body as b then
|
||||
s.append ("%N")
|
||||
s.append (b)
|
||||
s.append ("%N")
|
||||
end
|
||||
h.put_content_type_text_plain
|
||||
end
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ feature {NONE} -- Initialization
|
||||
do
|
||||
request := req
|
||||
create header.make
|
||||
create suggested_locations.make (0)
|
||||
create suggested_items.make (0)
|
||||
end
|
||||
|
||||
feature -- Header
|
||||
@@ -33,16 +33,32 @@ feature -- Header
|
||||
request: WSF_REQUEST
|
||||
-- Associated request.
|
||||
|
||||
suggested_locations: ARRAYED_LIST [TUPLE [location: READABLE_STRING_8; title: detachable READABLE_STRING_GENERAL]]
|
||||
suggested_items: ARRAYED_LIST [TUPLE [location: detachable READABLE_STRING_8; text: detachable READABLE_STRING_GENERAL; description: detachable READABLE_STRING_GENERAL]]
|
||||
-- Optional suggestions
|
||||
-- First is the default.
|
||||
|
||||
body: detachable READABLE_STRING_8
|
||||
-- Optional body
|
||||
-- Displayed as extra content
|
||||
|
||||
feature -- Element change
|
||||
|
||||
add_suggested_location (a_loc: READABLE_STRING_8; a_title: detachable READABLE_STRING_GENERAL)
|
||||
-- Add `a_loc' to `suggested_locations'
|
||||
add_suggested_location (a_loc: READABLE_STRING_8; a_title: detachable READABLE_STRING_GENERAL; a_description: detachable READABLE_STRING_GENERAL)
|
||||
-- Add `a_loc' to `suggested_items'
|
||||
do
|
||||
suggested_locations.force ([a_loc, a_title])
|
||||
suggested_items.force ([a_loc, a_title, a_description])
|
||||
end
|
||||
|
||||
add_suggested_text (a_text: READABLE_STRING_GENERAL; a_description: detachable READABLE_STRING_GENERAL)
|
||||
-- Add `a_text' to `suggested_items'
|
||||
do
|
||||
suggested_items.force ([Void, a_text, a_description])
|
||||
end
|
||||
|
||||
set_body (b: like body)
|
||||
-- Set `body' to `b'
|
||||
do
|
||||
body := b
|
||||
end
|
||||
|
||||
feature {WSF_RESPONSE} -- Output
|
||||
@@ -50,7 +66,8 @@ feature {WSF_RESPONSE} -- Output
|
||||
send_to (res: WSF_RESPONSE)
|
||||
local
|
||||
s: STRING
|
||||
l_title: detachable READABLE_STRING_GENERAL
|
||||
l_text: detachable READABLE_STRING_GENERAL
|
||||
l_loc: detachable READABLE_STRING_8
|
||||
h: like header
|
||||
do
|
||||
h := header
|
||||
@@ -85,25 +102,46 @@ feature {WSF_RESPONSE} -- Output
|
||||
s.append ("</div>")
|
||||
s.append ("Error 404 (Not Found)</div>")
|
||||
s.append ("<div id=%"message%">Error 404 (Not Found): <code>" + html_encoder.encoded_string (request.request_uri) + "</code></div>")
|
||||
if attached suggested_locations as lst and then not lst.is_empty then
|
||||
if attached suggested_items as lst and then not lst.is_empty then
|
||||
s.append ("<div id=%"suggestions%"><strong>Perhaps your are looking for:</strong><ul>")
|
||||
from
|
||||
lst.start
|
||||
until
|
||||
lst.after
|
||||
loop
|
||||
s.append ("<li>")
|
||||
l_title := lst.item.title
|
||||
if l_title = Void then
|
||||
l_title := lst.item.location
|
||||
l_text := lst.item.text
|
||||
l_loc := lst.item.location
|
||||
if l_loc /= Void then
|
||||
if l_text = Void then
|
||||
l_text := l_loc
|
||||
end
|
||||
s.append ("<li>")
|
||||
s.append ("<a href=%"" + l_loc + "%">" + html_encoder.encoded_string (l_text.to_string_32) + "</a>")
|
||||
elseif l_text /= Void then
|
||||
|
||||
s.append ("<li>")
|
||||
s.append (html_encoder.encoded_string (l_text.to_string_32))
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
if (l_loc /= Void or l_text /= Void) then
|
||||
if attached lst.item.description as l_desc then
|
||||
s.append ("<br/> - ")
|
||||
s.append (html_encoder.encoded_string (l_desc.to_string_32))
|
||||
s.append ("%N")
|
||||
end
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
s.append ("<a href=%"" + lst.item.location + "%">" + html_encoder.encoded_string (l_title.to_string_32) + "</a>")
|
||||
s.append ("</li>%N")
|
||||
|
||||
lst.forth
|
||||
end
|
||||
s.append ("</ul></div>%N")
|
||||
end
|
||||
if attached body as b then
|
||||
s.append ("<div>")
|
||||
s.append (b)
|
||||
s.append ("</div>%N")
|
||||
end
|
||||
|
||||
s.append ("<div id=%"footer%"></div>")
|
||||
s.append ("</body>%N")
|
||||
s.append ("</html>%N")
|
||||
@@ -113,24 +151,43 @@ feature {WSF_RESPONSE} -- Output
|
||||
s := "Error 404 (Not Found): "
|
||||
s.append (request.request_uri)
|
||||
s.append_character ('%N')
|
||||
if attached suggested_locations as lst and then not lst.is_empty then
|
||||
if attached suggested_items as lst and then not lst.is_empty then
|
||||
s.append ("%NPerhaps your are looking for:%N")
|
||||
from
|
||||
lst.start
|
||||
until
|
||||
lst.after
|
||||
loop
|
||||
s.append (" - ")
|
||||
l_title := lst.item.title
|
||||
if l_title = Void then
|
||||
l_title := lst.item.location
|
||||
l_text := lst.item.text
|
||||
l_loc := lst.item.location
|
||||
if l_loc /= Void then
|
||||
s.append (" - ")
|
||||
if l_text = Void then
|
||||
s.append (l_loc)
|
||||
else
|
||||
s.append (" : ")
|
||||
s.append (l_text.to_string_8)
|
||||
end
|
||||
elseif l_text /= Void then
|
||||
s.append (" - ")
|
||||
s.append (l_text.to_string_8)
|
||||
end
|
||||
if (l_loc /= Void or l_text /= Void) then
|
||||
s.append ("%N")
|
||||
if attached lst.item.description as l_desc then
|
||||
s.append (" ")
|
||||
s.append (l_desc.to_string_8)
|
||||
s.append ("%N")
|
||||
end
|
||||
end
|
||||
s.append (lst.item.location)
|
||||
s.append ("%N")
|
||||
|
||||
lst.forth
|
||||
end
|
||||
end
|
||||
if attached body as b then
|
||||
s.append ("%N")
|
||||
s.append (b)
|
||||
s.append ("%N")
|
||||
end
|
||||
|
||||
h.put_content_type_text_plain
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user