http status, rest api verbs put vs post, standards and naming convention of resources - josuamanuel/softwareDevelopmentPrinciples GitHub Wiki
http status
1xx: Informational - Communicates transfer protocol-level information 2xx: Success -Indicates that the client’s request was accepted successfully. 3xx: Redirection - Indicates that the client must take some additional action in order to complete their request. 4xx: Client Error - This category of error status codes points the finger at clients. 5xx: Server Error - The server takes responsibility for these error status codes.
* 200 OK
* 204 The existance of the request resource is guaranteed but the filter returns not elements or the response is an empty body.
* 302 Redirect
* 400 Bad request. Prameters are not allowed. path directories not mapping any valid request.
* 404 Resource not found. Maybe they exist but not in the right combination expected.
* 500 Server error.
* 504 Timeout.
https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/
Customer: id: 1 Name: Jose TypeTel1: Mobile Tel1: 07715242692 TypeTel2: landline Tel2: 07951312123
id: 2
Name: Antonia
TypeTel: Mobile
Tel1: 09129312312
id: 3
Name: Pepe
TypeTel: landline
Tel1: 09122322342
Houses: id: 1 address: 2 cornell road colour: red
id: 2
address: 10 Medhurst
colour: blue
id: 3
address: Raven court 2
colour: green
Customer-House:
customer.id: 1
house.id: 1
Date-buy: 2018-02-02
customer.id: 3
house.id: 2
Date-buy: 2018-02-02
FirstBuyRef: 12312412431
Agency: (without any items)
get customersaasas -> 400 Bad request. I cannot map the request to a valid service. Entity name doesn’t exist. get customers/xxxxx -> 400 Bad request. Customer entity only accept numbers. Validation of the input request was not met. get customers/1 -> 200 id: 1, Name: Jose... get customers/4 -> 404 Resource not found get customers?TypeTel=satellite -> 204 Resource url seems to be valid but nothing found. get customers/2?property=tel2 -> 204 If I can guarantee customer 2 exist but the property tel2 doesnt for this customer then 204 Otherwise 404 is more recommended.
get customers/1?property=tel2 -> 200 Tel2: 07951312123 get customers/houses -> 200 {[customer.id:1,house.id:2....],[customer.id:3,house.id:2....] get customers/houses?colour=green -> 204 We know customers and houses are valid entity names but the filter finds nothing. get customers/4/houses -> 404 It could only return 204 if it checks (though it doesnt have to) that there is a customer with id:4 and entity names customers and houses exists.
get customers/housesasa -> 400 even though customers is a valid entity houseasa doesnt match the name of a valid entity. get agencies -> 204 Entity agency exist but nothing to return.
1.- Something to consider is that the resource subject is the entire URI (removing protocol: ex: https://) and not only the values. For example get cards/{card-id}/cardblocks/{typeofblock} -> get cards/1234123412341234/cardblocks/freeze Then if we know the existence of card-id=1234123412341234 but this card-id doesn’t have typeofblock=freeze then we should return 404 instead of 204. The existence of the resource is defined by the entire URI path
2.- Order of identifiers in the resource path should be hierarchical. Exa: customers/f12312/cards/123123123/cardblocks
1 customer could have several cards and each card could have multiple contracts.
Unfortunately Some Organizations require the first part to describe the service to hit: customers//cards//cardblocks is not allowed in openshift, so routing a request to cardblocks service will not be possible because there is no way to match customer value f12312 and cards value 123123123 in the path.
3.- Resources that returns information aggregated from different resources. Experience resources: The definition of the response is highly condition for the requirements of the clients consuming API. The goal is to provide an experience to the customer. This will mean that they should return 200 and then informing in the response body of what they could found and what is missing.
Example get customers/f12312/contracts/123123123/cards/card-blocks
Response 1: if customer f12312 is not found so no data is returned. 404 body: {}
Other option is if we know that the customer exists but attributes customerName, contractStatus, cards don’t optionally we could return: 204 body: {}
Response 2: 200 Body: { “customer”: { “id”: ”f12312”, “customerName”: “Jose Marin” }, “contract”: { “id”: ”123123123”, “contractStatus”: ”A” }, “cards”: [ { “cardId”: “12312312”, “cardblocks”: { “freeze”: true, “atm”: false } }, { “cardId”: “8977655”, “cardBlocks”: { “freeze”: false, “atm”: true } } ] }
Response 3: 200 Body: { “customer”: {“id”: ”f12312”, “customerName”: “Jose Marin”}, “contract”: null, “cards”: null }
Response 3: 200 Body: { “customer”: { “id”: ”f12312”, “customerName”: null }, “contract”: { “id”: ”123123123”, “contractStatus”: ”A” }, “cards”: [ { “cardId”: “12312312”, “cardblocks”:null } ] }
Errors
4.- How to communicate Errors in Resources that returns information aggregated (experience MS): Experience MS are a little bit different as requirements are trying to tackle client needs. If there is a server error that stops from collecting some but not all of the information, the client can still use this information. Then it will need to respond with a 200. A 500 response will indicate that response data related to the resource can not be used except the error information supplied. Then for this type of services we will need to return in most cases error-handling information in the body:
For example:
Response 3: 200 Body: { “error”: { customer: {“status”:”200”,”message”: null} contract:{“status”:”500”,”message”:”status of card with a value C not in card_status_type”} cards:{“status”: null, “message”:null} }
“customer”: {“id”: ”f12312”, “customerName”: “Jose Marin”}, “contract”: null, “cards”: null }
Verbs and general estandards
10 Best Practices for Better RESTful API 0140602_restful_api_checklist_img Web APIs has become an very important topic in the last year. We at M-Way Solutions are working every day with different backend systems and therefore we know about the importance of a clean API design. Typically we use a RESTful design for our web APIs. The concept of REST is to separate the API structure into logical resources. There are used the HTTP methods GET, DELETE, POST and PUT to operate with the resources. These are 10 best practices to design a clean RESTful API:
-
Use nouns but no verbs For an easy understanding use this structure for every resource: Resource GET read POST create PUT update DELETE /cars Returns a list of cars Create a new car Bulk update of cars Delete all cars /cars/711 Returns a specific car Method not allowed (405) Updates a specific car Deletes a specific car Do not use verbs: /getAllCars /createNewCar /deleteAllRedCars
-
GET method and query parameters should not alter the state Use PUT, POST and DELETE methods instead of the GET method to alter the state. Do not use GET for state changes: GET /users/711?activate or GET /users/711/activate
-
Use plural nouns Do not mix up singular and plural nouns. Keep it simple and use only plural nouns for all resources. /cars instead of /car /users instead of /user /products instead of /product /settings instead of /setting
-
Use sub-resources for relations If a resource is related to another resource use subresources. GET /cars/711/drivers/ Returns a list of drivers for car 711 GET /cars/711/drivers/4 Returns driver #4 for car 711
-
Use HTTP headers for serialization formats Both, client and server, need to know which format is used for the communication. The format has to be specified in the HTTP-Header. Content-Type defines the request format. Accept defines a list of acceptable response formats.
-
Use HATEOAS Hypermedia as the Engine of Application State is a principle that hypertext links should be used to create a better navigation through the API. 01 { 02 "id": 711, 03 "manufacturer": "bmw", 04 "model": "X5", 05 "seats": 5, 06 "drivers": [ 07 { 08 "id": "23", 09 "name": "Stefan Jauker", 10 "links": [ 11 { 12 "rel": "self", 13 "href": "/api/v1/drivers/23" 14 } 15 ] 16 } 17 ] 18 }
-
Provide filtering, sorting, field selection and paging for collections Filtering: Use a unique query parameter for all fields or a query language for filtering. GET /cars?color=red Returns a list of red cars GET /cars?seats<=2 Returns a list of cars with a maximum of 2 seats Sorting: Allow ascending and descending sorting over multiple fields. GET /cars?sort=-manufactorer,+model This returns a list of cars sorted by descending manufacturers and ascending models. Field selection Mobile clients display just a few attributes in a list. They don’t need all attributes of a resource. Give the API consumer the ability to choose returned fields. This will also reduce the network traffic and speed up the usage of the API. GET /cars?fields=manufacturer,model,id,color Paging Use limit and offset. It is flexible for the user and common in leading databases. The default should be limit=20 and offset=0 GET /cars?offset=10&limit=5 To send the total entries back to the user use the custom HTTP header: X-Total-Count. Links to the next or previous page should be provided in the HTTP header link as well. It is important to follow this link header values instead of constructing your own URLs. Link: https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5; rel="next", https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3; rel="last", https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5; rel="first", https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5; rel="prev",
-
Version your API Make the API Version mandatory and do not release an unversioned API. Use a simple ordinal number and avoid dot notation such as 2.5. We are using the url for the API versioning starting with the letter „v“ /blog/api/v1
-
Handle Errors with HTTP status codes It is hard to work with an API that ignores error handling. Pure returning of a HTTP 500 with a stacktrace is not very helpful.
Use HTTP status codes The HTTP standard provides over 70 status codes to describe the return values. We don’t need them all, but there should be used at least a mount of 10. 200 – OK – Eyerything is working 201 – OK – New resource has been created 204 – OK – The resource was successfully deleted 304 – Not Modified – The client can use cached data 400 – Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g. „The JSON is not valid“ 401 – Unauthorized – The request requires an user authentication 403 – Forbidden – The server understood the request, but is refusing it or the access is not allowed. 404 – Not found – There is no resource behind the URI. 422 – Unprocessable Entity – Should be used if the server cannot process the enitity, e.g. if an image cannot be formatted or mandatory fields are missing in the payload. 500 – Internal Server Error – API developers should avoid this error. If an error occurs in the global catch blog, the stracktrace should be logged and not returned as response. Use error payloads All exceptions should be mapped in an error payload. Here is an example how a JSON payload should look like. 01 { 02 "errors": [ 03 { 04 "userMessage": "Sorry, the requested resource does not exist", 05 "internalMessage": "No car found in the database", 06 "code": 34, 07 "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345" 08 } 09 ] 10 } 10. Allow overriding HTTP method Some proxies support only POST and GET methods. To support a RESTful API with these limitations, the API needs a way to override the HTTP method. Use the custom HTTP Header X-HTTP-Method-Override to overrider the POST Method.
http://nanvel.name/2016/02/rest
VERBs
https://restfulapi.net/http-methods/
GET: List the members of the collection, complete with their member URIs for further navigation. For example, list all the cars for sale. Use GET requests to retrieve resource representation/information only – and not to modify it in any way. As GET requests do not change the state of the resource, these are said to be safe methods. Additionally, GET APIs should be idempotent, which means that making multiple identical requests must produce the same result every time until another API (POST or PUT) has changed the state of the resource on the server. This is why we could call a request get /time as we should get the same time until another api (post or put) updates the clock after one tick.
PUT: Meaning defined as "replace the entire collection with another collection". The ID of the collection is choosen by the client. POST: Create a new subordinate entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation. DELETE: Meaning defined as "delete the entire collection". PATCH: This a request to make partial update on a resource
HTTP METHOD CRUD ENTIRE COLLECTION (E.G. /USERS) SPECIFIC ITEM (E.G. /USERS/123) POST Create 201 (Created), ‘Location’ header with link to /users/{id} containing new ID. Avoid using POST on single resource GET Read 200 (OK), list of users. Use pagination, sorting and filtering to navigate big lists. 200 (OK), single user. 404 (Not Found), if ID not found or invalid. PUT Update/Replace 404 (Not Found), unless you want to update every resource in the entire collection of resource. 200 (OK) or 204 (No Content). Use 404 (Not Found), if ID not found or invalid. PATCH Partial Update/Modify 404 (Not Found), unless you want to modify the collection itself. 200 (OK) or 204 (No Content). Use 404 (Not Found), if ID not found or invalid. DELETE Delete 404 (Not Found), unless you want to delete the whole collection — use with caution. 200 (OK). 404 (Not Found), if ID not found or invalid.
Query parameters
https://restfulapi.net/resource-naming/
Path
For the path I have mainly seen hyphen.
http://api.example.com/inventory-managemen
Query Parameters:
Use underscore
customer_type=F&customer_number=1231231&scope=write
Why? Some systems are case insensitive so camel case searchString=asdasda is not recommended. Hyphen used in the path url but not in the identifier of a parameter in the query string. This is due that most languages don’t support variables with –
For example:
person = {}; person.first-name = ‘jose’; -à It doesn’t work in javascript or other languages.
person = {}; person.first_name = ‘jose’; -à OK
second option is camelCase. Never use hyphen (=dash)
URIS
We can use any of the three coding:
camelCase
snake_case
spinal-case
Though in general we observe:
URI path: The most common approach is to use spinal-case Query Params: snake_case for params names. Values are usually expressed with spinal-case.
The tendency is to use lowercases for the URI though there are some exceptions:
Values for query Params could contain Uppercase as they could be reference for which case is important. Uri-Path could use camelCase. For example, in gitlab we are referencing physical name files. We could have different files with same that share the same case-insensitive value. So, in order to access the right file we need to specify the file in case sensitive.