Merge branch 'master' of github.com:EiffelWebFramework/EWF
This commit is contained in:
@@ -1,327 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {REST_API_DOCUMENTATION}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_API_DOCUMENTATION [C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
REST_REQUEST_HANDLER [C]
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_router: like router; a_base_doc_url: like base_doc_url)
|
||||
do
|
||||
router := a_router
|
||||
base_doc_url := a_base_doc_url
|
||||
description := "Technical documention for the API"
|
||||
end
|
||||
|
||||
feature {NONE} -- Access: Implementation
|
||||
|
||||
router: REST_REQUEST_ROUTER [REST_REQUEST_HANDLER [C], C]
|
||||
|
||||
base_doc_url: READABLE_STRING_8
|
||||
|
||||
feature -- Access
|
||||
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
end
|
||||
|
||||
resource_value (ctx: C): detachable READABLE_STRING_32
|
||||
do
|
||||
if attached {WSF_STRING} ctx.item ("resource") as s then
|
||||
Result := s.value
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
rep: like new_html_page
|
||||
s: STRING
|
||||
rq: detachable REST_REQUEST_HANDLER [C]
|
||||
rq_resource: detachable READABLE_STRING_GENERAL
|
||||
-- l_dft_format_name: detachable STRING
|
||||
hdl_cursor: like router.new_cursor
|
||||
do
|
||||
rep := new_html_page
|
||||
rep.headers.put_content_type_text_html
|
||||
create s.make_empty
|
||||
|
||||
if
|
||||
attached resource_value (ctx) as l_resource
|
||||
then
|
||||
from
|
||||
hdl_cursor := router.new_cursor
|
||||
until
|
||||
hdl_cursor.after or rq /= Void
|
||||
loop
|
||||
if hdl_cursor.item.resource.same_string_general (l_resource) then
|
||||
rq := hdl_cursor.item.handler
|
||||
rq_resource := l_resource
|
||||
end
|
||||
hdl_cursor.forth
|
||||
end
|
||||
end
|
||||
-- if a_args /= Void and then not a_args.is_empty then
|
||||
-- rq := router.handler_by_path (a_args)
|
||||
-- if rq = Void then
|
||||
-- rq := handler_manager.smart_handler_by_path (a_args)
|
||||
---- if attached {REST_REQUEST_GROUP_HANDLER} rq as grp then
|
||||
---- rq := grp.handlers.handler_by_path (a_args)
|
||||
---- end
|
||||
-- end
|
||||
-- if
|
||||
-- rq /= Void and then
|
||||
-- attached rq.path_information (a_args) as l_info
|
||||
-- then
|
||||
-- l_dft_format_name := l_info.format
|
||||
-- end
|
||||
-- end
|
||||
|
||||
|
||||
if rq /= Void and then rq_resource /= Void then
|
||||
rep.set_big_title ("API: Technical documentation for ["+ rq_resource.as_string_8 +"]")
|
||||
|
||||
s.append_string ("<div class=%"api%">")
|
||||
s.append_string ("<h2 class=%"api-name%" >")
|
||||
|
||||
s.append_string ("<a href=%"" + base_doc_url + "%">.. Show all features ..</a>")
|
||||
s.append_string ("</h2></div>%N")
|
||||
|
||||
process_request_handler_doc (rq, rq_resource.as_string_8, s, ctx, req, res, Void)
|
||||
else
|
||||
rep.set_big_title ("API: Technical documentation")
|
||||
|
||||
from
|
||||
hdl_cursor := router.new_cursor
|
||||
until
|
||||
hdl_cursor.after
|
||||
loop
|
||||
if attached hdl_cursor.item as l_item then
|
||||
rq := l_item.handler
|
||||
rep.add_shortcut (l_item.resource)
|
||||
s.append ("<a name=%"" + rep.last_added_shortcut + "%"/>")
|
||||
process_request_handler_doc (rq, l_item.resource, s, ctx, req, res, Void)
|
||||
hdl_cursor.forth
|
||||
end
|
||||
end
|
||||
end
|
||||
rep.set_body (s)
|
||||
rep.send (res)
|
||||
rep.recycle
|
||||
end
|
||||
|
||||
process_request_handler_doc (rq: REST_REQUEST_HANDLER [C]; a_resource: STRING; buf: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; a_dft_format: detachable STRING)
|
||||
local
|
||||
l_dft_format_name: detachable STRING
|
||||
s: STRING
|
||||
l_uri_tpl: URI_TEMPLATE
|
||||
do
|
||||
s := buf
|
||||
|
||||
if a_dft_format /= Void then
|
||||
if rq.supported_format_names.has (a_dft_format) then
|
||||
l_dft_format_name := a_dft_format
|
||||
end
|
||||
end
|
||||
|
||||
s.append_string ("<div class=%"api%">")
|
||||
s.append_string ("<h2 class=%"api-name%" ><a href=%""+ url (req, base_doc_url, a_resource, False) +"%">"+ a_resource +"</a></h2>")
|
||||
s.append_string ("<div class=%"inner%">")
|
||||
-- if rq.hidden (req) then
|
||||
-- s.append_string ("<div class=%"api-description%">This feature is hidden</div>%N")
|
||||
-- else
|
||||
if attached rq.description as desc then
|
||||
s.append_string ("<div class=%"api-description%">" + desc + "</div>")
|
||||
end
|
||||
-- if attached {REST_REQUEST_GROUP_HANDLER} rq as grp then
|
||||
-- s.append_string ("<div class=%"api-format%">Handler: <strong>")
|
||||
-- if attached grp.handlers.new_cursor as l_handlers_cursor then
|
||||
-- from
|
||||
|
||||
-- until
|
||||
-- l_handlers_cursor.after
|
||||
-- loop
|
||||
-- s.append_string (" ")
|
||||
-- s.append_string ("<a class=%"api-handler%" href=%"")
|
||||
-- s.append_string (url (ctx, l_handlers_cursor.item.path, False))
|
||||
-- s.append_string ("%">"+ l_handlers_cursor.item.path +"</a>")
|
||||
-- l_handlers_cursor.forth
|
||||
-- end
|
||||
-- end
|
||||
-- s.append_string ("</strong></div>")
|
||||
-- end
|
||||
if attached rq.supported_format_names as l_formats and then not l_formats.is_empty then
|
||||
s.append_string ("<div class=%"api-format%">Supported formats: <strong>")
|
||||
if attached l_formats.new_cursor as l_formats_cursor then
|
||||
from
|
||||
|
||||
until
|
||||
l_formats_cursor.after
|
||||
loop
|
||||
s.append_string (" ")
|
||||
s.append_string ("<a class=%"api-name api-format")
|
||||
if l_formats_cursor.item ~ l_dft_format_name then
|
||||
s.append_string (" selected")
|
||||
end
|
||||
s.append_string ("%" href=%"" + url (req, base_doc_url, a_resource, False) + "." + l_formats_cursor.item + "%">"+ l_formats_cursor.item +"</a>")
|
||||
l_formats_cursor.forth
|
||||
end
|
||||
end
|
||||
s.append_string ("</strong></div>")
|
||||
end
|
||||
if attached rq.supported_request_method_names as l_methods and then not l_methods.is_empty then
|
||||
s.append_string ("<div class=%"api-method%">Supported request methods: <strong>")
|
||||
if attached l_methods.new_cursor as l_methods_cursor then
|
||||
from
|
||||
|
||||
until
|
||||
l_methods_cursor.after
|
||||
loop
|
||||
s.append_string (" ")
|
||||
s.append_string (l_methods_cursor.item)
|
||||
l_methods_cursor.forth
|
||||
end
|
||||
end
|
||||
s.append_string ("</strong></div>")
|
||||
end
|
||||
s.append_string ("<div class=%"api-auth%">Authentication required: <strong>" + rq.authentication_required (req).out + "</strong></div>")
|
||||
if attached {REST_REQUEST_URI_TEMPLATE_ROUTER_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT], REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]} router as l_uri_template_router then
|
||||
create l_uri_tpl.make (a_resource)
|
||||
if attached l_uri_tpl.query_variable_names as l_query_variable_names and then not l_query_variable_names.is_empty then
|
||||
s.append_string ("<div class=%"api-uri-template%">Query parameters: ")
|
||||
-- s.append_string (rq.path)
|
||||
from
|
||||
l_query_variable_names.start
|
||||
until
|
||||
l_query_variable_names.after
|
||||
loop
|
||||
if l_query_variable_names.isfirst then
|
||||
s.append_string ("?")
|
||||
else
|
||||
s.append_string ("&")
|
||||
end
|
||||
if attached l_query_variable_names.item as l_query_param then
|
||||
s.append_string ("<strong>" + l_query_param + "</strong>")
|
||||
s.append_string ("=<em>" + l_query_param + "</em>")
|
||||
end
|
||||
l_query_variable_names.forth
|
||||
end
|
||||
s.append_string ("</div>%N")
|
||||
end
|
||||
if attached l_uri_tpl.path_variable_names as l_path_variable_names and then not l_path_variable_names.is_empty then
|
||||
s.append_string ("<div class=%"api-uri-template%">Path Segment parameters: ")
|
||||
-- s.append_string (rq.path)
|
||||
from
|
||||
l_path_variable_names.start
|
||||
until
|
||||
l_path_variable_names.after
|
||||
loop
|
||||
if attached l_path_variable_names.item as l_seg_param then
|
||||
s.append_string ("<em>{" + l_seg_param + "}</em>")
|
||||
end
|
||||
l_path_variable_names.forth
|
||||
end
|
||||
s.append_string ("</div>%N")
|
||||
end
|
||||
|
||||
end
|
||||
-- if attached rq._parameters as l_uri_params and then not l_uri_params.is_empty then
|
||||
-- s.append_string ("<div class=%"api-uri-template%">URI Template: ")
|
||||
-- s.append_string (rq.path)
|
||||
-- if attached l_uri_params.new_cursor as l_uri_params_cursor then
|
||||
-- from
|
||||
|
||||
-- until
|
||||
-- l_uri_params_cursor.after
|
||||
-- loop
|
||||
-- if attached l_uri_params_cursor.item as l_uri_param then
|
||||
-- s.append_string ("/<strong>" + l_uri_param.name + "</strong>")
|
||||
-- s.append_string ("/<em>{" + l_uri_param.name + "}</em>")
|
||||
-- end
|
||||
-- l_uri_params_cursor.forth
|
||||
-- end
|
||||
-- end
|
||||
-- s.append_string ("</div>%N")
|
||||
-- end
|
||||
-- if attached rq.parameters as l_params and then not l_params.is_empty then
|
||||
-- s.append_string ("<div class=%"api-params%">Parameters: ")
|
||||
|
||||
-- --| show form only if we have a default format
|
||||
-- if l_dft_format_name = Void then
|
||||
-- s.append_string ("<span class=%"note%">to test the parameter(s), please first select a supported format.</span>%N")
|
||||
-- else
|
||||
-- if rq.method_post_supported then
|
||||
-- s.append_string ("<form id=%""+ rq.path +"%" method=%"POST%" action=%"" + ctx.script_url (rq.path) + "." + l_dft_format_name + "%">%N")
|
||||
-- else
|
||||
-- s.append_string ("<form id=%""+ rq.path +"%" method=%"GET%" action=%"" + ctx.script_url (rq.path) + "." + l_dft_format_name + "%">%N")
|
||||
-- end
|
||||
-- end
|
||||
-- s.append_string ("<ul>")
|
||||
-- if attached l_params.new_cursor as l_params_cursor then
|
||||
-- from
|
||||
|
||||
-- until
|
||||
-- l_params_cursor.after
|
||||
-- loop
|
||||
-- if attached l_params_cursor.item as l_param then
|
||||
-- s.append_string ("<li><strong>" + l_param.name + "</strong>")
|
||||
-- if l_param.optional then
|
||||
-- s.append_string (" <em>(Optional)</em>")
|
||||
-- end
|
||||
-- if attached l_param.description as l_param_desc then
|
||||
-- s.append_string (": <em>" + l_param_desc + "</em>")
|
||||
-- end
|
||||
-- if l_dft_format_name /= Void then
|
||||
-- s.append (" <input name=%"" + l_param.name + "%" type=%"text%" />")
|
||||
-- end
|
||||
-- s.append_string ("</li>")
|
||||
-- end
|
||||
-- l_params_cursor.forth
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if l_dft_format_name /= Void then
|
||||
-- s.append_string ("<input type=%"submit%" value=%"Test "+ rq.path + "." + l_dft_format_name + "%"/>")
|
||||
-- s.append_string ("</form>")
|
||||
-- end
|
||||
-- s.append_string ("</ul></div>")
|
||||
-- else
|
||||
-- if l_dft_format_name /= Void then
|
||||
-- s.append_string ("<a class=%"api-name%" href=%"" + ctx.script_url (a_resource + "." + l_dft_format_name) + "%">Test "+ a_resource + "." + l_dft_format_name + "</a>")
|
||||
-- else
|
||||
-- s.append_string ("<a class=%"api-name%" href=%"" + ctx.script_url (a_resource) + "%">Test "+ a_resource +"</a>")
|
||||
-- end
|
||||
-- end
|
||||
s.append_string ("</div>%N")
|
||||
-- end
|
||||
s.append_string ("</div>%N") -- inner
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_html_page: REST_API_DOCUMENTATION_HTML_PAGE
|
||||
do
|
||||
create Result.make ("API Documentation")
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2012, 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
|
||||
@@ -1,46 +1,14 @@
|
||||
note
|
||||
description: "Summary description for REST_REQUEST_AGENT_HANDLER."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_AGENT_HANDLER [C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
REST_REQUEST_AGENT_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_AGENT_HANDLER [C]
|
||||
rename
|
||||
execute as execute_application
|
||||
end
|
||||
|
||||
REST_REQUEST_HANDLER [C]
|
||||
select
|
||||
execute
|
||||
end
|
||||
WSF_URI_TEMPLATE_AGENT_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- status
|
||||
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := internal_authentication_required
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_authentication_required (b: like authentication_required)
|
||||
do
|
||||
internal_authentication_required := b
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_authentication_required: BOOLEAN
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -5,10 +5,10 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_REQUEST_HANDLER [C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
REST_REQUEST_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_URI_TEMPLATE_CONTEXT_HANDLER [WSF_HANDLER_CONTEXT]
|
||||
|
||||
WSF_HANDLER_HELPER
|
||||
|
||||
@@ -34,7 +34,7 @@ feature -- Element change
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
if request_method_name_supported (req.request_method) then
|
||||
@@ -52,26 +52,26 @@ feature -- Execution
|
||||
execute_rescue (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_application (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
deferred
|
||||
end
|
||||
|
||||
pre_execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
pre_execute (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
end
|
||||
|
||||
post_execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
post_execute (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
end
|
||||
|
||||
execute_rescue (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_rescue (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
post_execute (ctx, req, res)
|
||||
rescue
|
||||
--| Just in case, the rescue is raising other exceptions ...
|
||||
end
|
||||
|
||||
execute_unauthorized (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_unauthorized (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
res.put_header ({HTTP_STATUS_CODE}.unauthorized, Void)
|
||||
res.put_string ("Unauthorized")
|
||||
@@ -79,7 +79,7 @@ feature -- Execution
|
||||
|
||||
feature -- Auth
|
||||
|
||||
authenticated (ctx: C): BOOLEAN
|
||||
authenticated (ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT): BOOLEAN
|
||||
-- Is authenticated?
|
||||
do
|
||||
--| To redefine if needed
|
||||
|
||||
@@ -10,6 +10,8 @@ deferred class
|
||||
inherit
|
||||
WSF_HANDLER_CONTEXT
|
||||
|
||||
WSF_REQUEST_UTILITY
|
||||
|
||||
feature -- Accept: Content-Type
|
||||
|
||||
accepted_content_type: detachable READABLE_STRING_8
|
||||
@@ -23,7 +25,7 @@ feature -- Accept: Content-Type
|
||||
get_accepted_content_type (a_supported_content_types: detachable ARRAY [STRING_8])
|
||||
do
|
||||
if internal_accepted_content_type = Void then
|
||||
internal_accepted_content_type := request_accepted_content_type (a_supported_content_types)
|
||||
internal_accepted_content_type := request_accepted_content_type (request, a_supported_content_types)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -73,10 +75,10 @@ feature -- Format
|
||||
request_accepted_format (a_format_variable_name: detachable READABLE_STRING_8; a_supported_content_types: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8
|
||||
-- Format id for the request based on {HTTP_FORMAT_CONSTANTS}
|
||||
do
|
||||
if a_format_variable_name /= Void and then attached string_item (a_format_variable_name) as ctx_format then
|
||||
Result := ctx_format.as_string_8
|
||||
if a_format_variable_name /= Void and then attached {WSF_STRING} request.item (a_format_variable_name) as ctx_format then
|
||||
Result := ctx_format.value
|
||||
else
|
||||
Result := request_format_from_content_type (request_accepted_content_type (a_supported_content_types))
|
||||
Result := request_format_from_content_type (request_accepted_content_type (request, a_supported_content_types))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {REST_REQUEST_ROUTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_REQUEST_ROUTER [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
WSF_ROUTER [H, C]
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -8,10 +8,10 @@ deferred class
|
||||
REST_SERVICE
|
||||
|
||||
inherit
|
||||
REST_SERVICE_I [REST_REQUEST_HANDLER [REST_REQUEST_HANDLER_CONTEXT], REST_REQUEST_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -5,21 +5,13 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_SERVICE_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
REST_SERVICE_I
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE_I [H, C]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
feature -- Setup
|
||||
|
||||
router: REST_REQUEST_ROUTER [H, C]
|
||||
-- Request router
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_REQUEST_URI_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_REQUEST_URI_HANDLER
|
||||
|
||||
inherit
|
||||
REST_REQUEST_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -1,28 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_HANDLER_CONTEXT}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
WSF_URI_HANDLER_CONTEXT
|
||||
|
||||
REST_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -1,40 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_REQUEST_URI_ROUTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_ROUTER
|
||||
|
||||
inherit
|
||||
REST_REQUEST_URI_ROUTER_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT], REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
map_agent_with_request_methods
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REST_REQUEST_URI_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
h: REST_REQUEST_AGENT_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
do
|
||||
create h.make (a_action)
|
||||
map_with_request_methods (a_id, h, rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2012, 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
|
||||
@@ -1,36 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {REST_REQUEST_URI_ROUTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_ROUTER_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_URI_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_URI_ROUTER_I [H, C]
|
||||
|
||||
REST_REQUEST_ROUTER [H, C]
|
||||
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
-- map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: like {REST_REQUEST_AGENT_HANDLER}.action; rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
-- do
|
||||
-- Precursor (a_id, a_action, rqst_methods)
|
||||
-- end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -1,33 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_REQUEST_URI_ROUTING_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_ROUTING_HANDLER
|
||||
|
||||
inherit
|
||||
REST_REQUEST_URI_ROUTING_HANDLER_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT], REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: REST_REQUEST_URI_ROUTER
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -1,64 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {WSF_ROUTING_HANDLER }."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_ROUTING_HANDLER_I [H -> REST_REQUEST_HANDLER [C],
|
||||
C -> REST_REQUEST_URI_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_URI_ROUTING_HANDLER_I [H, C]
|
||||
redefine
|
||||
router,
|
||||
execute
|
||||
end
|
||||
|
||||
REST_REQUEST_HANDLER [C]
|
||||
undefine
|
||||
execute
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Status report
|
||||
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := internal_authentication_required
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_authentication_required: BOOLEAN
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
Precursor {WSF_URI_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
check should_not_occur: False end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: REST_REQUEST_URI_ROUTER_I [H, C]
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -1,30 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_URI_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REST_URI_SERVICE
|
||||
|
||||
inherit
|
||||
REST_SERVICE_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_HANDLER_CONTEXT], REST_REQUEST_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
feature -- Router
|
||||
|
||||
router: REST_REQUEST_URI_ROUTER
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, 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
|
||||
@@ -8,11 +8,11 @@ deferred class
|
||||
REST_REQUEST_URI_TEMPLATE_HANDLER
|
||||
|
||||
inherit
|
||||
REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
REST_REQUEST_HANDLER
|
||||
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -8,7 +8,7 @@ class
|
||||
REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
WSF_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
WSF_HANDLER_CONTEXT
|
||||
|
||||
REST_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_REQUEST_URI_TEMPLATE_ROUTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTER
|
||||
|
||||
inherit
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTER_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT], REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
map_agent_with_request_methods
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
h: REST_REQUEST_AGENT_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
do
|
||||
create h.make (a_action)
|
||||
map_with_request_methods (a_id, h, rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2012, 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
|
||||
@@ -1,29 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {REST_REQUEST_URI_TEMPLATE_ROUTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTER_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_URI_TEMPLATE_ROUTER_I [H, C]
|
||||
|
||||
REST_REQUEST_ROUTER [H, C]
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2012, 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
|
||||
@@ -1,34 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_REST_REQUEST_URI_TEMPLATE_ROUTING_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTING_HANDLER
|
||||
|
||||
inherit
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT], REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: REST_REQUEST_URI_TEMPLATE_ROUTER
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2012, 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
|
||||
@@ -1,66 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {WSF_ROUTING_HANDLER }."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I [H -> REST_REQUEST_HANDLER [C],
|
||||
C -> REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER_I [H, C]
|
||||
redefine
|
||||
router,
|
||||
execute
|
||||
end
|
||||
|
||||
REST_REQUEST_HANDLER [C]
|
||||
undefine
|
||||
execute
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Status report
|
||||
|
||||
authentication_required (req: WSF_REQUEST): BOOLEAN
|
||||
do
|
||||
Result := internal_authentication_required
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_authentication_required: BOOLEAN
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
pre_execute (ctx, req, res)
|
||||
Precursor {WSF_URI_TEMPLATE_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
post_execute (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
check should_not_occur: False end
|
||||
end
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: REST_REQUEST_URI_TEMPLATE_ROUTER_I [H, C]
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2012, 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
|
||||
@@ -8,17 +8,10 @@ deferred class
|
||||
REST_URI_TEMPLATE_SERVICE
|
||||
|
||||
inherit
|
||||
REST_SERVICE_I [REST_REQUEST_HANDLER [REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT], REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
feature -- Router
|
||||
|
||||
router: REST_REQUEST_URI_TEMPLATE_ROUTER
|
||||
REST_SERVICE_I
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -5,16 +5,27 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
AUTHENTICATION_FILTER [C -> WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
AUTHENTICATION_FILTER
|
||||
|
||||
inherit
|
||||
WSF_FILTER_HANDLER [C]
|
||||
WSF_FILTER_HANDLER [WSF_URI_TEMPLATE_HANDLER]
|
||||
|
||||
SHARED_DATABASE_API
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
-- redefine
|
||||
-- do_get
|
||||
-- end
|
||||
|
||||
SHARED_DATABASE_API
|
||||
|
||||
SHARED_EJSON
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter
|
||||
local
|
||||
l_auth: HTTP_AUTHORIZATION
|
||||
@@ -24,15 +35,24 @@ feature -- Basic operations
|
||||
attached Db_access.users.item (1) as l_user and then
|
||||
(attached l_auth.login as l_auth_login and then l_auth_login.is_equal (l_user.name)
|
||||
and attached l_auth.password as l_auth_password and then l_auth_password.is_equal (l_user.password)) then
|
||||
execute_next (ctx, req, res)
|
||||
execute_next (req, res)
|
||||
else
|
||||
handle_unauthorized ("Unauthorized", ctx, req, res)
|
||||
handle_unauthorized ("Unauthorized", req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Filter
|
||||
|
||||
execute_next (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
if attached next as n then
|
||||
n.execute (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
handle_unauthorized (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
handle_unauthorized (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Handle forbidden.
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
|
||||
@@ -10,7 +10,7 @@ class
|
||||
inherit
|
||||
ANY
|
||||
|
||||
WSF_URI_TEMPLATE_FILTERED_SERVICE
|
||||
WSF_FILTERED_SERVICE
|
||||
|
||||
WSF_HANDLER_HELPER
|
||||
|
||||
@@ -34,18 +34,20 @@ feature {NONE} -- Initialization
|
||||
create_filter
|
||||
-- Create `filter'
|
||||
local
|
||||
l_router: WSF_URI_TEMPLATE_ROUTER
|
||||
l_authentication_filter: AUTHENTICATION_FILTER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
l_user_filter: USER_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
l_user_handler: WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
l_routing_filter: WSF_ROUTING_FILTER [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
l_router: WSF_ROUTER
|
||||
l_authentication_filter_hdl: AUTHENTICATION_FILTER
|
||||
l_user_filter: USER_HANDLER
|
||||
l_user_handler: WSF_URI_TEMPLATE_HANDLER
|
||||
l_routing_filter: WSF_ROUTING_FILTER
|
||||
do
|
||||
create l_router.make (1)
|
||||
create l_authentication_filter
|
||||
create l_authentication_filter_hdl
|
||||
create l_user_filter
|
||||
l_authentication_filter.set_next (l_user_filter)
|
||||
l_user_handler := l_authentication_filter
|
||||
l_router.map_with_request_methods ("/user/{userid}", l_user_handler, << "GET" >>)
|
||||
l_authentication_filter_hdl.set_next (l_user_filter)
|
||||
l_user_handler := l_authentication_filter_hdl
|
||||
l_router.handle_with_request_methods ("/user/{userid}", l_user_handler, l_router.methods_get)
|
||||
-- l_router.map_with_request_methods ("/user/{userid}", l_user_handler, << "GET" >>)
|
||||
-- create l_routing_hdl.make_with_router (l_router)
|
||||
create l_routing_filter.make (l_router)
|
||||
l_routing_filter.set_execute_default_action (agent execute_default)
|
||||
filter := l_routing_filter
|
||||
|
||||
@@ -5,12 +5,14 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
USER_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
USER_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_FILTER_HANDLER [C]
|
||||
WSF_FILTER_HANDLER [WSF_URI_TEMPLATE_HANDLER]
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER [C]
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get
|
||||
end
|
||||
@@ -21,13 +23,13 @@ inherit
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (ctx, req, res)
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
do_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Using GET to retrieve resource information.
|
||||
-- If the GET request is SUCCESS, we response with
|
||||
-- 200 OK, and a representation of the user
|
||||
@@ -39,16 +41,16 @@ feature -- Basic operations
|
||||
if attached req.orig_path_info as orig_path then
|
||||
id := get_user_id_from_path (orig_path)
|
||||
if attached retrieve_user (id) as l_user then
|
||||
compute_response_get (ctx, req, res, l_user)
|
||||
compute_response_get (req, res, l_user)
|
||||
else
|
||||
handle_resource_not_found_response ("The following resource " + orig_path + " is not found ", ctx, req, res)
|
||||
handle_resource_not_found_response ("The following resource " + orig_path + " is not found ", req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
compute_response_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; l_user : USER)
|
||||
compute_response_get (req: WSF_REQUEST; res: WSF_RESPONSE; l_user : USER)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
l_msg : STRING
|
||||
|
||||
@@ -5,10 +5,23 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ORDER_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
ORDER_HANDLER
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_RESOURCE_HANDLER_HELPER [C]
|
||||
WSF_URI_HANDLER
|
||||
rename
|
||||
execute as uri_execute,
|
||||
new_mapping as new_uri_mapping
|
||||
end
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
rename
|
||||
execute as uri_template_execute,
|
||||
new_mapping as new_uri_template_mapping
|
||||
select
|
||||
new_uri_template_mapping
|
||||
end
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get,
|
||||
do_post,
|
||||
@@ -22,10 +35,16 @@ inherit
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (ctx, req, res)
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
feature -- API DOC
|
||||
@@ -34,7 +53,7 @@ feature -- API DOC
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Using GET to retrieve resource information.
|
||||
-- If the GET request is SUCCESS, we response with
|
||||
-- 200 OK, and a representation of the order
|
||||
@@ -49,12 +68,12 @@ feature -- HTTP Methods
|
||||
id := get_order_id_from_path (orig_path)
|
||||
if attached retrieve_order (id) as l_order then
|
||||
if is_conditional_get (req, l_order) then
|
||||
handle_resource_not_modified_response ("The resource" + orig_path + "does not change", ctx, req, res)
|
||||
handle_resource_not_modified_response ("The resource" + orig_path + "does not change", req, res)
|
||||
else
|
||||
compute_response_get (ctx, req, res, l_order)
|
||||
compute_response_get (req, res, l_order)
|
||||
end
|
||||
else
|
||||
handle_resource_not_found_response ("The following resource" + orig_path + " is not found ", ctx, req, res)
|
||||
handle_resource_not_found_response ("The following resource" + orig_path + " is not found ", req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -74,7 +93,7 @@ feature -- HTTP Methods
|
||||
end
|
||||
end
|
||||
|
||||
compute_response_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
||||
compute_response_get (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
l_msg : STRING
|
||||
@@ -96,7 +115,7 @@ feature -- HTTP Methods
|
||||
end
|
||||
end
|
||||
|
||||
do_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_put (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Updating a resource with PUT
|
||||
-- A successful PUT request will not create a new resource, instead it will
|
||||
-- change the state of the resource identified by the current uri.
|
||||
@@ -120,16 +139,16 @@ feature -- HTTP Methods
|
||||
if is_valid_to_update(l_order) then
|
||||
if is_conditional_put (req, l_order) then
|
||||
update_order( l_order)
|
||||
compute_response_put (ctx, req, res, l_order)
|
||||
compute_response_put (req, res, l_order)
|
||||
else
|
||||
handle_precondition_fail_response ("", ctx, req, res)
|
||||
handle_precondition_fail_response ("", req, res)
|
||||
end
|
||||
else
|
||||
--| FIXME: Here we need to define the Allow methods
|
||||
handle_resource_conflict_response (l_put +"%N There is conflict while trying to update the order, the order could not be update in the current state", ctx, req, res)
|
||||
handle_resource_conflict_response (l_put +"%N There is conflict while trying to update the order, the order could not be update in the current state", req, res)
|
||||
end
|
||||
else
|
||||
handle_bad_request_response (l_put +"%N is not a valid ORDER, maybe the order does not exist in the system", ctx, req, res)
|
||||
handle_bad_request_response (l_put +"%N is not a valid ORDER, maybe the order does not exist in the system", req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -153,7 +172,7 @@ feature -- HTTP Methods
|
||||
end
|
||||
|
||||
|
||||
compute_response_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
||||
compute_response_put (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
joc : JSON_ORDER_CONVERTER
|
||||
@@ -179,7 +198,7 @@ feature -- HTTP Methods
|
||||
end
|
||||
|
||||
|
||||
do_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Here we use DELETE to cancel an order, if that order is in state where
|
||||
-- it can still be canceled.
|
||||
-- 200 if is ok
|
||||
@@ -194,18 +213,18 @@ feature -- HTTP Methods
|
||||
if db_access.orders.has_key (id) then
|
||||
if is_valid_to_delete (id) then
|
||||
delete_order( id)
|
||||
compute_response_delete (ctx, req, res)
|
||||
compute_response_delete (req, res)
|
||||
else
|
||||
--| FIXME: Here we need to define the Allow methods
|
||||
handle_method_not_allowed_response (orig_path + "%N There is conflict while trying to delete the order, the order could not be deleted in the current state", ctx, req, res)
|
||||
handle_method_not_allowed_response (orig_path + "%N There is conflict while trying to delete the order, the order could not be deleted in the current state", req, res)
|
||||
end
|
||||
else
|
||||
handle_resource_not_found_response (orig_path + " not found in this server", ctx, req, res)
|
||||
handle_resource_not_found_response (orig_path + " not found in this server", req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
compute_response_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
compute_response_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -218,7 +237,7 @@ feature -- HTTP Methods
|
||||
res.put_header_text (h.string)
|
||||
end
|
||||
|
||||
do_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Here the convention is the following.
|
||||
-- POST is used for creation and the server determines the URI
|
||||
-- of the created resource.
|
||||
@@ -233,13 +252,13 @@ feature -- HTTP Methods
|
||||
l_post := retrieve_data (req)
|
||||
if attached extract_order_request (l_post) as l_order then
|
||||
save_order (l_order)
|
||||
compute_response_post (ctx, req, res, l_order)
|
||||
compute_response_post (req, res, l_order)
|
||||
else
|
||||
handle_bad_request_response (l_post +"%N is not a valid ORDER", ctx, req, res)
|
||||
handle_bad_request_response (l_post +"%N is not a valid ORDER", req, res)
|
||||
end
|
||||
end
|
||||
|
||||
compute_response_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
||||
compute_response_post (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
l_msg : STRING
|
||||
@@ -347,7 +366,9 @@ feature {NONE} -- Implementation Repository Layer
|
||||
json.add_converter(joc)
|
||||
create parser.make_parser (l_post)
|
||||
if attached parser.parse as jv and parser.is_parsed then
|
||||
Result ?= json.object (jv, "ORDER")
|
||||
if attached {like extract_order_request} json.object (jv, "ORDER") as res then
|
||||
Result := res
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
description : "REST Buck server"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
@@ -30,11 +29,11 @@ feature {NONE} -- Initialization
|
||||
|
||||
setup_router
|
||||
local
|
||||
order_handler: ORDER_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
order_handler: ORDER_HANDLER
|
||||
do
|
||||
create order_handler
|
||||
router.map_with_request_methods ("/order", order_handler, <<"POST">>)
|
||||
router.map_with_request_methods ("/order/{orderid}", order_handler, <<"GET", "DELETE", "PUT">>)
|
||||
router.handle_with_request_methods ("/order", order_handler, router.methods_POST)
|
||||
router.handle_with_request_methods ("/order/{orderid}", order_handler, router.methods_GET + router.methods_DELETE + router.methods_PUT)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
@@ -13,7 +13,7 @@ class
|
||||
HELLO_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
WSF_DEFAULT_SERVICE
|
||||
redefine
|
||||
@@ -27,12 +27,34 @@ feature {NONE} -- Initialization
|
||||
|
||||
setup_router
|
||||
do
|
||||
router.map_agent ("/hello", agent execute_hello)
|
||||
-- router.map (create {WSF_URI_MAPPING}.make ("/hello", create {WSF_AGENT_URI_HANDLER}.make (agent execute_hello)))
|
||||
map_agent_uri ("/hello", agent execute_hello, Void)
|
||||
|
||||
router.map_with_request_methods ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, router.methods_HEAD_GET_POST)
|
||||
router.map_with_request_methods ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, router.methods_GET_POST)
|
||||
-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}), router.methods_HEAD_GET_POST)
|
||||
map_uri_template ("/users/{user}/message/{mesgid}", create {USER_MESSAGE_HANDLER}, router.methods_HEAD_GET_POST)
|
||||
|
||||
router.map_agent_response_with_request_methods ("/users/{user}/{?op}", agent response_user, router.methods_GET)
|
||||
-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}), router.methods_GET_POST)
|
||||
map_uri_template ("/users/{user}/message/", create {USER_MESSAGE_HANDLER}, router.methods_GET_POST)
|
||||
|
||||
-- router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make ("/users/{user}/{?op}", create {WSF_AGENT_URI_TEMPLATE_RESPONSE_HANDLER}.make (agent response_user)), router.methods_GET)
|
||||
map_agent_uri_template_response ("/users/{user}/{?op}", agent response_user, router.methods_GET)
|
||||
end
|
||||
|
||||
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)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, create {WSF_URI_AGENT_HANDLER}.make (a_action)), rqst_methods)
|
||||
end
|
||||
|
||||
map_uri_template (a_tpl: READABLE_STRING_8; a_handler: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, a_handler), rqst_methods)
|
||||
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)
|
||||
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)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
@@ -43,7 +65,7 @@ feature -- Execution
|
||||
res.redirect_now_with_content (req.script_url ("/hello"), "Redirection to " + req.script_url ("/hello"), "text/html")
|
||||
end
|
||||
|
||||
execute_hello (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Computed response message.
|
||||
local
|
||||
mesg: WSF_HTML_PAGE_RESPONSE
|
||||
@@ -92,7 +114,7 @@ feature -- Execution
|
||||
res.send (mesg)
|
||||
end
|
||||
|
||||
response_user (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
response_user (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
-- Computed response message.
|
||||
local
|
||||
html: WSF_HTML_PAGE_RESPONSE
|
||||
@@ -100,15 +122,16 @@ feature -- Execution
|
||||
s: STRING_8
|
||||
l_username: STRING_32
|
||||
do
|
||||
if attached {WSF_STRING} ctx.path_parameter ("user") as u then
|
||||
if attached {WSF_STRING} req.path_parameter ("user") as u then
|
||||
l_username := (create {HTML_ENCODER}).general_decoded_string (u.value)
|
||||
if
|
||||
attached {WSF_STRING} req.query_parameter ("op") as l_op
|
||||
then
|
||||
if l_op.is_case_insensitive_equal ("quit") then
|
||||
create redir.make (req.script_url ("/hello"), 3)
|
||||
redir.set_title ("Bye " + u.url_encoded_value)
|
||||
redir.set_body ("Bye " + u.url_encoded_value + ",<br/> see you soon.<p>You will be redirected to " +
|
||||
create html.make
|
||||
redir.set_title ("Bye " + html.html_encoded_string (l_username))
|
||||
redir.set_body ("Bye " + html.html_encoded_string (l_username) + ",<br/> see you soon.<p>You will be redirected to " +
|
||||
redir.url_location + " in " + redir.delay.out + " second(s) ...</p>"
|
||||
)
|
||||
Result := redir
|
||||
|
||||
@@ -9,20 +9,20 @@ class
|
||||
USER_MESSAGE_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_RESPONSE_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
WSF_URI_TEMPLATE_RESPONSE_HANDLER
|
||||
|
||||
feature -- Access
|
||||
|
||||
response (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
local
|
||||
l_username: READABLE_STRING_32
|
||||
do
|
||||
if attached {WSF_STRING} ctx.path_parameter ("user") as u then
|
||||
if attached {WSF_STRING} req.path_parameter ("user") as u then
|
||||
l_username := html_decoded_string (u.value)
|
||||
if req.is_request_method ("GET") then
|
||||
Result := user_message_get (l_username, ctx, req)
|
||||
Result := user_message_get (l_username, req)
|
||||
elseif req.is_request_method ("POST") then
|
||||
Result := user_message_response_post (l_username, ctx, req)
|
||||
Result := user_message_response_post (l_username, req)
|
||||
else
|
||||
Result := unsupported_method_response (req)
|
||||
end
|
||||
@@ -46,7 +46,7 @@ feature -- Access
|
||||
end
|
||||
|
||||
|
||||
user_message_get (u: READABLE_STRING_32; ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST): WSF_HTML_PAGE_RESPONSE
|
||||
user_message_get (u: READABLE_STRING_32; req: WSF_REQUEST): WSF_HTML_PAGE_RESPONSE
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
@@ -59,7 +59,7 @@ feature -- Access
|
||||
Result.set_body (s)
|
||||
end
|
||||
|
||||
user_message_response_post (u: READABLE_STRING_32; ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST): WSF_HTML_PAGE_RESPONSE
|
||||
user_message_response_post (u: READABLE_STRING_32; req: WSF_REQUEST): WSF_HTML_PAGE_RESPONSE
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
|
||||
@@ -10,8 +10,12 @@ class
|
||||
inherit
|
||||
ANY
|
||||
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
|
||||
WSF_URI_ROUTED_SERVICE
|
||||
|
||||
WSF_DEFAULT_SERVICE
|
||||
|
||||
create
|
||||
@@ -34,14 +38,14 @@ feature {NONE} -- Initialization
|
||||
setup_router
|
||||
-- Setup router
|
||||
local
|
||||
www: WSF_FILE_SYSTEM_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
www: WSF_FILE_SYSTEM_HANDLER
|
||||
do
|
||||
router.map_agent ("/upload{?nb}", agent execute_upload)
|
||||
map_uri_template_agent ("/upload{?nb}", agent execute_upload)
|
||||
|
||||
create www.make (document_root)
|
||||
www.set_directory_index (<<"index.html">>)
|
||||
www.set_not_found_handler (agent execute_not_found)
|
||||
router.map_with_request_methods ("{/path}{?query}", www, <<"GET">>)
|
||||
router.handle_with_request_methods ("", www, router.methods_GET)
|
||||
end
|
||||
|
||||
feature -- Configuration
|
||||
@@ -59,6 +63,8 @@ feature -- Configuration
|
||||
if Result [Result.count] = Operating_environment.directory_separator then
|
||||
Result := Result.substring (1, Result.count - 1)
|
||||
end
|
||||
ensure
|
||||
not Result.ends_with (Operating_environment.directory_separator.out)
|
||||
end
|
||||
|
||||
files_root: READABLE_STRING_8
|
||||
@@ -79,13 +85,13 @@ feature -- Execution
|
||||
res.redirect_now_with_content (req.script_url ("/"), "Redirection to " + req.script_url ("/"), "text/html")
|
||||
end
|
||||
|
||||
execute_not_found (uri: READABLE_STRING_8; ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_not_found (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- `uri' is not found, redirect to default page
|
||||
do
|
||||
res.redirect_now_with_content (req.script_url ("/"), uri + ": not found.%NRedirection to " + req.script_url ("/"), "text/html")
|
||||
end
|
||||
|
||||
execute_upload (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_upload (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Upload page is requested, either GET or POST
|
||||
-- On GET display the web form to upload file, by passing ?nb=5 you can upload 5 images
|
||||
-- On POST display the uploaded files
|
||||
@@ -104,14 +110,14 @@ feature -- Execution
|
||||
page.set_body (l_body)
|
||||
l_body.append ("<h1>EWF: Upload image file</h1>%N")
|
||||
l_body.append ("<form action=%""+ req.script_url ("/upload") +"%" method=%"POST%" enctype=%"multipart/form-data%">%N")
|
||||
if attached ctx.string_query_parameter ("nb") as p_nb and then p_nb.is_integer then
|
||||
n := p_nb.to_integer
|
||||
if attached {WSF_STRING} req.query_parameter ("nb") as p_nb and then p_nb.is_integer then
|
||||
n := p_nb.integer_value
|
||||
else
|
||||
n := 1
|
||||
end
|
||||
if attached ctx.string_query_parameter ("demo") as p_demo then
|
||||
if attached {WSF_STRING} req.query_parameter ("demo") as p_demo then
|
||||
create fn.make_from_string (document_root)
|
||||
fn.set_file_name (p_demo.string)
|
||||
fn.set_file_name (p_demo.value)
|
||||
l_body.append ("File: <input type=%"file%" name=%"uploaded_file[]%" size=%"60%" value=%""+ html_encode (fn.string) +"%"></br>%N")
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Router
|
||||
|
||||
## Requirements
|
||||
* [URI Template](../../../protocol/rui_template)
|
||||
* [URI Template](../../../protocol/uri_template)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_URI_TEMPLATE_ROUTED_SERVICE}."
|
||||
description: "Summary description for {WSF_AGENT_CONTEXT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
WSF_AGENT_CONTEXT_HANDLER [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE_I [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
WSF_CONTEXT_HANDLER [C]
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
feature -- Change
|
||||
|
||||
create_router
|
||||
-- Create router
|
||||
--| it can be redefine to create with precise count if needed.
|
||||
set_action (a_action: like action)
|
||||
do
|
||||
create router.make (0)
|
||||
action := a_action
|
||||
end
|
||||
|
||||
feature -- Router
|
||||
feature -- Access
|
||||
|
||||
router: WSF_URI_TEMPLATE_ROUTER
|
||||
action: PROCEDURE [ANY, TUPLE [context: C; request: WSF_REQUEST; response: WSF_RESPONSE]]
|
||||
|
||||
;note
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
action.call ([ctx, req, res])
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
36
library/server/wsf/router/context/wsf_context_handler.e
Normal file
36
library/server/wsf/router/context/wsf_context_handler.e
Normal file
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "Summary description for {WSF_CONTEXT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_CONTEXT_HANDLER [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_HANDLER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {WSF_ROUTER} -- Mapping
|
||||
|
||||
new_mapping (a_resource: READABLE_STRING_8): WSF_ROUTER_CONTEXT_MAPPING [C]
|
||||
-- New mapping built with Current as handler
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,38 +1,36 @@
|
||||
note
|
||||
description: "[
|
||||
a WSF_ROUTE object associates a handler and the associated context at runtime
|
||||
Context for the handler execution
|
||||
It provides information related to the matching handler at runtime, i.e:
|
||||
- request: WSF_REQUEST -- Associated request
|
||||
- path: READABLE_STRING_8 -- Associated path
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_ROUTE [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_HANDLER_CONTEXT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (h: H; c: C)
|
||||
-- Instantiate Current with `h' and `c'
|
||||
make (req: like request; map: like mapping)
|
||||
do
|
||||
handler := h
|
||||
context := c
|
||||
request := req
|
||||
mapping := map
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: H
|
||||
-- Handler
|
||||
request: WSF_REQUEST
|
||||
-- Associated request
|
||||
|
||||
context: C
|
||||
-- Context associated to `handler' for execution
|
||||
mapping: WSF_ROUTER_MAPPING
|
||||
-- Associated mapping
|
||||
|
||||
invariant
|
||||
handler /= Void
|
||||
context /= Void
|
||||
|
||||
note
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
@@ -0,0 +1,30 @@
|
||||
note
|
||||
description: "Summary description for {WSF_ROUTER_CONTEXT_MAPPING}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ROUTER_CONTEXT_MAPPING [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTER_MAPPING
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: WSF_CONTEXT_HANDLER [C]
|
||||
-- Handler associated with Current mapping.
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "Summary description for {WSF_STARTS_WITH_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_STARTS_WITH_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {WSF_ROUTER} -- Mapping
|
||||
|
||||
new_mapping (a_uri: READABLE_STRING_8): WSF_STARTS_WITH_MAPPING
|
||||
do
|
||||
create Result.make (a_uri, Current)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,74 @@
|
||||
note
|
||||
description: "Summary description for EWF_STARTS_WITH_PATH."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_STARTS_WITH_MAPPING
|
||||
|
||||
inherit
|
||||
WSF_ROUTER_MAPPING
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_uri: READABLE_STRING_8; h: like handler)
|
||||
do
|
||||
handler := h
|
||||
uri := a_uri
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: WSF_STARTS_WITH_HANDLER
|
||||
|
||||
uri: READABLE_STRING_8
|
||||
|
||||
feature -- Status
|
||||
|
||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||
-- Return the handler if Current matches the request `req'.
|
||||
local
|
||||
p: READABLE_STRING_8
|
||||
s: like based_uri
|
||||
do
|
||||
p := path_from_request (req)
|
||||
s := based_uri (uri, a_router)
|
||||
if p.starts_with (s) then
|
||||
Result := handler
|
||||
a_router.execute_before (Current)
|
||||
handler.execute (s, req, res)
|
||||
a_router.execute_after (Current)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
based_uri (a_uri: like uri; a_router: WSF_ROUTER): like uri
|
||||
-- `uri' prefixed by the `WSF_ROUTER.base_url' if any
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
if attached a_router.base_url as l_base_url then
|
||||
create s.make_from_string (l_base_url)
|
||||
s.append_string (a_uri)
|
||||
Result := s
|
||||
else
|
||||
Result := a_uri
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,33 +1,35 @@
|
||||
note
|
||||
description: "[
|
||||
This class helps to build Routing handler based for WSF_URI_ROUTER
|
||||
]"
|
||||
description: "Summary description for {WSF_URI_AGENT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_ROUTING_HANDLER_I [H -> WSF_HANDLER [C],
|
||||
C -> WSF_URI_HANDLER_CONTEXT create make end]
|
||||
WSF_URI_AGENT_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_ROUTING_HANDLER [H, C]
|
||||
WSF_URI_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (n: INTEGER)
|
||||
make (a_action: like action)
|
||||
do
|
||||
create router.make (n)
|
||||
action := a_action
|
||||
end
|
||||
|
||||
feature {NONE} -- Routing
|
||||
action: PROCEDURE [ANY, TUPLE [request: WSF_REQUEST; response: WSF_RESPONSE]]
|
||||
|
||||
router: WSF_URI_ROUTER_I [H, C]
|
||||
feature -- Execution
|
||||
|
||||
;note
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
action.call ([req, res])
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
@@ -1,25 +1,18 @@
|
||||
note
|
||||
description: "[
|
||||
Request handler object which is called by a WSF_ROUTER
|
||||
A response handler should implement the method
|
||||
|
||||
response (ctx: C; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
|
||||
|
||||
The class is generic, this way one can use a custom WSF_HANDLER_CONTEXT if needed
|
||||
]"
|
||||
description: "Summary description for {WSF_URI_RESPONSE_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_RESPONSE_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_URI_RESPONSE_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_URI_HANDLER
|
||||
|
||||
feature -- Response
|
||||
|
||||
response (ctx: C; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
require
|
||||
is_valid_context: is_valid_context (req)
|
||||
deferred
|
||||
@@ -29,10 +22,10 @@ feature -- Response
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
res.send (response (ctx, req))
|
||||
res.send (response (req))
|
||||
end
|
||||
|
||||
note
|
||||
@@ -0,0 +1,47 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_ROUTED_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_ROUTED_SERVICE
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
feature -- Mapping helper: uri
|
||||
|
||||
map_uri (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER)
|
||||
do
|
||||
map_uri_with_request_methods (a_uri, h, Void)
|
||||
end
|
||||
|
||||
map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_MAPPING}.make (a_uri, h), rqst_methods)
|
||||
end
|
||||
|
||||
feature -- Mapping helper: uri agent
|
||||
|
||||
map_uri_agent (a_uri: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]])
|
||||
do
|
||||
map_uri_agent_with_request_methods (a_uri, proc, Void)
|
||||
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)
|
||||
do
|
||||
map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_HANDLER}.make (proc), rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
36
library/server/wsf/router/support/uri/wsf_uri_handler.e
Normal file
36
library/server/wsf/router/support/uri/wsf_uri_handler.e
Normal file
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "Summary description for {EWF_ROUTER_URI_PATH_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {WSF_ROUTER} -- Mapping
|
||||
|
||||
new_mapping (a_uri: READABLE_STRING_8): WSF_URI_MAPPING
|
||||
do
|
||||
create Result.make (a_uri, Current)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
80
library/server/wsf/router/support/uri/wsf_uri_mapping.e
Normal file
80
library/server/wsf/router/support/uri/wsf_uri_mapping.e
Normal file
@@ -0,0 +1,80 @@
|
||||
note
|
||||
description: "Summary description for EWF_URI_PATH."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_MAPPING
|
||||
|
||||
inherit
|
||||
WSF_ROUTER_MAPPING
|
||||
|
||||
create
|
||||
make,
|
||||
make_trailing_slash_ignored
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_uri: READABLE_STRING_8; h: like handler)
|
||||
do
|
||||
handler := h
|
||||
uri := a_uri
|
||||
end
|
||||
|
||||
make_trailing_slash_ignored (a_uri: READABLE_STRING_8; h: like handler)
|
||||
do
|
||||
make (a_uri, h)
|
||||
trailing_slash_ignored := True
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: WSF_URI_HANDLER
|
||||
|
||||
uri: READABLE_STRING_8
|
||||
|
||||
trailing_slash_ignored: BOOLEAN
|
||||
|
||||
feature -- Status
|
||||
|
||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||
local
|
||||
p: READABLE_STRING_8
|
||||
l_uri: like uri
|
||||
do
|
||||
p := path_from_request (req)
|
||||
l_uri := based_uri (uri, a_router)
|
||||
if l_uri.ends_with ("/") then
|
||||
if not p.ends_with ("/") then
|
||||
p := p + "/"
|
||||
end
|
||||
else
|
||||
if p.ends_with ("/") then
|
||||
p := p.substring (1, p.count - 1)
|
||||
end
|
||||
end
|
||||
if p.same_string (l_uri) then
|
||||
Result := handler
|
||||
a_router.execute_before (Current)
|
||||
handler.execute (req, res)
|
||||
a_router.execute_after (Current)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
based_uri (a_uri: like uri; a_router: WSF_ROUTER): like uri
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
if attached a_router.base_url as l_base_url then
|
||||
create s.make_from_string (l_base_url)
|
||||
s.append_string (a_uri)
|
||||
Result := s
|
||||
else
|
||||
Result := a_uri
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,31 +1,35 @@
|
||||
note
|
||||
description: "Summary description for WSF_URI_ROUTED_SERVICE."
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_AGENT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_ROUTED_SERVICE
|
||||
class
|
||||
WSF_URI_TEMPLATE_AGENT_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE_I [WSF_HANDLER [WSF_URI_HANDLER_CONTEXT], WSF_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
create_router
|
||||
-- Create router
|
||||
--| it can be redefine to create with precise count if needed.
|
||||
make (a_action: like action)
|
||||
do
|
||||
create router.make (0)
|
||||
action := a_action
|
||||
end
|
||||
feature -- Router
|
||||
|
||||
router: WSF_URI_ROUTER
|
||||
action: PROCEDURE [ANY, TUPLE [request: WSF_REQUEST; response: WSF_RESPONSE]]
|
||||
|
||||
;note
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
action.call ([req, res])
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
@@ -1,13 +1,14 @@
|
||||
note
|
||||
description: "Summary description for WSF_AGENT_HANDLER."
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_AGENT_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_URI_TEMPLATE_RESPONSE_AGENT_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_URI_TEMPLATE_RESPONSE_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
@@ -21,13 +22,13 @@ feature -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]
|
||||
action: FUNCTION [ANY, TUPLE [req: WSF_REQUEST], WSF_RESPONSE_MESSAGE]
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
do
|
||||
action.call ([ctx, req, res])
|
||||
Result := action.item ([req])
|
||||
end
|
||||
|
||||
note
|
||||
@@ -1,33 +1,31 @@
|
||||
note
|
||||
description: "Summary description for WSF_AGENT_RESPONSE_HANDLER."
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_RESPONSE_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_AGENT_RESPONSE_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_RESPONSE_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_RESPONSE_HANDLER [C]
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
feature -- Response
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (act: like action)
|
||||
do
|
||||
action := act
|
||||
response (req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
require
|
||||
is_valid_context: is_valid_context (req)
|
||||
deferred
|
||||
ensure
|
||||
Result_attached: Result /= Void
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
action: FUNCTION [ANY, TUPLE [ctx: C; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE]
|
||||
|
||||
feature -- Execution
|
||||
|
||||
response (ctx: C; req: WSF_REQUEST): WSF_RESPONSE_MESSAGE
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
Result := action.item ([ctx, req])
|
||||
res.send (response (req))
|
||||
end
|
||||
|
||||
note
|
||||
@@ -0,0 +1,47 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_ROUTED_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
feature -- Mapping helper: uri
|
||||
|
||||
map_uri_template (a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER)
|
||||
do
|
||||
map_uri_template_with_request_methods (a_tpl, h, Void)
|
||||
end
|
||||
|
||||
map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods)
|
||||
end
|
||||
|
||||
feature -- Mapping helper: uri agent
|
||||
|
||||
map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]])
|
||||
do
|
||||
map_uri_template_agent_with_request_methods (a_tpl, proc, Void)
|
||||
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)
|
||||
do
|
||||
map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,14 +1,20 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_ROUTED_SERVICE}."
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_ROUTING_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ROUTED_SERVICE
|
||||
class
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE_I [WSF_HANDLER [WSF_HANDLER_CONTEXT], WSF_HANDLER_CONTEXT]
|
||||
WSF_ROUTING_HANDLER
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_router
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "Summary description for EWF_URI_TEMPLATE_HANDLER."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {WSF_ROUTER} -- Mapping
|
||||
|
||||
new_mapping (a_tpl: READABLE_STRING_8): WSF_URI_TEMPLATE_MAPPING
|
||||
do
|
||||
create Result.make (a_tpl, Current)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,95 @@
|
||||
note
|
||||
description: "Summary description for {EWF_ROUTER_URI_TEMPLATE_PATH}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_MAPPING
|
||||
|
||||
inherit
|
||||
WSF_ROUTER_MAPPING
|
||||
|
||||
create
|
||||
make,
|
||||
make_from_template
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (s: READABLE_STRING_8; h: like handler)
|
||||
do
|
||||
make_from_template (create {URI_TEMPLATE}.make (s), h)
|
||||
end
|
||||
|
||||
make_from_template (tpl: URI_TEMPLATE; h: like handler)
|
||||
do
|
||||
template := tpl
|
||||
handler := h
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
template: URI_TEMPLATE
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_handler (h: like handler)
|
||||
do
|
||||
handler := h
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||
local
|
||||
tpl: URI_TEMPLATE
|
||||
p: READABLE_STRING_32
|
||||
new_src: detachable WSF_REQUEST_PATH_PARAMETERS_PROVIDER
|
||||
do
|
||||
p := path_from_request (req)
|
||||
tpl := based_uri_template (template, a_router)
|
||||
if attached tpl.match (p) as tpl_res then
|
||||
Result := handler
|
||||
a_router.execute_before (Current)
|
||||
--| Applied the context to the request
|
||||
--| in practice, this will fill the {WSF_REQUEST}.path_parameters
|
||||
create new_src.make (tpl_res.path_variables.count, tpl_res.path_variables)
|
||||
new_src.apply (req)
|
||||
handler.execute (req, res)
|
||||
--| Revert {WSF_REQUEST}.path_parameters_source to former value
|
||||
--| In case the request object passed by other handler that alters its values.
|
||||
new_src.revert (req)
|
||||
a_router.execute_after (Current)
|
||||
end
|
||||
rescue
|
||||
if new_src /= Void then
|
||||
new_src.revert (req)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
based_uri_template (a_tpl: like template; a_router: WSF_ROUTER): like template
|
||||
do
|
||||
if attached a_router.base_url as l_base_url then
|
||||
Result := a_tpl.duplicate
|
||||
Result.set_template (l_base_url + a_tpl.template)
|
||||
else
|
||||
Result := a_tpl
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,28 +1,24 @@
|
||||
note
|
||||
description: "[
|
||||
WSF_URI_ROUTING_HANDLER is a default descendant of WSF_URI_ROUTING_HANDLER_I
|
||||
for WSF_URI_ROUTER
|
||||
]"
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_AGENT_CONTEXT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_ROUTING_HANDLER
|
||||
WSF_URI_TEMPLATE_AGENT_CONTEXT_HANDLER [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_URI_ROUTING_HANDLER_I [WSF_HANDLER [WSF_URI_HANDLER_CONTEXT], WSF_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]
|
||||
|
||||
WSF_AGENT_CONTEXT_HANDLER [C]
|
||||
rename
|
||||
set_action as make
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: WSF_URI_ROUTER
|
||||
|
||||
;note
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
@@ -0,0 +1,47 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_CONTEXT_ROUTED_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_CONTEXT_ROUTED_SERVICE [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
feature -- Mapping helper: uri
|
||||
|
||||
map_uri_template (a_tpl: STRING; h: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C])
|
||||
do
|
||||
map_uri_template_with_request_methods (a_tpl, h, Void)
|
||||
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)
|
||||
do
|
||||
router.map_with_request_methods (create {WSF_URI_TEMPLATE_CONTEXT_MAPPING [C]}.make (a_tpl, h), rqst_methods)
|
||||
end
|
||||
|
||||
feature -- Mapping helper: uri agent
|
||||
|
||||
map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]])
|
||||
do
|
||||
map_uri_template_agent_with_request_methods (a_tpl, proc, Void)
|
||||
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)
|
||||
do
|
||||
map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_CONTEXT_HANDLER [C] }.make (proc), rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,41 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_ROUTING_CONTEXT_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_ROUTING_CONTEXT_HANDLER [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTING_HANDLER
|
||||
|
||||
WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]
|
||||
rename
|
||||
execute as uri_template_execute
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_router
|
||||
|
||||
feature -- Execution
|
||||
|
||||
uri_template_execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
--| For such routing handler, the previous context is lost
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,30 @@
|
||||
note
|
||||
description: "Summary description for EWF_URI_TEMPLATE_WITH_CONTEXT_HANDLER."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_CONTEXT_HANDLER [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_CONTEXT_HANDLER [C]
|
||||
|
||||
feature {WSF_ROUTER} -- Mapping
|
||||
|
||||
new_mapping (a_tpl: READABLE_STRING_8): WSF_URI_TEMPLATE_CONTEXT_MAPPING [C]
|
||||
do
|
||||
create Result.make (a_tpl, Current)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,97 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_CONTEXT_MAPPING}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_CONTEXT_MAPPING [C -> WSF_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTER_CONTEXT_MAPPING [C]
|
||||
|
||||
create
|
||||
make,
|
||||
make_from_template
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (s: READABLE_STRING_8; h: like handler)
|
||||
do
|
||||
make_from_template (create {URI_TEMPLATE}.make (s), h)
|
||||
end
|
||||
|
||||
make_from_template (tpl: URI_TEMPLATE; h: like handler)
|
||||
do
|
||||
template := tpl
|
||||
handler := h
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]
|
||||
|
||||
template: URI_TEMPLATE
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_handler (h: like handler)
|
||||
do
|
||||
handler := h
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||
local
|
||||
tpl: URI_TEMPLATE
|
||||
p: READABLE_STRING_32
|
||||
ctx: detachable C
|
||||
new_src: detachable WSF_REQUEST_PATH_PARAMETERS_PROVIDER
|
||||
do
|
||||
p := path_from_request (req)
|
||||
tpl := based_uri_template (template, a_router)
|
||||
if attached tpl.match (p) as tpl_res then
|
||||
Result := handler
|
||||
create ctx.make (req, Current)
|
||||
a_router.execute_before (Current)
|
||||
--| Applied the context to the request
|
||||
--| in practice, this will fill the {WSF_REQUEST}.path_parameters
|
||||
create new_src.make (tpl_res.path_variables.count, tpl_res.path_variables)
|
||||
new_src.apply (req)
|
||||
handler.execute (ctx, req, res)
|
||||
--| Revert {WSF_REQUEST}.path_parameters_source to former value
|
||||
--| In case the request object passed by other handler that alters its values.
|
||||
new_src.revert (req)
|
||||
a_router.execute_after (Current)
|
||||
end
|
||||
rescue
|
||||
if new_src /= Void then
|
||||
new_src.revert (req)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
based_uri_template (a_tpl: like template; a_router: WSF_ROUTER): like template
|
||||
do
|
||||
if attached a_router.base_url as l_base_url then
|
||||
Result := a_tpl.duplicate
|
||||
Result.set_template (l_base_url + a_tpl.template)
|
||||
else
|
||||
Result := a_tpl
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,50 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Default router based on URI map
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_ROUTER
|
||||
|
||||
inherit
|
||||
WSF_URI_ROUTER_I [WSF_HANDLER [WSF_URI_HANDLER_CONTEXT], WSF_URI_HANDLER_CONTEXT]
|
||||
redefine
|
||||
map_agent_with_request_methods, map_agent_response_with_request_methods
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Mapping agent
|
||||
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: WSF_URI_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
h: WSF_AGENT_HANDLER [WSF_URI_HANDLER_CONTEXT]
|
||||
do
|
||||
create h.make (a_action)
|
||||
map_with_request_methods (a_id, h, rqst_methods)
|
||||
end
|
||||
|
||||
map_agent_response_with_request_methods (a_id: READABLE_STRING_8; a_action: FUNCTION [ANY, TUPLE [ctx: WSF_URI_HANDLER_CONTEXT; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
h: WSF_AGENT_RESPONSE_HANDLER [WSF_URI_HANDLER_CONTEXT]
|
||||
do
|
||||
create h.make (a_action)
|
||||
map_with_request_methods (a_id, h, rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,60 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Context for the handler execution
|
||||
|
||||
It does not provide additional information compared to {WSF_HANDLER_CONTEXT}
|
||||
- request: WSF_REQUEST -- Associated request
|
||||
- path: READABLE_STRING_8 -- Associated path
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
WSF_HANDLER_CONTEXT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (req: WSF_REQUEST; p: like path)
|
||||
do
|
||||
request := req
|
||||
path := p
|
||||
end
|
||||
|
||||
feature -- Request data
|
||||
|
||||
apply (req: WSF_REQUEST)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
revert (req: WSF_REQUEST)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Item
|
||||
|
||||
item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Variable value for parameter or variable `a_name'
|
||||
-- See `{WSF_REQUEST}.item(s)'
|
||||
do
|
||||
Result := request.item (a_name)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,251 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
URL dispatcher/router based on simple URI mapping and request methods if precised
|
||||
The associated context {WSF_URI_HANDLER_CONTEXT} does not contains any additional information.
|
||||
|
||||
The matching check if the same path is mapped, or if a substring of the path is mapped
|
||||
|
||||
Examples:
|
||||
|
||||
map ("/users/", users_handler)
|
||||
map_with_request_methods ("/groups/", read_groups_handler, <<"GET">>)
|
||||
map_with_request_methods ("/groups/", write_groups_handler, <<"POST", "PUT", "DELETE">>)
|
||||
map_agent_with_request_methods ("/order/", agent do_get_order, <<"GET">>)
|
||||
map_agent_with_request_methods ("/order/", agent do_post_order, <<"POST">>)
|
||||
|
||||
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_ROUTER_I [H -> WSF_HANDLER [C], C -> WSF_URI_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTER [H, C]
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (n: INTEGER)
|
||||
do
|
||||
create handlers.make (n)
|
||||
handlers.compare_objects
|
||||
initialize
|
||||
end
|
||||
|
||||
make_with_base_url (n: INTEGER; a_base_url: like base_url)
|
||||
-- Make router allocated for at least `n' maps,
|
||||
-- and use `a_base_url' as base_url
|
||||
do
|
||||
make (n)
|
||||
set_base_url (a_base_url)
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Status report
|
||||
|
||||
handlers_matching_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable LIST [H]
|
||||
local
|
||||
l_res: READABLE_STRING_8
|
||||
do
|
||||
l_res := based_resource (a_resource)
|
||||
across
|
||||
handlers as c
|
||||
loop
|
||||
if c.item.resource.same_string (l_res) then
|
||||
if
|
||||
rqst_methods = Void or else
|
||||
across rqst_methods as rq some is_matching_request_methods (rq.item, c.item.request_methods) end
|
||||
then
|
||||
if Result = Void then
|
||||
create {ARRAYED_LIST [H]} Result.make (1)
|
||||
end
|
||||
Result.extend (c.item.handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Default: implementation
|
||||
|
||||
default_handler_context (req: WSF_REQUEST): C
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := handler_context (Void, req)
|
||||
end
|
||||
|
||||
feature -- Registration
|
||||
|
||||
map_with_request_methods (p: READABLE_STRING_8; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
l_uri: READABLE_STRING_8
|
||||
do
|
||||
if attached base_url as l_base_url then
|
||||
l_uri := l_base_url + p
|
||||
else
|
||||
l_uri := p
|
||||
end
|
||||
handlers.force ([h, l_uri, rqst_methods])
|
||||
h.on_handler_mapped (l_uri, rqst_methods)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
based_resource (a_resource: READABLE_STRING_8): READABLE_STRING_8
|
||||
do
|
||||
if attached base_url as l_base_url then
|
||||
Result := l_base_url + a_resource
|
||||
else
|
||||
Result := a_resource
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Handler
|
||||
|
||||
matching_route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
|
||||
local
|
||||
h: detachable H
|
||||
ctx: detachable C
|
||||
rq_method: READABLE_STRING_8
|
||||
do
|
||||
rq_method := request_method (req)
|
||||
|
||||
h := handler_by_path (source_uri (req), rq_method)
|
||||
if h = Void then
|
||||
if attached smart_handler_by_path (source_uri (req), rq_method) as info then
|
||||
h := info.handler
|
||||
ctx := handler_context (info.path, req)
|
||||
end
|
||||
end
|
||||
if h /= Void then
|
||||
if h.is_valid_context (req) then
|
||||
if ctx = Void then
|
||||
ctx := handler_context (Void, req)
|
||||
end
|
||||
create Result.make (h, ctx)
|
||||
else
|
||||
Result := Void
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Access: Implementation
|
||||
|
||||
handler_by_path (a_path: READABLE_STRING_GENERAL; rqst_method: READABLE_STRING_8): detachable H
|
||||
require
|
||||
a_path_valid: a_path /= Void
|
||||
local
|
||||
l_handlers: like handlers
|
||||
l_item: like handlers.item
|
||||
do
|
||||
l_handlers := handlers
|
||||
from
|
||||
l_handlers.start
|
||||
until
|
||||
l_handlers.after or Result /= Void
|
||||
loop
|
||||
l_item := l_handlers.item
|
||||
if is_matching_request_methods (rqst_method, l_item.request_methods) and a_path.same_string (l_item.resource) then
|
||||
Result := l_item.handler
|
||||
end
|
||||
l_handlers.forth
|
||||
end
|
||||
ensure
|
||||
a_path_unchanged: a_path.same_string (old a_path)
|
||||
end
|
||||
|
||||
smart_handler_by_path (a_path: READABLE_STRING_8; rqst_method: READABLE_STRING_8): detachable TUPLE [path: READABLE_STRING_8; handler: H]
|
||||
require
|
||||
a_path_valid: a_path /= Void
|
||||
local
|
||||
p: INTEGER
|
||||
l_context_path, l_path: READABLE_STRING_8
|
||||
h: detachable H
|
||||
do
|
||||
l_context_path := context_path (a_path)
|
||||
from
|
||||
p := l_context_path.count + 1
|
||||
until
|
||||
p <= 1 or Result /= Void
|
||||
loop
|
||||
l_path := l_context_path.substring (1, p - 1)
|
||||
h := handler_by_path (l_path, rqst_method)
|
||||
if h /= Void then
|
||||
Result := [l_path, h]
|
||||
else
|
||||
p := l_context_path.last_index_of ('/', p - 1)
|
||||
end
|
||||
variant
|
||||
p
|
||||
end
|
||||
ensure
|
||||
a_path_unchanged: a_path.same_string (old a_path)
|
||||
end
|
||||
|
||||
feature {NONE} -- Context factory
|
||||
|
||||
handler_context (p: detachable STRING; req: WSF_REQUEST): C
|
||||
local
|
||||
ctx: C
|
||||
do
|
||||
if p /= Void then
|
||||
create ctx.make (req, p)
|
||||
else
|
||||
create ctx.make (req, source_uri (req))
|
||||
end
|
||||
Result := ctx
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_cursor: ITERATION_CURSOR [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
-- Fresh cursor associated with current structure
|
||||
do
|
||||
Result := handlers.new_cursor
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
handlers: ARRAYED_LIST [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
-- Handlers indexed by the template expression
|
||||
-- see `templates'
|
||||
|
||||
context_path (a_path: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Prepared path from context which match requirement
|
||||
-- i.e: not empty, starting with '/'
|
||||
local
|
||||
p: INTEGER
|
||||
s: STRING_8
|
||||
do
|
||||
Result := a_path
|
||||
if Result.is_empty then
|
||||
Result := "/"
|
||||
else
|
||||
if Result[1] /= '/' then
|
||||
create s.make_from_string (Result)
|
||||
s.prepend_character ('/')
|
||||
Result := s
|
||||
end
|
||||
p := Result.index_of ('.', 1)
|
||||
if p > 0 then
|
||||
Result := Result.substring (1, p - 1)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
result_not_empty: not Result.is_empty
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,52 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Default router based on URI Template map
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_ROUTER
|
||||
|
||||
inherit
|
||||
WSF_URI_TEMPLATE_ROUTER_I [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
map_agent_with_request_methods,
|
||||
map_agent_response_with_request_methods
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Mapping agent
|
||||
|
||||
map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
h: WSF_AGENT_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
do
|
||||
create h.make (a_action)
|
||||
map_with_request_methods (a_id, h, rqst_methods)
|
||||
end
|
||||
|
||||
map_agent_response_with_request_methods (a_id: READABLE_STRING_8; a_action: FUNCTION [ANY, TUPLE [ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
local
|
||||
h: WSF_AGENT_RESPONSE_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
do
|
||||
create h.make (a_action)
|
||||
map_with_request_methods (a_id, h, rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,35 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER is a default descendant of WSF_URI_ROUTING_HANDLER_I
|
||||
for WSF_URI_TEMPLATE_ROUTER
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER_I [WSF_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT], WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: WSF_URI_TEMPLATE_ROUTER
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,137 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Context for the handler execution
|
||||
|
||||
The associated context {WSF_URI_TEMPLATE_HANDLER_CONTEXT} add information about the matched map
|
||||
- uri_template : the associated URI_TEMPLATE
|
||||
- uri_template_match : the matching result providing path variables
|
||||
- additional path_parameter (..) and related queries
|
||||
|
||||
In addition to what WSF_HANDLER_CONTEXT already provides, i.e:
|
||||
- request: WSF_REQUEST -- Associated request
|
||||
- path: READABLE_STRING_8 -- Associated path
|
||||
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
WSF_HANDLER_CONTEXT
|
||||
redefine
|
||||
item
|
||||
end
|
||||
|
||||
WSF_REQUEST_PATH_PARAMETERS_SOURCE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (req: WSF_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT; p: like path)
|
||||
do
|
||||
request := req
|
||||
uri_template := tpl
|
||||
uri_template_match := tpl_res
|
||||
path := p
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
uri_template: URI_TEMPLATE
|
||||
|
||||
uri_template_match: URI_TEMPLATE_MATCH_RESULT
|
||||
|
||||
feature -- Environment
|
||||
|
||||
path_parameters_count: INTEGER
|
||||
do
|
||||
Result := uri_template_match.path_variables.count
|
||||
end
|
||||
|
||||
urlencoded_path_parameters: TABLE_ITERABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := uri_template_match.path_variables
|
||||
end
|
||||
|
||||
previous_path_parameters_source: detachable WSF_REQUEST_PATH_PARAMETERS_SOURCE
|
||||
|
||||
apply (req: WSF_REQUEST)
|
||||
-- <Precursor>
|
||||
do
|
||||
previous_path_parameters_source := req.path_parameters_source
|
||||
req.set_path_parameters_source (Current)
|
||||
end
|
||||
|
||||
revert (req: WSF_REQUEST)
|
||||
-- <Precursor>
|
||||
do
|
||||
req.set_path_parameters_source (previous_path_parameters_source)
|
||||
previous_path_parameters_source := Void
|
||||
end
|
||||
|
||||
feature -- Item
|
||||
|
||||
item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Variable value for parameter or variable `a_name'
|
||||
-- See `{WSF_REQUEST}.item(s)'
|
||||
do
|
||||
Result := path_parameter (a_name) --| Should we handle url-encoded name?
|
||||
if Result = Void then
|
||||
Result := request.item (a_name)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Path parameter
|
||||
|
||||
path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
local
|
||||
n: READABLE_STRING_8
|
||||
do
|
||||
n := uri_template_match.encoded_name (a_name)
|
||||
if attached uri_template_match.path_variable (n) as s then
|
||||
create {WSF_STRING} Result.make (n, s)
|
||||
end
|
||||
end
|
||||
|
||||
is_integer_path_parameter (a_name: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Is path parameter related to `a_name' an integer value?
|
||||
do
|
||||
Result := attached string_path_parameter (a_name) as s and then s.is_integer
|
||||
end
|
||||
|
||||
integer_path_parameter (a_name: READABLE_STRING_GENERAL): INTEGER
|
||||
-- Integer value for path parameter `a_name' if relevant.
|
||||
require
|
||||
is_integer_path_parameter: is_integer_path_parameter (a_name)
|
||||
do
|
||||
Result := integer_from (path_parameter (a_name))
|
||||
end
|
||||
|
||||
string_path_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- String value for path parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_from (path_parameter (a_name))
|
||||
end
|
||||
|
||||
string_array_path_parameter (a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for path parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_array_for (a_name, agent string_path_parameter)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,228 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
URL dispatcher/router based on URI Template mapping and request methods if precised
|
||||
The associated context {WSF_URI_TEMPLATE_HANDLER_CONTEXT} contains information about the matched map.
|
||||
|
||||
Examples:
|
||||
|
||||
map ("/users/", users_handler)
|
||||
map_with_request_methods ("/order/{order-id}", order_handler, <<"GET", "POST">>)
|
||||
map_agent_with_request_methods ("/order/{order-id}", agent do_get_order, <<"GET">>)
|
||||
map_agent_with_request_methods ("/order/{order-id}", agent do_post_order, <<"POST">>)
|
||||
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_ROUTER_I [H -> WSF_HANDLER [C], C -> WSF_URI_TEMPLATE_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTER [H, C]
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (n: INTEGER)
|
||||
do
|
||||
create handlers.make (n)
|
||||
create templates.make (n)
|
||||
handlers.compare_objects
|
||||
initialize
|
||||
end
|
||||
|
||||
make_with_base_url (n: INTEGER; a_base_url: like base_url)
|
||||
-- Make router allocated for at least `n' maps,
|
||||
-- and use `a_base_url' as base_url
|
||||
do
|
||||
make (n)
|
||||
set_base_url (a_base_url)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
handlers_matching_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable LIST [H]
|
||||
local
|
||||
l_res: READABLE_STRING_8
|
||||
do
|
||||
l_res := based_resource (a_resource)
|
||||
across
|
||||
handlers as c
|
||||
loop
|
||||
if c.item.resource.same_string (l_res) then
|
||||
if
|
||||
rqst_methods = Void or else
|
||||
across rqst_methods as rq some is_matching_request_methods (rq.item, c.item.request_methods) end
|
||||
then
|
||||
if Result = Void then
|
||||
create {ARRAYED_LIST [H]} Result.make (1)
|
||||
end
|
||||
Result.extend (c.item.handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Registration
|
||||
|
||||
map_with_uri_template (uri: URI_TEMPLATE; h: H)
|
||||
require
|
||||
has_not_such_map: not has_map (uri.template, Void, h)
|
||||
do
|
||||
map_with_uri_template_and_request_methods (uri, h, Void)
|
||||
end
|
||||
|
||||
map_with_uri_template_and_request_methods (uri: URI_TEMPLATE; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
require
|
||||
uri_is_valid: uri.is_valid
|
||||
has_not_such_map: not has_map (uri.template, rqst_methods, h)
|
||||
local
|
||||
l_tpl: like {URI_TEMPLATE}.template
|
||||
l_uri: URI_TEMPLATE
|
||||
do
|
||||
l_uri := based_uri (uri)
|
||||
l_tpl := l_uri.template
|
||||
|
||||
handlers.force ([h, l_tpl, rqst_methods])
|
||||
templates.force (l_uri, l_tpl)
|
||||
h.on_handler_mapped (l_tpl, rqst_methods)
|
||||
end
|
||||
|
||||
map_with_request_methods (tpl: READABLE_STRING_8; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
do
|
||||
map_with_uri_template_and_request_methods (create {URI_TEMPLATE}.make (tpl), h, rqst_methods)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
based_uri (uri: URI_TEMPLATE): URI_TEMPLATE
|
||||
do
|
||||
if attached base_url as l_base_url then
|
||||
Result := uri.duplicate
|
||||
Result.set_template (l_base_url + uri.template)
|
||||
else
|
||||
Result := uri
|
||||
end
|
||||
end
|
||||
|
||||
based_resource (a_resource: READABLE_STRING_8): READABLE_STRING_8
|
||||
do
|
||||
if attached base_url as l_base_url then
|
||||
Result := l_base_url + a_resource
|
||||
else
|
||||
Result := a_resource
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Handler
|
||||
|
||||
matching_route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
|
||||
local
|
||||
l_handlers: like handlers
|
||||
t: READABLE_STRING_8
|
||||
p: READABLE_STRING_8
|
||||
l_req_method: READABLE_STRING_8
|
||||
l_res: URI_TEMPLATE_MATCH_RESULT
|
||||
do
|
||||
p := source_uri (req)
|
||||
from
|
||||
l_req_method := request_method (req)
|
||||
l_handlers := handlers
|
||||
l_handlers.start
|
||||
until
|
||||
l_handlers.after or Result /= Void
|
||||
loop
|
||||
if attached l_handlers.item as l_info then
|
||||
if is_matching_request_methods (l_req_method, l_info.request_methods) then
|
||||
t := l_info.resource
|
||||
if
|
||||
attached {WSF_ROUTING_HANDLER [H, C]} l_info.handler as rah and then
|
||||
p.starts_with (t)
|
||||
then
|
||||
create l_res.make_empty
|
||||
l_res.path_variables.force (p.substring (t.count + 1, p.count), "path")
|
||||
|
||||
create Result.make (l_info.handler, handler_context (p, req, create {URI_TEMPLATE}.make (t), l_res))
|
||||
elseif attached templates.item (t) as tpl and then
|
||||
attached tpl.match (p) as res
|
||||
then
|
||||
create Result.make (l_info.handler, handler_context (p, req, tpl, res))
|
||||
end
|
||||
end
|
||||
end
|
||||
l_handlers.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Default: implementation
|
||||
|
||||
default_handler_context (req: WSF_REQUEST): C
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := handler_context (Void, req, create {URI_TEMPLATE}.make ("/"), create {URI_TEMPLATE_MATCH_RESULT}.make_empty)
|
||||
end
|
||||
|
||||
feature {NONE} -- Context factory
|
||||
|
||||
handler_context (p: detachable READABLE_STRING_8; req: WSF_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT): C
|
||||
do
|
||||
if p /= Void then
|
||||
create Result.make (req, tpl, tpl_res, p)
|
||||
else
|
||||
create Result.make (req, tpl, tpl_res, source_uri (req))
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access: ITERABLE
|
||||
|
||||
new_cursor: ITERATION_CURSOR [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
-- Fresh cursor associated with current structure
|
||||
do
|
||||
Result := handlers.new_cursor
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
handlers: ARRAYED_LIST [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
-- Handlers indexed by the template expression
|
||||
-- see `templates'
|
||||
|
||||
templates: HASH_TABLE [URI_TEMPLATE, READABLE_STRING_8]
|
||||
-- URI Template indexed by the template expression
|
||||
|
||||
context_path (a_path: STRING): STRING
|
||||
-- Prepared path from context which match requirement
|
||||
-- i.e: not empty, starting with '/'
|
||||
local
|
||||
p: INTEGER
|
||||
do
|
||||
Result := a_path
|
||||
if Result.is_empty then
|
||||
Result := "/"
|
||||
else
|
||||
if Result[1] /= '/' then
|
||||
Result := "/" + Result
|
||||
end
|
||||
p := Result.index_of ('.', 1)
|
||||
if p > 0 then
|
||||
Result := Result.substring (1, p - 1)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
result_not_empty: not Result.is_empty
|
||||
end
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,47 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
This class helps to build Routing handler based for WSF_URI_TEMPLATE_ROUTER
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER_I [H -> WSF_HANDLER [C],
|
||||
C -> WSF_URI_TEMPLATE_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
WSF_ROUTING_HANDLER [H, C]
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (n: INTEGER)
|
||||
do
|
||||
create router.make (n)
|
||||
end
|
||||
|
||||
make_with_base_url (n: INTEGER; a_base_url: like base_url)
|
||||
-- Make allocated for at least `n' maps,
|
||||
-- and use `a_base_url' as base_url
|
||||
do
|
||||
create router.make_with_base_url (n, a_base_url)
|
||||
end
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: WSF_URI_TEMPLATE_ROUTER_I [H, C]
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,43 +1,71 @@
|
||||
note
|
||||
description: "[
|
||||
Request handler used to respond file system request.
|
||||
]"
|
||||
description: "Summary description for {WSF_FILE_SYSTEM_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_FILE_SYSTEM_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_FILE_SYSTEM_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_STARTS_WITH_HANDLER
|
||||
rename
|
||||
execute as execute_starts_with
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_root: READABLE_STRING_8)
|
||||
make (d: like document_root)
|
||||
require
|
||||
a_root_exists: node_exists (a_root)
|
||||
valid_d: (d /= Void and then not d.is_empty) implies not d.ends_with (operating_environment.directory_separator.out)
|
||||
local
|
||||
e: EXECUTION_ENVIRONMENT
|
||||
do
|
||||
document_root := a_root
|
||||
if d.is_empty then
|
||||
create e
|
||||
document_root := e.current_working_directory
|
||||
else
|
||||
document_root := d
|
||||
end
|
||||
ensure
|
||||
not document_root.is_empty and then not document_root.ends_with (operating_environment.directory_separator.out)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
document_root: READABLE_STRING_8
|
||||
-- Document root for the file system
|
||||
document_root: STRING
|
||||
max_age: INTEGER
|
||||
|
||||
index_disabled: BOOLEAN
|
||||
-- Index disabled?
|
||||
|
||||
directory_index: detachable ARRAY [READABLE_STRING_8]
|
||||
-- File serve if a directory index is requested
|
||||
|
||||
not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]
|
||||
|
||||
access_denied_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]
|
||||
not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE]]
|
||||
|
||||
access_denied_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE]]
|
||||
|
||||
feature -- Element change
|
||||
|
||||
enable_index
|
||||
do
|
||||
index_disabled := False
|
||||
end
|
||||
|
||||
disable_index
|
||||
do
|
||||
index_disabled := True
|
||||
end
|
||||
|
||||
set_max_age (a_seconds: like max_age)
|
||||
do
|
||||
max_age := a_seconds
|
||||
end
|
||||
|
||||
set_directory_index (idx: like directory_index)
|
||||
-- Set `directory_index' as `idx'
|
||||
do
|
||||
@@ -62,38 +90,25 @@ feature -- Element change
|
||||
|
||||
feature -- Execution
|
||||
|
||||
requested_path (ctx: C): detachable READABLE_STRING_8
|
||||
-- Path associated with the request
|
||||
-- i.e: path of the file system resource if any
|
||||
do
|
||||
if attached {WSF_STRING} ctx.item ("path") as v_path then
|
||||
Result := v_path.value.as_string_8
|
||||
end
|
||||
end
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
s: STRING
|
||||
p: STRING
|
||||
do
|
||||
if attached requested_path (ctx) as uri then
|
||||
process_uri (uri, ctx, req, res)
|
||||
p := req.path_info
|
||||
if p.starts_with (a_start_path) then
|
||||
p.remove_head (a_start_path.count)
|
||||
else
|
||||
s := "Hello " + ctx.path + "%N"
|
||||
s.append ("root=" + document_root)
|
||||
|
||||
create h.make
|
||||
h.put_content_type_text_html
|
||||
h.put_content_length (s.count)
|
||||
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
res.put_header_text (h.string)
|
||||
res.put_string (s)
|
||||
check starts_with_base: False end
|
||||
end
|
||||
process_uri (p, req, res)
|
||||
end
|
||||
|
||||
process_uri (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_starts_with (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
execute (a_start_path,req, res)
|
||||
end
|
||||
|
||||
process_uri (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
f: RAW_FILE
|
||||
fn: READABLE_STRING_8
|
||||
@@ -103,19 +118,23 @@ feature -- Execution
|
||||
if f.exists then
|
||||
if f.is_readable then
|
||||
if f.is_directory then
|
||||
respond_index (req.request_uri, fn, ctx, req, res)
|
||||
if index_disabled then
|
||||
process_directory_index_disabled (uri, req, res)
|
||||
else
|
||||
respond_file (f, ctx, req, res)
|
||||
process_index (req.request_uri, fn, req, res)
|
||||
end
|
||||
else
|
||||
respond_access_denied (uri, ctx, req, res)
|
||||
process_file (f, req, res)
|
||||
end
|
||||
else
|
||||
respond_not_found (uri, ctx, req, res)
|
||||
process_access_denied (uri, req, res)
|
||||
end
|
||||
else
|
||||
process_not_found (uri, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
respond_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
process_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
uri, s: STRING_8
|
||||
@@ -124,7 +143,7 @@ feature -- Execution
|
||||
do
|
||||
create d.make_open_read (dn)
|
||||
if attached directory_index_file (d) as f then
|
||||
respond_file (f, ctx, req, res)
|
||||
process_file (f, req, res)
|
||||
else
|
||||
uri := a_uri
|
||||
if not uri.is_empty and then uri [uri.count] /= '/' then
|
||||
@@ -170,31 +189,72 @@ feature -- Execution
|
||||
d.close
|
||||
end
|
||||
|
||||
respond_file (f: FILE; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
process_file (f: FILE; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
ext: READABLE_STRING_8
|
||||
ct: detachable READABLE_STRING_8
|
||||
fres: WSF_FILE_RESPONSE
|
||||
dt: DATE_TIME
|
||||
do
|
||||
ext := extension (f.name)
|
||||
ct := extension_mime_mapping.mime_type (ext)
|
||||
if ct = Void then
|
||||
ct := {HTTP_MIME_TYPES}.application_force_download
|
||||
end
|
||||
if
|
||||
attached req.meta_string_variable ("HTTP_IF_MODIFIED_SINCE") as s_if_modified_since and then
|
||||
attached file_date (f) as f_date and then (f_date >= rfc1123_http_date_format_to_date (s_if_modified_since))
|
||||
then
|
||||
process_not_modified (f_date, req, res)
|
||||
else
|
||||
create fres.make_with_content_type (ct, f.name)
|
||||
fres.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head))
|
||||
|
||||
-- cache control
|
||||
create dt.make_now_utc
|
||||
fres.header.put_cache_control ("private, max-age=" + max_age.out)
|
||||
fres.header.put_utc_date (dt)
|
||||
if max_age > 0 then
|
||||
dt := dt.twin
|
||||
dt.second_add (max_age)
|
||||
end
|
||||
fres.header.put_expires_date (dt)
|
||||
|
||||
fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head))
|
||||
res.send (fres)
|
||||
end
|
||||
end
|
||||
|
||||
respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
process_not_modified (a_utc_date: detachable DATE_TIME; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
dt: DATE_TIME
|
||||
do
|
||||
create dt.make_now_utc
|
||||
create h.make
|
||||
h.put_cache_control ("private, max-age=" + max_age.out)
|
||||
h.put_utc_date (dt)
|
||||
if max_age > 0 then
|
||||
dt := dt.twin
|
||||
dt.second_add (max_age)
|
||||
end
|
||||
h.put_expires_date (dt)
|
||||
|
||||
if a_utc_date /= Void then
|
||||
h.put_last_modified (a_utc_date)
|
||||
end
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.not_modified)
|
||||
res.put_header_text (h.string)
|
||||
res.flush
|
||||
end
|
||||
|
||||
process_not_found (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
s: STRING_8
|
||||
do
|
||||
if attached not_found_handler as hdl then
|
||||
hdl.call ([uri, ctx, req, res])
|
||||
hdl.call ([uri, req, res])
|
||||
else
|
||||
create h.make
|
||||
h.put_content_type_text_plain
|
||||
@@ -208,13 +268,13 @@ feature -- Execution
|
||||
end
|
||||
end
|
||||
|
||||
respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
process_access_denied (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
s: STRING_8
|
||||
do
|
||||
if attached access_denied_handler as hdl then
|
||||
hdl.call ([uri, ctx, req, res])
|
||||
hdl.call ([uri, req, res])
|
||||
else
|
||||
create h.make
|
||||
h.put_content_type_text_plain
|
||||
@@ -228,6 +288,26 @@ feature -- Execution
|
||||
end
|
||||
end
|
||||
|
||||
process_directory_index_disabled (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
s: STRING_8
|
||||
do
|
||||
if attached access_denied_handler as hdl then
|
||||
hdl.call ([uri, req, res])
|
||||
else
|
||||
create h.make
|
||||
h.put_content_type_text_plain
|
||||
create s.make_empty
|
||||
s.append ("Directory index: Access denied%N")
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.forbidden)
|
||||
h.put_content_length (s.count)
|
||||
res.put_header_text (h.string)
|
||||
res.put_string (s)
|
||||
res.flush
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
directory_index_file (d: DIRECTORY): detachable FILE
|
||||
@@ -259,7 +339,7 @@ feature {NONE} -- Implementation
|
||||
|
||||
resource_filename (uri: READABLE_STRING_8): READABLE_STRING_8
|
||||
do
|
||||
Result := real_filename (document_root + real_filename (uri))
|
||||
Result := real_filename (document_root + operating_environment.directory_separator.out + real_filename (uri))
|
||||
end
|
||||
|
||||
dirname (uri: READABLE_STRING_8): READABLE_STRING_8
|
||||
@@ -343,6 +423,35 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- implementation: date time
|
||||
|
||||
date_time_utility: HTTP_DATE_TIME_UTILITIES
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
file_date (f: FILE): DATE_TIME
|
||||
do
|
||||
Result := timestamp_to_date (f.date)
|
||||
end
|
||||
|
||||
rfc1123_http_date_format_to_date (s: STRING): DATE_TIME
|
||||
-- String representation of `dt' using the RFC 1123
|
||||
local
|
||||
t: STRING
|
||||
do
|
||||
t := s
|
||||
if t.ends_with ("GMT") then
|
||||
t := t.substring (1, t.count - 4)
|
||||
end
|
||||
create Result.make_from_string (t, "ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2")
|
||||
end
|
||||
|
||||
timestamp_to_date (n: INTEGER): DATE_TIME
|
||||
do
|
||||
Result := date_time_utility.unix_time_stamp_to_date_time (n)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
note
|
||||
description: "[
|
||||
Request handler object which is called by a WSF_ROUTER
|
||||
An handler should implement the method
|
||||
|
||||
execute (ctx, req, res)
|
||||
|
||||
The class is generic, this way one can use a custom WSF_HANDLER_CONTEXT if needed
|
||||
]"
|
||||
description: "Summary description for {WSF_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
ANY
|
||||
WSF_HANDLER
|
||||
|
||||
feature -- Status report
|
||||
|
||||
@@ -24,59 +15,16 @@ feature -- Status report
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
feature {WSF_ROUTER} -- Mapping
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
--
|
||||
-- `ctx': contains advanced data related to request_uri
|
||||
-- in the case of URI_TEMPLATE, it add support for "path_parameter"
|
||||
-- `req': request data
|
||||
-- `res': reponse stream
|
||||
--| note `ctx' can also provide data coming from `req'
|
||||
require
|
||||
is_valid_context: is_valid_context (req)
|
||||
new_mapping (a_resource: READABLE_STRING_8): WSF_ROUTER_MAPPING
|
||||
-- New mapping built with Current as handler
|
||||
deferred
|
||||
ensure
|
||||
response_status_set: res.status_is_set
|
||||
Result /= Void and then Result.handler = Current
|
||||
end
|
||||
|
||||
feature -- Execution: report
|
||||
|
||||
url (req: WSF_REQUEST; a_base: detachable READABLE_STRING_8; args: detachable STRING; abs: BOOLEAN): STRING
|
||||
-- Associated url based on `a_base' and `args'
|
||||
-- if `abs' then return absolute url
|
||||
local
|
||||
s: detachable STRING
|
||||
l_base: STRING
|
||||
do
|
||||
if a_base /= Void then
|
||||
l_base := a_base
|
||||
else
|
||||
l_base := req.request_uri
|
||||
end
|
||||
s := args
|
||||
if s /= Void and then s.count > 0 then
|
||||
if s[1] /= '/' then
|
||||
s := l_base + "/" + s
|
||||
else
|
||||
s := l_base + s
|
||||
end
|
||||
else
|
||||
s := l_base
|
||||
end
|
||||
if abs then
|
||||
Result := req.absolute_script_url (s)
|
||||
else
|
||||
Result := req.script_url (s)
|
||||
end
|
||||
ensure
|
||||
result_attached: Result /= Void
|
||||
end
|
||||
|
||||
feature {WSF_ROUTER} -- Routes change
|
||||
|
||||
on_handler_mapped (a_resource: READABLE_STRING_8; a_rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
on_mapped (a_mapping: like new_mapping; a_rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Callback called when a router map a route to Current handler
|
||||
do
|
||||
end
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Context for the handler execution
|
||||
It provides information related to the matching handler at runtime, i.e:
|
||||
- request: WSF_REQUEST -- Associated request
|
||||
- path: READABLE_STRING_8 -- Associated path
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
WSF_FORMAT_UTILITY
|
||||
export
|
||||
{NONE} all
|
||||
end
|
||||
|
||||
DEBUG_OUTPUT
|
||||
|
||||
feature -- Access
|
||||
|
||||
request: WSF_REQUEST
|
||||
-- Associated request
|
||||
|
||||
path: READABLE_STRING_8
|
||||
-- Associated path
|
||||
|
||||
feature -- Request data
|
||||
|
||||
apply (req: WSF_REQUEST)
|
||||
-- Apply current data to request `req'
|
||||
--| mainly to fill {WSF_REQUEST}.path_parameters
|
||||
deferred
|
||||
end
|
||||
|
||||
revert (req: WSF_REQUEST)
|
||||
-- Revert potential previous `apply' for request `req'
|
||||
--| mainly to restore previous {WSF_REQUEST}.path_parameters
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Url Query
|
||||
|
||||
script_absolute_url (a_path: STRING): STRING
|
||||
-- Absolute Url for the script if any, extended by `a_path'
|
||||
do
|
||||
Result := request.absolute_script_url (a_path)
|
||||
end
|
||||
|
||||
script_url (a_path: STRING): STRING
|
||||
-- Url relative to script name if any, extended by `a_path'
|
||||
require
|
||||
a_path_attached: a_path /= Void
|
||||
do
|
||||
Result := request.script_url (a_path)
|
||||
end
|
||||
|
||||
url (args: detachable STRING; abs: BOOLEAN): STRING
|
||||
-- Associated url based on `path' and `args'
|
||||
-- if `abs' then return absolute url
|
||||
local
|
||||
s,t: detachable STRING
|
||||
do
|
||||
s := args
|
||||
if s /= Void and then s.count > 0 then
|
||||
create t.make_from_string (path)
|
||||
if s[1] /= '/' and t[t.count] /= '/' then
|
||||
t.append_character ('/')
|
||||
t.append (s)
|
||||
else
|
||||
t.append (s)
|
||||
end
|
||||
s := t
|
||||
else
|
||||
s := path
|
||||
end
|
||||
if abs then
|
||||
Result := script_absolute_url (s)
|
||||
else
|
||||
Result := script_url (s)
|
||||
end
|
||||
ensure
|
||||
result_attached: Result /= Void
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
request_accepted_content_type (a_supported_content_types: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8
|
||||
-- Accepted content-type for the request, among the supported content types `a_supported_content_types'
|
||||
local
|
||||
s: detachable READABLE_STRING_8
|
||||
i,n: INTEGER
|
||||
do
|
||||
if
|
||||
attached accepted_content_types (request) as l_accept_lst and then
|
||||
not l_accept_lst.is_empty
|
||||
then
|
||||
from
|
||||
l_accept_lst.start
|
||||
until
|
||||
l_accept_lst.after or Result /= Void
|
||||
loop
|
||||
s := l_accept_lst.item
|
||||
if a_supported_content_types /= Void then
|
||||
from
|
||||
i := a_supported_content_types.lower
|
||||
n := a_supported_content_types.upper
|
||||
until
|
||||
i > n or Result /= Void
|
||||
loop
|
||||
if a_supported_content_types [i].same_string (s) then
|
||||
Result := s
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result := s
|
||||
end
|
||||
l_accept_lst.forth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Item
|
||||
|
||||
item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Variable value for parameter or variable `a_name'
|
||||
-- See `{WSF_REQUEST}.item(s)'
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Parameter
|
||||
|
||||
string_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- String value for any variable of parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_from (item (a_name))
|
||||
end
|
||||
|
||||
string_array_item (a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for query parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_array_for (a_name, agent string_item)
|
||||
end
|
||||
|
||||
feature -- Query parameter
|
||||
|
||||
query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Parameter value for query variable `a_name'
|
||||
--| i.e after the ? character
|
||||
do
|
||||
Result := request.query_parameter (a_name)
|
||||
end
|
||||
|
||||
string_query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- String value for query parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_from (query_parameter (a_name))
|
||||
end
|
||||
|
||||
string_array_query_parameter (a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for query parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_array_for (a_name, agent string_query_parameter)
|
||||
end
|
||||
|
||||
is_integer_query_parameter (a_name: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Is query parameter related to `a_name' an integer value?
|
||||
do
|
||||
Result := attached string_query_parameter (a_name) as s and then s.is_integer
|
||||
end
|
||||
|
||||
integer_query_parameter (a_name: READABLE_STRING_GENERAL): INTEGER
|
||||
-- Integer value for query parameter `a_name' if relevant.
|
||||
require
|
||||
is_integer_query_parameter: is_integer_query_parameter (a_name)
|
||||
do
|
||||
Result := integer_from (query_parameter (a_name))
|
||||
end
|
||||
|
||||
feature -- Convertion
|
||||
|
||||
string_from (a_value: detachable WSF_VALUE): detachable READABLE_STRING_32
|
||||
-- String value from `a_value' if relevant.
|
||||
do
|
||||
if attached {WSF_STRING} a_value as val then
|
||||
Result := val.value
|
||||
end
|
||||
end
|
||||
|
||||
integer_from (a_value: detachable WSF_VALUE): INTEGER
|
||||
-- String value from `a_value' if relevant.
|
||||
do
|
||||
if attached string_from (a_value) as val then
|
||||
if val.is_integer then
|
||||
Result := val.to_integer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
string_array_for (a_name: READABLE_STRING_GENERAL; a_item_fct: FUNCTION [ANY, TUPLE [READABLE_STRING_GENERAL], detachable READABLE_STRING_32]): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for query parameter `a_name' if relevant.
|
||||
local
|
||||
i: INTEGER
|
||||
n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := 1
|
||||
create Result.make_filled ("", 1, 5)
|
||||
until
|
||||
i = 0
|
||||
loop
|
||||
if attached a_item_fct.item ([a_name + "[" + i.out + "]"]) as v then
|
||||
Result.force (v, n)
|
||||
n := n + 1
|
||||
i := i + 1
|
||||
else
|
||||
i := 0 -- Exit
|
||||
end
|
||||
end
|
||||
Result.keep_head (n - 1)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := path
|
||||
end
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -5,12 +5,12 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ROUTED_SERVICE_I [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_ROUTED_SERVICE
|
||||
|
||||
feature -- Setup
|
||||
feature -- Initialization
|
||||
|
||||
initialize_router
|
||||
-- Initialize `router'
|
||||
-- Initialize router
|
||||
do
|
||||
create_router
|
||||
setup_router
|
||||
@@ -18,7 +18,9 @@ feature -- Setup
|
||||
|
||||
create_router
|
||||
-- Create `router'
|
||||
deferred
|
||||
--| could be redefine to initialize with proper capacity
|
||||
do
|
||||
create router.make (10)
|
||||
ensure
|
||||
router_created: router /= Void
|
||||
end
|
||||
@@ -30,25 +32,31 @@ feature -- Setup
|
||||
deferred
|
||||
end
|
||||
|
||||
router: WSF_ROUTER [H, C]
|
||||
-- Request router
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Dispatch the request
|
||||
-- and if you dispatch is found, execute the default procedure `execute_default'
|
||||
do
|
||||
if attached router.route (req) as r then
|
||||
router.execute_route (r, req, res)
|
||||
if attached router.dispatch_and_return_handler (req, res) as p then
|
||||
-- executed
|
||||
else
|
||||
execute_default (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Default procedure
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
feature -- Access
|
||||
|
||||
router: WSF_ROUTER
|
||||
-- Router used to dispatch the request according to the WSF_REQUEST object
|
||||
-- and associated request methods
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
@@ -1,111 +1,145 @@
|
||||
note
|
||||
description: "[
|
||||
URL dispatcher/router based on deferred mapping (to be defined in descendant)
|
||||
The associated context {WSF_HANDLER_CONTEXT} does contains information related to the matching at runtime.
|
||||
]"
|
||||
description: "Summary description for {EWF_ROUTER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ROUTER [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
|
||||
class
|
||||
WSF_ROUTER
|
||||
|
||||
inherit
|
||||
ITERABLE [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
ITERABLE [TUPLE [mapping: WSF_ROUTER_MAPPING; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_base_url
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
make (n: INTEGER)
|
||||
-- Create the router with a capacity of `n' mappings
|
||||
do
|
||||
create mappings.make (n)
|
||||
initialize (n)
|
||||
end
|
||||
|
||||
make_with_base_url (n: INTEGER; a_base_url: like base_url)
|
||||
-- Make router allocated for at least `n' maps,
|
||||
-- and use `a_base_url' as `base_url'
|
||||
--| This avoids prefixing all the resource string.
|
||||
do
|
||||
make (n)
|
||||
set_base_url (a_base_url)
|
||||
end
|
||||
|
||||
initialize (n: INTEGER)
|
||||
-- Initialize router
|
||||
do
|
||||
create pre_route_execution_actions
|
||||
create mappings.make (n)
|
||||
create pre_execution_actions
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS; a_handler: detachable H): BOOLEAN
|
||||
-- Has a map corresponding to `a_resource' and `rqst_methods' other than `a_handler'?
|
||||
do
|
||||
if attached handlers_matching_map (a_resource, rqst_methods) as lst then
|
||||
Result := a_handler = Void or else not lst.has (a_handler)
|
||||
end
|
||||
end
|
||||
|
||||
handlers_matching_map (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable LIST [H]
|
||||
-- Existing handlers matching map with `a_resource' and `rqst_methods'
|
||||
deferred
|
||||
end
|
||||
mappings: ARRAYED_LIST [TUPLE [mapping: WSF_ROUTER_MAPPING; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
-- Existing mappings
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
map (a_resource: READABLE_STRING_8; h: H)
|
||||
-- Map handler `h' with `a_resource'
|
||||
require
|
||||
has_not_such_map: not has_map (a_resource, Void, h)
|
||||
map (a_mapping: WSF_ROUTER_MAPPING)
|
||||
-- Map `a_mapping'
|
||||
do
|
||||
map_with_request_methods (a_resource, h, Void)
|
||||
map_with_request_methods (a_mapping, Void)
|
||||
end
|
||||
|
||||
map_routing (a_resource: READABLE_STRING_8; h: H)
|
||||
-- Map handler `h' with `a_resource'
|
||||
require
|
||||
has_not_such_map: not has_map (a_resource, Void, h)
|
||||
map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Map `a_mapping' for request methods `rqst_methods'
|
||||
do
|
||||
map (a_resource, h)
|
||||
mappings.extend ([a_mapping, rqst_methods])
|
||||
a_mapping.handler.on_mapped (a_mapping, rqst_methods)
|
||||
end
|
||||
|
||||
map_with_request_methods (a_resource: READABLE_STRING_8; h: H; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Map handler `h' with `a_resource' and `rqst_methods'
|
||||
require
|
||||
has_not_such_map: not has_map (a_resource, rqst_methods, h)
|
||||
deferred
|
||||
end
|
||||
feature -- Mapping handler
|
||||
|
||||
feature -- Mapping agent
|
||||
|
||||
map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]])
|
||||
-- Map `a_action' as an handler with `a_resource'
|
||||
handle (a_resource: READABLE_STRING_8; h: WSF_HANDLER)
|
||||
-- Map the mapping associated to handler `h' for resource `a_resource'
|
||||
do
|
||||
map_agent_with_request_methods (a_resource, a_action, Void)
|
||||
handle_with_request_methods (a_resource, h, Void)
|
||||
end
|
||||
|
||||
map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Map `a_action' as an handler with `a_resource' and `rqst_methods'
|
||||
handle_with_request_methods (a_resource: READABLE_STRING_8; h: WSF_HANDLER; rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Map the mapping associated to handler `h' for resource `a_resource'
|
||||
-- and only for request methods `rqst_methods'
|
||||
do
|
||||
map_with_request_methods (h.new_mapping (a_resource), rqst_methods)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_dispatched: BOOLEAN
|
||||
-- `dispatch' set `is_dispatched' to True
|
||||
-- if mapping was found, and associated handler executed
|
||||
|
||||
dispatch (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Dispatch request `req' among the `mappings'
|
||||
-- Set `is_dispatched' if the request were dispatched
|
||||
do
|
||||
if attached dispatch_and_return_handler (req, res) then
|
||||
check is_dispatched: is_dispatched end
|
||||
end
|
||||
end
|
||||
|
||||
dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable WSF_HANDLER
|
||||
-- Dispatch request `req' among the `mappings'
|
||||
-- And return the associated handler if mapping found and handler executed.
|
||||
local
|
||||
rah: WSF_AGENT_HANDLER [C]
|
||||
l_req_method: READABLE_STRING_8
|
||||
m: WSF_ROUTER_MAPPING
|
||||
do
|
||||
create rah.make (a_action)
|
||||
if attached {H} rah as h then
|
||||
map_with_request_methods (a_resource, h, rqst_methods)
|
||||
else
|
||||
check valid_agent_handler: False end
|
||||
is_dispatched := False
|
||||
l_req_method := request_method (req)
|
||||
|
||||
across
|
||||
mappings as c
|
||||
until
|
||||
Result /= Void
|
||||
loop
|
||||
if attached c.item as l_info then
|
||||
if is_matching_request_methods (l_req_method, l_info.request_methods) then
|
||||
m := l_info.mapping
|
||||
if attached m.routed_handler (req, res, Current) as r then
|
||||
is_dispatched := True
|
||||
Result := r
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Mapping response agent
|
||||
feature -- Hook
|
||||
|
||||
map_agent_response (a_resource: READABLE_STRING_8; a_function: FUNCTION [ANY, TUPLE [ctx: C; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE])
|
||||
-- Map response as Result `a_function' as an handler with `a_resource'
|
||||
execute_before (a_mapping: WSF_ROUTER_MAPPING)
|
||||
-- Execute before the handler associated with the matching mapping is executed
|
||||
do
|
||||
map_agent_response_with_request_methods (a_resource, a_function, Void)
|
||||
pre_execution_actions.call ([a_mapping])
|
||||
end
|
||||
|
||||
map_agent_response_with_request_methods (a_resource: READABLE_STRING_8; a_function: FUNCTION [ANY, TUPLE [ctx: C; req: WSF_REQUEST], WSF_RESPONSE_MESSAGE];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Map response as Result `a_function' as an handler with `a_resource' and `rqst_methods'
|
||||
local
|
||||
rah: WSF_AGENT_RESPONSE_HANDLER [C]
|
||||
execute_after (a_mapping: WSF_ROUTER_MAPPING)
|
||||
-- Execute after the handler associated with the matching mapping is executed
|
||||
--| Could be redefined to add specific hook.
|
||||
do
|
||||
create rah.make (a_function)
|
||||
if attached {H} rah as h then
|
||||
map_with_request_methods (a_resource, h, rqst_methods)
|
||||
else
|
||||
check valid_agent_handler: False end
|
||||
end
|
||||
end
|
||||
|
||||
pre_execution_actions: ACTION_SEQUENCE [TUPLE [WSF_ROUTER_MAPPING]]
|
||||
-- Action triggered before a route is execute
|
||||
--| Could be used for tracing, logging
|
||||
|
||||
feature -- Base url
|
||||
|
||||
count: INTEGER
|
||||
-- Number of mappings registered
|
||||
do
|
||||
Result := mappings.count
|
||||
end
|
||||
|
||||
base_url: detachable READABLE_STRING_8
|
||||
-- Common start of any route url
|
||||
|
||||
@@ -115,6 +149,7 @@ feature -- Element change
|
||||
-- Set `base_url' to `a_base_url'
|
||||
-- make sure no map is already added (i.e: count = 0)
|
||||
require
|
||||
a_valid_base_url: (a_base_url /= Void and then a_base_url.is_empty) implies (a_base_url.starts_with ("/") and not a_base_url.ends_with ("/"))
|
||||
no_handler_set: count = 0
|
||||
do
|
||||
if a_base_url = Void or else a_base_url.is_empty then
|
||||
@@ -124,105 +159,12 @@ feature -- Element change
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Hook
|
||||
|
||||
pre_route_execution_actions: ACTION_SEQUENCE [TUPLE [like route]]
|
||||
-- Action triggered before a route is execute
|
||||
--| Could be used for tracing, logging
|
||||
|
||||
feature -- Routing
|
||||
|
||||
route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
|
||||
-- Route matching `req'.
|
||||
do
|
||||
Result := matching_route (req)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_route (a_route: WSF_ROUTE [H,C]; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Process route `a_route'
|
||||
require
|
||||
a_route_attached: a_route /= Void
|
||||
local
|
||||
ctx: C
|
||||
do
|
||||
pre_route_execution_actions.call ([a_route])
|
||||
ctx := a_route.context
|
||||
ctx.apply (req)
|
||||
a_route.handler.execute (ctx, req, res)
|
||||
ctx.revert (req)
|
||||
rescue
|
||||
a_route.context.revert (req)
|
||||
end
|
||||
|
||||
dispatch (req: WSF_REQUEST; res: WSF_RESPONSE): BOOLEAN
|
||||
-- Dispatch `req, res' to the associated handler
|
||||
-- And return True is handled, otherwise False
|
||||
do
|
||||
if attached route (req) as r then
|
||||
Result := True
|
||||
execute_route (r, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable H
|
||||
-- Dispatch `req, res' to the associated handler
|
||||
-- And return this handler
|
||||
-- If Result is Void, this means no handler was found.
|
||||
do
|
||||
if attached route (req) as r then
|
||||
Result := r.handler
|
||||
execute_route (r, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Implementation
|
||||
|
||||
default_handler_context (req: WSF_REQUEST): C
|
||||
-- Default handler context associated with `req'.
|
||||
--| It can be used to build a context if needed.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- status report
|
||||
|
||||
count: INTEGER
|
||||
-- Count of maps handled by current
|
||||
do
|
||||
across
|
||||
Current as curs
|
||||
loop
|
||||
if attached {WSF_ROUTING_HANDLER [H, C]} curs.item.handler as rh then
|
||||
Result := Result + rh.count + 1 --| +1 for the handler itself
|
||||
else
|
||||
Result := Result + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Traversing
|
||||
|
||||
new_cursor: ITERATION_CURSOR [TUPLE [handler: H; resource: READABLE_STRING_8; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
new_cursor: ITERATION_CURSOR [TUPLE [mapping: WSF_ROUTER_MAPPING; request_methods: detachable WSF_ROUTER_METHODS]]
|
||||
-- Fresh cursor associated with current structure
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {WSF_ROUTED_SERVICE_I} -- Handler
|
||||
|
||||
source_uri (req: WSF_REQUEST): READABLE_STRING_32
|
||||
-- URI to use to find handler.
|
||||
do
|
||||
Result := req.path_info
|
||||
end
|
||||
|
||||
matching_route (req: WSF_REQUEST): detachable WSF_ROUTE [H, C]
|
||||
-- Handler whose map matched with `req' with associated Context
|
||||
require
|
||||
req_valid: source_uri (req) /= Void
|
||||
deferred
|
||||
ensure
|
||||
source_uri_unchanged: source_uri (req).same_string (old source_uri (req))
|
||||
Result := mappings.new_cursor
|
||||
end
|
||||
|
||||
feature -- Request methods helper
|
||||
|
||||
48
library/server/wsf/router/wsf_router_mapping.e
Normal file
48
library/server/wsf/router/wsf_router_mapping.e
Normal file
@@ -0,0 +1,48 @@
|
||||
note
|
||||
description: "Summary description for {WSF_ROUTER_MAPPING}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ROUTER_MAPPING
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_resource: READABLE_STRING_8; h: like handler)
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
handler: WSF_HANDLER
|
||||
-- Handler associated with Current mapping.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
|
||||
-- Return the handler if Current matches the request `req'.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
path_from_request (req: WSF_REQUEST): READABLE_STRING_32
|
||||
-- Path used by Current to check that Current mapping matches request `req'.
|
||||
do
|
||||
Result := req.path_info
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -62,11 +62,7 @@ feature {NONE} -- Initialization
|
||||
make_from_iterable (v: ITERABLE [READABLE_STRING_8])
|
||||
do
|
||||
make (1)
|
||||
across
|
||||
v as vc
|
||||
loop
|
||||
add_method_using_constant (vc.item)
|
||||
end
|
||||
add_methods (v)
|
||||
end
|
||||
|
||||
make_from_string (v: READABLE_STRING_8)
|
||||
@@ -115,6 +111,19 @@ feature -- Status change
|
||||
is_locked := True
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add alias "+" (a_other: WSF_ROUTER_METHODS): WSF_ROUTER_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)
|
||||
ensure
|
||||
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
enable_get
|
||||
@@ -328,6 +337,20 @@ feature -- Access
|
||||
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)
|
||||
@@ -358,15 +381,6 @@ feature {NONE} -- Implementation
|
||||
method_set: has (v.as_upper)
|
||||
end
|
||||
|
||||
add_method (v: READABLE_STRING_8)
|
||||
require
|
||||
is_upper_case: v.same_string (v.as_upper)
|
||||
do
|
||||
if not is_locked then
|
||||
methods.extend (v)
|
||||
end
|
||||
end
|
||||
|
||||
prune_method (v: READABLE_STRING_8)
|
||||
require
|
||||
is_upper_case: v.same_string (v.as_upper)
|
||||
|
||||
@@ -1,33 +1,30 @@
|
||||
note
|
||||
description: "[
|
||||
WSF_ROUTING_HANDLER is mainly to group a set of handler having the same base
|
||||
such as /users for
|
||||
/users/by/id/{id}
|
||||
/users/by/name/name}
|
||||
|
||||
It can be used to optimize the router, where the router checks only the base path before checking each entries
|
||||
Then for
|
||||
/a/a1
|
||||
/a/a2
|
||||
/a/a3
|
||||
/a/a4
|
||||
/b/b1
|
||||
/b/b2
|
||||
/b/b3
|
||||
2 routing handlers could be used "/a" and "/b"
|
||||
then to find the /b/b2 match, the router has to do only
|
||||
/a /b /b/b1 and /b/b2 i.e: 4 checks
|
||||
instead of /a/a1 /a/a2 /a/a3 /a/a4 /b/b1 /b/b2: i.e: 6 checks
|
||||
On router with deep arborescence this could be significant
|
||||
]"
|
||||
description: "Summary description for {WSF_ROUTING_HANDLER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_ROUTING_HANDLER [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_ROUTING_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_HANDLER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_with_router (a_router: like router)
|
||||
do
|
||||
router := a_router
|
||||
end
|
||||
|
||||
make (n: INTEGER)
|
||||
do
|
||||
make_with_router (create {WSF_ROUTER}.make (n))
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
router: WSF_ROUTER
|
||||
|
||||
feature -- Access
|
||||
|
||||
@@ -55,51 +52,16 @@ feature -- Element change
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
local
|
||||
r: detachable WSF_ROUTE [H, C]
|
||||
do
|
||||
r := router.route (req)
|
||||
if r = Void then
|
||||
res.put_header ({HTTP_STATUS_CODE}.not_found, <<[{HTTP_HEADER_NAMES}.header_content_length, "0"]>>)
|
||||
if attached router.dispatch_and_return_handler (req, res) as h then
|
||||
check is_dispatched: router.is_dispatched end
|
||||
else
|
||||
router.execute_route (r, req, res)
|
||||
res.put_header ({HTTP_STATUS_CODE}.not_found, <<[{HTTP_HEADER_NAMES}.header_content_length, "0"]>>)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Routing
|
||||
|
||||
router: WSF_ROUTER [H, C]
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Mapping
|
||||
|
||||
map (a_resource: READABLE_STRING_8; h: H)
|
||||
-- Map handler `h' with `a_resource'
|
||||
do
|
||||
router.map (a_resource, h)
|
||||
end
|
||||
|
||||
map_with_request_methods (a_resource: READABLE_STRING_8; h: H;
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
-- Map handler `h' with `a_resource' and `rqst_methods'
|
||||
do
|
||||
router.map_with_request_methods (a_resource, h, rqst_methods)
|
||||
end
|
||||
|
||||
map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]])
|
||||
do
|
||||
router.map_agent (a_resource, a_action)
|
||||
end
|
||||
|
||||
map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]];
|
||||
rqst_methods: detachable WSF_ROUTER_METHODS)
|
||||
do
|
||||
router.map_agent_with_request_methods (a_resource, a_action, rqst_methods)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -8,19 +8,19 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_FILTER_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_FILTER_HANDLER [H -> WSF_HANDLER]
|
||||
|
||||
inherit
|
||||
WSF_HANDLER [C]
|
||||
WSF_HANDLER
|
||||
|
||||
feature -- Access
|
||||
|
||||
next: detachable WSF_FILTER_HANDLER [C]
|
||||
-- Next filter
|
||||
next: detachable H
|
||||
-- Next handler
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_next (a_next: WSF_FILTER_HANDLER [C])
|
||||
set_next (a_next: like next)
|
||||
-- Set `next' to `a_next'
|
||||
do
|
||||
next := a_next
|
||||
@@ -28,16 +28,6 @@ feature -- Element change
|
||||
next_set: next = a_next
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
execute_next (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the `next' filter.
|
||||
do
|
||||
if attached next as n then
|
||||
n.execute (ctx, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
34
library/server/wsf/src/filter/wsf_filter_uri_handler.e
Normal file
34
library/server/wsf/src/filter/wsf_filter_uri_handler.e
Normal file
@@ -0,0 +1,34 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_FILTER_URI_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_FILTER_HANDLER [WSF_URI_HANDLER]
|
||||
|
||||
WSF_URI_HANDLER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_next (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
if attached next as n then
|
||||
n.execute (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -0,0 +1,34 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_FILTER_URI_TEMPLATE_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_FILTER_HANDLER [WSF_URI_TEMPLATE_HANDLER]
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_next (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
if attached next as n then
|
||||
n.execute (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -1,11 +1,11 @@
|
||||
note
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_FILTERED_SERVICE}."
|
||||
description: "Summary description for {WSF_FILTERED_SERVICE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_URI_TEMPLATE_FILTERED_SERVICE
|
||||
WSF_FILTERED_SERVICE
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
@@ -5,7 +5,7 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_ROUTING_FILTER [H -> WSF_HANDLER [C], C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_ROUTING_FILTER
|
||||
|
||||
inherit
|
||||
WSF_FILTER
|
||||
@@ -15,7 +15,7 @@ create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_router: WSF_ROUTER [H, C])
|
||||
make (a_router: WSF_ROUTER)
|
||||
do
|
||||
router := a_router
|
||||
ensure
|
||||
@@ -24,7 +24,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
router: WSF_ROUTER [H, C]
|
||||
router: WSF_ROUTER
|
||||
-- Router
|
||||
|
||||
execute_default_action: detachable PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]
|
||||
@@ -45,8 +45,8 @@ feature -- Basic operations
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter
|
||||
do
|
||||
if attached router.route (req) as r then
|
||||
router.execute_route (r, req, res)
|
||||
if attached router.dispatch_and_return_handler (req, res) then
|
||||
check router.is_dispatched end
|
||||
else
|
||||
execute_default (req, res)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
note
|
||||
description: "Summary description for {WSF_REQUEST_PATH_PARAMETERS_PROVIDER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_REQUEST_PATH_PARAMETERS_PROVIDER
|
||||
|
||||
inherit
|
||||
WSF_REQUEST_PATH_PARAMETERS_SOURCE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (nb: INTEGER; a_urlencoded_path_parameters: like urlencoded_path_parameters)
|
||||
do
|
||||
path_parameters_count := nb
|
||||
urlencoded_path_parameters := a_urlencoded_path_parameters
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
path_parameters_count: INTEGER
|
||||
|
||||
urlencoded_path_parameters: TABLE_ITERABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
-- Raw urlencoded path parameters.
|
||||
|
||||
feature -- Operation
|
||||
|
||||
previous_path_parameters_source: detachable WSF_REQUEST_PATH_PARAMETERS_SOURCE
|
||||
|
||||
apply (req: WSF_REQUEST)
|
||||
-- <Precursor>
|
||||
do
|
||||
previous_path_parameters_source := req.path_parameters_source
|
||||
req.set_path_parameters_source (Current)
|
||||
end
|
||||
|
||||
revert (req: WSF_REQUEST)
|
||||
-- <Precursor>
|
||||
do
|
||||
req.set_path_parameters_source (previous_path_parameters_source)
|
||||
previous_path_parameters_source := Void
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
112
library/server/wsf_extension/src/wsf_request_utility.e
Normal file
112
library/server/wsf_extension/src/wsf_request_utility.e
Normal file
@@ -0,0 +1,112 @@
|
||||
note
|
||||
description: "Summary description for {WSF_REQUEST_UTILITY}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_REQUEST_UTILITY
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
WSF_FORMAT_UTILITY
|
||||
export
|
||||
{NONE} all
|
||||
end
|
||||
|
||||
WSF_VALUE_UTILITY
|
||||
|
||||
feature -- Url Query
|
||||
|
||||
script_absolute_url (req: WSF_REQUEST; a_path: STRING): STRING
|
||||
-- Absolute Url for the script if any, extended by `a_path'
|
||||
do
|
||||
Result := req.absolute_script_url (a_path)
|
||||
end
|
||||
|
||||
script_url (req: WSF_REQUEST; a_path: STRING): STRING
|
||||
-- Url relative to script name if any, extended by `a_path'
|
||||
require
|
||||
a_path_attached: a_path /= Void
|
||||
do
|
||||
Result := req.script_url (a_path)
|
||||
end
|
||||
|
||||
url (req: WSF_REQUEST; a_path: STRING; args: detachable STRING; abs: BOOLEAN): STRING
|
||||
-- Associated url based on `path' and `args'
|
||||
-- if `abs' then return absolute url
|
||||
local
|
||||
s,t: detachable STRING
|
||||
do
|
||||
s := args
|
||||
if s /= Void and then s.count > 0 then
|
||||
create t.make_from_string (a_path)
|
||||
if s[1] /= '/' and t[t.count] /= '/' then
|
||||
t.append_character ('/')
|
||||
t.append (s)
|
||||
else
|
||||
t.append (s)
|
||||
end
|
||||
s := t
|
||||
else
|
||||
s := a_path
|
||||
end
|
||||
if abs then
|
||||
Result := script_absolute_url (req, s)
|
||||
else
|
||||
Result := script_url (req, s)
|
||||
end
|
||||
ensure
|
||||
result_attached: Result /= Void
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
request_accepted_content_type (req: WSF_REQUEST; a_supported_content_types: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8
|
||||
-- Accepted content-type for the request, among the supported content types `a_supported_content_types'
|
||||
local
|
||||
s: detachable READABLE_STRING_8
|
||||
i,n: INTEGER
|
||||
do
|
||||
if
|
||||
attached accepted_content_types (req) as l_accept_lst and then
|
||||
not l_accept_lst.is_empty
|
||||
then
|
||||
from
|
||||
l_accept_lst.start
|
||||
until
|
||||
l_accept_lst.after or Result /= Void
|
||||
loop
|
||||
s := l_accept_lst.item
|
||||
if a_supported_content_types /= Void then
|
||||
from
|
||||
i := a_supported_content_types.lower
|
||||
n := a_supported_content_types.upper
|
||||
until
|
||||
i > n or Result /= Void
|
||||
loop
|
||||
if a_supported_content_types [i].same_string (s) then
|
||||
Result := s
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result := s
|
||||
end
|
||||
l_accept_lst.forth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -5,160 +5,160 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_RESOURCE_HANDLER_HELPER [C -> WSF_HANDLER_CONTEXT]
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
|
||||
feature -- Execute template
|
||||
|
||||
execute_methods (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_methods (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request and dispatch according to the request method
|
||||
local
|
||||
m: READABLE_STRING_8
|
||||
do
|
||||
m := req.request_method.as_upper
|
||||
if m.same_string ({HTTP_REQUEST_METHODS}.method_get) then
|
||||
execute_get (ctx, req, res)
|
||||
execute_get (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_put) then
|
||||
execute_put (ctx, req, res)
|
||||
execute_put (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_delete) then
|
||||
execute_delete (ctx, req, res)
|
||||
execute_delete (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_post) then
|
||||
execute_post (ctx, req, res)
|
||||
execute_post (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_trace) then
|
||||
execute_trace (ctx, req, res)
|
||||
execute_trace (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_options) then
|
||||
execute_options (ctx, req, res)
|
||||
execute_options (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_head) then
|
||||
execute_head (ctx, req, res)
|
||||
execute_head (req, res)
|
||||
elseif m.same_string ({HTTP_REQUEST_METHODS}.method_connect) then
|
||||
execute_connect (ctx, req, res)
|
||||
execute_connect (req, res)
|
||||
else
|
||||
--| Eventually handle other methods...
|
||||
execute_extension_method (ctx, req, res)
|
||||
execute_extension_method (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Method Post
|
||||
|
||||
execute_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_post (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
if req.is_chunked_input then
|
||||
do_post (ctx, req, res)
|
||||
do_post (req, res)
|
||||
else
|
||||
if req.content_length_value > 0 then
|
||||
do_post (ctx, req, res)
|
||||
do_post (req, res)
|
||||
else
|
||||
handle_bad_request_response ("Bad request, content_length empty", ctx, req, res)
|
||||
handle_bad_request_response ("Bad request, content_length empty", req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method POST not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method POST not implemented", req, res)
|
||||
end
|
||||
|
||||
feature-- Method Put
|
||||
|
||||
execute_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_put (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
if req.is_chunked_input then
|
||||
do_put (ctx, req, res)
|
||||
do_put (req, res)
|
||||
else
|
||||
if req.content_length_value > 0 then
|
||||
do_put (ctx, req, res)
|
||||
do_put (req, res)
|
||||
else
|
||||
handle_bad_request_response ("Bad request, content_length empty", ctx, req, res)
|
||||
handle_bad_request_response ("Bad request, content_length empty", req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_put (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method PUT not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method PUT not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method Get
|
||||
|
||||
execute_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_get (ctx, req, res)
|
||||
do_get (req, res)
|
||||
end
|
||||
|
||||
do_get (ctx: C;req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method GET not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method GET not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method DELETE
|
||||
|
||||
execute_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_delete (ctx, req, res)
|
||||
do_delete (req, res)
|
||||
end
|
||||
|
||||
do_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method DELETE not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method DELETE not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method CONNECT
|
||||
|
||||
execute_connect (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_connect (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_connect (ctx, req, res)
|
||||
do_connect (req, res)
|
||||
end
|
||||
|
||||
do_connect (ctx: C;req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_connect (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method CONNECT not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method CONNECT not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method HEAD
|
||||
|
||||
execute_head (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_head (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_head (ctx, req, res)
|
||||
do_head (req, res)
|
||||
end
|
||||
|
||||
do_head (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_head (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method HEAD not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method HEAD not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method OPTIONS
|
||||
|
||||
execute_options (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_options (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_options (ctx, req, res)
|
||||
do_options (req, res)
|
||||
end
|
||||
|
||||
do_options (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_options (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method OPTIONS not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method OPTIONS not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method TRACE
|
||||
|
||||
execute_trace (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_trace (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_trace (ctx, req, res)
|
||||
do_trace (req, res)
|
||||
end
|
||||
|
||||
do_trace (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_trace (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method TRACE not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method TRACE not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Method Extension Method
|
||||
|
||||
execute_extension_method (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_extension_method (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
do_extension_method (ctx, req, res)
|
||||
do_extension_method (req, res)
|
||||
end
|
||||
|
||||
do_extension_method (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_extension_method (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
handle_not_implemented ("Method extension-method not implemented", ctx, req, res)
|
||||
handle_not_implemented ("Method extension-method not implemented", req, res)
|
||||
end
|
||||
|
||||
feature -- Retrieve content from WGI_INPUT_STREAM
|
||||
@@ -208,7 +208,7 @@ feature -- Handle responses
|
||||
Result := Void
|
||||
end
|
||||
|
||||
handle_bad_request_response (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
handle_bad_request_response (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -221,7 +221,7 @@ feature -- Handle responses
|
||||
res.put_string (a_description)
|
||||
end
|
||||
|
||||
handle_precondition_fail_response (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
handle_precondition_fail_response (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -234,7 +234,7 @@ feature -- Handle responses
|
||||
res.put_string (a_description)
|
||||
end
|
||||
|
||||
handle_internal_server_error (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
handle_internal_server_error (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -247,7 +247,7 @@ feature -- Handle responses
|
||||
res.put_string (a_description)
|
||||
end
|
||||
|
||||
handle_not_implemented (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
handle_not_implemented (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE )
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -260,7 +260,7 @@ feature -- Handle responses
|
||||
res.put_string (a_description)
|
||||
end
|
||||
|
||||
handle_method_not_allowed_response (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
handle_method_not_allowed_response (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -273,7 +273,7 @@ feature -- Handle responses
|
||||
res.put_string (a_description)
|
||||
end
|
||||
|
||||
handle_resource_not_found_response (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
handle_resource_not_found_response (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -287,7 +287,7 @@ feature -- Handle responses
|
||||
end
|
||||
|
||||
|
||||
handle_resource_not_modified_response (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
handle_resource_not_modified_response (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
@@ -302,7 +302,7 @@ feature -- Handle responses
|
||||
end
|
||||
|
||||
|
||||
handle_resource_conflict_response (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
handle_resource_conflict_response (a_description: STRING; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
|
||||
156
library/server/wsf_extension/src/wsf_value_utility.e
Normal file
156
library/server/wsf_extension/src/wsf_value_utility.e
Normal file
@@ -0,0 +1,156 @@
|
||||
note
|
||||
description: "Summary description for {WSF_VALUE_UTILITY}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_VALUE_UTILITY
|
||||
|
||||
feature -- Parameter
|
||||
|
||||
item (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Variable value for parameter or variable `a_name'
|
||||
-- See `{WSF_REQUEST}.item(s)'
|
||||
do
|
||||
Result := req.item (a_name)
|
||||
end
|
||||
|
||||
string_item (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- String value for any variable of parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_from (item (req, a_name))
|
||||
end
|
||||
|
||||
string_array_item (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for query parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_array_for (req, a_name, agent string_item)
|
||||
end
|
||||
|
||||
feature -- Query parameter
|
||||
|
||||
query_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Parameter value for query variable `a_name'
|
||||
--| i.e after the ? character
|
||||
do
|
||||
Result := req.query_parameter (a_name)
|
||||
end
|
||||
|
||||
string_query_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- String value for query parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_from (query_parameter (req, a_name))
|
||||
end
|
||||
|
||||
string_array_query_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for query parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_array_for (req, a_name, agent string_query_parameter)
|
||||
end
|
||||
|
||||
is_integer_query_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Is query parameter related to `a_name' an integer value?
|
||||
do
|
||||
Result := attached string_query_parameter (req, a_name) as s and then s.is_integer
|
||||
end
|
||||
|
||||
integer_query_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): INTEGER
|
||||
-- Integer value for query parameter `a_name' if relevant.
|
||||
require
|
||||
is_integer_query_parameter: is_integer_query_parameter (req, a_name)
|
||||
do
|
||||
Result := integer_from (query_parameter (req, a_name))
|
||||
end
|
||||
|
||||
feature -- Path parameter
|
||||
|
||||
path_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
do
|
||||
Result := req.path_parameter (a_name)
|
||||
end
|
||||
|
||||
|
||||
string_path_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- String value for path parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_from (path_parameter (req, a_name))
|
||||
end
|
||||
|
||||
string_array_path_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for path parameter `a_name' if relevant.
|
||||
do
|
||||
Result := string_array_for (req, a_name, agent string_path_parameter)
|
||||
end
|
||||
|
||||
is_integer_path_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Is path parameter related to `a_name' an integer value?
|
||||
do
|
||||
Result := attached string_path_parameter (req, a_name) as s and then s.is_integer
|
||||
end
|
||||
|
||||
integer_path_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): INTEGER
|
||||
-- Integer value for path parameter `a_name' if relevant.
|
||||
require
|
||||
is_integer_path_parameter: is_integer_path_parameter (req, a_name)
|
||||
do
|
||||
Result := integer_from (path_parameter (req, a_name))
|
||||
end
|
||||
|
||||
feature -- Convertion
|
||||
|
||||
string_from (a_value: detachable WSF_VALUE): detachable READABLE_STRING_32
|
||||
-- String value from `a_value' if relevant.
|
||||
do
|
||||
if attached {WSF_STRING} a_value as val then
|
||||
Result := val.value
|
||||
end
|
||||
end
|
||||
|
||||
integer_from (a_value: detachable WSF_VALUE): INTEGER
|
||||
-- String value from `a_value' if relevant.
|
||||
do
|
||||
if attached string_from (a_value) as val then
|
||||
if val.is_integer then
|
||||
Result := val.to_integer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
string_array_for (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_item_fct: FUNCTION [ANY, TUPLE [WSF_REQUEST, READABLE_STRING_GENERAL], detachable READABLE_STRING_32]): detachable ARRAY [READABLE_STRING_32]
|
||||
-- Array of string values for query parameter `a_name' if relevant.
|
||||
local
|
||||
i: INTEGER
|
||||
n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := 1
|
||||
create Result.make_filled ("", 1, 5)
|
||||
until
|
||||
i = 0
|
||||
loop
|
||||
if attached a_item_fct.item ([req, a_name + "[" + i.out + "]"]) as v then
|
||||
Result.force (v, n)
|
||||
n := n + 1
|
||||
i := i + 1
|
||||
else
|
||||
i := 0 -- Exit
|
||||
end
|
||||
end
|
||||
Result.keep_head (n - 1)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -27,7 +27,7 @@ feature {NONE} -- Initialization
|
||||
setup_router
|
||||
do
|
||||
-- Set the router here
|
||||
router.map_agent ("/hello/{user}", agent execute_hello)
|
||||
map_uri_template_agent ("/hello/{user}", agent execute_hello)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
@@ -43,7 +43,7 @@ feature -- Execution
|
||||
res.redirect_now_with_content (l_url, "Redirection to " + l_url, "text/html")
|
||||
end
|
||||
|
||||
execute_hello (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Computed response message.
|
||||
local
|
||||
mesg: WSF_HTML_PAGE_RESPONSE
|
||||
|
||||
Reference in New Issue
Block a user