Strategy for RESTfully posting many entities

2019-06-26 06:37发布

问题:

I am still in the process of getting comfortable with doing things the REST way.

In my situation, client software will be interacting with a RESTful service. Rarely, the client will upload its entire database of entities (each entity serializes into a roughly 5kb chunk of xml).

Perhaps I'm wrong, but the proper RESTful strategy seems to be to cycle through each entity and individually POST each one. However, there may plausibly be tens of thousands of these entities, and somehow so many rapid-fire POSTs doesn't seem kosher.

In this situation, it feels like packaging all the entities into one big xml representation would violate the RESTful way of doing things, but it would also avoid the need for thousands of POSTs.

Is there some standard-practice for accomplishing this? Thanks in advance!

回答1:

There are at least two problems here which prevent you from being RESTful.

  1. Each resource needs to be identified by a URI. Acting on the resource means that you must call the URI using an HTTP call. Consequently, you cannot call multiple actions in multiple resources in just one HTTP call.

  2. The resources are identified by nouns and represent entities. This implies that to insert an Employee and a Car you need to call two different resources for each of the respective entities.

So in summation you cannot take a purely RESTful approach here. However, REST is designed to help by way of conventions, not constrict you. The best solution here is for you to create a custom action which does what you need.

Alternately, you can create a generic wrapper entity with INSERT, UPDATE and other actions which take in blobs of disparate data as XML. However, this will undermine your other end points because now it becomes possible to insert a Car record through the generic wrapper and through the /Car/ URI.

Without knowing much about your actual requirements, I would suggest you don't expose this functionality via REST specifically. Behind the scenes you could still call your INSERT action methods within the various Controllers once you break up the incoming collection if disparate objects.



回答2:

I don't see why a "Packet of entities" cannot be considered a resource. Transactional writes certainly can consider database transaction to be a resource. I admit I haven't read Fielding's dissertation, but I don't see how wrapping several resources into a single representation would invalidate REST.

Database transactions do something like this. They will wrap smaller resources inside a transaction resource. It's true that usually they do this so that you can post those smaller resources, that can still be large, separately. But since the transaction itself is considered a resource, I don't believe that coming up with a representation for it that you could post as one POST request would make this design any less RESTful.

It's also used to the other direction. When the client GETs search results from the server, the server might wrap these inside a results resource so that the client can just get this one resource instead of several separate ones.

So I'd say that wrapping these small 5kb resources inside a larger collection resource can be considered RESTful and is probably the way you should go for.



回答3:

As long as the big wrapper has a valid media-type then it is fine to treat it as a single resource. Figuring out what that media-type is going to be is the tricky part.



回答4:

Nothing prevents you from creating more resources upon addition, aka post a resource that is a list of X to a resource that's a list of X using a POST.

You'd then send back a 201 created with the list of URIS of all resources created. Again, it's all perfectly allowable.

What you loose is the visibility to the intermediaries upon PUT, which prevent them from caching or modifying the specific resource at the specific URI. Although a smart intermediary would process the 201 for caching purposes.

And having one doesn't prevent you from having each created resource have its own URI post-creation (after the POST) and enable PUT / DELETE on those resources. Or a combination.