diff --git a/library/network/protocol/http/src/http_header.e b/library/network/protocol/http/src/http_header.e index a9cee805..e1bb19a7 100644 --- a/library/network/protocol/http/src/http_header.e +++ b/library/network/protocol/http/src/http_header.e @@ -819,6 +819,8 @@ feature {NONE} -- Implementation h.append_character ('%N') end +feature -- Access + date_to_rfc1123_http_date_format (dt: DATE_TIME): STRING_8 -- String representation of `dt' using the RFC 1123 local diff --git a/library/server/wsf/router/wsf_routed_service.e b/library/server/wsf/router/wsf_routed_service.e index 5f2c3499..9e94e806 100644 --- a/library/server/wsf/router/wsf_routed_service.e +++ b/library/server/wsf/router/wsf_routed_service.e @@ -35,13 +35,17 @@ feature -- Initialization feature -- Execution execute (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Dispatch the request + -- 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'. require req_attached: req /= Void res_attached: res /= Void do - if attached router.dispatch_and_return_handler (req, res) as p then + if unavailable then + handle_unavailable (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 attached router.dispatch_and_return_handler (req, res) as p then -- executed else execute_default (req, res) @@ -67,6 +71,119 @@ feature -- Access -- Router used to dispatch the request according to the WSF_REQUEST object -- and associated request methods +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 availabile 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 = True + res_attached: res /= Void + local + h: HTTP_HEADER + do + create h.make + h.put_content_type_text_plain + check attached {READABLE_STRING_8} unavailablity_message as m then + -- invariant + 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 unavailable_until /= Void then + check attached {DATE_TIME} unavailable_until as u then + -- $£#$%#! compiler! + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_retry_after, + h.date_to_rfc1123_http_date_format (u)) + end + end + res.put_header_text (h.string) + res.put_string (m) + end + end + + handle_request_uri_too_long (res: WSF_RESPONSE) + -- Write "Request URI too long" response to `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) + end + +invariant + + unavailblity_message_attached: unavailable implies unavailablity_message /= Void + unavailablity_duration_xor_unavailable_until: unavailability_duration > 0 implies unavailable_until = Void + ;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)"