Facebook is using a sort of web page prerendering mechanism in it’s in-app browser for mobile users [see disclosure here]. It is used by Facebook’s in-app browser to speed up page rendering for web link content shared on Facebook. But it can cause serious headaches, and this post should explain how to mitigate it with Apache or nginx.
Web page prerendering is not uncommon way of reducing frontend load times. Most today’s browsers support it, and some of them use it regularly (like Chrome – did you notice how first results on Google sometimes render instantly?!). Some browsers prefer “preview” instead of “prerender” [like Safari], so other browsers [like Chrome] had to accept both instructions for the same action.
We all know that Magento CPU cycles come at a price. You should test on your own whether this FB in-app feature has implications on your web server performance and expenditure.
Facebook’s “Liger preview” requests can be recognized in your server logs by:
- HTTP referer: “http://m.facebook.com”
- User-Agent has: FB_IAB/FB4A;FBAV (Facebook in-app browser for Android)
- x-fb-http-engine: Liger – this is the identifier of the engine, BUT, FB in-app does not send it every time! It is being sent only when X-Purpose is sent:
- X-Purpose: preview – page prerender/prefetcher HTTP header
- regular images are not loaded – FB in-app requests only for HTML page
Every owner of Facebook page(s) that regularly shares links and with more than 10K fans should test their website for this particular page requests, as it might severely impact web site performance. Please, check this article on how to precisely log and test how severe your web site is affected.
I’m affected, what now?!
Since these requests are marked with two significant HTTP headers, we’ll use them to block this type of requests. We don’t want to block ALL prerender/preview requests, only those that come from Facebook’s in-app browser engine signed as “Liger“.
In Apache, you can use [tested, verified]:
RewriteCond %{HTTP:x-fb-http-engine} Liger
RewriteCond %{HTTP:X-Purpose} preview
RewriteRule .* - [F,L]
In nginx, you can use [not tested, but should work; please verify]:
This rule checks for presence of one HTTP header [faster]:
if ($http_x_fb_http_engine = "Liger") {
return 403 "Access denied due to Facebook's 'Liger preview' site hammering";
}
This one covers requests when both headers are present [since nginx does not support logical AND, we have to use a trick] :
if ($http_x_fb_http_engine = "Liger") {
set $lp L;
}
if ($http_x_purpose = "preview") {
set $lp "${lp}P";
}
if ($lp = "LP") {
return 403 "Access denied due to Facebook's 'Liger preview' site hammering";
}
And that’s it!
Don’t forget, prerendering can be quite cool and useful, so not all prerender/preview requests should be blocked – only those that originate from “Liger” engine. Prerendering advantages will be covered in the next article so – stay tuned!