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:
Jocelyn Fiat
2012-12-13 13:58:42 -08:00
6 changed files with 173 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
<?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">
<root class="RESTBUCKS_SERVER" feature="make"/>
<file_rule>
@@ -9,7 +9,7 @@
</file_rule>
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<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>
<setting name="concurrency" value="thread"/>
<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="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="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="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_extension" location="..\..\library\server\wsf\wsf_extension-safe.ecf" readonly="false"/>
<cluster name="src" location="src\" recursive="true"/>

View File

@@ -54,13 +54,7 @@ feature -- API DOC
feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Using GET to retrieve resource information.
-- 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
-- <Precursor>
local
id: STRING
do

View 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

View 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

View File

@@ -4,13 +4,16 @@ note
date: "$Date$"
revision: "$Revision$"
class
WSF_RESOURCE_HANDLER_HELPER
class WSF_RESOURCE_HANDLER_HELPER
inherit
WSF_METHOD_HANDLERS
feature -- Execute template
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
m: READABLE_STRING_8
do
@@ -46,8 +49,8 @@ feature -- Method Get
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Using GET to retrieve resource information.
-- If the GET request is SUCCESS, we response with
-- 200 OK, and a representation of the person
-- If the GET request is SUCCESS, we respond with
-- 200 OK, and a representation of the resource.
-- 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
@@ -141,12 +144,12 @@ feature -- Method HEAD
do_head (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Using HEAD to retrieve resource information.
-- If the HEAD request is SUCCESS, we response with
-- 200 OK, and WITHOUT a representation of the person
-- If the HEAD request is not SUCCESS, we response with
-- 404 Resource not found
-- If is a Condition HEAD and the resource does not change we send a
-- 304, Resource not modifed
-- If the HEAD request is SUCCESS, we respond with
-- 200 OK, and WITHOUT a representation of the resource.
-- If the HEAD request is not SUCCESS, we respond with
-- 404 Resource not found.
-- If Conditional HEAD and the resource does not change we send a
-- 304, Resource not modifed.
do
handle_not_implemented ("Method HEAD not implemented", req, res)
end
@@ -160,6 +163,7 @@ feature -- Method OPTIONS
do_options (req: WSF_REQUEST; res: WSF_RESPONSE)
do
-- TODO - implement a default method that lists the accepted methods for the resource.
handle_not_implemented ("Method OPTIONS not implemented", req, res)
end
@@ -172,6 +176,7 @@ feature -- Method TRACE
do_trace (req: WSF_REQUEST; res: WSF_RESPONSE)
do
-- TODO - implement frozen, as there is only one permitted semantic.
handle_not_implemented ("Method TRACE not implemented", req, res)
end

View File

@@ -69,7 +69,6 @@ feature -- Mapping
io.error.put_string ("%N")
end
end
mappings.extend (create {WSF_ROUTER_ITEM}.make_with_request_methods (a_mapping, rqst_methods))
a_mapping.handler.on_mapped (a_mapping, rqst_methods)
end