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:
Jocelyn Fiat
2012-12-19 16:42:26 +01:00
parent 021f0eeaec
commit aa65c16957
26 changed files with 999 additions and 457 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433" library_target="restbucks">
<target name="restbucks"> <target name="restbucks">
<root class="RESTBUCKS_SERVER" feature="make"/> <root class="RESTBUCKS_SERVER" feature="make"/>
<file_rule> <file_rule>

View File

@@ -33,6 +33,8 @@ inherit
REFACTORING_HELPER REFACTORING_HELPER
SHARED_ORDER_VALIDATION SHARED_ORDER_VALIDATION
WSF_SELF_DOCUMENTED_HANDLER
feature -- execute feature -- execute
uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE) uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -51,6 +53,25 @@ feature -- API DOC
api_doc : STRING = "URI:/order METHOD: POST%N URI:/order/{orderid} METHOD: GET, PUT, DELETE%N" api_doc : STRING = "URI:/order METHOD: POST%N URI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
feature -- Documentation
mapping_documentation (m: WSF_ROUTER_MAPPING; a_request_methods: detachable WSF_REQUEST_METHODS): WSF_ROUTER_MAPPING_DOCUMENTATION
do
create Result.make (m)
if a_request_methods /= Void then
if a_request_methods.has_method_post then
Result.add_description ("URI:/order METHOD: POST")
elseif
a_request_methods.has_method_get
or a_request_methods.has_method_put
or a_request_methods.has_method_delete
then
Result.add_description ("URI:/order/{orderid} METHOD: GET, PUT, DELETE")
end
end
end
feature -- HTTP Methods feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE) do_get (req: WSF_REQUEST; res: WSF_RESPONSE)

View File

@@ -48,24 +48,8 @@ feature -- Execution
-- I'm using this method to handle the method not allowed response -- I'm using this method to handle the method not allowed response
-- in the case that the given uri does not have a corresponding http method -- in the case that the given uri does not have a corresponding http method
-- to handle it. -- to handle it.
local
h : HTTP_HEADER
l_description : STRING
l_api_doc : STRING
do do
if req.content_length_value > 0 then Precursor (req, res)
req.input.read_string (req.content_length_value.as_integer_32)
end
create h.make
h.put_content_type_text_plain
l_api_doc := "%NPlease check the API%NURI:/order METHOD: POST%NURI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
l_description := req.request_method + req.request_uri + " is not allowed" + "%N" + l_api_doc
l_description.append ("%NHTML documentation:/api/doc METHOD: GET%N")
h.put_content_length (l_description.count)
h.put_current_date
res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed)
res.put_header_text (h.string)
res.put_string (l_description)
end end
note note

View File

@@ -42,17 +42,17 @@ feature {NONE} -- Initialization
feature -- Helper: mapping feature -- Helper: mapping
map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_ROUTER_METHODS) map_agent_uri (a_uri: READABLE_STRING_8; a_action: like {WSF_URI_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods) router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods)
end end
map_uri_template (a_tpl: READABLE_STRING_8; a_handler: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_template (a_tpl: READABLE_STRING_8; a_handler: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, a_handler), rqst_methods) router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, a_handler), rqst_methods)
end end
map_agent_uri_template_response (a_tpl: READABLE_STRING_8; a_action: like {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}.action; rqst_methods: detachable WSF_ROUTER_METHODS) map_agent_uri_template_response (a_tpl: READABLE_STRING_8; a_action: like {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}.action; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, create {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}.make (a_action)), rqst_methods) router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, create {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}.make (a_action)), rqst_methods)
end end

View File

@@ -45,7 +45,7 @@ feature {NONE} -- Initialization
feature -- Documentation feature -- Documentation
mapping_documentation (m: WSF_ROUTER_MAPPING): WSF_ROUTER_MAPPING_DOCUMENTATION mapping_documentation (m: WSF_ROUTER_MAPPING; a_request_methods: detachable WSF_REQUEST_METHODS): WSF_ROUTER_MAPPING_DOCUMENTATION
do do
create Result.make (m) create Result.make (m)
Result.set_is_hidden (is_hidden) Result.set_is_hidden (is_hidden)
@@ -54,7 +54,7 @@ feature -- Documentation
feature {WSF_ROUTER} -- Mapping feature {WSF_ROUTER} -- Mapping
on_mapped (a_mapping: WSF_ROUTER_MAPPING; a_rqst_methods: detachable WSF_ROUTER_METHODS) on_mapped (a_mapping: WSF_ROUTER_MAPPING; a_rqst_methods: detachable WSF_REQUEST_METHODS)
-- Callback called when a router map a route to Current handler -- Callback called when a router map a route to Current handler
do do
if attached {WSF_STARTS_WITH_MAPPING} a_mapping as m then if attached {WSF_STARTS_WITH_MAPPING} a_mapping as m then

View File

@@ -191,14 +191,14 @@ feature {WSF_RESPONSE} -- Output
res.put_string (l_description) res.put_string (l_description)
end end
append_documentation_to (s: STRING_8; m: WSF_ROUTER_MAPPING; meths: detachable WSF_ROUTER_METHODS) append_documentation_to (s: STRING_8; m: WSF_ROUTER_MAPPING; meths: detachable WSF_REQUEST_METHODS)
local local
l_url: detachable STRING_8 l_url: detachable STRING_8
l_base_url: detachable READABLE_STRING_8 l_base_url: detachable READABLE_STRING_8
l_doc: detachable WSF_ROUTER_MAPPING_DOCUMENTATION l_doc: detachable WSF_ROUTER_MAPPING_DOCUMENTATION
do do
if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} m as l_doc_mapping then if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} m as l_doc_mapping then
l_doc := l_doc_mapping.documentation l_doc := l_doc_mapping.documentation (meths)
end end
if l_doc = Void or else not l_doc.is_hidden then if l_doc = Void or else not l_doc.is_hidden then

View File

@@ -9,7 +9,7 @@ deferred class
feature -- Documentation feature -- Documentation
mapping_documentation (m: WSF_ROUTER_MAPPING): WSF_ROUTER_MAPPING_DOCUMENTATION mapping_documentation (m: WSF_ROUTER_MAPPING; a_request_methods: detachable WSF_REQUEST_METHODS): WSF_ROUTER_MAPPING_DOCUMENTATION
deferred deferred
end end

View File

@@ -12,10 +12,10 @@ inherit
feature -- Documentation feature -- Documentation
documentation: WSF_ROUTER_MAPPING_DOCUMENTATION documentation (a_request_methods: detachable WSF_REQUEST_METHODS): WSF_ROUTER_MAPPING_DOCUMENTATION
do do
if attached {WSF_SELF_DOCUMENTED_HANDLER} handler as obj then if attached {WSF_SELF_DOCUMENTED_HANDLER} handler as obj then
Result := obj.mapping_documentation (Current) Result := obj.mapping_documentation (Current, a_request_methods)
else else
create Result.make (Current) create Result.make (Current)
end end

View File

@@ -17,7 +17,7 @@ feature -- Mapping helper: starts_with
map_starts_with_request_methods (a_uri, h, Void) map_starts_with_request_methods (a_uri, h, Void)
end end
map_starts_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_STARTS_WITH_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_ROUTER_METHODS) map_starts_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_STARTS_WITH_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_STARTS_WITH_CONTEXT_MAPPING [C]}.make (a_uri, h), rqst_methods) router.map_with_request_methods (create {WSF_STARTS_WITH_CONTEXT_MAPPING [C]}.make (a_uri, h), rqst_methods)
end end
@@ -29,7 +29,7 @@ feature -- Mapping helper: starts_with agent
map_starts_with_agent_with_request_methods (a_uri, proc, Void) map_starts_with_agent_with_request_methods (a_uri, proc, Void)
end end
map_starts_with_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [start_path: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_ROUTER_METHODS) map_starts_with_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [start_path: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
map_starts_with_request_methods (a_uri, create {WSF_STARTS_WITH_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods) map_starts_with_request_methods (a_uri, create {WSF_STARTS_WITH_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods)
end end

View File

@@ -17,7 +17,7 @@ feature -- Mapping helper: uri
map_uri_with_request_methods (a_uri, h, Void) map_uri_with_request_methods (a_uri, h, Void)
end end
map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_CONTEXT_MAPPING [C]}.make (a_uri, h), rqst_methods) router.map_with_request_methods (create {WSF_URI_CONTEXT_MAPPING [C]}.make (a_uri, h), rqst_methods)
end end
@@ -29,7 +29,7 @@ feature -- Mapping helper: uri agent
map_uri_agent_with_request_methods (a_uri, proc, Void) map_uri_agent_with_request_methods (a_uri, proc, Void)
end end
map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods) map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods)
end end

View File

@@ -17,7 +17,7 @@ feature -- Mapping helper: uri
map_uri_with_request_methods (a_uri, h, Void) map_uri_with_request_methods (a_uri, h, Void)
end end
map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, h), rqst_methods) router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, h), rqst_methods)
end end
@@ -29,7 +29,7 @@ feature -- Mapping helper: uri agent
map_uri_agent_with_request_methods (a_uri, proc, Void) map_uri_agent_with_request_methods (a_uri, proc, Void)
end end
map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_HANDLER}.make (proc), rqst_methods) map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_HANDLER}.make (proc), rqst_methods)
end end

View File

@@ -17,7 +17,7 @@ feature -- Mapping helper: uri
map_uri_template_with_request_methods (a_tpl, h, Void) map_uri_template_with_request_methods (a_tpl, h, Void)
end end
map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_TEMPLATE_CONTEXT_MAPPING [C]}.make (a_tpl, h), rqst_methods) router.map_with_request_methods (create {WSF_URI_TEMPLATE_CONTEXT_MAPPING [C]}.make (a_tpl, h), rqst_methods)
end end
@@ -29,7 +29,7 @@ feature -- Mapping helper: uri agent
map_uri_template_agent_with_request_methods (a_tpl, proc, Void) map_uri_template_agent_with_request_methods (a_tpl, proc, Void)
end end
map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods) map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods)
end end

View File

@@ -17,19 +17,19 @@ feature -- Mapping helper: uri
map_uri_template_with_request_methods (a_tpl, h, Void) map_uri_template_with_request_methods (a_tpl, h, Void)
end end
map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods) router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods)
end end
feature -- Mapping helper: uri agent feature -- Mapping helper: uri agent
map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]) map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]])
do do
map_uri_template_agent_with_request_methods (a_tpl, proc, Void) map_uri_template_agent_with_request_methods (a_tpl, proc, Void)
end end
map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_ROUTER_METHODS) map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
do do
map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods) map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods)
end end

View File

@@ -17,7 +17,7 @@ feature -- Status report
feature {WSF_ROUTER} -- Mapping feature {WSF_ROUTER} -- Mapping
on_mapped (a_mapping: WSF_ROUTER_MAPPING; a_rqst_methods: detachable WSF_ROUTER_METHODS) on_mapped (a_mapping: WSF_ROUTER_MAPPING; a_rqst_methods: detachable WSF_REQUEST_METHODS)
-- Callback called when a router map a route to Current handler -- Callback called when a router map a route to Current handler
do do
end end

View File

@@ -0,0 +1,483 @@
note
description: "[
Object that is use in relation with WSF_ROUTER, to precise which request methods is accepted.
For convenience, `make_from_iterable' is available, so that you can use <<"GET", "POST">> for instance
but remember manifest string are evil ...
Since in HTTP you can use your own custom request method, this is not possible to catch any typo
( for instance if you write "POST" instead of "P0ST" this is hard to find the error,
but in one case it uses upper "o" and in the other case this is zero "0"
)
The recommanded way to use is for instance
create {WSF_REQUEST_METHODS}.make_get_post
create methods; methods.enable_get; methods.enable_post
This sounds heavy, but this is much safer.
( note: in addition internally this first checks using reference comparison
and then compare string value, so it brings optimization for accepted request methods.
)
]"
date: "$Date$"
revision: "$Revision$"
class
WSF_REQUEST_METHODS
inherit
ITERABLE [READABLE_STRING_8]
redefine
default_create
end
HTTP_REQUEST_METHODS
redefine
default_create
end
create
default_create,
make,
make_from_iterable,
make_from_string
convert
to_array: {ARRAY [READABLE_STRING_8]},
make_from_iterable ({ITERABLE [READABLE_STRING_8], ITERABLE [STRING_8], ARRAY [READABLE_STRING_8], ARRAY [STRING_8]}),
make_from_string ({READABLE_STRING_8, STRING_8})
feature {NONE} -- Initialization
default_create
do
Precursor
make (1)
end
make (n: INTEGER)
do
create methods.make (n)
end
make_from_iterable (v: ITERABLE [READABLE_STRING_8])
do
make (1)
add_methods (v)
end
make_from_string (v: READABLE_STRING_8)
do
make_from_iterable (v.split (','))
end
feature -- Status report
is_locked: BOOLEAN
-- Is Current locked? And then can not be modified?
is_empty: BOOLEAN
do
Result := methods.count = 0
end
has (a_method: READABLE_STRING_8): BOOLEAN
-- Has `a_method' enabled?
require
a_method_is_uppercase: a_method.same_string (a_method.as_upper)
do
-- First look for string object itself,
-- in case `a_method' comes from one of the HTTP_REQUEST_METHODS constants
Result := across methods as c some c.item = a_method end
if not Result then
-- If not found, look for the same string value
Result := across methods as c some c.item.same_string_general (a_method) end
end
end
has_some_of (a_methods: WSF_REQUEST_METHODS): BOOLEAN
-- Has any methods from `a_methods' enabled?
do
Result := across a_methods as c some has (c.item) end
end
has_all_of (a_methods: WSF_REQUEST_METHODS): BOOLEAN
-- Has all methods from `a_methods' enabled?
do
Result := across a_methods as c all has (c.item) end
end
has_method_get: BOOLEAN
-- Has method GET enabled?
do
Result := has (method_get)
end
has_method_post: BOOLEAN
-- Has method POST enabled?
do
Result := has (method_post)
end
has_method_put: BOOLEAN
-- Has method PUT enabled?
do
Result := has (method_put)
end
has_method_delete: BOOLEAN
-- Has method DELETE enabled?
do
Result := has (method_delete)
end
has_method_options: BOOLEAN
-- Has method OPTIONS enabled?
do
Result := has (method_options)
end
has_method_head: BOOLEAN
-- Has method HEAD enabled?
do
Result := has (method_head)
end
has_method_trace: BOOLEAN
-- Has method TRACE enabled?
do
Result := has (method_trace)
end
has_method_connect: BOOLEAN
-- Has method CONNECT enabled?
do
Result := has (method_connect)
end
has_method_patch: BOOLEAN
-- Has method PATCH enabled?
do
Result := has (method_patch)
end
feature -- Access
new_cursor: INDEXABLE_ITERATION_CURSOR [READABLE_STRING_8]
-- Fresh cursor associated with current structure
do
Result := methods.new_cursor
end
feature -- Status change
lock
-- Lock current and prevent any change in methods
-- Once it is locked, it is impossible to unlock.
do
is_locked := True
end
feature -- Basic operations
plus alias "+" (a_other: WSF_REQUEST_METHODS): WSF_REQUEST_METHODS
-- Merge Current and a_other into Result
require
a_other_not_void: a_other /= Void
do
create Result.make_from_iterable (Current)
Result.add_methods (a_other)
end
feature -- Element change
enable_get
require
is_not_locked: not is_locked
get_disabled: not has (method_get)
do
methods.extend (method_get)
ensure
get_enabled: has (method_get)
end
disable_get
require
is_not_locked: not is_locked
get_enabled: has (method_get)
do
prune_method (method_get)
ensure
get_disabled: not has (method_get)
end
enable_post
require
is_not_locked: not is_locked
post_disabled: not has (method_post)
do
methods.extend (method_post)
ensure
post_enabled: has (method_post)
end
disable_post
require
is_not_locked: not is_locked
post_enabled: has (method_post)
do
prune_method (method_post)
ensure
post_disabled: not has (method_post)
end
enable_put
require
is_not_locked: not is_locked
put_disabled: not has (method_put)
do
methods.extend (method_put)
ensure
put_enabled: has (method_put)
end
disable_put
require
is_not_locked: not is_locked
put_enabled: has (method_put)
do
prune_method (method_put)
ensure
put_disabled: not has (method_put)
end
enable_delete
require
is_not_locked: not is_locked
delete_disabled: not has (method_delete)
do
methods.extend (method_delete)
ensure
delete_enabled: has (method_delete)
end
disable_delete
require
is_not_locked: not is_locked
delete_enabled: has (method_delete)
do
prune_method (method_delete)
ensure
delete_disabled: not has (method_delete)
end
enable_options
require
is_not_locked: not is_locked
options_disabled: not has (method_options)
do
methods.extend (method_options)
ensure
options_enabled: has (method_options)
end
disable_options
require
is_not_locked: not is_locked
options_enabled: has (method_options)
do
prune_method (method_options)
ensure
options_disabled: not has (method_options)
end
enable_head
require
is_not_locked: not is_locked
head_disabled: not has (method_head)
do
methods.extend (method_head)
ensure
head_enabled: has (method_head)
end
disable_head
require
is_not_locked: not is_locked
head_enabled: has (method_head)
do
prune_method (method_head)
ensure
head_disabled: not has (method_head)
end
enable_trace
require
is_not_locked: not is_locked
trace_disabled: not has (method_trace)
do
methods.extend (method_trace)
ensure
trace_enabled: has (method_trace)
end
disable_trace
require
is_not_locked: not is_locked
trace_enabled: has (method_trace)
do
prune_method (method_trace)
ensure
trace_disabled: not has (method_trace)
end
enable_connect
require
is_not_locked: not is_locked
connect_disabled: not has (method_connect)
do
methods.extend (method_connect)
ensure
connect_enabled: has (method_connect)
end
disable_connect
require
is_not_locked: not is_locked
connect_enabled: has (method_connect)
do
prune_method (method_connect)
ensure
connect_disabled: not has (method_connect)
end
enable_patch
require
is_not_locked: not is_locked
patch_disabled: not has (method_patch)
do
methods.extend (method_patch)
ensure
patch_enabled: has (method_patch)
end
disable_patch
require
is_not_locked: not is_locked
patch_enabled: has (method_patch)
do
prune_method (method_patch)
ensure
patch_disabled: not has (method_patch)
end
enable_custom (m: READABLE_STRING_8)
require
is_not_locked: not is_locked
not_blank: not across m as mc some mc.item.is_space end
custom_disabled: not has (m.as_upper)
do
methods.extend (m.as_upper)
ensure
custom_enabled: has (m.as_upper)
end
disable_custom (m: READABLE_STRING_8)
require
is_not_locked: not is_locked
not_blank: not across m as mc some mc.item.is_space end
custom_enabled: has (m.as_upper)
do
prune_method (m.as_upper)
ensure
custom_disabled: not has (m.as_upper)
end
feature -- Access
methods: ARRAYED_LIST [READABLE_STRING_8]
to_array: ARRAY [READABLE_STRING_8]
do
Result := methods.to_array
end
feature {WSF_REQUEST_METHODS} -- Implementation
add_methods (lst: ITERABLE [READABLE_STRING_8])
-- Enable methods from `lst'
do
if not is_locked then
across
lst as c
loop
add_method_using_constant (c.item)
end
end
end
feature {NONE} -- Implementation
add_method_using_constant (v: READABLE_STRING_8)
-- Add method `v' using method_* constant
do
if v.is_case_insensitive_equal (method_get) then
enable_get
elseif v.is_case_insensitive_equal (method_post) then
enable_post
elseif v.is_case_insensitive_equal (method_put) then
enable_put
elseif v.is_case_insensitive_equal (method_delete) then
enable_delete
elseif v.is_case_insensitive_equal (method_head) then
enable_head
elseif v.is_case_insensitive_equal (method_options) then
enable_options
elseif v.is_case_insensitive_equal (method_trace) then
enable_trace
elseif v.is_case_insensitive_equal (method_connect) then
enable_connect
elseif v.is_case_insensitive_equal (method_patch) then
enable_patch
else
enable_custom (v)
end
ensure
method_set: has (v.as_upper)
end
prune_method (v: READABLE_STRING_8)
require
is_upper_case: v.same_string (v.as_upper)
local
m: READABLE_STRING_8
do
if not is_locked then
from
methods.start
until
methods.after
loop
m := methods.item
if m = v or else m.same_string (v) then
methods.remove
else
methods.forth
end
end
end
end
invariant
methods_are_uppercase: across methods as c all c.item.same_string (c.item.as_upper) end
;note
copyright: "2011-2012, 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

View File

@@ -51,6 +51,7 @@ feature -- Execution
msg: WSF_DEFAULT_ROUTER_RESPONSE msg: WSF_DEFAULT_ROUTER_RESPONSE
do do
create msg.make_with_router (req, router) create msg.make_with_router (req, router)
msg.set_documentation_included (True)
res.send (msg) res.send (msg)
end end

View File

@@ -56,7 +56,7 @@ feature -- Mapping
map_with_request_methods (a_mapping, Void) map_with_request_methods (a_mapping, Void)
end end
map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_ROUTER_METHODS) map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `a_mapping' for request methods `rqst_methods' -- Map `a_mapping' for request methods `rqst_methods'
do do
debug ("router") debug ("router")
@@ -81,7 +81,7 @@ feature -- Mapping handler
handle_with_request_methods (a_resource, f, Void) handle_with_request_methods (a_resource, f, Void)
end end
handle_with_request_methods (a_resource: READABLE_STRING_8; f: WSF_ROUTER_MAPPING_FACTORY; rqst_methods: detachable WSF_ROUTER_METHODS) handle_with_request_methods (a_resource: READABLE_STRING_8; f: WSF_ROUTER_MAPPING_FACTORY; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map the mapping created by factory `f' for resource `a_resource' -- Map the mapping created by factory `f' for resource `a_resource'
-- and only for request methods `rqst_methods' -- and only for request methods `rqst_methods'
do do
@@ -150,7 +150,7 @@ feature {NONE} -- Dispatch implementation
feature -- Status report feature -- Status report
has_item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): BOOLEAN has_item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_REQUEST_METHODS): BOOLEAN
local local
m: WSF_ROUTER_MAPPING m: WSF_ROUTER_MAPPING
ok: BOOLEAN ok: BOOLEAN
@@ -177,7 +177,7 @@ feature -- Status report
end end
end end
item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable WSF_ROUTER_ITEM item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_REQUEST_METHODS): detachable WSF_ROUTER_ITEM
local local
m: WSF_ROUTER_MAPPING m: WSF_ROUTER_MAPPING
ok: BOOLEAN ok: BOOLEAN
@@ -206,11 +206,11 @@ feature -- Status report
end end
end end
allowed_methods_for_request (req: WSF_REQUEST): WSF_ROUTER_METHODS allowed_methods_for_request (req: WSF_REQUEST): WSF_REQUEST_METHODS
-- Allowed methods for `req' -- Allowed methods for `req'
local local
m: WSF_ROUTER_MAPPING m: WSF_ROUTER_MAPPING
l_rqsmethods: detachable WSF_ROUTER_METHODS l_rqsmethods: detachable WSF_REQUEST_METHODS
do do
create Result create Result
@@ -286,49 +286,49 @@ feature -- Traversing
feature -- Request methods helper feature -- Request methods helper
methods_head: WSF_ROUTER_METHODS methods_head: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result create Result
Result.enable_head Result.enable_head
Result.lock Result.lock
end end
methods_options: WSF_ROUTER_METHODS methods_options: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result create Result
Result.enable_options Result.enable_options
Result.lock Result.lock
end end
methods_get: WSF_ROUTER_METHODS methods_get: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result create Result
Result.enable_get Result.enable_get
Result.lock Result.lock
end end
methods_post: WSF_ROUTER_METHODS methods_post: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result create Result
Result.enable_post Result.enable_post
Result.lock Result.lock
end end
methods_put: WSF_ROUTER_METHODS methods_put: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result create Result
Result.enable_put Result.enable_put
Result.lock Result.lock
end end
methods_delete: WSF_ROUTER_METHODS methods_delete: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result create Result
Result.enable_delete Result.enable_delete
Result.lock Result.lock
end end
methods_head_get_post: WSF_ROUTER_METHODS methods_head_get_post: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result.make (3) create Result.make (3)
Result.enable_head Result.enable_head
@@ -337,7 +337,7 @@ feature -- Request methods helper
Result.lock Result.lock
end end
methods_get_put_delete: WSF_ROUTER_METHODS methods_get_put_delete: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result.make (3) create Result.make (3)
Result.enable_get Result.enable_get
@@ -346,7 +346,7 @@ feature -- Request methods helper
Result.lock Result.lock
end end
methods_head_get: WSF_ROUTER_METHODS methods_head_get: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result.make (2) create Result.make (2)
Result.enable_head Result.enable_head
@@ -354,7 +354,7 @@ feature -- Request methods helper
Result.lock Result.lock
end end
methods_get_post: WSF_ROUTER_METHODS methods_get_post: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result.make (2) create Result.make (2)
Result.enable_get Result.enable_get
@@ -362,7 +362,7 @@ feature -- Request methods helper
Result.lock Result.lock
end end
methods_put_post: WSF_ROUTER_METHODS methods_put_post: WSF_REQUEST_METHODS
once ("THREAD") once ("THREAD")
create Result.make (2) create Result.make (2)
Result.enable_put Result.enable_put
@@ -401,7 +401,7 @@ feature {NONE} -- Access: Implementation
end end
end end
is_matching_request_methods (a_request_method: READABLE_STRING_8; a_rqst_methods: detachable WSF_ROUTER_METHODS): BOOLEAN is_matching_request_methods (a_request_method: READABLE_STRING_8; a_rqst_methods: detachable WSF_REQUEST_METHODS): BOOLEAN
-- `a_request_method' is matching `a_rqst_methods' contents -- `a_request_method' is matching `a_rqst_methods' contents
do do
if a_rqst_methods /= Void and then not a_rqst_methods.is_empty then if a_rqst_methods /= Void and then not a_rqst_methods.is_empty then

View File

@@ -0,0 +1,67 @@
note
description: "Summary description for {WSF_ROUTER_AGENT_ITERATOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_ROUTER_AGENT_ITERATOR
inherit
WSF_ROUTER_ITERATOR
redefine
default_create,
process_router,
process_item,
process_mapping,
process_handler
end
feature {NONE} -- Initialization
default_create
do
Precursor
create on_router_actions.make
create on_item_actions.make
create on_mapping_actions.make
create on_handler_actions.make
end
feature -- Actions
on_router_actions: ACTION_SEQUENCE [TUPLE [WSF_ROUTER]]
on_item_actions: ACTION_SEQUENCE [TUPLE [WSF_ROUTER_ITEM]]
on_mapping_actions: ACTION_SEQUENCE [TUPLE [WSF_ROUTER_MAPPING]]
on_handler_actions: ACTION_SEQUENCE [TUPLE [WSF_HANDLER]]
feature -- Visitor
process_router (r: WSF_ROUTER)
do
on_router_actions.call ([r])
Precursor (r)
end
process_item (i: WSF_ROUTER_ITEM)
do
on_item_actions.call ([i])
Precursor (i)
end
process_mapping (m: WSF_ROUTER_MAPPING)
do
on_mapping_actions.call ([m])
Precursor (m)
end
process_handler (h: WSF_HANDLER)
do
on_handler_actions.call ([h])
Precursor (h)
end
end

View File

@@ -36,7 +36,7 @@ feature -- Access
mapping: WSF_ROUTER_MAPPING mapping: WSF_ROUTER_MAPPING
request_methods: detachable WSF_ROUTER_METHODS request_methods: detachable WSF_REQUEST_METHODS
feature -- Status report feature -- Status report

View File

@@ -0,0 +1,41 @@
note
description: "Summary description for {WSF_ROUTER_ITERATOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
WSF_ROUTER_ITERATOR
inherit
WSF_ROUTER_VISITOR
feature -- Visitor
process_router (r: WSF_ROUTER)
do
across
r as c
loop
process_item (c.item)
end
end
process_item (i: WSF_ROUTER_ITEM)
do
process_mapping (i.mapping)
end
process_mapping (m: WSF_ROUTER_MAPPING)
do
process_handler (m.handler)
end
process_handler (h: WSF_HANDLER)
do
if attached {WSF_ROUTING_HANDLER} h as r then
process_router (r.router)
end
end
end

View File

@@ -24,15 +24,13 @@ note
class class
WSF_ROUTER_METHODS WSF_ROUTER_METHODS
inherit obsolete
ITERABLE [READABLE_STRING_8] "Use WSF_REQUEST_METHODS"
redefine
default_create
end
HTTP_REQUEST_METHODS inherit
WSF_REQUEST_METHODS
redefine redefine
default_create plus
end end
create create
@@ -46,364 +44,21 @@ convert
make_from_iterable ({ITERABLE [READABLE_STRING_8], ITERABLE [STRING_8], ARRAY [READABLE_STRING_8], ARRAY [STRING_8]}), make_from_iterable ({ITERABLE [READABLE_STRING_8], ITERABLE [STRING_8], ARRAY [READABLE_STRING_8], ARRAY [STRING_8]}),
make_from_string ({READABLE_STRING_8, STRING_8}) make_from_string ({READABLE_STRING_8, STRING_8})
feature {NONE} -- Initialization
default_create
do
Precursor
make (1)
end
make (n: INTEGER)
do
create methods.make (n)
end
make_from_iterable (v: ITERABLE [READABLE_STRING_8])
do
make (1)
add_methods (v)
end
make_from_string (v: READABLE_STRING_8)
do
make_from_iterable (v.split (','))
end
feature -- Status report
is_locked: BOOLEAN
-- Is Current locked? And then can not be modified?
is_empty: BOOLEAN
do
Result := methods.count = 0
end
has (a_method: READABLE_STRING_8): BOOLEAN
-- Has `a_method' enabled?
require
a_method_is_uppercase: a_method.same_string (a_method.as_upper)
do
-- First look for string object itself,
-- in case `a_method' comes from one of the HTTP_REQUEST_METHODS constants
Result := across methods as c some c.item = a_method end
if not Result then
-- If not found, look for the same string value
Result := across methods as c some c.item.same_string_general (a_method) end
end
end
feature -- Access
new_cursor: INDEXABLE_ITERATION_CURSOR [READABLE_STRING_8]
-- Fresh cursor associated with current structure
do
Result := methods.new_cursor
end
feature -- Status change
lock
-- Lock current and prevent any change in methods
-- Once it is locked, it is impossible to unlock.
do
is_locked := True
end
feature -- Basic operations feature -- Basic operations
add alias "+" (a_other: WSF_ROUTER_METHODS): WSF_ROUTER_METHODS add (a_other: like plus): like plus
obsolete "Use `plus' or `alias +'"
do
Result := plus (a_other)
end
plus alias "+" (a_other: WSF_ROUTER_METHODS): WSF_ROUTER_METHODS
-- Merge Current and a_other into Result -- Merge Current and a_other into Result
require
a_other_not_void: a_other /= Void
do do
create Result.make_from_iterable (Current) create Result.make_from_iterable (Current)
Result.add_methods (a_other) Result.add_methods (a_other)
end end
feature -- Element change
enable_get
require
is_not_locked: not is_locked
get_disabled: not has (method_get)
do
methods.extend (method_get)
ensure
get_enabled: has (method_get)
end
disable_get
require
is_not_locked: not is_locked
get_enabled: has (method_get)
do
prune_method (method_get)
ensure
get_disabled: not has (method_get)
end
enable_post
require
is_not_locked: not is_locked
post_disabled: not has (method_post)
do
methods.extend (method_post)
ensure
post_enabled: has (method_post)
end
disable_post
require
is_not_locked: not is_locked
post_enabled: has (method_post)
do
prune_method (method_post)
ensure
post_disabled: not has (method_post)
end
enable_put
require
is_not_locked: not is_locked
put_disabled: not has (method_put)
do
methods.extend (method_put)
ensure
put_enabled: has (method_put)
end
disable_put
require
is_not_locked: not is_locked
put_enabled: has (method_put)
do
prune_method (method_put)
ensure
put_disabled: not has (method_put)
end
enable_delete
require
is_not_locked: not is_locked
delete_disabled: not has (method_delete)
do
methods.extend (method_delete)
ensure
delete_enabled: has (method_delete)
end
disable_delete
require
is_not_locked: not is_locked
delete_enabled: has (method_delete)
do
prune_method (method_delete)
ensure
delete_disabled: not has (method_delete)
end
enable_options
require
is_not_locked: not is_locked
options_disabled: not has (method_options)
do
methods.extend (method_options)
ensure
options_enabled: has (method_options)
end
disable_options
require
is_not_locked: not is_locked
options_enabled: has (method_options)
do
prune_method (method_options)
ensure
options_disabled: not has (method_options)
end
enable_head
require
is_not_locked: not is_locked
head_disabled: not has (method_head)
do
methods.extend (method_head)
ensure
head_enabled: has (method_head)
end
disable_head
require
is_not_locked: not is_locked
head_enabled: has (method_head)
do
prune_method (method_head)
ensure
head_disabled: not has (method_head)
end
enable_trace
require
is_not_locked: not is_locked
trace_disabled: not has (method_trace)
do
methods.extend (method_trace)
ensure
trace_enabled: has (method_trace)
end
disable_trace
require
is_not_locked: not is_locked
trace_enabled: has (method_trace)
do
prune_method (method_trace)
ensure
trace_disabled: not has (method_trace)
end
enable_connect
require
is_not_locked: not is_locked
connect_disabled: not has (method_connect)
do
methods.extend (method_connect)
ensure
connect_enabled: has (method_connect)
end
disable_connect
require
is_not_locked: not is_locked
connect_enabled: has (method_connect)
do
prune_method (method_connect)
ensure
connect_disabled: not has (method_connect)
end
enable_patch
require
is_not_locked: not is_locked
patch_disabled: not has (method_patch)
do
methods.extend (method_patch)
ensure
patch_enabled: has (method_patch)
end
disable_patch
require
is_not_locked: not is_locked
patch_enabled: has (method_patch)
do
prune_method (method_patch)
ensure
patch_disabled: not has (method_patch)
end
enable_custom (m: READABLE_STRING_8)
require
is_not_locked: not is_locked
not_blank: not across m as mc some mc.item.is_space end
custom_disabled: not has (m.as_upper)
do
methods.extend (m.as_upper)
ensure
custom_enabled: has (m.as_upper)
end
disable_custom (m: READABLE_STRING_8)
require
is_not_locked: not is_locked
not_blank: not across m as mc some mc.item.is_space end
custom_enabled: has (m.as_upper)
do
prune_method (m.as_upper)
ensure
custom_disabled: not has (m.as_upper)
end
feature -- Access
methods: ARRAYED_LIST [READABLE_STRING_8]
to_array: ARRAY [READABLE_STRING_8]
do
Result := methods.to_array
end
feature {WSF_ROUTER_METHODS} -- Implementation
add_methods (lst: ITERABLE [READABLE_STRING_8])
-- Enable methods from `lst'
do
if not is_locked then
across
lst as c
loop
add_method_using_constant (c.item)
end
end
end
feature {NONE} -- Implementation
add_method_using_constant (v: READABLE_STRING_8)
-- Add method `v' using method_* constant
do
if v.is_case_insensitive_equal (method_get) then
enable_get
elseif v.is_case_insensitive_equal (method_post) then
enable_post
elseif v.is_case_insensitive_equal (method_put) then
enable_put
elseif v.is_case_insensitive_equal (method_delete) then
enable_delete
elseif v.is_case_insensitive_equal (method_head) then
enable_head
elseif v.is_case_insensitive_equal (method_options) then
enable_options
elseif v.is_case_insensitive_equal (method_trace) then
enable_trace
elseif v.is_case_insensitive_equal (method_connect) then
enable_connect
elseif v.is_case_insensitive_equal (method_patch) then
enable_patch
else
enable_custom (v)
end
ensure
method_set: has (v.as_upper)
end
prune_method (v: READABLE_STRING_8)
require
is_upper_case: v.same_string (v.as_upper)
local
m: READABLE_STRING_8
do
if not is_locked then
from
methods.start
until
methods.after
loop
m := methods.item
if m = v or else m.same_string (v) then
methods.remove
else
methods.forth
end
end
end
end
invariant
methods_are_uppercase: across methods as c all c.item.same_string (c.item.as_upper) end
;note ;note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2012, 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)"

View File

@@ -0,0 +1,28 @@
note
description: "Summary description for {WSF_ROUTER_VISITOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
WSF_ROUTER_VISITOR
feature -- Visitor
process_router (r: WSF_ROUTER)
deferred
end
process_item (i: WSF_ROUTER_ITEM)
deferred
end
process_mapping (m: WSF_ROUTER_MAPPING)
deferred
end
process_handler (h: WSF_HANDLER)
deferred
end
end

View File

@@ -36,18 +36,26 @@ feature {WSF_RESPONSE} -- Output
local local
msg: WSF_RESPONSE_MESSAGE msg: WSF_RESPONSE_MESSAGE
req: like request req: like request
not_found: WSF_NOT_FOUND_RESPONSE
trace: WSF_TRACE_RESPONSE
do do
req := request req := request
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then
create trace.make (req) msg := trace_message (req)
msg := trace
else else
create not_found.make (req) msg := not_found_message (req)
msg := not_found
end end
res.send (msg) res.send (msg)
end 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 end

View File

@@ -9,7 +9,8 @@ class
inherit inherit
WSF_DEFAULT_RESPONSE WSF_DEFAULT_RESPONSE
redefine redefine
send_to send_to,
not_found_message
end end
create create
@@ -30,6 +31,18 @@ feature -- Access
router: WSF_ROUTER router: WSF_ROUTER
-- Associated 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 feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE) send_to (res: WSF_RESPONSE)
@@ -40,24 +53,100 @@ feature {WSF_RESPONSE} -- Output
local local
msg: WSF_RESPONSE_MESSAGE msg: WSF_RESPONSE_MESSAGE
req: like request req: like request
not_found: WSF_NOT_FOUND_RESPONSE
not_allowed: WSF_METHOD_NOT_ALLOWED_RESPONSE
trace: WSF_TRACE_RESPONSE
do do
req := request req := request
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then
create trace.make (req) msg := trace_message (req)
msg := trace elseif attached method_not_allowed_message (req) as not_allowed then
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 := not_allowed msg := not_allowed
else else
create not_found.make (req) msg := not_found_message (req)
msg := not_found
end end
res.send (msg) res.send (msg)
end 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 end

View File

@@ -23,6 +23,7 @@ feature {NONE} -- Initialization
request := req request := req
create header.make create header.make
create suggested_methods create suggested_methods
create suggested_items.make (0)
end end
feature -- Header feature -- Header
@@ -33,10 +34,18 @@ feature -- Header
request: WSF_REQUEST request: WSF_REQUEST
-- Associated request. -- Associated request.
suggested_methods: WSF_ROUTER_METHODS suggested_methods: WSF_REQUEST_METHODS
-- Optional suggestions -- Optional suggestions
-- First is the default. -- 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 feature -- Element change
set_suggested_methods (m: like suggested_methods) set_suggested_methods (m: like suggested_methods)
@@ -45,11 +54,31 @@ feature -- Element change
suggested_methods := m suggested_methods := m
end 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 feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE) send_to (res: WSF_RESPONSE)
local local
s: STRING s: STRING
l_text: detachable READABLE_STRING_GENERAL
l_loc: detachable READABLE_STRING_8
h: like header h: like header
do do
h := header h := header
@@ -62,7 +91,7 @@ feature {WSF_RESPONSE} -- Output
s := "Not allowed" s := "Not allowed"
if request.is_content_type_accepted ({HTTP_MIME_TYPES}.text_html) then 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 ("<title>")
s.append (html_encoder.encoded_string (request.request_uri)) s.append (html_encoder.encoded_string (request.request_uri))
s.append ("Error 405 (Method Not Allowed)!!") s.append ("Error 405 (Method Not Allowed)!!")
@@ -103,6 +132,48 @@ feature {WSF_RESPONSE} -- Output
end end
s.append ("%N") s.append ("%N")
end 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 ("<div id=%"footer%"></div>")
s.append ("</body>%N") s.append ("</body>%N")
s.append ("</html>%N") s.append ("</html>%N")
@@ -122,6 +193,43 @@ feature {WSF_RESPONSE} -- Output
end end
s.append ("%N") s.append ("%N")
end 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 h.put_content_type_text_plain
end end

View File

@@ -22,7 +22,7 @@ feature {NONE} -- Initialization
do do
request := req request := req
create header.make create header.make
create suggested_locations.make (0) create suggested_items.make (0)
end end
feature -- Header feature -- Header
@@ -33,16 +33,32 @@ feature -- Header
request: WSF_REQUEST request: WSF_REQUEST
-- Associated 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 -- Optional suggestions
-- First is the default. -- First is the default.
body: detachable READABLE_STRING_8
-- Optional body
-- Displayed as extra content
feature -- Element change feature -- Element change
add_suggested_location (a_loc: READABLE_STRING_8; a_title: detachable READABLE_STRING_GENERAL) 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_locations' -- Add `a_loc' to `suggested_items'
do 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 end
feature {WSF_RESPONSE} -- Output feature {WSF_RESPONSE} -- Output
@@ -50,7 +66,8 @@ feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE) send_to (res: WSF_RESPONSE)
local local
s: STRING s: STRING
l_title: detachable READABLE_STRING_GENERAL l_text: detachable READABLE_STRING_GENERAL
l_loc: detachable READABLE_STRING_8
h: like header h: like header
do do
h := header h := header
@@ -85,25 +102,46 @@ feature {WSF_RESPONSE} -- Output
s.append ("</div>") s.append ("</div>")
s.append ("Error 404 (Not Found)</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>") 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>") s.append ("<div id=%"suggestions%"><strong>Perhaps your are looking for:</strong><ul>")
from from
lst.start lst.start
until until
lst.after lst.after
loop loop
s.append ("<li>") l_text := lst.item.text
l_title := lst.item.title l_loc := lst.item.location
if l_title = Void then if l_loc /= Void then
l_title := lst.item.location 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 end
s.append ("<a href=%"" + lst.item.location + "%">" + html_encoder.encoded_string (l_title.to_string_32) + "</a>")
s.append ("</li>%N")
lst.forth lst.forth
end end
s.append ("</ul></div>%N") s.append ("</ul></div>%N")
end 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 ("<div id=%"footer%"></div>")
s.append ("</body>%N") s.append ("</body>%N")
s.append ("</html>%N") s.append ("</html>%N")
@@ -113,24 +151,43 @@ feature {WSF_RESPONSE} -- Output
s := "Error 404 (Not Found): " s := "Error 404 (Not Found): "
s.append (request.request_uri) s.append (request.request_uri)
s.append_character ('%N') 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") s.append ("%NPerhaps your are looking for:%N")
from from
lst.start lst.start
until until
lst.after lst.after
loop loop
s.append (" - ") l_text := lst.item.text
l_title := lst.item.title l_loc := lst.item.location
if l_title = Void then if l_loc /= Void then
l_title := lst.item.location 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 end
s.append (lst.item.location)
s.append ("%N")
lst.forth lst.forth
end end
end end
if attached body as b then
s.append ("%N")
s.append (b)
s.append ("%N")
end
h.put_content_type_text_plain h.put_content_type_text_plain
end end