Merge pull request #16 from colin-adams/master
Implementation for automatic HEAD and first pass at HTTP 1.1 conformance contracts
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="restbucks" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
||||||
<target name="restbucks">
|
<target name="restbucks">
|
||||||
<root class="RESTBUCKS_SERVER" feature="make"/>
|
<root class="RESTBUCKS_SERVER" feature="make"/>
|
||||||
<file_rule>
|
<file_rule>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
</file_rule>
|
</file_rule>
|
||||||
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||||
<debug name="nino" enabled="true"/>
|
<debug name="nino" enabled="true"/>
|
||||||
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
</option>
|
</option>
|
||||||
<setting name="concurrency" value="thread"/>
|
<setting name="concurrency" value="thread"/>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
@@ -21,9 +21,9 @@
|
|||||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="false"/>
|
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="false"/>
|
||||||
<library name="eel" location="..\..\contrib\ise_library\text\encryption\eel\eel-safe.ecf" readonly="false"/>
|
<library name="eel" location="..\..\contrib\ise_library\text\encryption\eel\eel-safe.ecf" readonly="false"/>
|
||||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||||
<library name="http" location="../../library/network/protocol/http/http-safe.ecf" readonly="false"/>
|
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf" readonly="false"/>
|
||||||
<library name="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
<library name="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||||
<library name="uri_template" location="../../library/text/parser/uri_template/uri_template-safe.ecf" readonly="false"/>
|
<library name="uri_template" location="..\..\library\text\parser\uri_template\uri_template-safe.ecf" readonly="false"/>
|
||||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||||
<library name="wsf_extension" location="..\..\library\server\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
<library name="wsf_extension" location="..\..\library\server\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||||
<cluster name="src" location="src\" recursive="true"/>
|
<cluster name="src" location="src\" recursive="true"/>
|
||||||
|
|||||||
@@ -54,15 +54,9 @@ feature -- API DOC
|
|||||||
feature -- HTTP Methods
|
feature -- HTTP Methods
|
||||||
|
|
||||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Using GET to retrieve resource information.
|
-- <Precursor>
|
||||||
-- If the GET request is SUCCESS, we response with
|
|
||||||
-- 200 OK, and a representation of the order
|
|
||||||
-- If the GET request is not SUCCESS, we response with
|
|
||||||
-- 404 Resource not found
|
|
||||||
-- If is a Condition GET and the resource does not change we send a
|
|
||||||
-- 304, Resource not modifed
|
|
||||||
local
|
local
|
||||||
id : STRING
|
id: STRING
|
||||||
do
|
do
|
||||||
if attached req.orig_path_info as orig_path then
|
if attached req.orig_path_info as orig_path then
|
||||||
id := get_order_id_from_path (orig_path)
|
id := get_order_id_from_path (orig_path)
|
||||||
@@ -93,7 +87,7 @@ feature -- HTTP Methods
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
compute_response_get (req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER)
|
compute_response_get (req: WSF_REQUEST; res: WSF_RESPONSE; l_order: ORDER)
|
||||||
local
|
local
|
||||||
h: HTTP_HEADER
|
h: HTTP_HEADER
|
||||||
l_msg : STRING
|
l_msg : STRING
|
||||||
|
|||||||
72
library/server/wsf/extension/wsf_method_handler.e
Normal file
72
library/server/wsf/extension/wsf_method_handler.e
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "Conforming handler for any HTTP 1.1 standard method"
|
||||||
|
|
||||||
|
author: "Colin Adams"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class WSF_METHOD_HANDLER
|
||||||
|
|
||||||
|
feature -- Method
|
||||||
|
|
||||||
|
do_method (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Respond to `req' using `res'.
|
||||||
|
require
|
||||||
|
req_not_void: req /= Void
|
||||||
|
res_not_void: res /= Void
|
||||||
|
deferred
|
||||||
|
ensure
|
||||||
|
valid_response_for_http_1_0: is_1_0 (req.server_protocol) implies
|
||||||
|
valid_response_for_http_1_0 (res.status_code)
|
||||||
|
empty_body_for_no_content_response: is_no_content_response (res.status_code) implies is_empty_content (res)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Contract support
|
||||||
|
|
||||||
|
is_1_0 (a_protocol: READABLE_STRING_8): BOOLEAN
|
||||||
|
-- Is `a_protocol' (a variant of) HTTP 1.0?
|
||||||
|
require
|
||||||
|
a_protocol_not_void: a_protocol /= Void
|
||||||
|
do
|
||||||
|
Result := a_protocol.count >= 8 and then
|
||||||
|
a_protocol.substring (1, 8) ~ "HTTP/1.0"
|
||||||
|
end
|
||||||
|
|
||||||
|
valid_response_for_http_1_0 (a_status_code: INTEGER): BOOLEAN
|
||||||
|
-- Is `a_status_code' a valid response to HTTP 1.0?
|
||||||
|
do
|
||||||
|
-- 1XX is forbidden
|
||||||
|
|
||||||
|
-- first approximation
|
||||||
|
Result := a_status_code >= {HTTP_STATUS_CODE}.ok
|
||||||
|
end
|
||||||
|
|
||||||
|
is_no_content_response (a_status_code: INTEGER): BOOLEAN
|
||||||
|
-- Is `a_status_code' one that does not permit an entity in the response?
|
||||||
|
do
|
||||||
|
inspect
|
||||||
|
a_status_code
|
||||||
|
when {HTTP_STATUS_CODE}.no_content then
|
||||||
|
Result := True
|
||||||
|
when {HTTP_STATUS_CODE}.reset_content then
|
||||||
|
Result := True
|
||||||
|
when {HTTP_STATUS_CODE}.not_modified then
|
||||||
|
Result := True
|
||||||
|
when {HTTP_STATUS_CODE}.conflict then
|
||||||
|
Result := True
|
||||||
|
else
|
||||||
|
-- default to False
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
is_empty_content (res: WSF_RESPONSE): BOOLEAN
|
||||||
|
-- Does `res' not contain an entity?
|
||||||
|
require
|
||||||
|
res_not_void: res /= Void
|
||||||
|
do
|
||||||
|
Result := res.transfered_content_length = 0 -- Is that the right measure?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
78
library/server/wsf/extension/wsf_method_handlers.e
Normal file
78
library/server/wsf/extension/wsf_method_handlers.e
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
note
|
||||||
|
|
||||||
|
description: "Conforming handlers for HTTP 1.1 standard methods"
|
||||||
|
|
||||||
|
author: "Colin Adams"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class WSF_METHOD_HANDLERS
|
||||||
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_get
|
||||||
|
select
|
||||||
|
do_get
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_put
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_put
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_connect
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_head
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_options
|
||||||
|
end
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLER
|
||||||
|
rename
|
||||||
|
do_method as do_trace
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Method
|
||||||
|
|
||||||
|
do_head (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Respond to `req' using `res'.
|
||||||
|
deferred
|
||||||
|
ensure then
|
||||||
|
empty_body: is_empty_content (res)
|
||||||
|
end
|
||||||
|
|
||||||
|
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Respond to `req' using `res'.
|
||||||
|
deferred
|
||||||
|
ensure then
|
||||||
|
non_empty_body: res.status_code = {HTTP_STATUS_CODE}.created implies
|
||||||
|
not is_empty_content (res)
|
||||||
|
location_header: res.status_code = {HTTP_STATUS_CODE}.created implies True -- WSF_RESPONSE needs enhancing
|
||||||
|
end
|
||||||
|
|
||||||
|
do_trace (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- Respond to `req' using `res'.
|
||||||
|
deferred
|
||||||
|
ensure then
|
||||||
|
non_empty_body: res.status_code = {HTTP_STATUS_CODE}.ok implies
|
||||||
|
not is_empty_content (res)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -4,13 +4,16 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
class
|
class WSF_RESOURCE_HANDLER_HELPER
|
||||||
WSF_RESOURCE_HANDLER_HELPER
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
WSF_METHOD_HANDLERS
|
||||||
|
|
||||||
feature -- Execute template
|
feature -- Execute template
|
||||||
|
|
||||||
execute_methods (req: WSF_REQUEST; res: WSF_RESPONSE)
|
execute_methods (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Execute request and dispatch according to the request method
|
-- Execute request and dispatch according to the request method.
|
||||||
local
|
local
|
||||||
m: READABLE_STRING_8
|
m: READABLE_STRING_8
|
||||||
do
|
do
|
||||||
@@ -46,8 +49,8 @@ feature -- Method Get
|
|||||||
|
|
||||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Using GET to retrieve resource information.
|
-- Using GET to retrieve resource information.
|
||||||
-- If the GET request is SUCCESS, we response with
|
-- If the GET request is SUCCESS, we respond with
|
||||||
-- 200 OK, and a representation of the person
|
-- 200 OK, and a representation of the resource.
|
||||||
-- If the GET request is not SUCCESS, we response with
|
-- If the GET request is not SUCCESS, we response with
|
||||||
-- 404 Resource not found
|
-- 404 Resource not found
|
||||||
-- If is a Condition GET and the resource does not change we send a
|
-- If is a Condition GET and the resource does not change we send a
|
||||||
@@ -141,12 +144,12 @@ feature -- Method HEAD
|
|||||||
|
|
||||||
do_head (req: WSF_REQUEST; res: WSF_RESPONSE)
|
do_head (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
-- Using HEAD to retrieve resource information.
|
-- Using HEAD to retrieve resource information.
|
||||||
-- If the HEAD request is SUCCESS, we response with
|
-- If the HEAD request is SUCCESS, we respond with
|
||||||
-- 200 OK, and WITHOUT a representation of the person
|
-- 200 OK, and WITHOUT a representation of the resource.
|
||||||
-- If the HEAD request is not SUCCESS, we response with
|
-- If the HEAD request is not SUCCESS, we respond with
|
||||||
-- 404 Resource not found
|
-- 404 Resource not found.
|
||||||
-- If is a Condition HEAD and the resource does not change we send a
|
-- If Conditional HEAD and the resource does not change we send a
|
||||||
-- 304, Resource not modifed
|
-- 304, Resource not modifed.
|
||||||
do
|
do
|
||||||
handle_not_implemented ("Method HEAD not implemented", req, res)
|
handle_not_implemented ("Method HEAD not implemented", req, res)
|
||||||
end
|
end
|
||||||
@@ -160,6 +163,7 @@ feature -- Method OPTIONS
|
|||||||
|
|
||||||
do_options (req: WSF_REQUEST; res: WSF_RESPONSE)
|
do_options (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
do
|
do
|
||||||
|
-- TODO - implement a default method that lists the accepted methods for the resource.
|
||||||
handle_not_implemented ("Method OPTIONS not implemented", req, res)
|
handle_not_implemented ("Method OPTIONS not implemented", req, res)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -172,6 +176,7 @@ feature -- Method TRACE
|
|||||||
|
|
||||||
do_trace (req: WSF_REQUEST; res: WSF_RESPONSE)
|
do_trace (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
do
|
do
|
||||||
|
-- TODO - implement frozen, as there is only one permitted semantic.
|
||||||
handle_not_implemented ("Method TRACE not implemented", req, res)
|
handle_not_implemented ("Method TRACE not implemented", req, res)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ feature -- Mapping
|
|||||||
io.error.put_string ("%N")
|
io.error.put_string ("%N")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mappings.extend (create {WSF_ROUTER_ITEM}.make_with_request_methods (a_mapping, rqst_methods))
|
mappings.extend (create {WSF_ROUTER_ITEM}.make_with_request_methods (a_mapping, rqst_methods))
|
||||||
a_mapping.handler.on_mapped (a_mapping, rqst_methods)
|
a_mapping.handler.on_mapped (a_mapping, rqst_methods)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user