Modeling Version Control Operations in REST
We recently added version control capabilities to our system, it is difficult for us to model these capabilities with RESTful.
The system works as follows when configured in versioning mode, before making changes to an entity, you first need to validate it (a private copy is created for that user). After modifying the local copy, the user can check it out to check in the changes, or undo checkout to revert the changes.
We discuss which approach is appropriate for modeling check-in, check-out, get-version, and undo check-out operations.
so let's say we have a resource (called my-resource)
http://my-system/my-resources/{id}
and we want to add version control capabilities on top of that, we argue between the following two approaches:
-
Work oriented
Incoming: POST to http: // my-system / my-resources / {id} / check-in
Check out: POST to http: // my-system / my-resources / {id} / check-out
Get version: GET http: // my-system / my-resources / {id} / versions / {version-id}
Cancel checkout : POST to http: // my-system / my-resources / {id} / undo-check-out
-
Resource oriented
Registration: POST to http: // my-system / my-resources / {id} / versions
Check out: POST to http: // my-system / my-resources / {id} / check-out
Get version: GET http: // my-system / my-resources / {id} / versions / {version-id}
Cancel checkout : DELETE to http: // my-system / my-resources / {id} / check-out
What do you think? Do you have a suggestion on how to model these operations? Are you familiar with similar public APIs to consult with?
source to share
This is very similar to the simple RCS version control model. Assuming the same underlying resource url structure as you suggested, I would model it like this in a RESTful API:
GET http: // my-system / my-resources / {id} => return the current state of the resource 'id', with -out check the blocking status encoded in the header of the HTTP extension ( X-checkout-status: unlocked
for example)
POST http: // my-system / my-resources / {id} / versions => check check out
- if successful, return HTTP status 201 with a header
Location:
pointing to the new temporary version resource (see below for version URL format) - otherwise, return an HTTP 409 conflict status code indicating that the resource has already been verified
GET http: // my-system / my-resources / {id} / versions / {version} => get the verified version of the resource
PUT http: // my-system / my-resources / {id} / versions / {version} => save changes, resource
POST http: // my-system / my-resources / {id} / versions / {version} => commit the changes to keep the main resource in the process (maybe a header line is needed to commit X-checkout-status: unlocked
)
DELETE http: // my-system / my-resources / {id} / versions / {version} => release the checkout lock without saving changes to the main resource
DELETE http: // my-system / my-resources / {id} / versions => release all file locks; must require administrative privileges (but it is useful to flush outdated locks)
There are a few differences from your design. First, I was explicit about how updates are actually made to a retrieved resource. Second, I used the header X-checkout-status
and various HTTP codes to indicate if the file is currently locked and the success or failure of various version control operations.
The most critical difference, however, is that we treat the "versions" url space as an explicit collection, and therefore using the normal POST / DELETE / etc. exit control operations.
source to share
You just described two RPC APIs. If you want RESTful APIs try something like this:
GET {resource url}
200 OK
Location: {resource url}
<resource>
<!-- Rest of your resource goes here -->
<operation id="check-out" href="{check-out url}" method="post">
</resource>
Using the URL and method in the resource view, you can check the resource to create a working copy:
POST {check-out url}
200 OK
Location: {working copy url}
<working-copy>
<!-- Info about the working copy goes here -->
<operation id="check-in" href="{check-in url}" method="post">
<operation id="discard" href="{undo check-out url}" method="post">
<!-- Additional operations, as needed, to modify the working copy -->
</working-copy>
Use the operations defined in the working copy to either check it on completion:
POST {check-in url}
200 OK
Location: {resource url}
<resource>
<!-- Modified resource data goes here -->
<operation id="check-out" href="{check-out url}" method="post">
</resource>
or discard it:
POST {undo check-out url}
200 OK
Location: {resource url}
<resource>
<!-- Original resource data goes here -->
<operation id="check-out" href="{check-out url}" method="post">
</resource>
Your resources are now self-descriptive and have their own URLs to uniquely identify them.
source to share
Not REST (although Fielding is on the committee), but WEBDAV is the standard way of version control over HTTP.
Another Apache project, Sling , seems to contain REST APIs via a repository (although I couldn't see the full description of the HTTP API anywhere, just small examples)
The third place to look at is the Atom Publishing Protocol , which allows you to simply publish a resource.
source to share