Background
I'm building an API that allows clients to manipulate geospatial objects. These objects contain a location on the world (in latitude/longitude), and a good bit of metadata. The actual API is rather large, so I present a simplified version here.
Current API
Consider an API with two objects, features and attributes.
The feature endpoint is /api/feature
and looks like:
{
id: 5,
name: "My super cool feature",
geometry: {
type: "Point",
coordinates: [
-88.043355345726,
43.293055846667315
]
}
}
The attribute endpoint is /api/attribute
. An attribute looks like:
{
id: 3,
feature_id: 5,
name: "attr-name",
value: "value"
}
You can interact with these objects by issuing HTTP requests to their endpoints using different HTTP methods, like you might expect:
GET /api/feature/5
reads the feature with id 5.PUT /api/feature/5
updates the feature with id 5.POST /api/feature
creates a new feature.DELETE /api/feature/5
deletes the feature with id 5.
Same goes for attributes.
Attributes are related to features by foreign key (commonly expressed as "features have many attributes").
The Problem
It would be useful to be able to make a copy of a feature and all its metadata (all the attributes that belong to it). The use case is more or less, "I just made this feature and gave it a bunch of attributes, now I want the same thing... but over there." So the only difference between the two features would be their geometries.
Solution #1: Make the client do it.
My first thought was to just have the client do it. Create a new feature with the same name at a new location, then iterate through all the attributes on the source feature, issuing POST
requests to make copies of them on the new feature. This, however, suffers from a few problems. First, it isn't atomic. Should the client's Internet connection flake out during this process, you'd be left with an incomplete copy, which is lame. Second, it'd probably be slow, especially for features with many attributes. Anyway, this is a bad idea.
Solution #2: Add copy functionality to the API.
Doing the copy server-side, in a single API call, would be the better approach. This leads me to https://www.rfc-editor.org/rfc/rfc2518#section-8.8 and the COPY
method. Being able to do a deep copy of a feature in a single COPY /api/feature/5
request seems ideal.
The Question
My issue, here, is the semantics of COPY
don't quite fit the use I envision for it. Issuing a COPY
request on a resource executes a copy of that resource to the destination specified in the Destination
header. According to the RFC, Destination
must be present, and it must be a URI specifying where the copied resource will end up. In my case, the destination for the copied feature is a geometry, which is decidedly not a URI.
So, my questions are: Would stuffing json for the geometry into the Destination
header of a COPY
request be a perversion of the spec? Is COPY
even the right thing to use, here? If not, what alternatives are there? I just want to be sure I'm implementing this in the most HTTP-kosher way.