Facebook: field expansion in batch requests? - facebook

Is it possible to make a batch request with one (or more) of the batched requests using field expansion?
For instance, say I'd like information about me, my listen data. These are the three batch requests I wrap up:
{'method': 'GET', 'relative_url': 'me'}
{'method': 'GET', 'relative_url': 'me/music.listens'}
{'method': 'GET', 'relative_url': 'me/friends?fields=name,first_name,last_name,music.listens.limit(1)'}
But when I make the batch request, the first two responses come back with the data I expect and the third response comes back with data in this format (not the data I requested):
{'access_token': '<access token here>'}
I read all about batch requests here:
https://developers.facebook.com/docs/graph-api/making-multiple-requests/
and about field expansions here:
https://developers.facebook.com/docs/graph-api/using-graph-api/
Am I missing something?

You could even combine this into one query:
/me?fields=name,first_name,last_name,music.listens,friends.fields(name,first_name,last_name,music.listens.limit(1))
I noticed that you have a surplus "u" in your request definition
{'method': 'GET', 'relative_url': u'me'}
maybe you should fix this. Anyway, as I said, you dont need the Batch API to combine the requests.

Related

REST : GET but with a requestBody

I'm writing an Endpoint who will extract data. My issue is, the client request need to pass a list of (very complex) object to my enpoint, along other complexe datas.
The whole thing look to complexe to pass by parameters.
Should I still use a GET? can I do it with a requestBody? Or can I do a POST with a response body ?
My endpoint still need to respect REST
the data I need to pass:
{id :"anUuid",
comment : "some very long text sometime more than 1000 char",
dataComputedByOtherServer:[{id:"anUuid",stuff:{"a lot of other stuff"}}]
}
the response body:
{
//allong with the usual REST response http code and other error message
payload:{
moreComplexData:[{id:"anUuid",stuff:{"a lot of other stuff"}}]
}
}
There's no body payload with an HTTP GET - you'll need to use POST (or PUT) to send this as needed.
A payload within a GET request message has no defined semantics -- https://www.rfc-editor.org/rfc/rfc7231#section-4.3.1
So GET is out of bounds.
In the long term, the method want may eventually be SEARCH; see https://github.com/httpwg/http-extensions/issues/943
While POST with the header defined in #942 would help, POST is still an unsafe method that poorly reflects the safe, idempotent semantics of search-like operations. I therefore argue that a a SEARCH method is needed to have a safe, idempotent method with explicit caching support, in opposition to POST which explicitly is not cacheable.
But we aren't there as of 2019: the semantics of SEARCH are still defined by the WebDAV specification, where they don't quite mean what you want.

Rest API enveloping or not

I have one question that i am finding hard to clearly identify the correct answer.
My API has one endpoint that does pagination. So, in the response i have to return to the client the total number of lines afected by the query. The count of records in practice.
I have read that, i should be passing metadata like what i want in the body, enveloping it, but i have also read that, it is not ok to afect the body with meta-data and that the future is to return only non meta-data on the body meaning that it must be on the response header.
O'reilly
If the information you are conveying through a custom HTTP header is important for the correct interpretation of the request or response, include that information in the body of the request or response or the URI used for the request. Avoid custom headers for such usages.
So, my question is, what is the correct approach to the problem? Should i pass the number of lines in response headers or put it in the message body.
Thank you very much.
For pagination, you could use an envelope in the response payload:
{
"data": [...],
"paging": {
"first": "http://api.example.com/foo?page=1&size=10",
"previous": "http://api.example.com/foo?page=2&size=10"
"next": "http://api.example.com/foo?page=4&size=10"
"last": "http://api.example.com/foo?page=5&size=10"
}
}
A similar approach is described in the RFC 5005: each page of results is a separate resource, which contains hyperlinks to the previous and next page of results
You also could use the Link header (line breaks are just for readability purposes):
Link: <http://api.example.com/foo?page=1&size=10>; rel="first",
<http://api.example.com/foo?page=2&size=10>; rel="previous",
<http://api.example.com/foo?page=4&size=10>; rel="next",
<http://api.example.com/foo?page=5&size=10>; rel="last"
Check the link relations registered in IANA.
For returning the number of records, I've seen some APIs using custom headers such as X-Total-Count, but I don't recommend such approach. Send those details in the response payload then.

Play 2.2.x: Query parameters in POST body to avoid exceeding URL limit

I have an API route that takes a list which can sometimes be so long that it exceeds the URL length limit for some browsers. It looks like this:
GET /api/test Controller.test(potentiallyLongList: List[Long], other: String, ...)
To avoid this problem we have decided that if the client sees that the list is too long, it will switch to sending the potentiallyLongList parameter in the POST body.
I'm wondering what the best way to do this is? The potentiallyLongList parameter shows up in several routes so I'd like to avoid having two methods for each one.
One thing I thought of is to catch all POST requests, check if they have the list in the body, and then move it to the URL and send it through Play's routing process again. Unfortunately the onRouteRequest handler in Global.scala hasn't parsed the body yet, so I can't do that.
Is there any way in an action to modify the url and then run the full request again? Or is there a better way I can solve this problem?

Chrome Postman REST: reusing response values as request params in collections?

I'm playing around with Postman REST extension's collections feature.
I have 2 requests: the 1st returns a sessionId in its response body and the 2nd requires the {{sessionId}} value as query param. Can I tell Postman to save the body of the 1st response to the {{sessionId}} variable?
I currently have to a) execute 1st request and b) copy response body and paste it as a value of the 2nd request's query param every time...
thanks,
-nikita
Absolutely Yes!
Here is a json example:
I added the following to the Tests Tab of the first request:
var data = JSON.parse(responseBody);
postman.setGlobalVariable("session_id", data['session_id']);
Basically retrieving the data from responseBody and set it as a global variable
Then in the second request, the URL would be something like this:
http://{{whateverhost}}/api/v1/somefunction/{{session_id}}
Hope this helps.
Cheers

a restful api only uses clean urls - no url variables or post variables

A restful api has to use either get, post, put or delete request methods. The behavaiour and data submitted is entirely determined by the uri string. No query paramters or post variables.
Is this true ?
Valid : http://example.com/foo/84
Not valid : http://example.com/foo/?value=84
Valid :
$.ajax({
  type: 'POST',
  url: "http://example.com/foo/84",
  success: success,
  dataType: dataType
});
Not valid :
$.ajax({
type: 'POST',
url: "http://example.com/foo/",
data: 84,
success: success,
dataType: dataType
});
edit
Two answers so far, and the contradict each other.
Here goes a third answer that contradicts the other two.
RESTful URI is almost an oxymoron. The semantics of the URI is irrelevant to REST, the only thing that matters to REST is that one URI identifies only one resource. Other than that, an URI is an atomic identifier, and its semantics are irrelevant.
For REST it doesn't matter if the URI pointing to a user resource for Joe Doe is:
http://example.com/users/joedoe
Or:
http://example.com/users?username=joedoe
Or:
http://example.com/jif892mfd02-18f2
Or even:
ftp://example.com/users/joedoe.json
It doesn't matter! URIs don't need to have any meaning in a RESTful application. People spend so much time designing meaningful URIs for their REST application, while they should be concerned with their media types. When you click a link on a webpage, you don't care about the semantics of the URI, you only care about the label. The same thing happens with a client using a REST API. The documentation of your media type should describe what links are available and what they do, through labels, and you simply follow them.
If you're concerned with the semantics of the URI, this is a sign that your clients are building URIs from some template in documentation, and you're not using HATEOAS, which means you're not doing REST at all.
POST variables are definitely OK otherwise how would you submit a new resource or update it?
GET parameters are fine to specify how the resource should be rendered. So indeed http://example.com/foo/?value=84 is not right - the URL doesn't represent a resource.
However, http://example.com/user/84?fields=first_name,last_name would be ok. In that case, you would use the additional query parameters to specify that you only want the first name and last name for that resource.
Saying that http://example.com/foo/?value=84 is not valid is not entireley true. What i mean is that as long that it is a valid URL it will work and you'll be able to get the parameters via get or post.
On the other hand, REST is an architecture and one of its demands is a clean URL (one that does not include params with a '?') so such a url is not considered a REST like URL.
So if you intend to build a REST based application, you should only use clean urls.
EDIT:
I see from the comments below you have a problem understanding what is REST so i'll try to give a simple example:
In order to get data you will probably use http://example.com/foo/84 as a get request and the rest FW knows to get resource foo with id 84.
In order to post data about foo, you might call: http://example.com/foo/84 as a POST request and now the Rest FW know that since its a post request it will call the method responsible for handling post and not the one for handling get
To delete, you call the same URL with DELETE action and i think you know the rest.
So, although you have the same URL it really matters if its a GET/POST/PUT/DELETE request.