-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfacebook-request-throttle.php
109 lines (96 loc) · 2.78 KB
/
facebook-request-throttle.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
/**
* Plugin Name: Facebook Request Throttle
* Description: Limits the request frequency from Facebook's web crawler.
* Version: 2.3
* Author: Nadim Tuhin
* Author URI: https://nadimtuhin.com
*/
if (!defined('ABSPATH')) {
die('We\'re sorry, but you can not directly access this file.');
}
// Number of seconds permitted between each hit from meta-externalagent / facebookexternalhit
define('FACEBOOK_REQUEST_THROTTLE', 60.0);
/**
* Check if the request is from Facebook's web crawler
*
* @return bool
*/
function nt_isRequestFromFacebook() {
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
return !empty($userAgent) && (
strpos($userAgent, 'meta-externalagent') !== false ||
strpos($userAgent, 'facebookexternalhit') !== false
);
}
/**
* Check if the request is for an image file
*
* @return bool
*/
function nt_isImageRequest() {
$requestPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$fileExtension = strtolower(pathinfo($requestPath, PATHINFO_EXTENSION));
$allowedImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
return in_array($fileExtension, $allowedImageExtensions);
}
/**
* Get the last access time of Facebook's web crawler
*
* @return float|null
*/
function nt_getLastAccessTime() {
return get_transient('nt_facebook_last_access_time');
}
/**
* Set the last access time of Facebook's web crawler
*
* @param float $currentTime
* @return bool
*/
function nt_setLastAccessTime($currentTime) {
// Set the transient to last just slightly longer than the throttle time
return set_transient(
'nt_facebook_last_access_time',
$currentTime,
FACEBOOK_REQUEST_THROTTLE + 1
);
}
/**
* Throttle Facebook crawler requests to prevent overload
*/
function nt_facebookRequestThrottle() {
// Skip throttling for image requests
if (nt_isImageRequest()) {
return;
}
$lastAccessTime = nt_getLastAccessTime();
$currentTime = microtime(TRUE);
// Check if we need to throttle
if (!$lastAccessTime) {
error_log("No last access time found.");
} elseif ($currentTime - $lastAccessTime < FACEBOOK_REQUEST_THROTTLE) {
nt_sendThrottleResponse();
}
// Attempt to set last access time
if (!nt_setLastAccessTime($currentTime)) {
error_log("Failed to set last access time for Facebook web crawler.");
nt_sendThrottleResponse();
}
}
/**
* Send throttle response with appropriate headers
*/
function nt_sendThrottleResponse() {
status_header(429);
header('Retry-After: 60');
wp_die(
'Too Many Requests',
'Too Many Requests',
['response' => 429]
);
}
// Main logic - only run throttle check for Facebook requests
if (nt_isRequestFromFacebook()) {
nt_facebookRequestThrottle();
}