diff --git a/examples/restbucksCRUD/readme.md b/examples/restbucksCRUD/readme.md index 0d11adbe..f17c04d9 100644 --- a/examples/restbucksCRUD/readme.md +++ b/examples/restbucksCRUD/readme.md @@ -1,52 +1,287 @@ Restbuck Eiffel Implementation based on the book of REST in Practice +==================================================================== +This is an ihmplementation of CRUD pattern for manipulate resources, this is the first step to use +the HTTP protocol as an application protocol instead of a transport protocol. -This is an implementation of CRUD web services as is presented in the book +Restbuck Protocol +----------------- -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. + + + + + + +
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.
+ +Resource Represenation +---------------------- +The previous tables shows a contrat, the URI or URI template, allows us to indentify resources, now we will chose a +representacion, for this particular case we will use JSON. + +Note:
+1. *A resource can have multiple URIs*.
+2. *A resource can have multiple Representations*.
+ +RESTBUCKS_SERVER +---------------- +This class implement the main entry of our REST CRUD service, we are using a default connector (Nino Connector, +using a WebServer written in Eiffel). +We are inheriting from URI_TEMPLATE_ROUTED_SERVICE, this allows us to map our service contrat, as is shown in the previous +table, the mapping is defined in the feature setup_router, this also show that the class ORDER_HANDLER will be encharge +of to handle different type of request to the ORDER resource. -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 - } - ] - } + class + RESTBUCKS_SERVER + + inherit + ANY + + URI_TEMPLATE_ROUTED_SERVICE + + DEFAULT_SERVICE + -- Here we are using a default connector using the default Nino Connector, + -- but it's possible to use other connector (CGI or FCGI). + + create + make + + feature {NONE} -- Initialization + + make + -- Initialize the router (this will have the request handler and + -- their context). + do + initialize_router + make_and_launch + end + + create_router + do + create router.make (2) + end + + setup_router + local + order_handler: ORDER_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT] + do + create order_handler + router.map_with_request_methods ("/order", order_handler, <<"POST">>) + router.map_with_request_methods ("/order/{orderid}", order_handler, <<"GET", "DELETE", "PUT">>) + end + + feature -- Execution + + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) + -- 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 : HTTP_HEADER + l_description : STRING + l_api_doc : STRING + do + if req.content_length_value > 0 then + req.input.read_string (req.content_length_value.as_integer_32) + end + create h.make + 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.put_current_date + res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed) + res.write_header_text (h.string) + res.write_string (l_description) + end + + end -How to Read an order - * Uri: http://localhost:8080/order/{order_id} - * Method: GET +How to Create an order with POST +-------------------------------- + +Here is the convention that we are using: +POST is used for creation and the server determines the URI of the created resource. +If the request POST is SUCCESS, the server will create the order and will response with +201 CREATED, the Location header will contains the newly created order's URI, +if the request POST is not SUCCESS, the server will response with +400 BAD REQUEST, the client send a bad request or +500 INTERNAL_SERVER_ERROR, when the server can deliver the request. + + POST /order HTTP/1.1 + Host: 127.0.0.1:8080 + Connection: keep-alive + Content-Length: 196 + Origin: chrome-extension://fhjcajmcbmldlhcimfajhfbgofnpcjmb + Content-Type: application/json + Accept: */* + Accept-Encoding: gzip,deflate,sdch + Accept-Language: es-419,es;q=0.8,en;q=0.6 + Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 + + { + "location":"takeAway", + "items":[ + { + "name":"Late", + "option":"skim", + "size":"Small", + "quantity":1 + } + ] + } + +Response success + + HTTP/1.1 201 Created + Status 201 Created + Content-Type application/json + Content-Length 123 + Location http://localhost:8080/order/1 + Date FRI,09 DEC 2011 20:34:20.00 GMT + + { + "id" : "1", + "location" : "takeAway", + "status" : "submitted", + "items" : [ { + "name" : "late", + "size" : "small", + "quantity" : 1, + "option" : "skim" + } ] + } + + +How to Read an order with GET +----------------------------- +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 Conditional GET and the resource does not change we send a 304, Resource not modifed + + HTTP/1.1 200 OK + + Status 200 OK + Content-Type application/json + Content-Length 123 + Date FRI,09 DEC 2011 20:53:46.00 GMT + etag 2ED3A40954A95D766FC155682DC8BB52 + + { + "id" : "1", + "location" : "takeAway", + "status" : "submitted", + "items" : [ { + "name" : "late", + "size" : "small", + "quantity" : 1, + "option" : "skim" + } ] + } +How to Update an order with PUT +------------------------------- +A successful PUT request will not create a new resource, instead it will change the state of the resource identified by the current uri. +If success we response with 200 and the updated order. +404 if the order is not found +400 in case of a bad request +500 internal server error +If the request is a Conditional PUT, and it does not mat we response 415, precondition failed. -How to Update an order - * Uri: http://localhost:8080/order/{order_id} - * Method: PUT +Suposse that we had created an Order with the values shown in the _How to create an order with POST_ +But we change our decision and we want to stay in the shop. -How to Delete an order - * Uri: http://localhost:8080/order/{order_id} - * Method: DELETE + PUT /order/1 HTTP/1.1 + Content-Length: 122 + Content-Type: application/json; charset=UTF-8 + Host: localhost:8080 + Connection: Keep-Alive + Expect: 100-Continue + + { + "id" : "1", + "location" : "in shop", + "status" : "submitted", + "items" : [ { + "name" : "late", + "size" : "small", + "quantity" : 1, + "option" : "skim" + } ] + } + + +Response success + + HTTP/1.1 200 OK + Status 200 OK + Content-Type application/json + Date FRI,09 DEC 2011 21:06:26.00 GMT + etag 8767F900674B843E1F3F70BCF3E62403 + Content-Length 122 + + { + "id" : "1", + "location" : "in shop", + "status" : "submitted", + "items" : [ { + "name" : "late", + "size" : "small", + "quantity" : 1, + "option" : "skim" + } ] + } + +How to Delete an order with DELETE +---------------------------------- +Here we use DELETE to cancel an order, if that order is in state where it can still be canceled. +204 if is ok +404 Resource not found +405 if consumer and service's view of the resouce state is inconsisent +500 if we have an internal server error + + + DELETE /order/1 HTTP/1.1 + Host: localhost:8080 + Connection: Keep-Alive + +Response success + + HTTP/1.1 204 No Content + + Status 204 No Content + Content-Type application/json + Date FRI,09 DEC 2011 21:10:51.00 GMT + +If we want to check that the resource does not exist anymore we can try to retrieve a GET /order/1 and we will receive a +404 No Found + + GET /order/1 HTTP/1.1 + Host: localhost:8080 + Connection: Keep-Alive + +Response + + HTTP/1.1 404 Not Found + + Status 404 Not Found + Content-Type application/json + Content-Length 44 + Date FRI,09 DEC 2011 21:14:17.79 GMT + + The following resource/order/1 is not found + + +References +---------- +1. [How to get a cup of coffe](http://www.infoq.com/articles/webber-rest-workflow) +2. [Rest in Practice] (http://restinpractice.com/default.aspx)