diff --git a/examples/upload_image/src/image_uploader.e b/examples/upload_image/src/image_uploader.e
index 02bbbd69..06f1037d 100644
--- a/examples/upload_image/src/image_uploader.e
+++ b/examples/upload_image/src/image_uploader.e
@@ -10,16 +10,7 @@ class
inherit
ANY
- WSF_ROUTED_SKELETON_SERVICE
- undefine
- requires_proxy
- end
-
- WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE
-
- WSF_NO_PROXY_POLICY
-
- WSF_DEFAULT_SERVICE
+ WSF_DEFAULT_SERVICE [IMAGE_UPLOADER_EXECUTION]
SHARED_EXECUTION_ENVIRONMENT
@@ -31,224 +22,12 @@ feature {NONE} -- Initialization
make
-- Initialize Current
do
- initialize_router
-
-
-- To use particular port number (as 9090) with Nino connector
-- Uncomment the following line
set_service_option ("port", 9090)
make_and_launch
end
- setup_router
- -- Setup router
- local
- www: WSF_FILE_SYSTEM_HANDLER
- do
- map_uri_template_agent_with_request_methods ("/upload/{name}{?nb}", agent execute_upload_put, router.methods_put)
- map_uri_template_agent ("/upload{?nb}", agent execute_upload)
-
- create www.make_with_path (document_root)
- www.set_directory_index (<<"index.html">>)
- www.set_not_found_handler (agent execute_not_found)
- router.handle_with_request_methods ("", www, router.methods_GET)
- end
-
-feature -- Configuration
-
- document_root: PATH
- -- Document root to look for files or directories
- once
- Result := execution_environment.current_working_path.extended ("htdocs")
- ensure
- not Result.name.ends_with (Operating_environment.directory_separator.out)
- end
-
- files_root: PATH
- -- Uploaded files will be stored in `files_root' folder
- once
- Result := document_root.extended ("files")
- end
-
-feature -- Execution
-
- 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 (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
- local
- l_body: STRING_8
- l_safe_filename: STRING_8
- fn: PATH
- page: WSF_HTML_PAGE_RESPONSE
- n: INTEGER
- do
- if req.is_request_method ("GET") or else not req.has_uploaded_file then
- create page.make
- page.set_title ("EWF: Upload file")
- page.add_style (req.script_url ("style.css"), "all")
- create l_body.make_empty
- page.set_body (l_body)
- l_body.append ("
EWF: Upload image file
%N")
- l_body.append ("")
- res.send (page)
- else
- create l_body.make (255)
- l_body.append ("EWF: Uploaded files
%N")
- l_body.append ("")
-
- create page.make
- page.set_title ("EWF: uploaded image")
- page.add_style ("../style.css", "all")
- page.set_body (l_body)
- res.send (page)
- end
- end
-
- execute_upload_put (req: WSF_REQUEST; res: WSF_RESPONSE)
- -- Upload page is requested, PUT
- require
- is_put_request_method: req.is_put_request_method
- local
- l_body: STRING_8
- l_safe_filename: detachable READABLE_STRING_32
- fn: PATH
- page: WSF_HTML_PAGE_RESPONSE
- n: INTEGER
- do
- create l_body.make (255)
- l_body.append ("EWF: Uploaded files
%N")
- l_body.append ("")
-
- create page.make
- page.set_title ("EWF: uploaded image")
- page.add_style ("../style.css", "all")
- page.set_body (l_body)
- res.send (page)
- end
-
-
-feature {NONE} -- Encoder
-
- new_temporary_output_file (n: detachable READABLE_STRING_8): detachable FILE
- local
- bp: detachable PATH
- d: DIRECTORY
- i: INTEGER
- do
- create bp.make_current
- create d.make_with_path (bp)
- if not d.exists then
- d.recursive_create_dir
- end
- if n /= Void then
- bp := bp.extended ("tmp-download-" + n)
- else
- bp := bp.extended ("tmp")
- end
- from
- i := 0
- until
- Result /= Void or i > 100
- loop
- i := i + 1
- create {RAW_FILE} Result.make_with_path (bp.appended ("__" + i.out))
- if Result.exists then
- Result := Void
- else
- Result.open_write
- end
- end
- ensure
- Result /= Void implies Result.is_open_write
- end
-
- url_encode (s: READABLE_STRING_32): STRING_8
- -- URL Encode `s' as Result
- do
- Result := url_encoder.encoded_string (s)
- end
-
- url_encoder: URL_ENCODER
- once
- create Result
- end
-
- html_encode (s: READABLE_STRING_32): STRING_8
- -- HTML Encode `s' as Result
- do
- Result := html_encoder.encoded_string (s)
- end
-
- html_encoder: HTML_ENCODER
- once
- create Result
- end
-
note
copyright: "2011-2012, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
diff --git a/examples/upload_image/src/image_uploader_execution.e b/examples/upload_image/src/image_uploader_execution.e
new file mode 100644
index 00000000..84f51c87
--- /dev/null
+++ b/examples/upload_image/src/image_uploader_execution.e
@@ -0,0 +1,261 @@
+note
+ description: "Summary description for {IMAGE_UPLOADER_EXECUTION}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ IMAGE_UPLOADER_EXECUTION
+
+inherit
+ WSF_EXECUTION
+ redefine
+ initialize
+ end
+
+ WSF_ROUTED_SKELETON_EXECUTION
+ undefine
+ requires_proxy
+ end
+
+ WSF_NO_PROXY_POLICY
+
+ WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ initialize
+ do
+ Precursor
+ initialize_router
+ end
+
+ setup_router
+ -- Setup router
+ local
+ www: WSF_FILE_SYSTEM_HANDLER
+ do
+ map_uri_template_agent_with_request_methods ("/upload/{name}{?nb}", agent execute_upload_put, router.methods_put)
+ 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.handle_with_request_methods ("", www, router.methods_GET)
+ end
+
+feature -- Configuration
+
+ document_root: READABLE_STRING_8
+ -- Document root to look for files or directories
+ local
+ e: EXECUTION_ENVIRONMENT
+ dn: DIRECTORY_NAME
+ once
+ create e
+ create dn.make_from_string (e.current_working_directory)
+ dn.extend ("htdocs")
+ Result := dn.string
+ 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
+ -- Uploaded files will be stored in `files_root' folder
+ local
+ dn: DIRECTORY_NAME
+ once
+ create dn.make_from_string (document_root)
+ dn.extend ("files")
+ Result := dn.string
+ end
+
+feature -- Execution
+
+ 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 (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
+ local
+ l_body: STRING_8
+ l_safe_filename: STRING_8
+ fn: PATH
+ page: WSF_HTML_PAGE_RESPONSE
+ n: INTEGER
+ do
+ if req.is_request_method ("GET") or else not req.has_uploaded_file then
+ create page.make
+ page.set_title ("EWF: Upload file")
+ page.add_style (req.script_url ("style.css"), "all")
+ create l_body.make_empty
+ page.set_body (l_body)
+ l_body.append ("EWF: Upload image file
%N")
+ l_body.append ("")
+ res.send (page)
+ else
+ create l_body.make (255)
+ l_body.append ("EWF: Uploaded files
%N")
+ l_body.append ("")
+
+ create page.make
+ page.set_title ("EWF: uploaded image")
+ page.add_style ("../style.css", "all")
+ page.set_body (l_body)
+ res.send (page)
+ end
+ end
+
+ execute_upload_put (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Upload page is requested, PUT
+ require
+ is_put_request_method: req.is_put_request_method
+ local
+ l_body: STRING_8
+ l_safe_filename: detachable READABLE_STRING_32
+ fn: PATH
+ page: WSF_HTML_PAGE_RESPONSE
+ n: INTEGER
+ do
+ create l_body.make (255)
+ l_body.append ("EWF: Uploaded files
%N")
+ l_body.append ("")
+
+ create page.make
+ page.set_title ("EWF: uploaded image")
+ page.add_style ("../style.css", "all")
+ page.set_body (l_body)
+ res.send (page)
+ end
+
+
+feature {NONE} -- Encoder
+
+ new_temporary_output_file (n: detachable READABLE_STRING_8): detachable FILE
+ local
+ bp: detachable PATH
+ d: DIRECTORY
+ i: INTEGER
+ do
+ create bp.make_current
+ create d.make_with_path (bp)
+ if not d.exists then
+ d.recursive_create_dir
+ end
+ if n /= Void then
+ bp := bp.extended ("tmp-download-" + n)
+ else
+ bp := bp.extended ("tmp")
+ end
+ from
+ i := 0
+ until
+ Result /= Void or i > 100
+ loop
+ i := i + 1
+ create {RAW_FILE} Result.make_with_path (bp.appended ("__" + i.out))
+ if Result.exists then
+ Result := Void
+ else
+ Result.open_write
+ end
+ end
+ ensure
+ Result /= Void implies Result.is_open_write
+ end
+
+ url_encode (s: READABLE_STRING_32): STRING_8
+ -- URL Encode `s' as Result
+ do
+ Result := url_encoder.encoded_string (s)
+ end
+
+ url_encoder: URL_ENCODER
+ once
+ create Result
+ end
+
+ html_encode (s: READABLE_STRING_32): STRING_8
+ -- HTML Encode `s' as Result
+ do
+ Result := html_encoder.encoded_string (s)
+ end
+
+ html_encoder: HTML_ENCODER
+ once
+ create Result
+ end
+
+end
diff --git a/library/server/ewsgi/connectors/nino/src/nino_service.e b/library/server/ewsgi/connectors/nino/src/nino_service.e
index fd020b39..8f596a28 100644
--- a/library/server/ewsgi/connectors/nino/src/nino_service.e
+++ b/library/server/ewsgi/connectors/nino/src/nino_service.e
@@ -4,50 +4,48 @@ note
revision: "$Revision$"
class
- NINO_SERVICE
+ NINO_SERVICE [G -> WGI_EXECUTION create make end]
create
make,
- make_custom,
- make_with_callback,
- make_custom_with_callback
+ make_custom
feature {NONE} -- Implementation
- make (a_service: WGI_SERVICE)
+ make
-- Initialize `Current'.
do
- make_custom (a_service, Void)
+ make_custom (Void)
end
- make_custom (a_service: WGI_SERVICE; a_base_url: detachable STRING)
+ make_custom (a_base_url: detachable STRING)
-- Initialize `Current'.
require
base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/")
do
- create connector.make_with_base (a_service, a_base_url)
+ create connector.make_with_base (a_base_url)
end
- make_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]])
- -- Initialize `Current'.
- do
- make_custom_with_callback (a_callback, Void)
- end
+-- make_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]])
+-- -- Initialize `Current'.
+-- do
+-- make_custom_with_callback (a_callback, Void)
+-- end
- make_custom_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]; a_base_url: detachable STRING)
- -- Initialize `Current'.
- require
- base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/")
- local
- app: WGI_AGENT_SERVICE
- do
- create app.make (a_callback)
- make_custom (app, a_base_url)
- end
+-- make_custom_with_callback (a_callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE]]; a_base_url: detachable STRING)
+-- -- Initialize `Current'.
+-- require
+-- base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/")
+-- local
+-- app: WGI_AGENT_SERVICE
+-- do
+-- create app.make (a_callback)
+-- make_custom (app, a_base_url)
+-- end
feature -- Access
- connector: WGI_NINO_CONNECTOR
+ connector: WGI_NINO_CONNECTOR [G]
-- Web server connector
feature -- Status report
@@ -104,7 +102,7 @@ feature -- Server
end
note
- copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
+ copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e
index 03696fd6..7543a0df 100644
--- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e
+++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e
@@ -15,11 +15,11 @@ create
feature {NONE} -- Initialization
- make (a_service: like service)
+ make --(a_service: like service)
local
cfg: HTTP_SERVER_CONFIGURATION
do
- service := a_service
+-- service := a_service
create cfg.make
create server.make (cfg)
@@ -29,11 +29,11 @@ feature {NONE} -- Initialization
create on_stopped_actions
end
- make_with_base (a_service: like service; a_base: like base)
+ make_with_base (a_base: like base)
require
a_base_starts_with_slash: (a_base /= Void and then not a_base.is_empty) implies a_base.starts_with ("/")
do
- make (a_service)
+ make -- (a_service)
set_base (a_base)
end
@@ -45,10 +45,10 @@ feature -- Access
version: STRING_8 = "0.1"
-- Version of Current connector
-feature {NONE} -- Access
+--feature {NONE} -- Access
- service: WGI_SERVICE
- -- Gateway Service
+-- service: WGI_SERVICE
+-- -- Gateway Service
feature -- Access
@@ -139,7 +139,7 @@ feature -- Server
create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current)
create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), create {WGI_NINO_ERROR_STREAM}.make_stderr (a_socket.descriptor.out))
req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text)
-
+
create {G} exec.make (req, res)
exec.execute
res.flush
@@ -161,7 +161,7 @@ feature -- Server
end
if exec /= Void then
exec.clean
- end
+ end
end
rescue
if not retried then
@@ -171,7 +171,7 @@ feature -- Server
end
note
- copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
+ copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/ewsgi/src/wgi_execution.e b/library/server/ewsgi/specification/connector/wgi_execution.e
similarity index 100%
rename from library/server/ewsgi/src/wgi_execution.e
rename to library/server/ewsgi/specification/connector/wgi_execution.e
diff --git a/library/server/ewsgi/src/wgi_exporter.e b/library/server/ewsgi/specification/connector/wgi_exporter.e
similarity index 100%
rename from library/server/ewsgi/src/wgi_exporter.e
rename to library/server/ewsgi/specification/connector/wgi_exporter.e
diff --git a/library/server/wsf/connector/nino/wsf_nino_service_launcher.e b/library/server/wsf/connector/nino/wsf_nino_service_launcher.e
index 553f20fe..35038b09 100644
--- a/library/server/wsf/connector/nino/wsf_nino_service_launcher.e
+++ b/library/server/wsf/connector/nino/wsf_nino_service_launcher.e
@@ -67,7 +67,7 @@ feature {NONE} -- Initialization
verbose := l_verbose_str.as_lower.same_string ("true")
end
end
- create conn.make (Current)
+ create conn.make --(Current)
connector := conn
conn.on_launched_actions.extend (agent on_launched)
diff --git a/library/server/wsf/default/nino/wsf_default_response_service.e b/library/server/wsf/default/nino/wsf_default_response_service.e
index 0cefc7da..db3fddc6 100644
--- a/library/server/wsf/default/nino/wsf_default_response_service.e
+++ b/library/server/wsf/default/nino/wsf_default_response_service.e
@@ -4,15 +4,15 @@ note
revision: "$Revision$"
deferred class
- WSF_DEFAULT_RESPONSE_SERVICE
+ WSF_DEFAULT_RESPONSE_SERVICE [G -> WSF_EXECUTION create make end]
inherit
- WSF_DEFAULT_SERVICE
+ WSF_DEFAULT_SERVICE [G]
- WSF_RESPONSE_SERVICE
+ WSF_RESPONSE_SERVICE [G]
note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
+ copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e b/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e
new file mode 100644
index 00000000..7daacd25
--- /dev/null
+++ b/library/server/wsf/router/policy/service/wsf_routed_skeleton_execution.e
@@ -0,0 +1,291 @@
+note
+ description: "Summary description for {WSF_ROUTED_SKELETON_EXECUTION}."
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_ROUTED_SKELETON_EXECUTION
+
+inherit
+ WSF_ROUTED_EXECUTION
+ redefine
+ execute
+ end
+
+ WSF_SYSTEM_OPTIONS_ACCESS_POLICY
+
+ WSF_PROXY_USE_POLICY
+
+feature -- Execution
+
+ execute
+ -- If the service is available, and request URI is not too long, dispatch the request
+ -- and if handler is not found, execute the default procedure `execute_default'.
+ local
+ l_sess: WSF_ROUTER_SESSION
+ req: WSF_REQUEST; res: WSF_RESPONSE
+ do
+ req := request
+ res := response
+
+ --| When we reach here, the request has already passed check for 400 (Bad request),
+ --| which is implemented in WSF_REQUEST.make_from_wgi (when it calls `analyze').
+ if unavailable then
+ handle_unavailable (res)
+ elseif requires_proxy (req) then
+ handle_use_proxy (req, res)
+ elseif
+ maximum_uri_length > 0 and then
+ req.request_uri.count.to_natural_32 > maximum_uri_length
+ then
+ handle_request_uri_too_long (res)
+ elseif
+ req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) and then
+ req.request_uri.same_string ("*")
+ then
+ handle_server_options (req, res)
+ else
+ create l_sess
+ router.dispatch (req, res, l_sess)
+ if not l_sess.dispatched then
+ execute_default
+ end
+ end
+ end
+
+feature -- Measurement
+
+ maximum_uri_length: NATURAL
+ -- Maximum length in characters (or zero for no limit) permitted
+ -- for {WSF_REQUEST}.request_uri
+
+feature -- Status report
+
+ unavailable: BOOLEAN
+ -- Is service currently unavailable?
+
+ unavailablity_message: detachable READABLE_STRING_8
+ -- Message to be included as text of response body for {HTTP_STATUS_CODE}.service_unavailable
+
+ unavailability_duration: NATURAL
+ -- Delta seconds for service unavailability (0 if not known)
+
+ unavailable_until: detachable DATE_TIME
+ -- Time at which service becomes available again (if known)
+
+feature -- Status setting
+
+ set_available
+ -- Set `unavailable' to `False'.
+ do
+ unavailable := False
+ unavailablity_message := Void
+ unavailable_until := Void
+ ensure
+ available: unavailable = False
+ unavailablity_message_detached: unavailablity_message = Void
+ unavailable_until_detached: unavailable_until = Void
+ end
+
+ set_unavailable (a_message: READABLE_STRING_8; a_duration: NATURAL; a_until: detachable DATE_TIME)
+ -- Set `unavailable' to `True'.
+ require
+ a_message_attached: a_message /= Void
+ a_duration_xor_a_until: a_duration > 0 implies a_until = Void
+ do
+ unavailable := True
+ unavailablity_message := a_message
+ unavailability_duration := a_duration
+ ensure
+ unavailable: unavailable = True
+ unavailablity_message_aliased: unavailablity_message = a_message
+ unavailability_duration_set: unavailability_duration = a_duration
+ unavailable_until_aliased: unavailable_until = a_until
+ end
+
+ set_maximum_uri_length (a_len: NATURAL)
+ -- Set `maximum_uri_length' to `a_len'.
+ -- Can pass zero to mean no restrictions.
+ do
+ maximum_uri_length := a_len
+ ensure
+ maximum_uri_length_set: maximum_uri_length = a_len
+ end
+
+feature {NONE} -- Implementation
+
+ handle_unavailable (res: WSF_RESPONSE)
+ -- Write "Service unavailable" response to `res'.
+ require
+ unavailable: unavailable
+ res_attached: res /= Void
+ local
+ h: HTTP_HEADER
+ do
+ create h.make
+ h.put_content_type_text_plain
+ check attached unavailablity_message as m then
+ -- invariant `unavailability_message_attached' plus precondition `unavailable'
+ h.put_content_length (m.count)
+ h.put_current_date
+ res.set_status_code ({HTTP_STATUS_CODE}.service_unavailable)
+ if unavailability_duration > 0 then
+ h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, unavailability_duration.out)
+ elseif attached unavailable_until as u then
+ h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after,
+ h.date_to_rfc1123_http_date_format (u))
+ end
+ res.put_header_text (h.string)
+ res.put_string (m)
+ end
+ ensure
+ response_status_is_set: res.status_is_set
+ status_is_service_unavailable: res.status_code = {HTTP_STATUS_CODE}.service_unavailable
+ body_sent: res.message_committed and then res.transfered_content_length > 0
+ body_content_was_unavailablity_message: True -- doesn't seem to be any way to check
+ end
+
+ handle_request_uri_too_long (res: WSF_RESPONSE)
+ -- Write "Request URI too long" response into `res'.
+ require
+ res_attached: res /= Void
+ local
+ h: HTTP_HEADER
+ m: READABLE_STRING_8
+ do
+ create h.make
+ h.put_content_type_text_plain
+ h.put_current_date
+ m := "Maximum permitted length for request URI is " + maximum_uri_length.out + " characters"
+ h.put_content_length (m.count)
+ res.set_status_code ({HTTP_STATUS_CODE}.request_uri_too_long)
+ res.put_header_text (h.string)
+ res.put_string (m)
+ ensure
+ response_status_is_set: res.status_is_set
+ status_is_request_uri_too_long: res.status_code = {HTTP_STATUS_CODE}.request_uri_too_long
+ body_sent: res.message_committed and then res.transfered_content_length > 0
+ end
+
+ frozen handle_server_options (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Write response to OPTIONS * into `res'.
+ require
+ req_attached: req /= Void
+ res_attached: res /= Void
+ method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options)
+ server_options_requested: req.request_uri.same_string ("*")
+ do
+ --| First check if forbidden.
+ --| (N.B. authentication requires an absoluteURI (RFC3617 page 3), and so cannot be used for OPTIONS *.
+ --| Otherwise construct an Allow response automatically from the router.
+ if is_system_options_forbidden (req) then
+ handle_system_options_forbidden (req, res)
+ else
+ handle_system_options (req, res)
+ end
+ ensure
+ response_status_is_set: res.status_is_set
+ valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or
+ res.status_code = {HTTP_STATUS_CODE}.not_found or res.status_code = {HTTP_STATUS_CODE}.ok
+ header_sent: res.header_committed and res.message_committed
+ end
+
+ frozen handle_system_options_forbidden (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Write a 403 Forbidden or a 404 Not found response into `res'.
+ require
+ req_attached: req /= Void
+ res_attached: res /= Void
+ method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options)
+ server_options_requested: req.request_uri.same_string ("*")
+ local
+ m: detachable READABLE_STRING_8
+ h: HTTP_HEADER
+ do
+ m := system_options_forbidden_text (req)
+ if attached {READABLE_STRING_8} m as l_msg then
+ create h.make
+ h.put_content_type_text_plain
+ h.put_current_date
+ h.put_content_length (l_msg.count)
+ res.set_status_code ({HTTP_STATUS_CODE}.forbidden)
+ res.put_header_text (h.string)
+ res.put_string (l_msg)
+ else
+ create h.make
+ h.put_content_type_text_plain
+ h.put_current_date
+ h.put_content_length (0)
+ res.set_status_code ({HTTP_STATUS_CODE}.not_found)
+ res.put_header_text (h.string)
+ end
+ ensure
+ response_status_is_set: res.status_is_set
+ valid_response_code: res.status_code = {HTTP_STATUS_CODE}.forbidden or
+ res.status_code = {HTTP_STATUS_CODE}.not_found
+ header_sent: res.header_committed
+ message_sent: res.message_committed
+ end
+
+ handle_system_options (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Write response to OPTIONS * into `res'.
+ -- This may be redefined by the user, but normally this will not be necessary.
+ require
+ req_attached: req /= Void
+ res_attached: res /= Void
+ method_is_options: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options)
+ server_options_requested: req.request_uri.same_string ("*")
+ local
+ h: HTTP_HEADER
+ do
+ create h.make
+ h.put_content_type_text_plain
+ h.put_current_date
+ h.put_allow (router.all_allowed_methods)
+ h.put_content_length (0)
+ res.set_status_code ({HTTP_STATUS_CODE}.ok)
+ res.put_header_text (h.string)
+ ensure
+ response_status_is_set: res.status_is_set
+ response_code_ok: res.status_code = {HTTP_STATUS_CODE}.ok
+ header_sent: res.header_committed and res.message_committed
+ empty_body: res.transfered_content_length = 0
+ end
+
+ frozen handle_use_proxy (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Write Use Proxy response `res'.
+ require
+ res_attached: res /= Void
+ req_attached: req /= Void
+ proxy_required: requires_proxy (req)
+ local
+ h: HTTP_HEADER
+ do
+ create h.make
+ h.put_content_type_text_plain
+ h.put_current_date
+ h.put_location (proxy_server (req).string)
+ h.put_content_length (0)
+ res.put_header_lines (h)
+ res.set_status_code ({HTTP_STATUS_CODE}.use_proxy)
+ ensure
+ response_status_is_set: res.status_is_set
+ response_code_use_proxy: res.status_code = {HTTP_STATUS_CODE}.use_proxy
+ end
+
+invariant
+
+ unavailability_message_attached: unavailable implies attached unavailablity_message as m and then
+ m.count > 0
+ unavailability_duration_xor_unavailable_until: unavailability_duration > 0 implies unavailable_until = Void
+
+;note
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, 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/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e b/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e
new file mode 100644
index 00000000..ee087582
--- /dev/null
+++ b/library/server/wsf/router/support/uri/helpers/wsf_uri_helper_for_routed_execution.e
@@ -0,0 +1,60 @@
+note
+ description: "Facilities inheritance to add URI base routing to a routed execution"
+
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class WSF_URI_HELPER_FOR_ROUTED_EXECUTION
+
+feature -- Access
+
+ router: WSF_ROUTER
+ -- Router used to dispatch the request according to the WSF_REQUEST object
+ -- and associated request methods;
+ -- This should not be implemented by descendants. Instead, you gain an effective
+ -- version by also inheriting from WSF_ROUTED_EXECUTION, or one of it's descendants.
+ deferred
+ ensure
+ router_not_void: Result /= Void
+ end
+
+feature -- Mapping helper: uri
+
+ map_uri (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER)
+ -- Map `h' as handler for `a_uri'
+ 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_REQUEST_METHODS)
+ -- Map `h' as handler for `a_uri' for request methods `rqst_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]])
+ -- Map `proc' as handler for `a_uri'
+ 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_REQUEST_METHODS)
+ -- Map `proc' as handler for `a_uri' for request methods `rqst_methods'.
+ do
+ map_uri_with_request_methods (a_uri, create {WSF_URI_AGENT_HANDLER}.make (proc), rqst_methods)
+ end
+
+note
+ copyright: "2011-2013, 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/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e b/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e
new file mode 100644
index 00000000..223b8292
--- /dev/null
+++ b/library/server/wsf/router/support/uri_template/helpers/wsf_uri_template_helper_for_routed_execution.e
@@ -0,0 +1,73 @@
+note
+ description: "Facilities inheritance to add URI template-base routing to a routed execution"
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION
+
+feature -- Access
+
+ router: WSF_ROUTER
+ -- Router used to dispatch the request according to the WSF_REQUEST object
+ -- and associated request methods;
+ -- This should not be implemented by descendants. Instead, you gain an effective
+ -- version by also inheriting from WSF_ROUTED_SERVICE, or one of it's descendants.
+ deferred
+ ensure
+ router_not_void: Result /= Void
+ end
+
+feature -- Mapping helper: uri template
+
+ map_uri_template (a_tpl: STRING; h: WSF_URI_TEMPLATE_HANDLER)
+ -- Map `h' as handler for `a_tpl'
+ require
+ a_tpl_attached: a_tpl /= Void
+ h_attached: h /= Void
+ 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_REQUEST_METHODS)
+ -- Map `h' as handler for `a_tpl' for request methods `rqst_methods'.
+ require
+ a_tpl_attached: a_tpl /= Void
+ h_attached: h /= Void
+ do
+ router.map_with_request_methods (create {WSF_URI_TEMPLATE_MAPPING}.make (a_tpl, h), rqst_methods)
+ end
+
+feature -- Mapping helper: uri template agent
+
+ map_uri_template_agent (a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]])
+ -- Map `proc' as handler for `a_tpl'
+ require
+ a_tpl_attached: a_tpl /= Void
+ proc_attached: proc /= Void
+ 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_REQUEST_METHODS)
+ -- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'.
+ require
+ a_tpl_attached: a_tpl /= Void
+ proc_attached: proc /= Void
+ do
+ map_uri_template_with_request_methods (a_tpl, create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (proc), rqst_methods)
+ end
+
+note
+ copyright: "2011-2013, 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/router/wsf_routed_execution.e b/library/server/wsf/router/wsf_routed_execution.e
new file mode 100644
index 00000000..40581dcc
--- /dev/null
+++ b/library/server/wsf/router/wsf_routed_execution.e
@@ -0,0 +1,76 @@
+note
+ description: "Summary description for {WSF_ROUTED_EXECUTION}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_ROUTED_EXECUTION
+
+feature -- Router
+
+ initialize_router
+ -- Initialize router
+ do
+ create_router
+ setup_router
+ end
+
+ create_router
+ -- Create `router'
+ --| could be redefine to initialize with proper capacity
+ do
+ create router.make (10)
+ ensure
+ router_created: router /= Void
+ end
+
+ setup_router
+ -- Setup `router'
+ require
+ router_created: router /= Void
+ deferred
+ end
+
+feature -- Access
+
+ request: WSF_REQUEST
+ deferred
+ end
+
+ response: WSF_RESPONSE
+ deferred
+ end
+
+ router: WSF_ROUTER
+ -- Router used to dispatch the request according to the WSF_REQUEST object
+ -- and associated request methods
+
+feature -- Execution
+
+ execute
+ -- Dispatch the request
+ -- and if handler is not found, execute the default procedure `execute_default'.
+ local
+ sess: WSF_ROUTER_SESSION
+ do
+ create sess
+ router.dispatch (request, response, sess)
+ if not sess.dispatched then
+ execute_default
+ end
+ ensure
+ response_status_is_set: response.status_is_set
+ end
+
+ execute_default
+ -- Dispatch requests without a matching handler.
+ local
+ msg: WSF_DEFAULT_ROUTER_RESPONSE
+ do
+ create msg.make_with_router (request, router)
+ msg.set_documentation_included (True)
+ response.send (msg)
+ end
+
+end
diff --git a/library/server/wsf/src/wsf_execution.e b/library/server/wsf/src/wsf_execution.e
index b99b89c0..9af7db08 100644
--- a/library/server/wsf/src/wsf_execution.e
+++ b/library/server/wsf/src/wsf_execution.e
@@ -28,6 +28,14 @@ feature {NONE} -- Initialization
Precursor (req, res)
create request.make_from_wgi (wgi_request)
create response.make_from_wgi (wgi_response)
+ initialize
+ end
+
+ initialize
+ -- Initialize Current object.
+ --| To be redefined if needed.
+ do
+
end
feature {NONE} -- Access