If-Match implemented in skeleton handler
This commit is contained in:
15
library/server/wsf/router/wsf_get_helper.e
Normal file
15
library/server/wsf/router/wsf_get_helper.e
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "[
|
||||||
|
Policy-driven helpers to implement processing of GET and HEAD requests.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class WSF_GET_HELPER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
WSF_METHOD_HELPER
|
||||||
|
|
||||||
|
end
|
||||||
80
library/server/wsf/router/wsf_method_helper.e
Normal file
80
library/server/wsf/router/wsf_method_helper.e
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "[
|
||||||
|
Policy-driven helpers to implement a method.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class WSF_METHOD_HELPER
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
resource_exists: BOOLEAN
|
||||||
|
-- Does the requested resource (request URI) exist?
|
||||||
|
|
||||||
|
feature -- Setting
|
||||||
|
|
||||||
|
set_resource_exists
|
||||||
|
-- Set `resource_exists' to `True'.
|
||||||
|
do
|
||||||
|
resource_exists := True
|
||||||
|
ensure
|
||||||
|
set: resource_exists
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute_new_resource (req: WSF_REQUEST; res: WSF_RESPONSE; a_handler: WSF_SKELETON_HANDLER)
|
||||||
|
-- Write response to non-existing resource requested by `req.' into `res'.
|
||||||
|
-- Policy routines are available in `a_handler'.
|
||||||
|
-- This default implementation does not apply for PUT requests.
|
||||||
|
-- The behaviour for POST requests depends upon a policy.
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
res_attached: res /= Void
|
||||||
|
a_handler_attached: a_handler /= Void
|
||||||
|
do
|
||||||
|
if a_handler.resource_previously_existed (req) then
|
||||||
|
--| TODO - should we be passing the entire request, or should we further
|
||||||
|
--| simplify the programmer's task by passing `req.path_translated'?
|
||||||
|
if a_handler.resource_moved_permanently (req) then
|
||||||
|
-- TODO 301 Moved Permanently
|
||||||
|
elseif a_handler.resource_moved_temporarily (req) then
|
||||||
|
-- TODO 302 Found
|
||||||
|
else
|
||||||
|
-- TODO 410 Gone
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- TODO 404 Not Found
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
execute_existing_resource (req: WSF_REQUEST; res: WSF_RESPONSE; a_handler: WSF_SKELETON_HANDLER)
|
||||||
|
-- Write response to existing resource requested by `req.' into `res'.
|
||||||
|
-- Policy routines are available in `a_handler'.
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
res_attached: res /= Void
|
||||||
|
a_handler_attached: a_handler /= Void
|
||||||
|
not_if_match_star: attached req.http_if_match as l_if_match implies not l_if_match.same_string ("*")
|
||||||
|
local
|
||||||
|
l_etags: LIST [READABLE_STRING_32]
|
||||||
|
do
|
||||||
|
if attached req.http_if_match as l_if_match then
|
||||||
|
l_etags := l_if_match.split (',')
|
||||||
|
|
||||||
|
else
|
||||||
|
-- TODO: check_if_unmodified_since (req, res, a_handler)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_precondition_failed (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
--
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
res_attached: res /= Void
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
25
library/server/wsf/router/wsf_method_helper_factory.e
Normal file
25
library/server/wsf/router/wsf_method_helper_factory.e
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "[
|
||||||
|
Default factory for policy-driven method helpers.
|
||||||
|
Extension methods can be implemented here.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class WSF_METHOD_HELPER_FACTORY
|
||||||
|
|
||||||
|
feature -- Factory
|
||||||
|
|
||||||
|
new_method_helper (a_method: READABLE_STRING_8): detachable WSF_METHOD_HELPER
|
||||||
|
-- New object for processing `a_method'
|
||||||
|
require
|
||||||
|
a_method_attached: a_method /= Void
|
||||||
|
do
|
||||||
|
if a_method.is_case_insensitive_equal ({HTTP_REQUEST_METHODS}.method_get) or
|
||||||
|
a_method.is_case_insensitive_equal ({HTTP_REQUEST_METHODS}.method_head) then
|
||||||
|
create {WSF_GET_HELPER} Result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
37
library/server/wsf/router/wsf_options_policy.e
Normal file
37
library/server/wsf/router/wsf_options_policy.e
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "[
|
||||||
|
Default policy for responing to OPTIONS requests other than OPTIONS*
|
||||||
|
By overriding `execute_options', clients can add a body, for example.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class WSF_OPTIONS_POLICY
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute_options (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER)
|
||||||
|
-- Write response to `req' into `res'.
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
options_request: req.is_request_method ({HTTP_REQUEST_METHODS}.method_options)
|
||||||
|
res_attached: res /= Void
|
||||||
|
a_router_attached: a_router /= Void
|
||||||
|
local
|
||||||
|
l_methods: WSF_REQUEST_METHODS
|
||||||
|
h: HTTP_HEADER
|
||||||
|
do
|
||||||
|
create h.make
|
||||||
|
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
|
h.put_content_type ({HTTP_MIME_TYPES}.text_plain)
|
||||||
|
h.put_current_date
|
||||||
|
h.put_content_length (0)
|
||||||
|
l_methods := a_router.allowed_methods_for_request (req)
|
||||||
|
if not l_methods.is_empty then
|
||||||
|
h.put_allow (l_methods)
|
||||||
|
end
|
||||||
|
res.put_header_text (h.string)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
40
library/server/wsf/router/wsf_previous_policy.e
Normal file
40
library/server/wsf/router/wsf_previous_policy.e
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "[
|
||||||
|
Policies for deciding if a resource that currently doesn't exist used to do so.
|
||||||
|
This default implementation assumes that no resources used to exist.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class WSF_PREVIOUS_POLICY
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
resource_previously_existed (req: WSF_REQUEST) : BOOLEAN
|
||||||
|
-- Did `req.path_translated' exist previously?
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
do
|
||||||
|
-- No. Override if this is not want you want.
|
||||||
|
end
|
||||||
|
|
||||||
|
resource_moved_permanently (req: WSF_REQUEST) : BOOLEAN
|
||||||
|
-- Was `req.path_translated' moved permanently?
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
previously_existed: resource_previously_existed (req)
|
||||||
|
do
|
||||||
|
-- No. Override if this is not want you want.
|
||||||
|
end
|
||||||
|
|
||||||
|
resource_moved_temporarily (req: WSF_REQUEST) : BOOLEAN
|
||||||
|
-- Was `req.path_translated' moved temporarily?
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
previously_existed: resource_previously_existed (req)
|
||||||
|
do
|
||||||
|
-- No. Override if this is not want you want.
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
98
library/server/wsf/router/wsf_skeleton_handler.e
Normal file
98
library/server/wsf/router/wsf_skeleton_handler.e
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "[
|
||||||
|
Policy-driven handlers.
|
||||||
|
Implementers only need to concentrate on creating content.
|
||||||
|
]"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class WSF_SKELETON_HANDLER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
WSF_URI_TEMPLATE_ROUTING_HANDLER
|
||||||
|
redefine
|
||||||
|
execute
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_OPTIONS_POLICY
|
||||||
|
|
||||||
|
WSF_PREVIOUS_POLICY
|
||||||
|
|
||||||
|
WSF_METHOD_HELPER_FACTORY
|
||||||
|
|
||||||
|
feature -- Execution
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
check
|
||||||
|
known_method: True -- Can't be done until WSF_METHOD_NOT_ALLOWED_RESPONSE
|
||||||
|
-- is refactored.
|
||||||
|
-- Then maybe this can become a precondition. But we will still (?)
|
||||||
|
-- need a check that it isn't CONNECT or TRACE (it MIGHT be HEAD).
|
||||||
|
end
|
||||||
|
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) then
|
||||||
|
execute_options (req, res, router)
|
||||||
|
else
|
||||||
|
if attached new_method_helper (req.request_method) as l_helper then
|
||||||
|
execute_method (req, res, l_helper)
|
||||||
|
else
|
||||||
|
handle_internal_server_error (res)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
execute_method (req: WSF_REQUEST; res: WSF_RESPONSE; a_helper: WSF_METHOD_HELPER)
|
||||||
|
-- Write response to `req' into `res', using `a_helper' as a logic helper.
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
res_attached: res /= Void
|
||||||
|
a_helper_attached: a_helper /= Void
|
||||||
|
do
|
||||||
|
check_resource_exists (req, a_helper)
|
||||||
|
if a_helper.resource_exists then
|
||||||
|
a_helper.execute_existing_resource (req, res, Current)
|
||||||
|
else
|
||||||
|
if attached req.http_if_match as l_if_match and then l_if_match.same_string ("*") then
|
||||||
|
a_helper.handle_precondition_failed (req, res)
|
||||||
|
else
|
||||||
|
a_helper.execute_new_resource (req, res, Current)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
check_resource_exists (req: WSF_REQUEST; a_helper: WSF_METHOD_HELPER)
|
||||||
|
-- Call `a_helper.set_resource_exists' to indicate that `req.path_translated'
|
||||||
|
-- is the name of an existing resource.
|
||||||
|
-- Optionally, also call `req.set_server_data', if this is now available as a by-product
|
||||||
|
-- of the existence check.
|
||||||
|
require
|
||||||
|
req_attached: req /= Void
|
||||||
|
a_helper_attached: a_helper /= Void
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_internal_server_error (res: WSF_RESPONSE)
|
||||||
|
-- Write "Internal Server Error" response to `res'.
|
||||||
|
require
|
||||||
|
res_attached: res /= Void
|
||||||
|
local
|
||||||
|
h: HTTP_HEADER
|
||||||
|
m: STRING_8
|
||||||
|
do
|
||||||
|
create h.make
|
||||||
|
h.put_content_type_text_plain
|
||||||
|
m := "Server failed to handle request properly"
|
||||||
|
h.put_content_length (m.count)
|
||||||
|
h.put_current_date
|
||||||
|
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
|
||||||
|
res.put_string (m)
|
||||||
|
ensure
|
||||||
|
response_status_is_set: res.status_is_set
|
||||||
|
status_is_service_unavailable: res.status_code = {HTTP_STATUS_CODE}.internal_server_error
|
||||||
|
body_sent: res.message_committed and then res.transfered_content_length > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user