From 31ba0a8828e2ecd52d91044b1bdc7df6df8bc733 Mon Sep 17 00:00:00 2001 From: Colin Adams Date: Thu, 11 Apr 2013 09:23:41 +0100 Subject: [PATCH] Handle Precondition Failed for If-Match: * where there is no handler for the resource --- .gitignore | 1 + .../specification/request/wgi_meta_names.e | 2 + .../response/wsf_default_router_response.e | 24 ++++ .../wsf_precondition_failed_message.e | 130 ++++++++++++++++++ library/server/wsf/src/wsf_request.e | 6 + 5 files changed, 163 insertions(+) create mode 100644 library/server/wsf/src/response/wsf_precondition_failed_message.e diff --git a/.gitignore b/.gitignore index c4d48214..332345d9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ tests/temp/ .svn/ *.swp *~ +*# diff --git a/library/server/ewsgi/specification/request/wgi_meta_names.e b/library/server/ewsgi/specification/request/wgi_meta_names.e index 7eeb913e..a4578a6b 100644 --- a/library/server/ewsgi/specification/request/wgi_meta_names.e +++ b/library/server/ewsgi/specification/request/wgi_meta_names.e @@ -52,6 +52,8 @@ feature -- Access http_access_control_request_headers: STRING = "HTTP_ACCESS_CONTROL_REQUEST_HEADERS" + http_if_match: STRING = "HTTP_IF_MATCH" + gateway_interface: STRING = "GATEWAY_INTERFACE" auth_type: STRING = "AUTH_TYPE" diff --git a/library/server/wsf/src/response/wsf_default_router_response.e b/library/server/wsf/src/response/wsf_default_router_response.e index cc933b03..bfe35c6e 100644 --- a/library/server/wsf/src/response/wsf_default_router_response.e +++ b/library/server/wsf/src/response/wsf_default_router_response.e @@ -58,8 +58,20 @@ feature {WSF_RESPONSE} -- Output if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then msg := trace_message (req) elseif attached method_not_allowed_message (req) as not_allowed then + --| We give this precedence over 412 Precondition Failed or 404 Not Found, + --| as we assume the existence of a handler for at least one method + --| indicates existence of the resource. This is obviously not the + --| case if the only method allowed is POST, but the handler ought + --| to handle the 404 Not Found and 412 Precondition Failed cases in that case. + --| Ditto for template URI handlers where not all template variable + --| values map to existing resources. msg := not_allowed + elseif attached req.http_if_match as l_match and then l_match.same_string ("*") then + msg := precondition_failed_message (req) else + --| Other response codes are possible, such as 301 Moved permananently, + --| 302 Found and 410 Gone. But these require handlers to implement, + --| so no other code can be given at this point. msg := not_found_message (req) end res.send (msg) @@ -67,7 +79,17 @@ feature {WSF_RESPONSE} -- Output feature {NONE} -- Implementation + precondition_failed_message (req: WSF_REQUEST): WSF_PRECONDITION_FAILED_MESSAGE + -- Automatically generated response for 412 Precondition Failed response + require + req_attached: req /= Void + do + create Result.make (req) + end + method_not_allowed_message (req: WSF_REQUEST): detachable WSF_METHOD_NOT_ALLOWED_RESPONSE + require + req_attached: req /= Void local vis: WSF_ROUTER_AGENT_ITERATOR do @@ -114,6 +136,8 @@ feature {NONE} -- Implementation end not_found_message (req: WSF_REQUEST): WSF_NOT_FOUND_RESPONSE + require + req_attached: req /= Void local vis: WSF_ROUTER_AGENT_ITERATOR do diff --git a/library/server/wsf/src/response/wsf_precondition_failed_message.e b/library/server/wsf/src/response/wsf_precondition_failed_message.e new file mode 100644 index 00000000..da0ac71f --- /dev/null +++ b/library/server/wsf/src/response/wsf_precondition_failed_message.e @@ -0,0 +1,130 @@ +note + description: "[ + This class is used to report a 412 Precondition Failed page + ]" + date: "$Date$" + revision: "$Revision$" + +class WSF_PRECONDITION_FAILED_MESSAGE + +inherit + + WSF_RESPONSE_MESSAGE + + SHARED_HTML_ENCODER + +create + + make + +feature {NONE} -- Initialization + + make (req: WSF_REQUEST) + -- Initialize setting `request' from `req'. + do + request := req + create header.make + ensure + req_aliased: request = req + end + +feature -- Header + + header: HTTP_HEADER + -- Response' header + + request: WSF_REQUEST + -- Associated request. + + body: detachable READABLE_STRING_8 + -- Optional body + -- Displayed as extra content + +feature -- Element change + + set_body (b: like body) + -- Set `body' to `b' + do + body := b + end + +feature {WSF_RESPONSE} -- Output + + send_to (res: WSF_RESPONSE) + local + s: STRING + l_text: detachable READABLE_STRING_GENERAL + l_loc: detachable READABLE_STRING_8 + h: like header + do + h := header + res.set_status_code ({HTTP_STATUS_CODE}.precondition_failed) + + if request.is_content_type_accepted ({HTTP_MIME_TYPES}.text_html) then + s := "" + s.append ("") + s.append (html_encoder.encoded_string (request.request_uri)) + s.append ("Error 412 (Precondition Failed)") + s.append ("%N") + s.append ("[ + + + + + ]") + s.append ("
") + s.append ("
") + s.append ("
") + s.append ("
") + s.append ("
") + s.append ("Error 412 (Precondition Failed)
") + s.append ("
Error 412 (Precondition Failed): " + html_encoder.encoded_string (request.request_uri) + "
") + if attached body as b then + s.append ("
") + s.append (b) + s.append ("
%N") + end + + s.append ("
") + s.append ("%N") + s.append ("%N") + + h.put_content_type_text_html + else + s := "Error 412 (Precondition Failed): " + s.append (request.request_uri) + s.append_character ('%N') + if attached body as b then + s.append ("%N") + s.append (b) + s.append ("%N") + end + + h.put_content_type_text_plain + end + h.put_content_length (s.count) + res.put_header_text (h.string) + res.put_string (s) + res.flush + end + +note + + copyright: "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/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index eeea1a54..7371842f 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -1042,6 +1042,12 @@ feature -- HTTP_* Result := wgi_request.http_access_control_request_headers end + http_if_match: detachable READABLE_STRING_8 + -- Existence check on resource + do + Result := meta_string_variable ({WGI_META_NAMES}.http_if_match) + end + feature -- Extra CGI environment variables request_uri: READABLE_STRING_8