Facebook Messenger Bots: Image Caching - facebook

I am building a bot for FB Messenger. One of the scenarios require using the Generic Template of the sendAPI. However, it seems like FB Messenger is caching the images included in the template. Is there a way to avoid that?
One thing to note here is that I am using ExpressJS and I am serving the images through a normal controller using res.sendFile(..) as opposed to serving them as static files. I also disabled caching using the following:
app.use(function(req, res, next) {
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');
next()
});

Related

Force POST form submission to send cookies

I'm working on a feature for a Chrome extension which requires making a same-origin POST request to an endpoint. For brevity, I'll leave out the particular details of the website. This request creates a resource of a given kind. I've succeeded in being able to create many kinds of these resources, but there's one type in particular that always fails.
When you use the website's own UI to create this kind of resource, I noticed that the resulting POST request is sent with the cookie header, along with some other stuff that looks unfamiliar to me. Here's an excerpt of the request headers:
:authority:www.example.com
:method:POST
:path:/path/to/endpoint
:scheme:https
[...]
cookie: [...]
The cookies are not sent for any other resource type, just this one.
Now, since this passes along cookies, the website's own javascript can't be using ajax. In fact, the site is posting to an <iframe> by linking a <form> to an <iframe> of a particular name.
So, I modified my Chrome extension code to use forms to post to iframes instead of making an ajax request, just like it's done natively on the website. However, the resulting POST requests still do not pass cookies. I have found nothing unique about the parts of the website's UI which create these special resources which might cause the requests to pass cookies.
How does Chrome decide when to pass cookies in a web request? How can I force it to do this for a <form> submission?
EDIT: Here are some more details, as requested.
To create a resource, just POST multipart data to /resource-endpoint. In jQuery you might do something like
var data = new FormData();
data.append('property', 'value'); // Add payload values
$.ajax({
url: '/resource-endpoint'
type: 'POST',
cache: false,
contentType: false,
processData: false,
data: data
});
Doing it this way will create most resources, except for the "special" resource. Since AJAX requests cannot pass along cookies, and the request to create the "special" resource must include cookies, I have to mimic the website's UI more closely.
var id = 'some-id';
var iframe = $('<iframe name="' + id + '"></iframe>');
$(document.body).append(iframe);
var form = $('<form></form>');
form.attr({
target: id,
action: '/resource-endpoint,
method: 'POST',
enctype: 'multipart/form-data'
});
// Add payload values
form.append('<input name="property" value="value" />');
$(document.body).append(form);
form.submit();
This still sends along requests, but there appears to be something missing, because requests to create the "special" resource do not include cookies. I'm not sure how the native website javascript is doing this, as I can't find any difference between the forms that create regular resources and the form that creates "special" resources.
EDIT: Nevermind, I saw a native "special resource" POST request from the UI which doesn't pass along these cookies, so the secret must not be the cookies.

Angular/Node/Express/Passport - Issues when connecting to facebook(CORS)

i'm trying to use facebook authentication on my NodeJs server. i came to the tutorial of http://scotch.io/ and have it working locally when using a REST client(Postman, etc).
To improve the UI i used Angular JS as a front end. but when i call a http.get to my specific route given on the NodeJs back-end i get the following error in chome and firefox:
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%…0%2Fapi%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=3000000000006. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'localhost:8080' is therefore not allowed access.
i've tried several solutions on StackOverflow but its still not working...
my NodeJs uses Express 4.* and a CORS middleware.
for Angular i found several ways to enable CORS, none working so far.
I hope you can help me:D Thanks in advance!
You can use 'window.location="http://localhost:3000/auth/facebook"'; in your Angular Controller from where you send the request to your Express Server which contains passport.authenticate stuff.
This will stop your angular to call facebook auth dialogue page as AJAX request.
It works for me!
I'm using Angular with Node/Express as well, and the following function works for me with my own backend services (I'm currently not using it with Facebook to be honest), so just check it out:
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Access-Control-Allow-Origin');
res.header("Access-Control-Max-Age", "86400"); // 24 hours
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
};
Then, you need to use it tin the app.confiure()method as follows:
// configure Express
app.configure(function() {
app.use(allowCrossDomain);
...
});
It's important to use it BEFORE all other directrives!

How do I convert a REST HttpRequest captured via a web proxy tool into a link a user can click?

I have used a proxy tool to capture a certain REST HttpRequest. The request is a HTTP PUT command followed by an extremely long REST link containing specific data that gets sent to the server.
In the proxy tool it looks something like this:
Header
PUT http://XXX.XXX.XXX.XXX:8080/rest/blah/blah/.../ HTTP/1.1
Host: XXX.XXX.XXX.XXX:8080
User-Agent: Mozilla/5.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-language: en-us, en:q=0.5
Proxy Connection:keep-alive
Content-Type:XMLHttpRequest
Referer: http://XXX.XXX.XXX.XXX:8080/plugins/blah/blah
Content-length: 11156
Cookie: JSESSIONID=<really long alpha numeric>
Body:
{"links":{"self":"/rest/plugins/1.0/blah/blah.....
...
... lots and lots of JSON text
}
}
So the proxy tool has been helpful in identifying what the request looks like.
But the only way to generate this request is by clicking a button on the webpage. I would like to send exact same request on my own (like creating a custom link that when clicked generates a similar request to the one shown above). How do I do this?
Also, anything I type in the web browser URL area automatically is a "GET". How do I force a PUT?
Cookie: JSESSIONID=
This clearly indicates that the API you want to use is not a REST API, because it violates the stateless constraint of REST.
How do I force a PUT?
Probably you don't have a way to do that. It depends on the security settings of the web API. If you want to do this with AJAX from the browser, and your domain is different from the APIs domain, then you need a CORS header from the API, which allows your domain to read cross origin responses. By PUT the browsers sends a preflight first, and if it cannot read the response, it will never send the real PUT. Security policy and other headers can block XSS in the browser, so you probably don't have a way to do this from browser.
You can do this from your server by copying the request details and catching the session id somehow.
If the API allows access to 3rd party clients, then I suggest you to contact with them. If not, then you 99% that you won't be able to do this.

Calling external REST web service from Single Page Application

I am creating a SPA with Backbone & Underscore JS. The basic feature of the app being that on entering a search term , it needs a trigger an external REST web service call and fetch the JSON response. However when i try this, the browser cancels the request as i guess it tries to make a cross-domain AJAX call.
I am hosting this SPA in my local and the REST web service is hosted on a external server. If i need to make cross-domain calls, what is the procedure which i need to follow without making any changes in the server side? I heard JSONP is one of the alternatives but not sure on the approach.
It looks like it is the same problem as in this question. It is pretty useful:
JSONP and Backbone.js
If your external service supports it already, you are correct that JSONP would be the way to go for cross domain requests without having to change anything on the server side. I assume you're using jQuery. Here's an example from jQuery's docs:
var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
$.getJSON( flickerAPI, {
tags: "mount rainier",
tagmode: "any",
format: "json"
})
.done(function( data ) {
console.log(data);
});
You'll notice the ?jsoncallback=? in the flickr URL. That tells flickr to wrap the response in a JSONP callback instead of just returning normal JSON. When flickr sees that, they wrap the response like this:
jQuery19104044632513541728_1395560629443({
"title": "Recent Uploads tagged mountrainier",
...other json data...
});
So instead of returing JSON, they wrap it in a function call which jQuery puts on the global window object. That function call will call your success function with the json data.
Luckily, you don't have to know anything about the inner-workings of it. All you do is call $.getJSON and it'll work!

GWT JSONP with Post not Get

I have a web service in the form `http://....../methodName
It returns a jsonp result such as:
methodName(["a":"a", "b":"b"])
GWT provides JsonpRequestBuilder class to parse jsonp.
JsonpRequestBuilder rb = new JsonpRequestBuilder();
rb.setCallbackParam("callback");
rb.requestObject("http://...../methodName", new AsyncCallback<TestJS>(){
...
});
This structure makes a request to url :
"http://...../methodName/?callback=__gwt_jsonp_P0.onSuccess".
My web service returns a callback with methodName not with __gwt_json.....
So gwt could not create a JavaScriptObject from that response.
Also JsonpRequestBuilder works with GET not POST.
How can I achieve those: Sending requests with POST and modifying GWT's default callback name.
JSONP will NOT work with POST. Its not a GWT limitation btw.
JSONP is essentially including a javascript file from your server. So, when you make a JSONP call, a temporary tag is added to the DOM.
Now, a <script> tag can always makes a GET request. That's a browser thing, and GWT cannot do much about it.
If you want to make a cross-domain POST call, you have to chose from one of the following options (and they have nothing to do with GWT)
Use Flash plus a crossdomain.xml that allows cross domain posts
Use Cross Origin Resource Sharing, or CORS. NOTE that this is only supported in modern browsers
Use a proxy server on your domain
Unfortunatly, this isn't how JsonP works. The requests are made by adding a tag to the page, and the results are passed into a function wrapped around the data – in your case, __gwt_jsonp_P0.onSuccess.
The callback name can't be affected, at least while using JsonpRequestBuilder – the system needs to account for the fact that you could send multiple requests out at once, possibly even to different endpoints. A JsonP endpoint that doesn't allow the caller to customize the callback function name is very unusual, and even more odd is an endpoint expecting JsonP calls that expects an impossible POST.
You can implement your own JsonP client side code by using the ScriptElement type, and registering your own global callback to call into your GWT java code.
Look into the API docs for the web service, and see if there is perhaps a better way to communicate with it, perhaps by using a proxy on your own server, avoiding the cross domain issue altogether.