What is best practice for data synchronization operation between client and server?
We have 2 (or more) resources:
cars -> year, model, engine
toys -> color, brand, weight
And we need to get updated resources from server in case of any updates on them. For example: someone made changes from another client on the same data and we need to transfer those updates to our client application.
Request:
http://api.example.com/sync?data=cars,toys (verb?)
http://api.example.com/synchronizations?data=cars,toys (virtual resource "synchronizations")
Response with mixed data:
status code: 200
{
message: "ok",
data: {
cars: [
{
year: 2015,
model: "Fiat 500"
engine: 0.9
},
{
year: 2004,
model: "Nissan Sunny"
engine: 1.3
}
],
toys: [
{
color: "yellow",
brand: "Bruder"
weight: 2
}
],
}
}
or response with status code 204 if no updates available. In my opinion making separated http calls in not a good solution. What if we have 100 resources (=100 http calls)?
I am not an expert, but one method I have used in the past is to ask for a "signature" of the data, as opposed to always going and getting the data. The signature can be a hash of the data you are looking for. So, flow would be something like:
Get signature hash of the data
http://api.example.com/sync/signature/cars
Which returns the signature hash
Check if the signature is different from the last time you retrieved the data
If the signature is different, go and get the data
http://api.example.com/sync/cars
Have the REST also add the new signature to the data
{
message: "ok",
data: {
cars: [
{
year: 2015,
model: "Fiat 500"
engine: 0.9
},
{
year: 2004,
model: "Nissan Sunny"
engine: 1.3
},
],
signature: "570a90bfbf8c7eab5dc5d4e26832d5b1"
}
}
Related
My web application requires a REST endpoint GET /products whose semantics is to retrieve a set of products from a product catalogue.
Each product has a set of attributes including an image in PNG format:
[
{
productId: 123,
name: "boat",
image: "\\x89504e470d0a1a0..." <-- PNG retrieved from PostgreSQL bytea
},
{
productId: 456,
name: "helicopter",
image: ...
}
... and many more
]
I believe this approach is not REST compliant because the image's Mime-Type is not explicitly mentioned.
The approach that is closer to the REST spirit would be to include, instead of the binary data, a hyperlink to the image resource
[
{
productId: 123,
name: "boat",
image: {
href: "/product/123/image <-- GET response to this resource has Mime-Type image/png
}
},
{
productId: 456,
name: "helicopter",
image: {
href: "/product/123/image <-- GET response to this resource has Mime-Type image/png
}
}
... and many more
]
But in that case the client would need to GET the product images one-by-one which adds significant overhead to the network (TCP connections) and the database (querying for the images one-by-one).
Is there a best practice for embedding multiple images in a single json response with the correct Mime-Type?
Is there a best practice for embedding multiple images in a single json response with the correct Mime-Type?
It sounds like what you are looking for is the "data" URL Scheme (RFC 2397), which allows you to specify the media type as part of the URL.
data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7
I need help with loopback framework.
I have two models: Post and Media.
Examples:
Media
{
id: ObjectId("...a1"),
type: "gif",
path: "some/folder"
},
{
id: ObjectId("...a2"),
type: "mp4",
path: "some/folder"
},
Post
{
id: ObjectId("...b1"),
title: "Apollo 13",
content: [
{
mediaId: ObjectId("...a1"),
header: "header-1",
description: "descr-1"
},
{
mediaId: ObjectId("...a2"),
header: "header-2",
description: "descr-2"
}
]
},
{
id: ObjectId("...b2"),
title: "2 seconds to Moon",
content: [
{
mediaId: ObjectId("...a1"),
header: "header-3",
description: "descr-3"
},
]
}
As you can guess I'm going to use MongoDb. I want to describe a relation between this two models, but not sure how to do it in the right way.
If I had only array of mediaIds, I'd make it through referenceMany. Now it's look more like embedsMany, but embeds many what?
I even tried to make something like MediaItem model and give it transient datasource. But I didn't make it works right with rest APIs.
At final I want to get one or many posts with including media data such as type and path fields.
Any thoughts?
Probably you should use HasManyThrough relation (http://loopback.io/doc/en/lb2/HasManyThrough-relations.html) and then include filter (http://loopback.io/doc/en/lb2/Include-filter.html)
I was wondering how in a REST API (or REST like API) one should deal with a resource modification that have impact on an other resource.
For the sake of clarity I'll take the example of a bill. A bill contains several lines and each line have an amount. The bill also have a property stating the total amount, which is the sum of all lines' amount.
A representation of a bill using JSON could be :
{
id: 156,
amount: 12,
lines: [
1: {
label : 'Item 1'
amount: 8
}
2: {
label: 'Item 2',
amount: 4
}
]
}
What is a the best way to update a line and be informed the bill amount has changed ?
I came up with some ideas, they all have advantages and drawbacks.
Solution 1 : Use one resource
That solution came from that question : "Should resources have impact on other resource ?"
Answering no leads to the use of only one resource for a bill and its lines. This allows to use patch on the bill resource.
Furthermore we could argue that a bill without lines makes no sense.
Request
PATCH api.something.com/bills/156
{
lines: [
1: {
amount: 4
}
]
}
Or, using RFC6902
PATCH api.something.com/bills/156
[
{ "op": "replace", "path": "/lines/1/amount", "value": 4 }
]
Response
HTTP/1.1 200 Success
{
id: 156,
amount: 8,
lines: [
1: {
label : 'Item 1'
amount: 4
}
2: {
label: 'Item 2',
amount: 4
}
]
}
Advantages :
One resource
No need to deal with embedded resources
If line order changes (deletion or addition) we will have the new one
Drawbacks :
Loosing the super handy POST on api.something.com/bills/156/lines for lines addition.
Loosing the super handy DELETE/PATCH on api.something.com/bills/156/lines/1 for line deletion/modification
Solution 2 : Call on subresource and redirect
If we agree on using a subresource for lines one solution is to use a 303 Redirect response, as Roy T. Fielding proposes.
Line addition
Request
POST api.something.com/bills/156/lines
{
label: 'Item 156',
amount: 10
}
Response
HTTP/1.1 303 See other
Location: https://api.something.com/bills/156
Line update
Request
PATCH api.something.com/bills/156/lines/
{
amount: 5
}
Response
HTTP/1.1 303 See other
Location: https://api.something.com/bills/156
Line deletion
Request
DELETE api.something.com/bills/156/lines/2
Response
HTTP/1.1 303 See other
Location: https://api.something.com/bills/156
Drawbacks:
Lines are part of bill and are also subresources
Have to fetch the bill resource with the lines when a line is added, deleted, or modified
Works only for resources we don't care that much about (subresource or without an intersting content)
Advantages :
Use of post, put and delete
Solution 3 : Use links
Third option is to use links, using HAL for instance.
HAL allows to add properties to link. Introducing a hasChange property solves the problem.
A line amount update would works like this :
Request
PATCH api.something.com/bills/156/lines/1
{
amount: 5
}
Response
HTTP/1.1 200 Success
{
amount:5,
label: "Item 1",
"_links": {
"bill": {
"href": "/bill/156",
hasChanged: true
}
}
}
Advantages :
Works for non subresource
Works when several resources are updated
Drawbacks :
Dealing with links. (But links are a major part of REST)
I'm curious to know if someone can advise for or against one of the solutions because they all seem interesting to me.
I have a table Article, a table Tag and a joint table to associate a tag to an article.
While creating a new Article, by sending a POST request to /Service.svc/Articles, is it possible to enclose in the JSON object a list of Tag ids to be associated?
Something like:
{
title: "My article title",
text: "The content:",
Tags: [ { id: 1 }, { id: 2 }, { id: 3 } ]
}
If not can I send the list of tags in one request? For example:
/Service.svc/Articles(1)/Tags
[ { id: 1 }, { id: 2 }, { id: 3 } ]
Or do I have to make as many requests as they are tags?
Thank you very much in advance.
You can modify just the links by POST/PUT/DELETE to the $links URL as described here: http://www.odata.org/developers/protocols/operations#CreatingLinksbetweenEntries
The samples there use ATOM/XML, but the respective JSON format is also possible.
To send multiple operations to the server in one request (to save the roundtrips) you can create a batch request as described here:
http://www.odata.org/developers/protocols/batch
As a follow up to my previous question about REST URIs for retrieving statistical information for a web forum Resource, I want to know if it is possible to use the internal anchors as filter hints. See example below:
a) Get all statistics:
GET /group/5t7yu8i9io0op/stat
{
group_id: "5t7yu8i9io0op",
top_ranking_users: {
[ { user: "george", posts: 789, rank: 1 },
{ user: "joel", posts: 560, rank: 2 } ...]
},
popular_topics: {
[ ... ]
},
new_topics: {
[ ... ]
}
}
b) GET only popular topics
GET /group/5t7yu8i9io0op/stat#popular_topics
{
group_id: "5t7yu8i9io0op",
popular_topics: {
[ ... ]
}
}
c) GET only top ranking users
GET /group/5t7yu8i9io0op/stat#top_ranking_users
{
group_id: "5t7yu8i9io0op",
top_ranking_users: {
[ { user: "george", posts: 789, rank: 1 },
{ user: "joel", posts: 560, rank: 2 } ...]
}
}
Or should I be using query parameters ?
Not sure what you are trying to do exactly, but make sure you understand that fragment identifiers are not seen by the server, they are chopped off by the client connector.
See: http://www.nordsc.com/blog/?p=17
I've never seen anchors being used that way - it's interesting. That being said, I'd suggest using query parameters for a couple of reasons:
They're standard - and consumers of your api will be comfortable with them. There's nothing more annoying that dealing with a quirky api.
Many frameworks will auto-parse the query parameters and set them in a dictionary on the request object (or whatever analogue exists in your framework / http server library).
I think it would make more sense to have:
/group/5t7yu8i9io0op/stat/top_users
/group/5t7yu8i9io0op/stat/popular_topics
/group/5t7yu8i9io0op/stat/new_topics
/group/5t7yu8i9io0op/stat/user/george
No you cannot do that because as Jan points out the server will never see that fragment identifier. Literally, that part of the url will not reach the server.