Notes/Advanced Programming/projects/API Design Research.md
2024-12-07 21:07:38 +01:00

8.1 KiB

type
practical

Updating information

Can we have optional fields in the update PUT and POST request?

The existence of the PATCH request

The PATCH HTTP method applies partial modifications to a resource. PATCH is somewhat analogous to the "update" concept found in CRUD (in general, HTTP is different than CRUD, and the two should not be confused).1

Hence, this definition also answers the question as to why we should be careful with the usage of PATCH if we consider it.

Usage of PUT

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload. 2

This implies that complete resource representation is required (all the fields), as Jackson(Spring) will reset the missing ones to their default values (e.g. int = 0, boolean = false, String = null, etc.)

Complete request example

Request:

{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",
  "author": "Yo mama",
  "genre": "Horror",
  "publisher": "Team 22",
  "publishDate": "2023-09-01",
  "pages": 320
}

Response:

<<< 200 OK
{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",
  "author": "Yo mama",
  "genre": "Horror",
  "publisher": "Team 22",
  "publishDate": "2023-09-01",
  "pages": 320
}

Incomplete request example

(this is assuming the above request happened already) Request:

{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",

  
  "publisher": "Team 22",
  
  "pages": 320
}

Response:


<<< 200 OK
{
  "isbn": "978-3-16-148410-0",
  "name": "Among us story",
  "author": null,
  "genre": null,
  "publisher": "Team 22",
  "publishDate": null,
  "pages": 320
}

Usage of POST

Contrary to PUT:

The POST method is used to request that the target resource process the enclosed representation according to the resource's own specific semantics. The meaning of a POST request is determined by the server and is usually dependent on the resource identified by the Request-URI.3

Therefore we can send requests which contain data that are non-complete resource representations. We do have to explain this to the other team tho...

i.e. Request:

{
  "isbn": "978-3-16-148410-0"
}

Response:

<<< 201 Created
{
  "isbn": "978-3-16-148410-0",
  "name": null,
  "author": null,
  "genre": null,
  "publisher": null,
  "publishDate": null,
  "pages": 0
}


General "style" remarks

(based on the API conventions + CRUD principle)

The base URL should be neat, elegant, and simple so that developers using your product can easily use them in their web applications. A long and difficult-to-read base URL is not just bad to look at, but can also be prone to mistakes when trying to recode it. Nouns should always be trusted.4

Hence, using a verb in POST /api/v1/book/create and PUT /api/v1/book/update is not ideal.

Table4 of common conventions for the usage of HTTP requests:

Resource POST GET PUT DELETE
/customers Create a new customer Retrieve all customers Bulk update of customers Remove all customers
/customers/1 Error Retrieve the details for customer 1 Update the details of customer 1 if it exists Remove customer 1
/customers/1/orders Create a new order for customer 1 Retrieve all orders for customer 1 Bulk update of orders for customer 1 Remove all orders for customer 1

Hence, in our case:

Resource POST GET PUT DELETE
/books Create a new book Retrieve all books (+ optional parameters for filtering) 405 Remove all books
/books/{isbn} 405 Retrieve the details for book with isbn Update the details of book with isbn if exists Remove book with isbn

Conclusion / TL;DR

Given the information provided above, I propose we change the current specification as follows:

Method Old URL/Description New URL/Description Reasoning
POST /api/v1/book/create - Create book - pass JSON body (isbn is required) /api/v1/books - Create a book - pass JSON body (isbn is required) Use resource-based naming convention (books as a collection). HTTP POST implies creation; no need for /create.
PUT /api/v1/book/update - Update book - pass JSON body (isbn is required) /api/v1/books/{isbn} - Update a specific book - pass JSON body Use path parameter ({isbn}) to specify which book to update. HTTP PUT implies updating a specific resource.
GET /api/v1/book?genre={genre}&author={author}&data="csv" - Get book(s) by property in csv/json format /api/v1/books?genre={genre}&author={author} - Get books by property. Use Accept header for csv/json format Use plural books for collections. Use HTTP Accept header for content negotiation (CSV/JSON), keeping URLs clean.
DELETE /api/v1/book?genre={genre}&author={author} - Delete book(s) by property /api/v1/books - Delete books - pass filter criteria in body or delete one by /api/v1/books/{isbn} DELETE requests with body for filtering criteria, or use path param for deleting a single resource for better clarity.
POST /api/v1/book/import?data="csv" - Import books from csv/json file (isbn is required for each) /api/v1/books/import - Import books from CSV/JSON file - pass file in body; use Content-Type header Use resource-based naming (books/import). The Content-Type header indicates file type (CSV/JSON); keep query params clean.