Added "Date:" helper feature in EWF_HEADER
Added license.lic to restbuck example, and mainly copyright to Javier Use HTTP_STATUS_CODES Minor improvements using object tests Cosmetic (indentation, ..)
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="http_client" location="..\..\..\library\client\http_client\http_client-safe.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\..\ext\text\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="http_client" location="..\..\..\library\client\http_client\http_client.ecf"/>
|
||||
<library name="json" location="..\..\..\ext\text\json\library\json.ecf" readonly="false"/>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<library name="thread" location="$ISE_LIBRARY/library/thread/thread.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
|
||||
@@ -18,6 +18,8 @@ feature {NONE} -- Initialization
|
||||
h: LIBCURL_HTTP_CLIENT
|
||||
sess: HTTP_CLIENT_SESSION
|
||||
s: READABLE_STRING_8
|
||||
j: JSON_PARSER
|
||||
id: detachable STRING
|
||||
do
|
||||
create h.make
|
||||
sess := h.new_session ("http://127.0.0.1")
|
||||
@@ -36,11 +38,23 @@ feature {NONE} -- Initialization
|
||||
]"
|
||||
|
||||
if attached sess.post ("/order", Void, s) as r then
|
||||
print (r.body)
|
||||
if attached r.body as m then
|
||||
create j.make_parser (m)
|
||||
|
||||
if j.is_parsed and attached j.parse_object as j_o then
|
||||
if attached {JSON_STRING} j_o.item ("id") as l_id then
|
||||
id := l_id.item
|
||||
end
|
||||
print (m)
|
||||
io.put_new_line
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if attached sess.get ("/order/1", Void) as r then
|
||||
if id /= Void and then attached sess.get ("/order/" + id, Void) as r then
|
||||
print (r.body)
|
||||
io.put_new_line
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
4
examples/restbucks/license.lic
Normal file
4
examples/restbucks/license.lic
Normal file
@@ -0,0 +1,4 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -9,13 +9,18 @@ class
|
||||
create
|
||||
make
|
||||
|
||||
feature --Initialization
|
||||
feature -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create orders.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
orders : HASH_TABLE[ORDER,STRING]
|
||||
|
||||
orders: HASH_TABLE [ORDER, STRING]
|
||||
|
||||
;note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -6,9 +6,14 @@ note
|
||||
|
||||
class
|
||||
SHARED_DATABASE_API
|
||||
feature
|
||||
|
||||
feature -- Access
|
||||
|
||||
db_access: DATABASE_API
|
||||
once
|
||||
create Result.make
|
||||
end
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -84,4 +84,7 @@ invariant
|
||||
valid_coffe : is_valid_coffee_type (name)
|
||||
valid_customization : is_valid_milk_type (option)
|
||||
valid_quantity : quantity > 0
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -48,4 +48,7 @@ feature -- Access
|
||||
once
|
||||
Result := <<"small","mediumn", "large">>
|
||||
end
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -6,64 +6,73 @@
|
||||
|
||||
class
|
||||
JSON_ORDER_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create object.make ("","","")
|
||||
create object.make ("", "", "")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
object : ORDER
|
||||
|
||||
object: ORDER
|
||||
|
||||
value: detachable JSON_OBJECT
|
||||
|
||||
value : detachable JSON_OBJECT
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: attached like value): detachable like object
|
||||
-- Convert from JSON value. Returns Void if unable to convert
|
||||
local
|
||||
lstr1, lstr2, lstr3 : detachable STRING_32
|
||||
q: detachable INTEGER_8
|
||||
s_name, s_key, s_option: detachable STRING_32
|
||||
q: INTEGER_8
|
||||
o: ORDER
|
||||
i : ITEM
|
||||
l_val : detachable JSON_ARRAY
|
||||
l_array : detachable ARRAYED_LIST[JSON_VALUE]
|
||||
jv : detachable JSON_OBJECT
|
||||
l_array : detachable LIST [JSON_VALUE]
|
||||
is_valid_from_json : BOOLEAN
|
||||
do
|
||||
is_valid_from_json := True
|
||||
lstr1 ?= json.object (j.item (id_key), Void)
|
||||
lstr2 ?= json.object (j.item (location_key), Void)
|
||||
lstr3 ?= json.object (j.item (status_key), Void)
|
||||
l_val ?= j.item (items_key)
|
||||
|
||||
create o.make (lstr1, lstr2, lstr3)
|
||||
s_name ?= json.object (j.item (id_key), Void)
|
||||
s_key ?= json.object (j.item (location_key), Void)
|
||||
s_option ?= json.object (j.item (status_key), Void)
|
||||
|
||||
if l_val /= void then
|
||||
create o.make (s_name, s_key, s_option)
|
||||
|
||||
if attached {JSON_ARRAY} j.item (items_key) as l_val then
|
||||
l_array := l_val.array_representation
|
||||
from
|
||||
l_array.start
|
||||
until
|
||||
l_array.after
|
||||
loop
|
||||
jv ?= l_array.item_for_iteration
|
||||
if jv /= Void then
|
||||
lstr1 ?= json.object (jv.item (name_key), Void)
|
||||
lstr2 ?= json.object (jv.item (size_key), Void)
|
||||
lstr3 ?= json.object (jv.item (option_key), Void)
|
||||
q ?= json.object (jv.item (quantity_key),Void)
|
||||
if lstr1/= Void and then lstr2 /= Void and then lstr3 /= Void then
|
||||
if is_valid_item_customization(lstr1,lstr2,lstr3,q) then
|
||||
create i.make (lstr1, lstr2,lstr3, q)
|
||||
if attached {JSON_OBJECT} l_array.item_for_iteration as jv then
|
||||
if attached {INTEGER_8} json.object (jv.item (quantity_key), Void) as l_integer then
|
||||
q := l_integer
|
||||
else
|
||||
q := 0
|
||||
end
|
||||
|
||||
s_name ?= json.object (jv.item (id_key), Void)
|
||||
s_key ?= json.object (jv.item (location_key), Void)
|
||||
s_option ?= json.object (jv.item (status_key), Void)
|
||||
|
||||
if s_name /= Void and s_key /= Void and s_option /= Void then
|
||||
if is_valid_item_customization (s_name, s_key, s_option,q) then
|
||||
create i.make (s_name, s_key, s_option, q)
|
||||
o.add_item (i)
|
||||
else
|
||||
is_valid_from_json := false
|
||||
is_valid_from_json := False
|
||||
end
|
||||
else
|
||||
is_valid_from_json := false
|
||||
is_valid_from_json := False
|
||||
end
|
||||
end
|
||||
|
||||
@@ -75,7 +84,6 @@ feature -- Conversion
|
||||
else
|
||||
Result := o
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
to_json (o: like object): like value
|
||||
@@ -98,7 +106,7 @@ feature -- Conversion
|
||||
i := o.items.item_for_iteration
|
||||
create jv.make
|
||||
jv.put (json.value (i.name), name_key)
|
||||
jv.put (json.value (i.size),size_key)
|
||||
jv.put (json.value (i.size), size_key)
|
||||
jv.put (json.value (i.quantity), quantity_key)
|
||||
jv.put (json.value (i.option), option_key)
|
||||
ja.add (jv)
|
||||
@@ -108,6 +116,7 @@ feature -- Conversion
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
id_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("id")
|
||||
@@ -147,12 +156,12 @@ feature -- Conversion
|
||||
create Result.make_json ("quantity")
|
||||
end
|
||||
|
||||
|
||||
option_key : JSON_STRING
|
||||
|
||||
once
|
||||
create Result.make_json ("option")
|
||||
end
|
||||
|
||||
feature -- Validation
|
||||
|
||||
is_valid_item_customization ( name : STRING_32; size: STRING_32; option : STRING_32; quantity : INTEGER_8 ) : BOOLEAN
|
||||
@@ -163,4 +172,7 @@ feature -- Validation
|
||||
Result := ic.is_valid_coffee_type (name) and ic.is_valid_milk_type (option) and ic.is_valid_size_option (size) and quantity > 0
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -12,14 +12,14 @@ feature -- Initialization
|
||||
|
||||
make ( an_id : detachable STRING_32; a_location: detachable STRING_32; a_status: detachable STRING_32)
|
||||
do
|
||||
create {ARRAYED_LIST[ITEM]}items.make (10)
|
||||
create {ARRAYED_LIST [ITEM]} items.make (10)
|
||||
if an_id /= Void then
|
||||
set_id(an_id)
|
||||
set_id (an_id)
|
||||
else
|
||||
set_id ("")
|
||||
end
|
||||
if a_location /= Void then
|
||||
set_location(a_location)
|
||||
set_location (a_location)
|
||||
else
|
||||
set_location ("")
|
||||
end
|
||||
@@ -40,6 +40,7 @@ feature -- Access
|
||||
revision : INTEGER
|
||||
|
||||
feature -- element change
|
||||
|
||||
set_id (an_id : STRING_32)
|
||||
do
|
||||
id := an_id
|
||||
@@ -61,7 +62,6 @@ feature -- element change
|
||||
status_asigned : status.same_string (a_status)
|
||||
end
|
||||
|
||||
|
||||
add_item (a_item : ITEM)
|
||||
require
|
||||
valid_item: a_item /= Void
|
||||
@@ -71,7 +71,6 @@ feature -- element change
|
||||
has_item : items.has (a_item)
|
||||
end
|
||||
|
||||
|
||||
add_revision
|
||||
do
|
||||
revision := revision + 1
|
||||
@@ -106,4 +105,7 @@ feature -- Report
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -51,4 +51,7 @@ feature -- Access
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -13,4 +13,7 @@ feature
|
||||
create Result
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -5,10 +5,10 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ORDER_HANDLER[C -> REQUEST_HANDLER_CONTEXT]
|
||||
ORDER_HANDLER [C -> REQUEST_HANDLER_CONTEXT]
|
||||
inherit
|
||||
REQUEST_HANDLER[C]
|
||||
REQUEST_RESOURCE_HANDLER_HELPER[C]
|
||||
REQUEST_HANDLER [C]
|
||||
REQUEST_RESOURCE_HANDLER_HELPER [C]
|
||||
redefine
|
||||
do_get,
|
||||
do_post,
|
||||
@@ -20,8 +20,8 @@ inherit
|
||||
REFACTORING_HELPER
|
||||
SHARED_ORDER_VALIDATION
|
||||
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
-- Execute request handler
|
||||
do
|
||||
@@ -29,7 +29,9 @@ feature -- execute
|
||||
end
|
||||
|
||||
feature -- API DOC
|
||||
|
||||
api_doc : STRING = "URI:/order METHOD: POST%N URI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
@@ -43,7 +45,7 @@ feature -- HTTP Methods
|
||||
l_order : detachable ORDER
|
||||
jv : detachable JSON_VALUE
|
||||
id : STRING
|
||||
uri : LIST[READABLE_STRING_32]
|
||||
uri : LIST [READABLE_STRING_32]
|
||||
h : EWF_HEADER
|
||||
do
|
||||
if attached req.orig_path_info as orig_path then
|
||||
@@ -56,7 +58,7 @@ feature -- HTTP Methods
|
||||
jv ?= json.value (l_order)
|
||||
if attached jv as j then
|
||||
create h.make
|
||||
h.put_status (ok)
|
||||
h.put_status ({HTTP_STATUS_CODE}.ok)
|
||||
h.put_content_type ("application/json")
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
@@ -64,12 +66,12 @@ feature -- HTTP Methods
|
||||
if l_order /= Void then
|
||||
h.add_header ("Etag: " + l_order.etag)
|
||||
end
|
||||
res.set_status_code (ok)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (j.representation)
|
||||
end
|
||||
else
|
||||
handle_resource_not_found_response ("The following resource"+ orig_path+ " is not found ", req.content_type, res)
|
||||
handle_resource_not_found_response ("The following resource" + orig_path + " is not found ", ctx, req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -85,7 +87,7 @@ feature -- HTTP Methods
|
||||
fixme ("TODO handle an Internal Server Error")
|
||||
fixme ("Refactor the code, create new abstractions")
|
||||
fixme ("Add Header Date to the response")
|
||||
fixme ("Put implememntation is wrong!!!!")
|
||||
fixme ("Put implementation is wrong!!!!")
|
||||
req.input.read_stream (req.content_length_value.as_integer_32)
|
||||
l_post := req.input.last_string
|
||||
l_order := extract_order_request(l_post)
|
||||
@@ -93,7 +95,7 @@ feature -- HTTP Methods
|
||||
if l_order /= Void and then db_access.orders.has_key (l_order.id) then
|
||||
update_order( l_order)
|
||||
create h.make
|
||||
h.put_status (ok)
|
||||
h.put_status ({HTTP_STATUS_CODE}.ok)
|
||||
h.put_content_type ("application/json")
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
@@ -105,16 +107,15 @@ feature -- HTTP Methods
|
||||
jv ?= json.value (l_order)
|
||||
if jv /= Void then
|
||||
h.put_content_length (jv.representation.count)
|
||||
res.set_status_code (ok)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (jv.representation)
|
||||
end
|
||||
else
|
||||
handle_bad_request_response(l_post +"%N is not a valid ORDER, maybe the order does not exist in the system",req.content_type,res)
|
||||
handle_bad_request_response (l_post +"%N is not a valid ORDER, maybe the order does not exist in the system", ctx, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
do_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
local
|
||||
uri: LIST [READABLE_STRING_32]
|
||||
@@ -129,15 +130,15 @@ feature -- HTTP Methods
|
||||
if db_access.orders.has_key (id) then
|
||||
delete_order( id)
|
||||
create h.make
|
||||
h.put_status (no_content)
|
||||
h.put_status ({HTTP_STATUS_CODE}.no_content)
|
||||
h.put_content_type ("application/json")
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
h.put_utc_date (time)
|
||||
end
|
||||
res.set_status_code (no_content)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.no_content)
|
||||
res.write_headers_string (h.string)
|
||||
else
|
||||
handle_resource_not_found_response (orig_path + " not found in this server",req.content_type, res)
|
||||
handle_resource_not_found_response (orig_path + " not found in this server", ctx, req, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -153,50 +154,45 @@ feature -- HTTP Methods
|
||||
-- HTTP_RESPONSE 500 INTERNAL_SERVER_ERROR, when the server can deliver the request
|
||||
local
|
||||
l_post: STRING
|
||||
l_order : detachable ORDER
|
||||
do
|
||||
req.input.read_stream (req.content_length_value.as_integer_32)
|
||||
l_post := req.input.last_string
|
||||
l_order := extract_order_request(l_post)
|
||||
if l_order /= Void then
|
||||
save_order( l_order)
|
||||
if attached extract_order_request (l_post) as l_order then
|
||||
save_order (l_order)
|
||||
compute_response_post (ctx, req, res, l_order)
|
||||
else
|
||||
handle_bad_request_response(l_post +"%N is not a valid ORDER", req.content_type,res)
|
||||
handle_bad_request_response (l_post +"%N is not a valid ORDER", ctx, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
compute_response_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER)
|
||||
local
|
||||
h: EWF_HEADER
|
||||
l_msg : STRING
|
||||
jv : detachable JSON_VALUE
|
||||
l_location : STRING
|
||||
do
|
||||
create h.make
|
||||
h.put_status (created)
|
||||
h.put_content_type ("application/json")
|
||||
jv ?= json.value (l_order)
|
||||
if jv /= Void then
|
||||
h.put_status ({HTTP_STATUS_CODE}.created)
|
||||
h.put_content_type_application_json
|
||||
if attached {JSON_VALUE} json.value (l_order) as jv then
|
||||
l_msg := jv.representation
|
||||
h.put_content_length (l_msg.count)
|
||||
if attached req.http_host as host then
|
||||
l_location := "http://"+host +req.request_uri+"/" + l_order.id
|
||||
h.add_header ("Location:"+ l_location)
|
||||
l_location := "http://" + host + req.request_uri + "/" + l_order.id
|
||||
h.put_location (l_location)
|
||||
end
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
h.add_header ("Date:" + time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
end
|
||||
res.set_status_code (created)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.created)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (l_msg)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Implementation Repository Layer
|
||||
feature {NONE} -- Implementation Repository Layer
|
||||
|
||||
save_order ( an_order : ORDER)
|
||||
save_order (an_order: ORDER)
|
||||
-- save the order to the repository
|
||||
local
|
||||
i : INTEGER
|
||||
@@ -214,14 +210,14 @@ feature -- Implementation Repository Layer
|
||||
db_access.orders.force (an_order, an_order.id)
|
||||
end
|
||||
|
||||
update_order ( an_order : ORDER)
|
||||
update_order (an_order: ORDER)
|
||||
-- update the order to the repository
|
||||
do
|
||||
an_order.add_revision
|
||||
db_access.orders.force (an_order, an_order.id)
|
||||
end
|
||||
|
||||
delete_order ( an_order : STRING)
|
||||
delete_order (an_order: STRING)
|
||||
-- update the order to the repository
|
||||
do
|
||||
db_access.orders.remove (an_order)
|
||||
@@ -233,17 +229,16 @@ feature -- Implementation Repository Layer
|
||||
local
|
||||
joc : JSON_ORDER_CONVERTER
|
||||
parser : JSON_PARSER
|
||||
l_order : detachable ORDER
|
||||
jv : detachable JSON_VALUE
|
||||
do
|
||||
create joc.make
|
||||
json.add_converter(joc)
|
||||
create parser.make_parser (l_post)
|
||||
jv ?= parser.parse
|
||||
if jv /= Void and parser.is_parsed then
|
||||
l_order ?= json.object (jv, "ORDER")
|
||||
Result := l_order
|
||||
if attached parser.parse as jv and parser.is_parsed then
|
||||
Result ?= json.object (jv, "ORDER")
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -16,15 +16,11 @@ inherit
|
||||
|
||||
DEFAULT_WGI_APPLICATION
|
||||
|
||||
WGI_RESPONSE_STATUS_CODES
|
||||
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
|
||||
make
|
||||
do
|
||||
initialize_router
|
||||
@@ -33,7 +29,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
create_router
|
||||
do
|
||||
create router.make (5)
|
||||
create router.make (2)
|
||||
end
|
||||
|
||||
setup_router
|
||||
@@ -51,7 +47,6 @@ feature -- Execution
|
||||
-- I'm using this method to handle the method not allowed response
|
||||
-- in the case that the given uri does not have a corresponding http method
|
||||
-- to handle it.
|
||||
|
||||
local
|
||||
h : EWF_HEADER
|
||||
l_description : STRING
|
||||
@@ -61,19 +56,19 @@ feature -- Execution
|
||||
req.input.read_stream (req.content_length_value.as_integer_32)
|
||||
end
|
||||
create h.make
|
||||
h.put_status (method_not_allowed)
|
||||
h.put_content_type ("application/json")
|
||||
h.put_status ({HTTP_STATUS_CODE}.method_not_allowed)
|
||||
h.put_content_type_text_plain
|
||||
l_api_doc := "%NPlease check the API%NURI:/order METHOD: POST%NURI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
|
||||
l_description := req.request_method + req.request_uri + " is not allowed" + "%N" + l_api_doc
|
||||
h.put_content_length (l_description.count)
|
||||
h.add_header ("Date:"+ ((create{HTTP_DATE_TIME_UTILITIES}).now_utc).formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
res.set_status_code (method_not_allowed)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (l_description)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,258 +0,0 @@
|
||||
note
|
||||
description: "Based on http://en.wikipedia.org/wiki/List_of_HTTP_status_codes."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WGI_RESPONSE_STATUS_CODES
|
||||
|
||||
feature -- 1xx Informational
|
||||
|
||||
Continue : INTEGER = 100
|
||||
--This means that the server has received the request headers, and that the client should proceed to send the request body
|
||||
--(in the case of a request for which a body needs to be sent; for example, a POST request).
|
||||
--If the request body is large, sending it to a server when a request has already been rejected based upon inappropriate headers is inefficient.
|
||||
--To have a server check if the request could be accepted based on the request's headers alone,
|
||||
--a client must send Expect: 100-continue as a header in its initial request[2] and check if a 100 Continue status code is received in response
|
||||
--before continuing (or receive 417 Expectation Failed and not continue).
|
||||
|
||||
Switching_Protocols : INTEGER = 101
|
||||
--This means the requester has asked the server to switch protocols and the server is acknowledging that it will do so.
|
||||
|
||||
Processing : INTEGER = 102 -- (WebDAV) (RFC 2518)
|
||||
--As a WebDAV request may contain many sub-requests involving file operations, it may take a long time to complete the request.
|
||||
--This code indicates that the server has received and is processing the request, but no response is available yet.
|
||||
--This prevents the client from timing out and assuming the request was lost.
|
||||
|
||||
Checkpoint : INTEGER = 103
|
||||
--This code is used in the Resumable HTTP Requests Proposal to resume aborted PUT or POST requests.
|
||||
|
||||
Request_URI_too_long_ie7 : INTEGER = 122
|
||||
--This is a non-standard IE7-only code which means the URI is longer than a maximum of 2083 characters
|
||||
|
||||
|
||||
feature -- 2xx Success
|
||||
|
||||
OK : INTEGER = 200
|
||||
--Standard response for successful HTTP requests. The actual response will depend on the request method used.
|
||||
--In a GET request, the response will contain an entity corresponding to the requested resource.
|
||||
--In a POST request the response will contain an entity describing or containing the result of the action.
|
||||
|
||||
Created : INTEGER = 201
|
||||
--The request has been fulfilled and resulted in a new resource being created.
|
||||
|
||||
Accepted : INTEGER = 202
|
||||
--The request has been accepted for processing, but the processing has not been completed.
|
||||
--The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place.
|
||||
|
||||
Non_Authoritative_Information : INTEGER = 203 --(since HTTP/1.1)
|
||||
--The server successfully processed the request, but is returning information that may be from another source.
|
||||
|
||||
No_Content : INTEGER = 204
|
||||
--The server successfully processed the request, but is not returning any content.
|
||||
|
||||
Reset_Content : INTEGER = 205
|
||||
--The server successfully processed the request, but is not returning any content.
|
||||
--Unlike a 204 response, this response requires that the requester reset the document view.
|
||||
|
||||
|
||||
Partial_Content : INTEGER = 206
|
||||
--The server is delivering only part of the resource due to a range header sent by the client.
|
||||
--The range header is used by tools like wget to enable resuming of interrupted downloads,
|
||||
--or split a download into multiple simultaneous streams.
|
||||
|
||||
Multi_Status : INTEGER = 207 --(WebDAV) (RFC 4918)
|
||||
--The message body that follows is an XML message and can contain a number of separate response codes,
|
||||
-- depending on how many sub-requests were made.
|
||||
|
||||
IM_Used : INTEGER = 226 -- (RFC 3229)
|
||||
--The server has fulfilled a GET request for the resource, and the response is a representation of the result of one
|
||||
--or more instance-manipulations applied to the current instance.
|
||||
|
||||
feature -- 3xx Redirection
|
||||
|
||||
|
||||
Multiple_Choices : INTEGER = 300
|
||||
--Indicates multiple options for the resource that the client may follow.
|
||||
--It, for instance, could be used to present different format options for video, list files with different extensions, or word sense disambiguation.
|
||||
|
||||
Moved_Permanently : INTEGER = 301
|
||||
--This and all future requests should be directed to the given URI.
|
||||
|
||||
Found : INTEGER = 302
|
||||
--This is an example of industrial practice contradicting the standard.
|
||||
--HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect (the original describing phrase was "Moved Temporarily"),
|
||||
--but popular browsers implemented 302 with the functionality of a 303 See Other.
|
||||
--Therefore, HTTP/1.1 added status codes 303 and 307 to distinguish between the two behaviours.
|
||||
--However, some Web applications and frameworks use the 302 status code as if it were the 303.
|
||||
|
||||
See_Other : INTEGER = 303 -- (since HTTP/1.1)
|
||||
--The response to the request can be found under another URI using a GET method.
|
||||
--When received in response to a POST (or PUT/DELETE), it should be assumed that the server
|
||||
--has received the data and the redirect should be issued with a separate GET message.
|
||||
|
||||
Not_Modified : INTEGER = 304
|
||||
--Indicates the resource has not been modified since last requested.
|
||||
--Typically, the HTTP client provides a header like the If-Modified-Since header to provide a time against which to compare.
|
||||
--Using this saves bandwidth and reprocessing on both the server and client,
|
||||
--as only the header data must be sent and received in comparison to the entirety of the page being re-processed by the server,
|
||||
--then sent again using more bandwidth of the server and client.
|
||||
|
||||
Use_Proxy : INTEGER = 305 --(since HTTP/1.1)
|
||||
--Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons.
|
||||
|
||||
Switch_Proxy : INTEGER = 306
|
||||
--No longer used. Originally meant "Subsequent requests should use the specified proxy."
|
||||
|
||||
Temporary_Redirect : INTEGER = 307 --(since HTTP/1.1)
|
||||
--In this occasion, the request should be repeated with another URI, but future requests can still use the original URI.
|
||||
--In contrast to 303, the request method should not be changed when reissuing the original request.
|
||||
--For instance, a POST request must be repeated using another POST request.
|
||||
|
||||
Resume_Incomplete : INTEGER = 308
|
||||
--This code is used in the Resumable HTTP Requests Proposal to resume aborted PUT or POST requests.
|
||||
|
||||
feature -- 4xx Client Error
|
||||
|
||||
Bad_Request : INTEGER = 400
|
||||
--The request cannot be fulfilled due to bad syntax.
|
||||
|
||||
Unauthorized : INTEGER = 401
|
||||
--Similar to 403 Forbidden, but specifically for use when authentication is possible but has failed or not yet been provided.
|
||||
--The response must include a WWW-Authenticate header field containing a challenge applicable to the requested resource.
|
||||
--See Basic access authentication and Digest access authentication.
|
||||
|
||||
Payment_Required : INTEGER = 402
|
||||
--Reserved for future use.The original intention was that this code might be used as part of some form of digital cash or micropayment scheme,
|
||||
--but that has not happened, and this code is not usually used.
|
||||
--As an example of its use, however, Apple's MobileMe service generates a 402 error ("httpStatusCode:402" in the Mac OS X Console log) if the MobileMe account is delinquent.
|
||||
|
||||
Forbidden : INTEGER = 403
|
||||
--The request was a legal request, but the server is refusing to respond to it.
|
||||
--Unlike a 401 Unauthorized response, authenticating will make no difference.
|
||||
|
||||
Not_Found : INTEGER = 404
|
||||
--The requested resource could not be found but may be available again in the future.
|
||||
--Subsequent requests by the client are permissible.
|
||||
|
||||
Method_Not_Allowed : INTEGER = 405
|
||||
--A request was made of a resource using a request method not supported by that resource;
|
||||
--for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource.
|
||||
|
||||
Not_Acceptable : INTEGER = 406
|
||||
--The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
|
||||
|
||||
Proxy_Authentication_Required : INTEGER = 407
|
||||
--The client must first authenticate itself with the proxy.
|
||||
|
||||
Request_Timeout : INTEGER = 408
|
||||
--The server timed out waiting for the request. According to W3 HTTP specifications:
|
||||
--"The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time."
|
||||
|
||||
Conflict : INTEGER = 409
|
||||
--Indicates that the request could not be processed because of conflict in the request, such as an edit conflict.
|
||||
|
||||
Gone : INTEGER = 410
|
||||
--Indicates that the resource requested is no longer available and will not be available again.
|
||||
--This should be used when a resource has been intentionally removed and the resource should be purged.
|
||||
-- Upon receiving a 410 status code, the client should not request the resource again in the future.
|
||||
-- Clients such as search engines should remove the resource from their indices.
|
||||
--Most use cases do not require clients and search engines to purge the resource, and a "404 Not Found" may be used instead.
|
||||
|
||||
Length_Required : INTEGER = 411
|
||||
--The request did not specify the length of its content, which is required by the requested resource.
|
||||
|
||||
Precondition_Failed : INTEGER = 412
|
||||
--The server does no t meet one of the preconditions that the requester put on the request.
|
||||
|
||||
Request_Entity_Too_Large : INTEGER = 413
|
||||
--The request is larger than the server is willing or able to process.
|
||||
|
||||
Request_URI_Too_Long : INTEGER = 414
|
||||
--The URI provided was too long for the server to process.
|
||||
|
||||
Unsupported_Media_Type : INTEGER = 415
|
||||
--The request entity has a media type which the server or resource does not support.
|
||||
--For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.
|
||||
|
||||
Requested_Range_Not_Satisfiable : INTEGER = 416
|
||||
--The client has asked for a portion of the file, but the server cannot supply that portion.
|
||||
--For example, if the client asked for a part of the file that lies beyond the end of the file.
|
||||
|
||||
Expectation_Failed : INTEGER = 417
|
||||
--The server cannot meet the requirements of the Expect request-header field.
|
||||
|
||||
Im_a_teapot : INTEGER = 418 --(RFC 2324)
|
||||
--This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324,
|
||||
--Hyper Text Coffee Pot Control Protocol, and is not expected to be implemented by actual HTTP servers.
|
||||
|
||||
Unprocessable_Entity : INTEGER = 422 --(WebDAV) (RFC 4918)
|
||||
--The request was well-formed but was unable to be followed due to semantic errors.
|
||||
|
||||
Locked : INTEGER = 423 --(WebDAV) (RFC 4918)
|
||||
--The resource that is being accessed is locked.
|
||||
|
||||
Failed_Dependency : INTEGER = 424 --(WebDAV) (RFC 4918)
|
||||
--The request failed due to failure of a previous request (e.g. a PROPPATCH).
|
||||
|
||||
Unordered_Collection : INTEGER = 425 --(RFC 3648)
|
||||
--Defined in drafts of "WebDAV Advanced Collections Protocol",
|
||||
--but not present in "Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol".
|
||||
|
||||
Upgrade_Required : INTEGER = 426 -- (RFC 2817)
|
||||
--The client should switch to a different protocol such as TLS/1.0.
|
||||
|
||||
No_Response : INTEGER = 444
|
||||
--A Nginx HTTP server extension. The server returns no information to the client and closes the connection (useful as a deterrent for malware).
|
||||
|
||||
Retry_With : INTEGER = 449
|
||||
--A Microsoft extension. The request should be retried after performing the appropriate action.
|
||||
|
||||
Blocked_by_Windows_Parental_Controls : INTEGER = 450
|
||||
--A Microsoft extension. This error is given when Windows Parental Controls are turned on and are blocking access to the given webpage.
|
||||
|
||||
Client_Closed_Request : INTEGER = 499
|
||||
--An Nginx HTTP server extension.
|
||||
--This code is introduced to log the case when the connection is closed by client while HTTP server is processing its request,
|
||||
-- making server unable to send the HTTP header back.
|
||||
|
||||
feature -- 5xx Server Error
|
||||
Internal_Server_Error : INTEGER = 500
|
||||
--A generic error message, given when no more specific message is suitable.
|
||||
|
||||
Not_Implemented : INTEGER = 501
|
||||
--The server either does not recognise the request method, or it lacks the ability to fulfill the request.
|
||||
|
||||
Bad_Gateway : INTEGER = 502
|
||||
--The server was acting as a gateway or proxy and received an invalid response from the upstream server.
|
||||
|
||||
Service_Unavailable : INTEGER = 503
|
||||
--The server is currently unavailable (because it is overloaded or down for maintenance). Generally, this is a temporary state.
|
||||
|
||||
Gateway_Timeout : INTEGER = 504
|
||||
--The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
|
||||
|
||||
HTTP_Version_Not_Supported : INTEGER = 505
|
||||
--The server does not support the HTTP protocol version used in the request.
|
||||
|
||||
Variant_Also_Negotiates : INTEGER = 506 --(RFC 2295)
|
||||
--Transparent content negotiation for the request results in a circular reference.
|
||||
|
||||
Insufficient_Storage : INTEGER = 507 -- (WebDAV)(RFC 4918)
|
||||
--The server is unable to store the representation needed to complete the request.
|
||||
|
||||
Bandwidth_Limit_Exceeded : INTEGER = 509 -- (Apache bw/limited extension)
|
||||
--This status code, while used by many servers, is not specified in any RFCs.
|
||||
|
||||
Not_Extended : INTEGER = 510 -- (RFC 2774)
|
||||
--Further extensions to the request are required for the server to fulfill it.[20]
|
||||
|
||||
network_read_timeout_error : INTEGER = 598 --598 (Informal convention)
|
||||
--This status code is not specified in any RFCs, but is used by some HTTP proxies to signal a network read
|
||||
--timeout behind the proxy to a client in front of the proxy.
|
||||
|
||||
network_connect_timeout_error : INTEGER = 599
|
||||
--This status code is not specified in any RFCs, but is used by some HTTP proxies to signal a
|
||||
--network connect timeout behind the proxy to a client in front of the proxy.
|
||||
end
|
||||
@@ -207,6 +207,23 @@ feature -- Content related header
|
||||
|
||||
feature -- Others
|
||||
|
||||
put_date (s: READABLE_STRING_8)
|
||||
do
|
||||
put_header_key_value ("Date", s)
|
||||
end
|
||||
|
||||
put_current_date
|
||||
-- Put current date time with "Date" header
|
||||
do
|
||||
put_utc_date (create {DATE_TIME}.make_now_utc)
|
||||
end
|
||||
|
||||
put_utc_date (dt: DATE_TIME)
|
||||
-- Put UTC date time `dt' with "Date" header
|
||||
do
|
||||
put_date (dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
end
|
||||
|
||||
put_expires (n: INTEGER)
|
||||
do
|
||||
put_header_key_value ("Expires", n.out)
|
||||
|
||||
@@ -1,251 +1,233 @@
|
||||
note
|
||||
description: "Work in progress Common abstraction to handle REST methods"
|
||||
description: "Work in progress Common abstraction to handle RESTfull methods"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
REQUEST_RESOURCE_HANDLER_HELPER[C -> REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
HTTP_STATUS_CODE
|
||||
REQUEST_RESOURCE_HANDLER_HELPER [C -> REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
feature -- Execute template
|
||||
|
||||
execute_methods (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
-- Execute request and dispatch according to the request method
|
||||
local
|
||||
m: READABLE_STRING_8
|
||||
do
|
||||
if req.request_method.same_string ("GET") then
|
||||
execute_get (ctx,req,res)
|
||||
elseif req.request_method.same_string ("PUT") then
|
||||
execute_put (ctx,req,res)
|
||||
elseif req.request_method.same_string ("DELETE") then
|
||||
execute_delete (ctx,req,res)
|
||||
elseif req.request_method.same_string ("POST") then
|
||||
execute_post (ctx,req,res)
|
||||
elseif req.request_method.same_string ("TRACE") then
|
||||
execute_trace (ctx,req,res)
|
||||
elseif req.request_method.same_string ("OPTIONS") then
|
||||
execute_options (ctx,req,res)
|
||||
elseif req.request_method.same_string ("HEAD") then
|
||||
execute_head (ctx,req,res)
|
||||
elseif req.request_method.same_string ("CONNECT") then
|
||||
execute_connect (ctx,req,res)
|
||||
-- elseif req.request_method.is_valid_extension_method then
|
||||
-- execute_extension_method (req,res)
|
||||
m := req.request_method
|
||||
if m.same_string ("GET") then
|
||||
execute_get (ctx, req, res)
|
||||
elseif m.same_string ("PUT") then
|
||||
execute_put (ctx, req, res)
|
||||
elseif m.same_string ("DELETE") then
|
||||
execute_delete (ctx, req, res)
|
||||
elseif m.same_string ("POST") then
|
||||
execute_post (ctx, req, res)
|
||||
elseif m.same_string ("TRACE") then
|
||||
execute_trace (ctx, req, res)
|
||||
elseif m.same_string ("OPTIONS") then
|
||||
execute_options (ctx, req, res)
|
||||
elseif m.same_string ("HEAD") then
|
||||
execute_head (ctx, req, res)
|
||||
elseif m.same_string ("CONNECT") then
|
||||
execute_connect (ctx, req, res)
|
||||
else
|
||||
--| Eventually handle other methods...
|
||||
end
|
||||
rescue
|
||||
handle_internal_server_error ("Internal Server Error", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method Post
|
||||
|
||||
feature-- Method Post
|
||||
execute_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
if req.content_length_value > 0 then
|
||||
do_post (ctx,req,res)
|
||||
do_post (ctx, req, res)
|
||||
else
|
||||
handle_bad_request_response("Bad request, content_lenght empty", req.content_type, res)
|
||||
handle_bad_request_response ("Bad request, content_length empty", ctx, req, res)
|
||||
end
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error",req.content_type,res)
|
||||
end
|
||||
|
||||
do_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method POST not implemented", req.content_type, res)
|
||||
handle_not_implemented ("Method POST not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature-- Method Put
|
||||
|
||||
execute_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
if req.content_length_value > 0 then
|
||||
do_put (ctx,req,res)
|
||||
do_put (ctx, req, res)
|
||||
else
|
||||
handle_bad_request_response("Bad request, content_lenght empty", req.content_type, res)
|
||||
handle_bad_request_response ("Bad request, content_length empty", ctx, req, res)
|
||||
end
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error", req.content_type,res)
|
||||
end
|
||||
|
||||
do_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method PUT not implemented", req.content_type,res)
|
||||
handle_not_implemented ("Method PUT not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method Get
|
||||
|
||||
execute_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_get (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error",req.content_type,res)
|
||||
do_get (ctx, req, res)
|
||||
end
|
||||
|
||||
do_get (ctx: C;req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method HEAD not implemented", req.content_type, res)
|
||||
handle_not_implemented ("Method HEAD not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method DELETE
|
||||
|
||||
execute_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_delete (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error",req.content_type,res)
|
||||
do_delete (ctx, req, res)
|
||||
end
|
||||
|
||||
do_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method DELETE not implemented", req.content_type, res)
|
||||
handle_not_implemented ("Method DELETE not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method CONNECT
|
||||
|
||||
execute_connect (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_connect (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error",req.content_type,res)
|
||||
do_connect (ctx, req, res)
|
||||
end
|
||||
|
||||
do_connect (ctx: C;req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method CONNECT not implemented", req.content_type, res)
|
||||
handle_not_implemented ("Method CONNECT not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method HEAD
|
||||
|
||||
execute_head (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_head (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error", req.content_type, res)
|
||||
do_head (ctx, req, res)
|
||||
end
|
||||
|
||||
do_head (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method HEAD not implemented", req.content_type, res)
|
||||
handle_not_implemented ("Method HEAD not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method OPTIONS
|
||||
|
||||
execute_options (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_options (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error",req.content_type,res)
|
||||
do_options (ctx, req, res)
|
||||
end
|
||||
|
||||
do_options (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method OPTIONS not implemented", req.content_type,res)
|
||||
handle_not_implemented ("Method OPTIONS not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method TRACE
|
||||
|
||||
execute_trace (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_trace (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error", req.content_type, res)
|
||||
do_trace (ctx, req, res)
|
||||
end
|
||||
|
||||
do_trace (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method TRACE not implemented", req.content_type,res)
|
||||
handle_not_implemented ("Method TRACE not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Method Extension Method
|
||||
|
||||
execute_extension_method (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
do_extension_method (ctx,req,res)
|
||||
rescue
|
||||
handle_internal_server_error("Internal Server Error",req.content_type,res)
|
||||
do_extension_method (ctx, req, res)
|
||||
end
|
||||
|
||||
do_extension_method (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
handle_not_implemented ("Method EXTENSION METHOD not implemented",req.content_type, res)
|
||||
handle_not_implemented ("Method EXTENSION method not implemented", ctx, req, res)
|
||||
end
|
||||
|
||||
feature -- Handle responses
|
||||
handle_bad_request_response (a_description:STRING; content_type : detachable READABLE_STRING_32 ; res: WGI_RESPONSE_BUFFER )
|
||||
|
||||
handle_bad_request_response (a_description:STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER )
|
||||
local
|
||||
h : EWF_HEADER
|
||||
do
|
||||
create h.make
|
||||
h.put_status (bad_request)
|
||||
if attached content_type as l_content_type then
|
||||
h.put_status ({HTTP_STATUS_CODE}.bad_request)
|
||||
if attached ctx.request_content_type (Void) as l_content_type then
|
||||
h.put_content_type (l_content_type)
|
||||
else
|
||||
h.put_content_type ("*/*")
|
||||
end
|
||||
h.put_content_length (a_description.count)
|
||||
h.add_header ("Date:"+ get_date)
|
||||
res.set_status_code (bad_request)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.bad_request)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (a_description)
|
||||
end
|
||||
|
||||
|
||||
|
||||
handle_internal_server_error (a_description:STRING; content_type : detachable READABLE_STRING_32 ; res: WGI_RESPONSE_BUFFER )
|
||||
handle_internal_server_error (a_description:STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER )
|
||||
local
|
||||
h : EWF_HEADER
|
||||
do
|
||||
create h.make
|
||||
h.put_status (internal_server_error)
|
||||
if attached content_type as l_content_type then
|
||||
h.put_status ({HTTP_STATUS_CODE}.internal_server_error)
|
||||
if attached ctx.request_content_type (Void) as l_content_type then
|
||||
h.put_content_type (l_content_type)
|
||||
else
|
||||
h.put_content_type ("*/*")
|
||||
end
|
||||
h.put_content_length (a_description.count)
|
||||
h.add_header ("Date:"+ get_date)
|
||||
res.set_status_code (internal_server_error)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (a_description)
|
||||
end
|
||||
|
||||
|
||||
|
||||
handle_not_implemented (a_description:STRING; content_type : detachable READABLE_STRING_32; res: WGI_RESPONSE_BUFFER )
|
||||
handle_not_implemented (a_description: STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER )
|
||||
local
|
||||
h : EWF_HEADER
|
||||
do
|
||||
create h.make
|
||||
h.put_status (not_implemented)
|
||||
if attached content_type as l_content_type then
|
||||
h.put_status ({HTTP_STATUS_CODE}.not_implemented)
|
||||
if attached ctx.request_content_type (Void) as l_content_type then
|
||||
h.put_content_type (l_content_type)
|
||||
else
|
||||
h.put_content_type ("*/*")
|
||||
end
|
||||
h.put_content_length (a_description.count)
|
||||
h.add_header ("Date:"+ get_date)
|
||||
res.set_status_code (not_implemented)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.not_implemented)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (a_description)
|
||||
end
|
||||
|
||||
|
||||
handle_resource_not_found_response (a_description:STRING; content_type : detachable READABLE_STRING_32; res: WGI_RESPONSE_BUFFER)
|
||||
handle_resource_not_found_response (a_description:STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
local
|
||||
h : EWF_HEADER
|
||||
do
|
||||
create h.make
|
||||
h.put_status (not_found)
|
||||
if attached content_type as l_content_type then
|
||||
h.put_status ({HTTP_STATUS_CODE}.not_found)
|
||||
if attached ctx.request_content_type (Void) as l_content_type then
|
||||
h.put_content_type (l_content_type)
|
||||
else
|
||||
h.put_content_type ("*/*")
|
||||
end
|
||||
h.put_content_length (a_description.count)
|
||||
h.add_header ("Date:"+ get_date)
|
||||
res.set_status_code (not_found)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||
res.write_headers_string (h.string)
|
||||
res.write_string (a_description)
|
||||
end
|
||||
|
||||
feature -- Date Utilities
|
||||
get_date : STRING
|
||||
do
|
||||
Result := ((create{HTTP_DATE_TIME_UTILITIES}).now_utc).formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT"
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
Reference in New Issue
Block a user