RESTful archiving of entities in WebAPI - rest

I've implemented CRUD functionality pretty restfully in my WebAPI project. I'm now trying to implement Archiving of objects (not quite deleting) - if only there were an ARCHIVE HTTP method.
I see two options:
1) Have isArchived as a property of every archive-able entity, which must be included in PUT and POST requests even if archiving isn't relevant to the request. Archiving an entity would be a matter of calling PUT /api/object/id with isArchived set to true. Seems bulky on the wire but restful.
2) Have an RPC-ish url like PUT /api/object/id/archive that doesn't require a body. Seems the most efficient but not restful.
What's everyone doing in the "archive my stuff via an api call" space?

This is an excellent question, but I suspect it may eventually be marked as opinionated because I don't see a correct answer... as the OP also stated.
I would recommend treating the archive as a separate object store (or, even, different object types), if that makes sense for your system. Object design should not depend upon how the DB persists your data.
Thus, this is the most RESTful design I can come up with right now (assuming archiving and updating are always separate actions -- which they should be):
Typical (everybody knows this):
GET /api/object get all current objects
POST /api/object new current object
PUT /api/object/id update current object
DELETE /api/object/id delete current object
GET /api/object/id get current object
The weirdness:
POST /api/object/id/archive move object to archive (makes some REST sense)
POST /api/object/id move object from archive (muddy)
The archive:
GET /api/object/archive get all archive objects
PUT /api/object/id/archive update archive object (if possible)
DELETE /api/object/id/archive delete archive object (tempting for unarchive)
GET /api/object/id/archive get archive object
Or, maybe one of these mods for archive URLs:
GET /api/object/archive/id get archive object
GET /api/objectarchive/id get archive object
But......
The above feels pretty muddy (not very self-documenting) for moving objects in and out of the archive. It also leads to some REST API design pain where update/delete/get of an archived object probably don't need archive-specific functions. Thus, I ultimately settled on this:
GET /api/object get all objects
GET /api/object?archived=false get all current objects
GET /api/object?archived=true get all archive objects
POST /api/object new current object, returns all current objects*
PUT /api/object/id update object (current or archived; cannot change archive state)
DELETE /api/object/id delete object (current or archived), returns objects of same archive state as deleted*
GET /api/object/id get object (current or archived)*
PUT /api/object/id/archive body:{archived:true} move object to archive, returns all current objects*
PUT /api/object/id/archive body:{archived:false} move object from archive, returns all archive objects*
* Return could be expanded/overridden with a query string if design calls for it.
Admittedly, this is mostly a reversal from my earlier statement of treating the archive as a separate object store. Yet, that thought process is what ultimately led to this compromise in design. This feels good to me on most fronts.
I, personally, don't agree with using the query string for anything but... uh... queries. So, I don't. Payload for data changes -- no matter how small -- should go in the body (when it doesn't fit with a REST verb and URL, that is).

If you always archive a particular resource and never delete it, I would repurpose DELETE to actually archive. If you really need to differentiate between delete and archive, I would either do
GET /foo/33
200 OK
<foo id="33">blah</foo>
POST /archive
<foo id="33">blah</foo>
201 Created
Location: http://example.org/archive/foo/33
or just
POST /archive?target=http://example.org/foo/33
201 Created
Location: http://example.org/archive/foo/33

I'd use the /api/object/id?archive=true approach.
But, as to whether you should use PUT or POST depends. If you use PUT, any subsequent calls to the same URL would not change anything about the resource. If you use POST, the implementer expects that any subsequent calls to that URL will indeed change the state. (Don't ask me how, I'm assuming that you will use the PUT verb on this one.)
This is due to the fact that PUT operations should be idempotent. See section 9.1.2 here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

I would probably use the /api/object/id endpoint with a query parameter, so it looks something like /api/object/id?isArchived=true. You can still use whatever HTTP verb you were using.

Related

PATCH API REST best naming option

I want to add, or replace a coupon to an order via api. I thought in this two possibilities
PATCH /api/orders/{id}
{ "couponCode": "test"}
PATCH /api/orders/{id}/coupon/{couponCode}
I like the second because it's important in the application to apply a coupon code, and this url specifies it very well.
Are first and second valid possibilities following REST? The second option is valid with PUT and PATCH HTTP Methods?
Which do you think is better?
Thanks
The PATCH method is not particularly RESTful on its own. REST is about transferring state, and PATCH doesn't really do that, instead it sends an instruction for an update.
So to make things RESTful what you will want to do is a PUT request to create and replace the state of a coupon in full.
With that being out of the way, this is not an endorsement against using PATCH, but my idea about this is that it's a good idea to:
Provide a proper PUT request to fully replace existing state.
With that in place add support for PATCH to optimize things that might be slow or clumsy.
So if you want to use PATCH on /api/orders/{id}, I would first wonder: how does the PUT version look like?
I don't fully understand what a PATCH on /api/orders/{id}/coupon/{couponCode} would mean. Are you updating the coupon code? It's odd because the code exists in the uri. A DELETE + a PUT makes more sense to me. Or maybe the HTTP MOVE method might even help? (MOVE also falls in the 'not RESTful camp but it's a nice optimization for GET + DELETE + `PUT).
If an order only ever has 1 coupon, I would prefer a uri structure like /api/orders/{id}/coupon because it's a nice singular resource and it makes total sense to replace it with PUT (or PATCH it).

Moving child resource to another parent in REST

I have a REST service.
And now I need to have functionality to move some child resources from one parent to another, for example move a book from one author to another.
My variant is:
POST /api/books/x/moveto/y
But how to create such architect the RESTful way?
From a REST point of view, URLs should be used to locate the resources rather than expressing operations. To express operations, the existing HTTP verbs should be used.
Looks like your "move" operation is all about replacing the author of the book.
And the PUT method seems to be the way to go:
4.3.4. 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. [...]
So, you can have an endpoint like the following:
PUT /api/books/{bookId}/author
And the request payload will contain a representation of the new author.
I think in this case updating the author as suggested in Cassio's answer is a good solution. For less obvious "actions" I use PATCH endpoints. Consider archiving a book:
PATCH /api/books/{bookId}/archive
The intent is obvious -- archive the book with this identifier. For more complex actions, include a body or use a query string parameter. For instance, moving a book out of one category and into another (assume a book can have 0-many categories):
PATCH /api/books/{bookId}/move
{
fromCategoryId: 100,
toCategoryId: 200
}
Or:
PATCH /api/books/{bookId}/move?fromCategoryId=100&toCategoryId=200
In the end, IMO, what matters most is readability and consistency. There is not necessarily a "right" way to do this sort of thing.

Varnish 3.0.3 req.hash_always_miss vs Vary

I'm trying to build a system that can purge and regenerate URLs as required for a particular system. I previously was having issues with purging when the system located the object by hash but missed the variant as I didn't have a "purge;" in my vcl_miss (only in my vcl_hit, some guides/example vcl files do not mention this need but the main documentation does here).
What I'm trying to figure-out is if I need to do something similar for a REGEN call. From my understanding, "set req.hash_always_miss = true;" will mean that the old hash is missed and a new hash object is generated. Subsequent calls will find the new hash, but may still miss that object if there is not an appropriate variant in the cache.
Could someone confirm for me whether a subsequent request missing the variant in the new object will lead directly to a cache miss and fetch, rather than finding any of the variants from the previous object?
hash_always_miss will only influence the current/ongoing request and the cache contents that it replaces. A fetch will always happen, and the object will be put into the cache using the same rules as any other miss/fetch sequence.
The "old" other variants of the same hash are still valid objects and will be served to a client indicating request headers matching the varied headers.
hash_always_miss will replace the current variant, and nothing else.
To answer your question, the second part of your sentence is most correct.

Proper way to construct this REST URI?

I want to have a REST resource for Foo and I want to be able to perform a POST to create a new Foo.
Foos can only be of two subtypes - Fizz and Buzz (the models are FooFizz and FooBuzz on the backend and both extend Foo). All Foos are either a Fizz or a Buzz. Most of the other models follow this pattern too (generic with subtypes for Fizz and Buzz). For the short and medium term, there will not be a new type added to Foos. In the long term it's more likely that this application will be obsolete before a new type is added, but the possibility exists.
At any rate, here are some URI schemes I came up with for working with Foos.
POST /foo?type=fizz
POST /foo/fizz
POST /fizz/foo
POST /foo-fizz
POST /foo/{foo-id}/fizz
My thoughts on this:
(1) might be unnecessary client-server coupling since it's dependent on the query string being properly formed. But it makes the most sense to me.
(2) and (3) are undesirable because you want to be able to have the URI go /foo/{foo-id} for performing operations on an individual Foo.
(4) requires Fizzes and Buzzes to become completely separate branches of the URI tree
(5) seems like a decent scheme although it might mess up the URI tree.
I'd be strongly tempted to just have a POST to /foo with the type of foo to be created (fizz or buzz) being determined by the contents of the document being POSTed. It would respond with a suitable redirect to the URI for the newly created foo (/foo/{fooId}, presumably) through which you'd manipulate things in the normal way.
Admittedly, I am not a REST expert, however here are my two cents.
Why would you even have a post to foo/{foo-id}? In that case, it would be more of a PUT for an update. The only time you would need to post would be if the id was being auto-created and unknown until actually created. So, in that case, I would lean towards 1 as you are creating a foo and the rest is just information needed to create foo. After that point, would you even need to care about the subtype (fizz or buzz)? I would assume the foo/{foo-id} would be enough information to work on it individually and determine the type from it.
So:
POST /foo?type=fizz
**You could possibly even remove the query string and send it in as your creation data, but that is up to you
GET /foo/{foo-id} ...retrieve the created foo
PUT /foo/{foo-id} ...update the created foo
DELETE /foo/{foo-id} ...delete the created foo
That is what I would do at least.
<soapbox>If you are really doing a RESTful architecture, then you shouldn't need to ask this question</soapbox>.
RESTful architectures include links in the representation that direct the flow of the application. If you are creating a new resource that is a child of a parent resource, then the representation of the parent resource should have an embedded link that tells you what URL and (potentially) which verb to use. Something like:
<link rel="add-child" method="POST" href="http://foo/1234">Add a new child</link>
If you are creating a wholly new root resource then, you probably want to POST to an absolute URL and have either the response document or Location header tell your application where to retrieve a new representation from. The target resource is essentially the "entry point" into your application's state machine.

How to construct URIs for RESTful service that operates tree-like data?

Assume I have tree-like data, e.g. “files” and “folders”, basic operations are “list folder”, “create folder”, “rename”, “create file”, “fetch file”.
So how can I construct URIs for RESTful service? I've tried a few times but all solutions look not very nice to me.
For example, if I have “folder” resource referenced by URI `http://example.com/rest/here_path_to_folder, how can I list folder items? Fetch “file” from this folder?
I've seen Amazon AWS docs, they are using not very clean approach—passing “folder” path and folders delimiter as query arguments, this could cause ambiguity because different URIs will reference the same resource. Also I've tried appending keywords to the end of path, so listing “files” looked like:
GET /rest/path/to/folder:list HTTP/1.1
Rename:
POST /rest/path/to/folder:rename?target=NEW_NAME HTTP/1.1
But it still look terrible for me. So do you know any success stories of using 100% REST on hierarchial data?
I think it should be quite simple to use URIs to represent your hierarchical data structure. Although URIs don't strictly imply hierarchy (some people like to keep then completely opaque), meaningful URIs do have a naturally hierarchical feel and they should map nicely to your file/folder example.
In a RESTful system, resources have a common interface which (in your case) is defined by the HTTP verbs. The URI identifies a resource, REST dictates that it shouldn't be used to indicate the operation you are trying to perform.
So instead of
GET /rest/path/to/folder:list HTTP/1.1
I'd propose that to list the contents of a folder (find out it's state) you simply use:
GET /rest/path/to/folder HTTP/1.1
This should return a list of URIs which represent the files and subfolders that this folder contains. Then to get the contents of one of the files, I might then invoke:
GET /rest/path/to/folder/myfile HTTP/1.1
Renaming is a bit more tricky. In some cases a DELETE followed by a PUT would work, but I'm guessing you want to retain the folder contents without having to re-upload. One option is a PUT where the body contains a new folder path, which responds with a 204 and the Location header value pointing to the newly created folder (as described in 'Renaming a tag' here). Optional: If you want to be really friendly to your users, you could also return a 301 status (Moved permanently) with a link to the new URI if the anyone makes a request to the old URI.
Remember the path is just one of the properties that makes up the state of a folder, you can update that state with PUT without needing to introduce a custom 'rename' operation. In your case, you happen to use the path to decide your URI, but it's perfectly valid for a state change to cause a change in the URI.