Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide implementation guidance on handling UUIDs in POST/PUT #51

Closed
laurelmay opened this issue May 17, 2022 · 4 comments · Fixed by #57
Closed

Provide implementation guidance on handling UUIDs in POST/PUT #51

laurelmay opened this issue May 17, 2022 · 4 comments · Fixed by #57
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@laurelmay
Copy link
Contributor

Throughout the OSCAL REST API Specification, many paths support PATCH, PUT, and POST operations. One of the complexities of the specification today is that the primary identifier of objects, their UUID, can generally be provided in two places: the request path and the request body. Because in many cases PUT, POST (and PATCH) can be invoked in such a way that the results should be similar or identical, guidance should be provided on when each is most appropriate. We want to ensure that for each operation, we keep the meanings of the underlying HTTP verbs in mind.

We likely want to provide guidance similar to the following:

POST

A POST request should be the preferred option for creating new objects, especially when the ID of the object is not already a value that the client cares about. The primary/root object of a POST request should not specify a uuid attribute and servers must return an HTTP 4xx error if one is specified.

PUT

A PUT operation can be used to update an object by entirely replacing its definition and it can be used to create new objects when a specific uuid is required. For example, a client may allow a user to create several new objects and specify relationships between them; to support this, the UUIDs may be generated client-side. Server implementations should support this flow by allowing objects to be created with a specified UUID.

The PUT operation today is defined to include the UUID in the request path as well as in the request body. This opens the path to conflicts between the IDs. We should provide guidance that clients may omit the UUID from the request body; however, if it is specified it must match the UUID in the path (and servers must return an HTTP 4xx error if they do not match). Additionally, if a client makes a PUT request to a path for which no object with that UUID exists, a new object should be created with that ID.

Diagram(s)

I am not particularly well-versed in creating diagrams; however, the following ideally helps clarify the recommendation a bit:

Choosing between PUT and POST

graph LR
  Init([Make a request]) --> Pref{Preference on UUID}
  Pref -->|Yes| PUT
  Pref -->|No| POST
Loading

Making a POST request

graph LR
  POST([POST]) --> UUID{Is UUID specified in body}
  UUID -->|Yes| Error([Error])
  UUID -->|No| Z[Create new resource<br/>and generate UUID]
Loading

Making a PUT request

graph LR
  PUT([PUT]) --> UUID{Is UUID specified in body}
  UUID -->|No| Exist
  UUID -->|Yes| UUIDMatch
  UUIDMatch{Does the body UUID<br/>match path UUID}
  UUIDMatch -->|No| Error([Error])
  UUIDMatch -->|Yes| Exist
  Exist{Does a resource with the<br/>UUID already exist}
  Exist -->|Yes| Update[Update matching resource]
  Exist -->|No| Create[Create new resource<br/>with given UUID]
Loading

Potential specification changes

We may need to make adjustments to the specification to allow for bodies to exclude the UUID objects (or we may need to make adjustments in some cases to require them).

Related discussion

This has been discussed previously in:

@laurelmay laurelmay added the documentation Improvements or additions to documentation label May 17, 2022
@laurelmay
Copy link
Contributor Author

We may want to consider, under a separate ticket, documenting recommendations around handling "renaming" or "re-IDing" an object (my preference would be a DELETE + PUT; however one could envision an implementation that would have allowed PUTing with different IDs in path/body for this purpose).

@rgauss rgauss added this to the 0.4 Tech Investments milestone May 23, 2022
@naiqbal
Copy link

naiqbal commented Jun 27, 2022

@kylelaker we sized this issue. Fyi

@kperk103 kperk103 self-assigned this Jun 28, 2022
@kperk103
Copy link
Contributor

@kylelaker Should this be added in the `openapi.yaml'?

@laurelmay
Copy link
Contributor Author

Great question -- I almost feel like there could be a benefit in having the in-depth explanation in a separate markdown file (perhaps in the docs/ folder) that we then link to from the openapi.yaml file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants