diff --git a/examples/restbucks/readme.txt b/examples/restbucks/readme.txt new file mode 100644 index 00000000..dfff1b30 --- /dev/null +++ b/examples/restbucks/readme.txt @@ -0,0 +1,51 @@ +Restbuck Eiffel Implementation based on the book of REST in Practice + + +Verb URI or template Use +POST /order Create a new order, and upon success, receive a Locationheader specifying the new order’s URI. +GET /order/{orderId} Request the current state of the order specified by the URI. +PUT /order/{orderId} Update an order at the given URI with new information, providing the full representation. +DELETE /order/{orderId} Logically remove the order identified by the given URI. + + +How to Create an order + + * Uri: http://localhost:8080/order + * Method: POST + * Note: you will get in the response the "location" of the new your order. + * HEADERS: + + Content-Type: application/json + + * Example CONTENT + + { + "location":"takeAway", + "items":[ + { + "name":"Late", + "option":"skim", + "size":"Small", + "quantity":1 + } + ] + } + + + +How to Read an order + * Uri: http://localhost:8080/order/{order_id} + * Method: GET + + + + +How to Update an order + * Uri: http://localhost:8080/order/{order_id} + * Method: PUT + + +How to Delete an order + * Uri: http://localhost:8080/order/{order_id} + * Method: DELETE + diff --git a/examples/restbucks/src/resource/order_handler.e b/examples/restbucks/src/resource/order_handler.e index 372abbf6..c1204e89 100644 --- a/examples/restbucks/src/resource/order_handler.e +++ b/examples/restbucks/src/resource/order_handler.e @@ -27,8 +27,6 @@ feature -- execute process_delete (ctx,req,res) elseif req.request_method.same_string ("POST") then process_post (ctx,req,res) - else - handle_method_not_allowed (req.request_method + " " + req.request_uri +"%N API Contract %N" +api_doc, res) end end @@ -37,12 +35,54 @@ feature -- API DOC feature -- HTTP Methods process_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + local + l_values: HASH_TABLE [STRING_32, STRING] + l_missings: LINKED_LIST [STRING] + l_full: BOOLEAN + l_post: STRING + joc : JSON_ORDER_CONVERTER + parser : JSON_PARSER + l_order : detachable ORDER + jv : detachable JSON_VALUE + l_location, id : STRING + uri : LIST[READABLE_STRING_32] + h : EWF_HEADER + http_if_not_match : STRING do - handle_not_implemented ("GET: "+ req.request_uri + "%N Not implemented", res) + fixme ("TODO handle error conditions") + if attached req.orig_path_info as orig_path then + uri := orig_path.split ('/') + id := uri.at (3) + create joc.make + json.add_converter(joc) + if db_access.orders.has_key (id) then + l_order := db_access.orders.item (id) + jv ?= json.value (l_order) + if attached jv as j then + create h.make + h.put_status (ok) + h.put_content_type ("application/json") + + if l_order /= Void then + h.add_header ("Etag: " + l_order.etag) + end + res.set_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 ", res) + end + end + + end process_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do + if req.content_length_value > 0 then + req.input.read_stream (req.content_length_value.as_integer_32) + end handle_not_implemented ("PUT: "+ req.request_uri + "%N Not implemented", res) end @@ -170,20 +210,6 @@ feature -- Implementation end - handle_method_not_allowed (a_description:STRING; res: WGI_RESPONSE_BUFFER ) - local - h : EWF_HEADER - do - create h.make - h.put_status (method_not_allowed) - h.put_content_type ("application/json") - h.put_content_length (a_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) - res.write_headers_string (h.string) - res.write_string (a_description) - end - handle_not_implemented (a_description:STRING; res: WGI_RESPONSE_BUFFER ) local @@ -212,17 +238,19 @@ feature -- Implementation -- end --- handle_resource_not_found_response (a_description:STRING; an_output: HTTPD_SERVER_OUTPUT ) --- local --- rep: detachable REST_RESPONSE --- do --- create rep.make (path) --- rep.headers.put_status (rep.headers.not_found) --- rep.headers.put_content_type_application_json --- rep.set_message (a_description) --- an_output.put_string (rep.string) --- rep.recycle --- end + handle_resource_not_found_response (a_description:STRING; res: WGI_RESPONSE_BUFFER) + local + h : EWF_HEADER + do + create h.make + h.put_status (not_found) + h.put_content_type ("application/json") + h.put_content_length (a_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 (not_found) + res.write_headers_string (h.string) + res.write_string (a_description) + end -- handle_method_not_supported_response (ctx :REST_REQUEST_CONTEXT) diff --git a/examples/restbucks/src/restbucks_server.e b/examples/restbucks/src/restbucks_server.e index cfca360a..8f331f93 100644 --- a/examples/restbucks/src/restbucks_server.e +++ b/examples/restbucks/src/restbucks_server.e @@ -16,6 +16,9 @@ inherit DEFAULT_WGI_APPLICATION + WGI_RESPONSE_STATUS_CODES + + create make @@ -45,147 +48,30 @@ feature {NONE} -- Initialization feature -- Execution execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + -- 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_url: STRING - e: EXECUTION_ENVIRONMENT - n: INTEGER - i: INTEGER + h : EWF_HEADER + l_description : STRING + l_api_doc : STRING do - create h.make - l_url := req.script_url ("/home") - n := 3 - h.put_refresh (l_url, 5) - res.set_status_code (200) - res.write_headers_string (h.string) - from - create e - until - n = 0 - loop - if n > 1 then - res.write_string ("Redirected to " + l_url + " in " + n.out + " seconds :%N") - else - res.write_string ("Redirected to " + l_url + " in 1 second :%N") - end - res.flush - from - i := 1 - until - i = 1001 - loop - res.write_string (".") - if i \\ 100 = 0 then - res.write_string ("%N") + if req.content_length_value > 0 then + req.input.read_stream (req.content_length_value.as_integer_32) end - res.flush - e.sleep (1_000_000) - i := i + 1 - end - res.write_string ("%N") - n := n - 1 - end - res.write_string ("You are now being redirected...%N") - res.flush + create h.make + h.put_status (method_not_allowed) + h.put_content_type ("application/json") + 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) + res.write_headers_string (h.string) + res.write_string (l_description) end - execute_home (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) - do - res.write_header (200, <<["Content-Type", "text/html"]>>) - res.write_string ("
Hello World ?!%N") - res.write_string ("