PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.16
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.16
2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / telemetry / class-request_monitor.php

class-request_monitor.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.16, at telemetry/class-request_monitor.php

328 lines 10.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // If this file is called directly, abort.
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Request monitoring
9 *
10 * */
11
12 class Metasync_Telemetry_Request_Monitor {
13
14 # telemetry manager
15 private $telemetry_manager;
16
17 # construct
18 function __construct(){
19 $this->telemetry_manager = Metasync_Telemetry_Manager::get_instance();
20 }
21
22 /**
23 * Get current timestamp for logging
24 */
25 private function log_timestamp() {
26 return current_time('mysql');
27 }
28
29 # uri strings
30
31 # These are sections of the uri to look for in a request
32 # prevents logging unauthorized requests
33 protected $loggable_uri_strings = [
34 'metasync', 'searchatlas'
35 ];
36
37
38 /**
39 * Check Loggable URI
40 * This method helps us check that the uri is permitted
41 * Otherwise it returns fals
42 *
43 */
44 function log_uri_permitted($uri) {
45
46 # Get permitted URI strings
47 $permitted_strings = $this->loggable_uri_strings;
48
49 # If an asterisk is used, allow all
50 if ($permitted_strings === '*') {
51 return true;
52 }
53
54 # Check if any string is in the URI
55 foreach ($permitted_strings as $string) {
56 if (strpos($uri, $string) !== false) {
57 return true; # Found a match
58 }
59 }
60
61 # Return false for no matches
62 return false;
63 }
64
65 # @section
66 # Monitors Incoming and Outgoing Request Data
67
68 # let's monitor outgoing logs
69 function api_monitor_outgoing($preempt, $args, $url){
70
71 # ignore wp chron requests
72 if(strpos($url, 'wp-cron.php') !== false){
73 return $preempt;
74 }
75
76 # check that the route is permitted for logging
77 if ( empty($url) || $this->log_uri_permitted($url) == False ){
78 return $preempt;
79 }
80
81 # prepare the request object
82 $request = [
83 'timestamp' => $this->log_timestamp(),
84 'type' => 'outgoing_request',
85 'method' => $args['method'] ?? 'undefined',
86 'request_url' => $url,
87 'args' => $args
88 ];
89
90 # send the request with telemetry manager
91 $this->telemetry_manager->send_message('Outgoing Request', 'info', $request);
92
93
94 # Return preempt to allow the request to continue
95 return $preempt;
96
97 }
98
99 # monitor incoming
100 function api_monitor_incoming($result, $server, $request){
101
102 # check that the route is permitted for logging
103 if ( empty($request->get_route()) || $this->log_uri_permitted($request->get_route()) == False ){
104 return $result;
105 }
106
107 # prepare the reuqest
108
109 $request_data = [
110 'timestamp' => $this->log_timestamp(),
111 'type' => 'incoming_request',
112 'method' => $request->get_method(),
113 'uri' => $request->get_route(),
114 'headers' => $request->get_headers(),
115 'body' => $request->get_params()
116 ];
117
118 # if the request is not GET attach get params
119 if($request->get_method() !== 'GET'){
120
121 #append request get params
122 $request_data['_GET_params'] = $_GET;
123 }
124
125 $this->telemetry_manager->send_message('Incoming Request', 'info', $request_data);
126
127
128 # Return result to allow the request to continue
129 return $result;
130 }
131
132 # @section
133 # Monitors the Request Responses
134 # Helps checking for errors
135
136 # monitor the response to an outgoing API call
137 # function monitor_outgoing_response($response, $context, $url, $parsed_args){
138 function monitor_outgoing_response($response, $parsed_args, $url){
139
140 # Skip logging for wp-cron requests
141 if (strpos($url, 'wp-cron.php') !== false) {
142 return $response;
143 }
144
145 # check that the route is permitted for logging
146 if ( empty($url) || $this->log_uri_permitted($url) == False ){
147 return $response;
148 }
149
150 # request data
151 $response_data = [
152 'timestamp' => $this->log_timestamp(),
153 'type' => 'outgoing_response',
154 'status_code' => $response['response']['code'] ?? '',
155 'url' => $url,
156 'response_data' => $this->sanitize_outgoing_response($response),
157 'args' => $this->sanitize_args($parsed_args)
158 ];
159
160 #return the response
161 $this->telemetry_manager->send_message('Outgoing Response', 'info', $response_data);
162
163
164 # Return response to allow it to continue
165 return $response;
166 }
167
168 # monitor the response to an incoming api call
169 function monitor_incoming_response($response, $server, $request){
170
171 # check that the route is permitted for logging
172 if ( empty($request->get_route()) || $this->log_uri_permitted($request->get_route()) == False ){
173 return $response;
174 }
175
176 # prepare the response object
177 $response_object = array(
178 'timestamp' => $this->log_timestamp(),
179 'type' => 'incoming_response',
180 'status_code' => $response->get_status() ?? '',
181 'url' => $request->get_route(),
182 'method' => $request->get_method(),
183 'response_data' => $this->sanitize_response_data($response),
184 'request_data' => $this->sanitize_request_data($request)
185 );
186
187 # let record the response
188
189 $this->telemetry_manager->send_message('Incoming Response', 'info', $response_object);
190
191 # Return response to allow it to continue
192 return $response;
193
194 }
195
196 /**
197 * Sanitize WP_REST_Response object for serialization
198 *
199 * @param mixed $response The response object
200 * @return array Sanitized response data
201 */
202 private function sanitize_response_data($response) {
203 if (!is_object($response)) {
204 return is_array($response) ? $response : array();
205 }
206
207 return array(
208 'status' => method_exists($response, 'get_status') ? $response->get_status() : null,
209 'data' => method_exists($response, 'get_data') ? $response->get_data() : null,
210 'headers' => method_exists($response, 'get_headers') ? $response->get_headers() : null,
211 'links' => method_exists($response, 'get_links') ? $response->get_links() : null
212 );
213 }
214
215 /**
216 * Sanitize WP_REST_Request object for serialization
217 *
218 * @param mixed $request The request object
219 * @return array Sanitized request data
220 */
221 private function sanitize_request_data($request) {
222 if (!is_object($request)) {
223 return is_array($request) ? $request : array();
224 }
225
226 return array(
227 'method' => method_exists($request, 'get_method') ? $request->get_method() : null,
228 'route' => method_exists($request, 'get_route') ? $request->get_route() : null,
229 'params' => method_exists($request, 'get_params') ? $request->get_params() : null,
230 'headers' => method_exists($request, 'get_headers') ? $request->get_headers() : null,
231 'body' => method_exists($request, 'get_body') ? $request->get_body() : null
232 );
233 }
234
235 /**
236 * Sanitize outgoing HTTP response for serialization
237 *
238 * @param array $response The HTTP response array
239 * @return array Sanitized response data
240 */
241 private function sanitize_outgoing_response($response) {
242 if (!is_array($response)) {
243 return $response;
244 }
245
246 $sanitized = array();
247
248 // Safely extract response data
249 if (isset($response['response'])) {
250 $sanitized['response'] = array(
251 'code' => $response['response']['code'] ?? null,
252 'message' => $response['response']['message'] ?? null
253 );
254 }
255
256 if (isset($response['headers'])) {
257 $sanitized['headers'] = $response['headers'];
258 }
259
260 if (isset($response['body'])) {
261 $sanitized['body'] = $response['body'];
262 }
263
264 if (isset($response['cookies'])) {
265 $sanitized['cookies'] = $response['cookies'];
266 }
267
268 return $sanitized;
269 }
270
271 /**
272 * Sanitize HTTP request arguments for serialization
273 *
274 * @param array $args The HTTP request arguments
275 * @return array Sanitized arguments
276 */
277 private function sanitize_args($args) {
278 if (!is_array($args)) {
279 return $args;
280 }
281
282 $sanitized = array();
283
284 // Only include safe, serializable data
285 $safe_keys = array('method', 'timeout', 'redirection', 'httpversion', 'user-agent', 'reject_unsafe_urls', 'blocking', 'sslverify', 'stream', 'filename', 'decompress');
286
287 foreach ($safe_keys as $key) {
288 if (isset($args[$key])) {
289 $sanitized[$key] = $args[$key];
290 }
291 }
292
293 // Sanitize headers if present
294 if (isset($args['headers']) && is_array($args['headers'])) {
295 $sanitized['headers'] = $args['headers'];
296 }
297
298 // Sanitize body if present (but limit size)
299 if (isset($args['body'])) {
300 $body = $args['body'];
301 if (is_string($body) && strlen($body) > 1000) {
302 $body = substr($body, 0, 1000) . '... [truncated]';
303 }
304 $sanitized['body'] = $body;
305 }
306
307 return $sanitized;
308 }
309
310 /**
311 * @see monitor_api_calls
312 *
313 */
314 function monitor_api_calls(){
315 # log incoming requests
316 add_filter('rest_pre_dispatch', [$this, 'api_monitor_incoming'],10, 3);
317
318 # add hook to monitor outgoing api requests
319 add_filter('pre_http_request', [$this, 'api_monitor_outgoing'], 1, 3);
320
321 # Hook to monitor outgoing API responses
322 add_action('http_response', [$this, 'monitor_outgoing_response'], 10, 4);
323
324 # Monitor incoming request responses
325 add_filter('rest_post_dispatch', [$this, 'monitor_incoming_response'], 10, 3);
326
327 }
328 }