How to reference a resource in a update-request of a hypermedia api? - api

I did some research about how REST APIs work and how to link resources via hypermedia. Most of the examples about linking resources is related to the response of the server. But I wonder how to reference to other resources when a certain resource should be updated.
Let´s take the simple resource of a person living at a specific location:
/api/persons/alice
{
"name": "Alice",
"location": {
"id": 1,
"links": {
"self": "/api/locations/1"
}
}
}
Now I want to update the location to another existing location. But how do I represent that?
Would I:
refer to the id of the new location
PUT /api/persons/alice
{
"name": "Alice",
"location": 2
}
refer to the URI of the new location
PUT /api/persons/alice
{
"name": "Alice",
"location": "/api/locations/2"
}
anything else?

HTTP PUT has remote authoring semantics - you should think of the payload as being the new representation of a document, being manipulated by some general purpose HTTP aware document editor.
GET /api/persons/alice HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"name": "Alice",
"location": {
"id": 1,
"links": {
"self": "/api/locations/1"
}
}
}
PUT /api/persons/alice HTTP/1.1
Content-Type: application/json
{
"name": "Alice",
"location": {
"id": 2,
"links": {
"self": "/api/locations/2"
}
}
}
200 OK
The assumption here is that the consumer of your API is familiar with the schema here, and understands the semantics, which fields are optional, which are required, and so on.
(Getting this to work on a long time scale means investing effort in designing your schema well, choosing reasonable defaults, and so on).
Please observe this part of the PUT specification with care:
An origin server SHOULD verify that the PUT representation is consistent with any constraints the server has for the target resource that cannot or will not be changed by the PUT.... When a PUT representation is inconsistent with the target resource, the origin server SHOULD either make them consistent, by transforming the representation or changing the resource configuration...
...
An origin server MUST NOT send a validator header field (Section 7.2), such as an ETag or Last-Modified field, in a successful response to PUT unless the request's representation data was saved without any transformation applied to the body....
In other words, the server doesn't need to "store" the new representation as provided.

Related

Shopware 6 Admin Api - Updating existing record through patch method. Not working

shopware 6 admin api patch - why it's failing? I get error "Only single write operations are supported"
Following is api for rule-condition entity in the database, I update it with Id.
For same api get method is working!
url: api/rule-condition/dbb0d904c7c14860a9a94cf26b94eca6
method: patch
json body
[
{
"op": "replace",
"path": "/data/attributes/value/email",
"value": "test#gmail.com"
}
]
response:
{
"errors": [
{
"code": "0",
"status": "400",
"title": "Bad Request",
"detail": "Only single write operations are supported. Please send the entities one by one or use the /sync api endpoint.",
.......
I also tried changing json body to following
{
"data": {
"attributes": {
"value": {
"email": "test#gmail.com"
}
}
} }
Still it's not updating. Can somebody check and let me know what am i missing?
Documentation I followed:
https://shopware.stoplight.io/docs/admin-api/ZG9jOjEyMzA4NTQ5-writing-entities
This website has all apis and example methods. https://swagger.docs.fos.gg/,
rule-condition entity can also be found there.
Btw : I used postman for testing api
You're passing an array of objects in the request body, suggesting you want to update multiple records, but the endpoint only supports updating a single record. The correct payload in your case should look like this:
{
"value": {
"operator": "=",
"email": "test#gmail.com"
}
}
Notice that value is a json field and not only includes a single value. The exact content and the names of the properties of value depend on the type of condition used and usually it also includes the operator used in the condition.

A 400 error occurs when creating a OneDrive API upload session

Create an upload session to upload large files to oneDrive.
Below is the request address.
https://graph.microsoft.com/beta/users/{userId}/drive/root:/UploadFiles/{fileName}:/createUploadSession
Request Body
{
"item": {
"#odata.type": "microsoft.graph.driveItemUploadableProperties",
"#microsoft.graph.conflictBehavior": "rename",
"name": "largefile.dat"
}
}
An Invalid request error occurs. What's wrong with it? I watched the tutorial and tested it.
POST /drive/root:/{item-path}:/createUploadSession
Content-Type: application/json
{
"item": {
"#odata.type": "microsoft.graph.driveItemUploadableProperties",
"#microsoft.graph.conflictBehavior": "rename",
"name": "largefile.dat"
}
}
https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-beta#create-an-upload-session
As Shiva suggested in a comment on the question, the issue is that the value of #odata.type is not correct for this case. In general you should not provide it at all as the schema is strongly typed and therefore the appropriate value can be derived without any client-driven hints.

How to post event with metadata to stream through HTTP API

I'm using EventStore and want to post a message (event) to it. I use the HTTP API for testing purposes. I've managed to post the event itself, with an event type specified, but I can't figure out how to specify metadata for my event. (and I must provide this metadata because my consuming application on the other side expects it).
This is what my HTTP request looks like:
Content-Type: application/json
ES-EventType: My.own.event.type
POST http://10.0.75.2:2113/web/index.html#/streams/foobar
{
"props": "andvalues"
}
Do I specify metadata in the body in through headers? I can't find much docs about this, only the official that doesn't mention it.
The documentation mentions the full schema for an event being written. It looks like this:
[
{
"eventId" : "string",
"eventType" : "string",
"data" : "object",
"metadata" : "object"
}
]
For example:
[
{
"eventId": "fbf4a1a1-b4a3-4dfe-a01f-ec52c34e16e4",
"eventType": "event-type",
"data": { "a": "1" },
"metadata": { "b": "2" }
}
]
Note that it's an array, and that you must pass content-type as application/vnd.eventstore.events+json
Check this page, scroll to Event Store Events Media Type.

HATEOAS API Object Design

What is the current best practice on using pragmatic hateoas when a POST object may differ from the GET object of the same resource? For example, would the following be bad API design?
For the resource /families a client may POST a new family and include many "members":[] in the same request.
/members is also a resource
Given a successful POST or GET, the server returns an object that includes a different "family" object to include links:
{
"id": 123,
"name": "The Adams Family",
"_links": {
"members": { "href": "/families/123/members" }
}
I think it would be better to use nested resources in this case e.g. in HAL+JSON:
{
"id": 123,
"name": "The Adams Family",
"_embedded": {
"members": {
"_links": {
"self": {
"href": "/families/123/members"
}
}
}
}
}
I think your solution is okay as well, but you have to define the members link relation in the documentation, so the clients (and their developers) will know that "members" means family members, and not for example members of any collection (e.g. hydra defines a member property for collection items and schema.org defines a members property for organization members).

REST Media Type Proliferation

I took a look at this question that seeks to address the issue of REST media-type explosion. One of the suggestions was to have a media-type that describes a collection of anything. So for example, we could have an application/vnd.collection+json which is a collection with well-defined semantics that can hold a list of references to other resources:
{
"size": "3"
"elements": [
{ "href" : "http://my.api.com/resource/1" },
{ "href" : "http://my.api.com/resource/2" },
{ "href" : "http://my.api.com/resource/3" }
]
}
I know an option to alleviate chattiness is to include embedded representations of resources. How would a "generic" media-type for lists accomplish that? Don't the semantics of the list change based on which embedded resource is inside it? This is especially relevant if embedded resources have different processing-rules (which would ideally be conveyed by the media type). Would be alright in this case to allow in-band information that describes the media type of the embedded resource? For example we could have application/vnd.collection+json for both links and embedded resources that do something like this:
{
"size": "3"
"element-content-type": "application/vnd.link+json"
"elements": [
{ "href" : "http://my.api.com/resource/1" },
{ "href" : "http://my.api.com/resource/2" },
{ "href" : "http://my.api.com/resource/3" }
]
}
and if it contains an embedded resource:
{
"size": "3"
"element-content-type": "application/vnd.resource+json"
"elements": [
{
"id": "1"
"name": "Cool Resource"
},
{
"id": "2"
"name": "Awesome Resource"
},
{
"id": "3"
"name": "Super Awesome Resource"
}
]
}
The assumption is that application/vnd.link+json and application/vnd.resource+json have been documented as well.
I thought about this a little bit more, and I think it is actually OK to include the content-type like that. The reason is, we already do this. In HTML the script tag has a type attribute that can be application/javascript or application/vbscript (for example). The provides the browser a hint as to how to process the content of that tag. Similarly, I think the content-type in the above example achieves the same purpose: it tells the client how to process the elements in the collection.
I wanted to update this answer some more. It appears that another way to do this is to use a rel. At least, this is how HAL does it. You can create a namespaced rel with a curie so that you end up resolving the rel to a URL that points to documentation about that resource. This way you have access to the documentation and that should tell you all you need to know about the resource(s).