The recommended way to handle optimistic locking in a RESTful interface seems to be by returning an ETag from the GET, and supplying an If-Match on the PUT, ie:
GET /items/1 --> gives client an ETag for a single item
PUT /items/1 <-- client gives it back as If-Match for checking
How do I use this scheme with multiple items, for example if I want to batch GETting multiple items from a single URI:
GET /items --> How do I return multiple ETags for multiple items here?
Alternatively, if ETags/If-Match don’t cope with this situation, what’s a recommended approach? Or should I just roll my own?
tl;dr: it’s OK to assign etags to a resource that contains a "collection" but it is up to the app to manage the identification/change of the items in that collection when determining a valid etag.
A resource in the REST architectural style does not imply it is a single item or a collection. It simply represents the state of the application at a given point in a workflow. A resource will contain descriptive data and hopefully, links to possible next steps at that point in the workflow. The workflow could be as simple as get an order status or complex like ordering items on an eCommerce site complete with the ability to cancel the order.
An etag is a mechanism for determining whether a particular state (resource) is up-to-date or not. Assigning an etag to a resource that returns a collection of data means that your application is identifying that state of the collection items at that point and if anything in those items changes, the prior etag value would no longer be valid. It’s up to your application to decide when collection items change and how to identify the individual items. In other words, etags apply to resources but not individual components of a given resource.