Does it make sense to use internal anchors for filtering a REST API's representation? - rest

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.

Related

Custom filters that accept objects - lighthouse-php

I am using lighthouse-php as Api Gateway in a micro services architecture.
So for all my types I make a request internally through Guzzle.
But I am needing to implement filters that are suitable for any type and that give flexibility when making queries.
I need to implement a query like this:
query news (
order_by: {publication_date: desc}
where: {
_or: {categories_id: { _eq: 1 }, title: { _ilike: "news" } }
}
limit: 10
offset: 20
) {
id
category_name: name
photo
publication_date
text
title
}
But I have no idea how to implement this "where" filter that receives a composite object as in this example.
Remember that this query will not use any model within lumen, since it will be a custom query that will make a request to the microservice of news.
What I need is the way that my query receives whatever comes in where, limit and order, to send it on request. But I have no idea how to build something like this in the scheme.
Anyone have any idea how to do it?
Thanks friends.
Yes, you can.
Just now I'm making an component that will receive criterias to filter in graphql query so I need to fill filter's where params with those criterias.
Imagine the following schema:
type News{
id: ID!
title: String!
views: Int!
}
type Query{
getNews(where: _ #whereConditions(columns:["title", "views"])) : [News!] #all
}
We can make a query and fill where variables later
query GetNews($whereNews: [GetNewsWhereWhereConditions!]){
getNews(where: {OR: $whereNews}){
title
views
}
}
When querying we can fill the variables sending an object like
{
"where":[
{"column": "TITLE", "operator": "LIKE", "value": "Amazing title"},
{"column": "VIEWS", "operator": "GTE", "value": 10,
]
}

Omit response fields on Bing maps query

I'm looking for ways to reduce my bing maps query response size. For example - If I'm interested in the road distance between Seattle and LA, I'd query:
http://dev.virtualearth.net/REST/V1/Routes?wp.0=seattle&wp.1=losangeles&key=
(sorry, you'll have to use your own key)
... and that would give me something this (~1kB):
{
...
[
{
estimatedTotal: 1,
resources:
[
{
__type: "Route:http://schemas.microsoft.com/search/local/ws/rest/v1",
bbox:
[
34.053493,
-123.393781,
47.604151,
-118.242588
],
id: "v65,h-1259215200,i0,a0,cen-US,dAAAAAAAAAAA1,y0,s1,m1,o1,t4,w5D47BElTIPU1~ArgmUSjRxBABAADgAVva_j4A0~U2VhdHRsZSwgV0E1~~~,w9ecGAxFDffU1~ArgmUSgxwaIFAADgAQw_AT8A0~TG9zIEFuZ2VsZXMsIENB0~~~,k1",
distanceUnit: "Kilometer",
durationUnit: "Second",
routeLegs:
[],
travelDistance: 1827.815,
travelDuration: 58573,
travelDurationTraffic: 60478
}
]
}
],
...
This would look good, except expanding the routeLegs node gives me another ~23kB of data in the response - the full route - which I don't need. Anyone knows a way how to filter this out (either routeLegs or any of the underlying nodes?)
Thanks
You can now use the routeAttributes parameter documented here: https://msdn.microsoft.com/en-us/library/ff701717.aspx

REST, cross-references and performances, which compromise?

After reading this excellent thread REST Complex/Composite/Nested Resources about nested structures in REST responses, I still have a question. What's the best choice in terms of performance about the response ?
Let's take an example.
I have an Category object, which contains some Questions. Those Questions contains some Answers. All of these structures have meta-informations.
Now, when querying an url like GET http://<base_url>/categories/, should I include a description of the Categories only, include Question description ? Which one, full description or simplified one ?
In other terms, what's the best solution between those :
{
"results":[
{
'id':1,
'name':'category1',
'description':'foobar',
'questions':[
{
'id':1234,
'question':'My question',
'author' : 4235345,
'answers':[
{
'id':56786,
'user':456,
'votes':6,
'answer':'It's an answer !'
},
{
'id':3486,
'user':4564,
'votes':2,
'answer':'It's another answer !'
},
]
},
...
]
}
...
]
}
OR SOLUTION 2 :
{
"results":[
{
'id':1,
'name':'category1',
'description':'foobar',
'questions':[
{
'id':1234,
'url':'http://foobar/questions/1234'
'answers':[
{
'id':56786,
'url':'http://foobar/answers/56786'
},
{
'id':3486,
'url':'http://foobar/answers/3486'
},
]
},
...
]
}
...
]
}
OR SOLUTION 3 :
{
"results":[
{
'id':1,
'name':'category1',
'description':'foobar',
'questions':'http://foobar/categories/1/questions'
}
...
]
}
Or maybe another solution ?
Thanks !
That depends on what the application will do with the data. If it is only going to display a list of categories, then it is very inefficient to transfer all the data it ever needs at once, especially if the categories are many, which will decrease response time of user (absolute no no).
These scenarios depend heavily on application and usage of data.
One optimization that we can do is, we can create two requests,
GET http://<base_url>/categories
Which will return minimal data immediately and another request,
GET http://<base_url>/categories?all=true
Which will return all data.
Then the client app can make some clever optimizations like, when user requests for categories, request one is sent and it will immediately render the data. Then after getting the list of categories the user will be idle for some time looking and we can use this opportunity to request all data using request two.
However, as I said this will largely depend on the application.

Returning objects with multiple types in a RESTful way

I'm currently designing an API to handle requests from mobile clients. To achieve some degree of decoupling between backend and client I would like to define the webservices in a RESTful way. The challenge that I am facing is returning multiple objects with different types for a single call.
Lets say we have the following Model:
Harbour ... Top level entry
Boat shed ... Assigned to a specific harbour (0..n)
Boat ... Assigned to a specific boat shed (0..n), or directly to a harbour (0..n)
As far as i understand REST, if I now want to display all the boats and sheds in the harbour I would send two requests:
/harbours/{harbour_id}/boats Returning a list of all boats. Boats in a shed would contain an id linking to the shed they are in
/harbours/{harbour_id}/sheds Returning a list of all sheds
As I want to use the web service in a mobile scenario, it would be ideal to combine these two calls into one. This could then either return the list of boats with the shed object nested within, or both object types side by side:
/harbours/22/boats
[
{
"id":1,
"boatName":"Mary",
"boatShed":{
"id":1,
"shedName":"Dock 1",
"capacity":55
}
},
{
"id":2,
"boatName":"Jane",
"boatShed":{
"id":1,
"shedName":"Dock 1",
"capacity":55
}
}
]
or
/harbours/22/boats
{
"boats":[
{
"id":1,
"boatName":"Mary",
"boatShedId":1
},
{
"id":2,
"boatName":"Jane",
"boatShedId":1
}
],
"sheds":[
{
"id":1,
"shedName":"Dock 1",
"capacity":55
}
]
}
My question now is, which of these ways is closer to the idea behind REST, or is it not RESTful at all?
As #Tarken mentioned /boats request should not return sheds in the top level (since the url assumes you're asking for collection of resource Boat)
If you have relations defined as follows
Harbour:
boats: Boat[]
sheds: Shed[]
Shed:
boats: Boat[]
Boat:
harbour: Harbour
shed: Shed
/harbours/ID then returns a Harbour representation with boats and sheds relation set.
{
boats:
[
{ Boat },
{ Boat },
..
],
sheds:
[
{ Shed },
{ Shed },
..
],
...
}
Nothing is against restful principles here - the url uniquely identifies a resource and resource representation can be anything, with links to other resources as well.
Create a Harbour model which contains both Boat Shed and Boat information. If i am implementing the service in Java, then i would have done something like this :
class Boat{
...
}
class BoatShed{
...
}
class Harbour{
List<Boat> boats;
List<BoatShed> boatSheds;
...
}
You can create an API like /api/harbours/{harbourId}.
As per your question you want to display all the boats and sheds in the harbour, say id=1234, you can make a request like this :
GET /api/harbours/1234
This will return list of Boats and list of Boat Sheds like this:
{
"boats":[
{
"id":1,
"boatName":"Mary",
"boatShedId":1
},
{
"id":2,
"boatName":"Mary2",
"boatShedId":2
}
],
"sheds":[
{
"id":1,
"shedName":"Dock 1",
"capacity":55
},
{
"id":2,
"shedName":"Dock 2",
"capacity":50
}
]
}
EDIT
As you want to get boats and Sheds side by side by sending one request, the api/hourbours/{id} looks good according to REST API design principles.
Getting all sheds while requesting for boats is not in accordance with ideal REST API design, but if you want to achieve the same you can d the following.
If you want that way, then first one /api//harbours/{id}/boats looks good to me.

In WCF Data Services, can I enclose a list of references to another entity while creating a new object?

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