PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 8.5.71
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v8.5.71
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
wpvr / vendor / posthog / posthog-php / lib / Consumer / Socket.php

Socket.php in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 8.5.71, at vendor/posthog/posthog-php/lib/Consumer/Socket.php

238 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PostHog\Consumer;
4
5 use Exception;
6 use PostHog\QueueConsumer;
7
8 class Socket extends QueueConsumer
9 {
10 protected $type = "Socket";
11 private $socket_failed;
12
13 /**
14 * Creates a new socket consumer for dispatching async requests immediately
15 * @param string $apiKey
16 * @param array $options
17 * number "timeout" - the timeout for connecting
18 * function "error_handler" - function called back on errors.
19 * boolean "debug" - whether to use debug output, wait for response.
20 */
21 public function __construct($apiKey, $options = array())
22 {
23 if (!isset($options["timeout"])) {
24 $options["timeout"] = 5;
25 }
26
27 parent::__construct($apiKey, $options);
28 }
29
30 /**
31 * Define getter method for consumer type
32 *
33 * @return string
34 */
35 public function getConsumer()
36 {
37 return $this->type;
38 }
39
40 public function flushBatch($batch)
41 {
42 $socket = $this->createSocket();
43
44 if (!$socket) {
45 return;
46 }
47
48 $payload = $this->payload($batch);
49 $payload = json_encode($payload);
50
51 $body = $this->createBody($this->host, $payload);
52 if (false === $body) {
53 return false;
54 }
55
56 return $this->makeRequest($socket, $body);
57 }
58
59 private function createSocket()
60 {
61 if ($this->socket_failed) {
62 return false;
63 }
64
65 $protocol = $this->ssl() ? "ssl" : "tcp";
66 $port = $this->ssl() ? 443 : 80;
67 $timeout = $this->options["timeout"];
68
69 try {
70 // Open our socket to the API Server.
71 // Since we're try catch'ing prevent PHP logs.
72 $socket = @pfsockopen(
73 $protocol . "://" . $this->host,
74 $port,
75 $errno,
76 $errstr,
77 $timeout
78 );
79
80 // If we couldn't open the socket, handle the error.
81 if (false === $socket) {
82 $this->handleError($errno, $errstr);
83 $this->socket_failed = true;
84
85 return false;
86 }
87
88 return $socket;
89 } catch (Exception $e) {
90 $this->handleError($e->getCode(), $e->getMessage());
91 $this->socket_failed = true;
92
93 return false;
94 }
95 }
96
97 /**
98 * Attempt to write the request to the socket, wait for response if debug
99 * mode is enabled.
100 * @param resource $socket the handle for the socket
101 * @param string $req request body
102 * @param boolean $retry
103 * @return boolean $success
104 */
105 private function makeRequest($socket, $req, $retry = true)
106 {
107 $bytes_written = 0;
108 $bytes_total = strlen($req);
109 $closed = false;
110
111 // Retries with exponential backoff until success
112 $backoff = 100; // Set initial waiting time to 100ms
113
114 while (true) {
115 // Send request to server
116 while (!$closed && $bytes_written < $bytes_total) {
117 try {
118 // Since we're try catch'ing prevent PHP logs.
119 $written = @fwrite($socket, substr($req, $bytes_written));
120 } catch (Exception $e) {
121 $this->handleError($e->getCode(), $e->getMessage());
122 $closed = true;
123 }
124 if (!isset($written) || !$written) {
125 $closed = true;
126 } else {
127 $bytes_written += $written;
128 }
129 }
130
131 // Get response for request
132 $statusCode = 0;
133 $errorMessage = "";
134
135 if (!$closed) {
136 $res = $this->parseResponse(fread($socket, 2048));
137 $statusCode = (int)$res["status"];
138 $errorMessage = $res["message"];
139 }
140 fclose($socket);
141
142 // If status code is 200, return true
143 if (200 == $statusCode) {
144 return true;
145 }
146
147 // If status code is greater than 500 and less than 600, it indicates server error
148 // Error code 429 indicates rate limited.
149 // Retry uploading in these cases.
150 if (($statusCode >= 500 && $statusCode <= 600) || 429 == $statusCode || 0 == $statusCode) {
151 if ($backoff >= $this->maximum_backoff_duration) {
152 break;
153 }
154
155 usleep($backoff * 1000);
156 } elseif ($statusCode >= 400) {
157 if ($this->debug()) {
158 $this->handleError($res["status"], $res["message"]);
159 }
160
161 break;
162 }
163
164 // Retry uploading...
165 $backoff *= 2;
166 $socket = $this->createSocket();
167 }
168
169 return true;
170 }
171
172 /**
173 * Create the body to send as the post request.
174 * @param string $host
175 * @param string $content
176 * @return string body
177 */
178 private function createBody($host, $content)
179 {
180 $req = "";
181 $req .= "POST /batch/ HTTP/1.1\r\n";
182 $req .= "Host: " . $host . "\r\n";
183 $req .= "Content-Type: application/json\r\n";
184 $req .= "Accept: application/json\r\n";
185
186 // Send user agent in the form of {library_name}/{library_version} as per RFC 7231.
187 $content_json = json_decode($content, true);
188 $libName = $content_json['batch'][0]['library'];
189 $libVersion = $content_json['batch'][0]['library_version'];
190 $req .= "User-Agent: ${libName}/${libVersion}\r\n";
191
192 // Compress content if compress_request is true
193 if ($this->compress_request) {
194 $content = gzencode($content);
195
196 $req .= "Content-Encoding: gzip\r\n";
197 }
198
199 $req .= "Content-length: " . strlen($content) . "\r\n";
200 $req .= "\r\n";
201 $req .= $content;
202
203 // Verify message size is below than 32KB
204 if (strlen($req) >= 32 * 1024) {
205 if ($this->debug()) {
206 $msg = "Message size is larger than 32KB";
207 error_log("[PostHog][" . $this->type . "] " . $msg);
208 }
209
210 return false;
211 }
212
213 return $req;
214 }
215
216 /**
217 * Parse our response from the server, check header and body.
218 * @param string $res
219 * @return array
220 * string $status HTTP code, e.g. "200"
221 * string $message JSON response from the api
222 */
223 private function parseResponse($res)
224 {
225 $contents = explode("\n", $res);
226
227 // Response comes back as HTTP/1.1 200 OK
228 // Final line contains HTTP response.
229 $status = explode(" ", $contents[0], 3);
230 $result = $contents[count($contents) - 1];
231
232 return array(
233 "status" => isset($status[1]) ? $status[1] : null,
234 "message" => $result
235 );
236 }
237 }
238