diff --git a/library/server/wsf/router/context/wsf_router_context_mapping.e b/library/server/wsf/router/context/wsf_router_context_mapping.e index afc38f1e..92c1f23f 100644 --- a/library/server/wsf/router/context/wsf_router_context_mapping.e +++ b/library/server/wsf/router/context/wsf_router_context_mapping.e @@ -9,6 +9,9 @@ deferred class inherit WSF_ROUTER_MAPPING + redefine + debug_output + end feature -- Access @@ -17,6 +20,14 @@ feature -- Access deferred end +feature -- Status report + + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := Precursor + " {" + {C}.name + "}" + end + note copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e b/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e index fb707b90..2fc99843 100644 --- a/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e +++ b/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e @@ -195,7 +195,6 @@ feature {WSF_RESPONSE} -- Output local l_url: detachable STRING_8 l_base_url: detachable READABLE_STRING_8 - hdl: WSF_HANDLER l_doc: detachable WSF_ROUTER_MAPPING_DOCUMENTATION do if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} m as l_doc_mapping then diff --git a/library/server/wsf/router/wsf_router.e b/library/server/wsf/router/wsf_router.e index dda16aa0..c47f03f3 100644 --- a/library/server/wsf/router/wsf_router.e +++ b/library/server/wsf/router/wsf_router.e @@ -1,6 +1,10 @@ note - description: "Summary description for {EWF_ROUTER}." - author: "" + description: "[ + URL dispatching of request + + Map a route to an handler according to the request method and path + + ]" date: "$Date$" revision: "$Revision$" @@ -10,6 +14,8 @@ class inherit ITERABLE [WSF_ROUTER_ITEM] + WSF_REQUEST_EXPORTER + create make, make_with_base_url @@ -53,6 +59,17 @@ feature -- Mapping map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_ROUTER_METHODS) -- Map `a_mapping' for request methods `rqst_methods' do + debug ("router") + -- Display conflict in mapping + if has_item_associated_with_resource (a_mapping.associated_resource, rqst_methods) then + io.error.put_string ("Mapping: " + a_mapping.debug_output + ": conflict with existing mapping") + if attached item_associated_with_resource (a_mapping.associated_resource, rqst_methods) as l_conflicted then + io.error.put_string (": " + l_conflicted.debug_output) + end + io.error.put_string ("%N") + end + end + mappings.extend (create {WSF_ROUTER_ITEM}.make_with_request_methods (a_mapping, rqst_methods)) a_mapping.handler.on_mapped (a_mapping, rqst_methods) end @@ -92,10 +109,28 @@ feature -- Access -- And return the associated handler if mapping found and handler executed. local l_req_method: READABLE_STRING_8 + head_res: WSF_HEAD_RESPONSE_WRAPPER + do + l_req_method := request_method (req) + is_dispatched := False + Result := dispatch_and_return_handler_for_request_method (req, res, l_req_method) + if Result = Void and l_req_method = {HTTP_REQUEST_METHODS}.method_head then + check is_not_dispatched: not is_dispatched end + create head_res.make_from_response (res) + req.set_request_method ({HTTP_REQUEST_METHODS}.method_GET) + Result := dispatch_and_return_handler_for_request_method (req, head_res, {HTTP_REQUEST_METHODS}.method_GET) + end + end + +feature {NONE} -- Dispatch implementation + + dispatch_and_return_handler_for_request_method (req: WSF_REQUEST; res: WSF_RESPONSE; a_request_method: READABLE_STRING_8): detachable WSF_HANDLER + -- Dispatch request `req' among the `mappings' + -- And return the associated handler if mapping found and handler executed. + local m: WSF_ROUTER_MAPPING do is_dispatched := False - l_req_method := request_method (req) across mappings as c @@ -103,7 +138,7 @@ feature -- Access Result /= Void loop if attached c.item as l_info then - if is_matching_request_methods (l_req_method, l_info.request_methods) then + if is_matching_request_methods (a_request_method, l_info.request_methods) then m := l_info.mapping if attached m.routed_handler (req, res, Current) as r then is_dispatched := True diff --git a/library/server/wsf/router/wsf_router_item.e b/library/server/wsf/router/wsf_router_item.e index 77e3ae04..7978fbd1 100644 --- a/library/server/wsf/router/wsf_router_item.e +++ b/library/server/wsf/router/wsf_router_item.e @@ -1,6 +1,11 @@ note - description: "Summary description for {WSF_ROUTER_ITEM}." - author: "" + description: "[ + Entry of WSF_ROUTER + It contains + - mapping + - request methods + + ]" date: "$Date$" revision: "$Revision$" @@ -38,11 +43,7 @@ feature -- Status report debug_output: STRING -- String that should be displayed in debugger to represent `Current'. do - if attached {DEBUG_OUTPUT} mapping as d then - create Result.make_from_string (d.debug_output) - else - create Result.make_from_string (mapping.generator) - end + create Result.make_from_string (mapping.debug_output) if attached request_methods as mtds then Result.append_string (" [ ") across @@ -66,4 +67,15 @@ feature -- Change invariant mapping_attached: mapping /= Void +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + end diff --git a/library/server/wsf/src/wsf_head_response_wrapper.e b/library/server/wsf/src/wsf_head_response_wrapper.e new file mode 100644 index 00000000..4575b317 --- /dev/null +++ b/library/server/wsf/src/wsf_head_response_wrapper.e @@ -0,0 +1,81 @@ +note + description: "[ + This class is a wrapper on a standard WSF_RESPONSE + It is used to compute a HEAD request based on a GET request method handling + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_HEAD_RESPONSE_WRAPPER + +inherit + WSF_RESPONSE + redefine + put_character, + put_string, + put_substring, + put_chunk, + put_chunk_end + end + + WSF_RESPONSE_EXPORTER + +create + make_from_response + +feature {NONE} -- Initialization + + make_from_response (res: WSF_RESPONSE) + do + wsf_response := res + make_from_wgi (res.wgi_response) + end + +feature {WSF_RESPONSE} -- Access + + wsf_response: WSF_RESPONSE + -- Wrapped response + +feature -- Output operation + + put_character (c: CHARACTER_8) + do + -- HEAD has no content + end + + put_string (s: READABLE_STRING_8) + do + -- HEAD has no content + end + + put_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER) + do + -- HEAD has no content + end + + put_chunk (s: READABLE_STRING_8; a_extension: detachable READABLE_STRING_8) + do + -- HEAD has no content + end + + put_chunk_end + do + -- HEAD has no content + end + +invariant + transfered_content_length_is_zero: transfered_content_length = 0 + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index 67820eee..ad31a9dc 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -39,6 +39,7 @@ feature {NONE} -- Initialization tb: like meta_variables_table do wgi_request := r + create string_equality_tester if attached r.meta_variables as l_vars then create tb.make_with_key_tester (l_vars.count, string_equality_tester) @@ -55,21 +56,26 @@ feature {NONE} -- Initialization create error_handler.make create uploaded_files_table.make_with_key_tester (0, string_equality_tester) set_raw_input_data_recorded (False) - create {STRING_32} empty_string.make_empty + create {IMMUTABLE_STRING_32} empty_string.make_empty create execution_variables_table.make_with_key_tester (0, string_equality_tester) execution_variables_table.compare_objects initialize analyze + ensure + wgi_request_set: wgi_request = r + request_method_set: request_method.same_string (r.request_method) end initialize -- Specific initialization local s8: detachable READABLE_STRING_8 + req: WGI_REQUEST do init_mime_handlers + req := wgi_request --| Content-Length if attached content_length as s and then s.is_natural_64 then @@ -79,18 +85,21 @@ feature {NONE} -- Initialization end -- Content-Type - s8 := wgi_request.content_type + s8 := req.content_type if s8 /= Void then create content_type.make_from_string (s8) else content_type := Void end + --| Request Methods + request_method := req.request_method + --| PATH_INFO - path_info := raw_url_encoder.decoded_string (wgi_request.path_info) + path_info := raw_url_encoder.decoded_string (req.path_info) --| PATH_TRANSLATED - s8 := wgi_request.path_translated + s8 := req.path_translated if s8 /= Void then path_translated := raw_url_encoder.decoded_string (s8) end @@ -211,6 +220,15 @@ feature -- Eiffel WGI access Result := wgi_request.wgi_connector end +feature {WSF_REQUEST_EXPORTER} -- Override value + + set_request_method (a_request_method: like request_method) + -- Set `request_method' to `a_request_method' + -- note: this is mainly to have smart handling of HEAD request + do + request_method := a_request_method + end + feature {NONE} -- Access: global variable items_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] @@ -679,9 +697,6 @@ feature -- Access: CGI meta parameters - 1.1 -- This variable is specific to requests made with HTTP. -- -- Servers MUST provide this metavariable to scripts. - do - Result := wgi_request.request_method - end script_name: READABLE_STRING_8 -- The SCRIPT_NAME metavariable is set to a URL path that could diff --git a/library/server/wsf/src/wsf_request_exporter.e b/library/server/wsf/src/wsf_request_exporter.e new file mode 100644 index 00000000..bd64e63d --- /dev/null +++ b/library/server/wsf/src/wsf_request_exporter.e @@ -0,0 +1,20 @@ +note + description: "Objects that can access low level features of {WSF_REQUEST}" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_REQUEST_EXPORTER + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end + diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e index 51b703dc..0a53da00 100644 --- a/library/server/wsf/src/wsf_response.e +++ b/library/server/wsf/src/wsf_response.e @@ -31,6 +31,8 @@ feature {NONE} -- Initialization wgi_response := r end +feature {WSF_RESPONSE_EXPORTER} -- Properties + wgi_response: WGI_RESPONSE -- Associated WGI_RESPONSE diff --git a/library/server/wsf/src/wsf_response_exporter.e b/library/server/wsf/src/wsf_response_exporter.e new file mode 100644 index 00000000..a75c81f9 --- /dev/null +++ b/library/server/wsf/src/wsf_response_exporter.e @@ -0,0 +1,19 @@ +note + description: "Objects that can access low level features of {WSF_RESPONSE}" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_RESPONSE_EXPORTER + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end