]> jfr.im git - irc/unrealircd/unrealircd-webpanel.git/blame - api/common_api.php
Fix typo, reported by Jellis lol
[irc/unrealircd/unrealircd-webpanel.git] / api / common_api.php
CommitLineData
fd4848e4 1<?php
c06c1713 2include "../inc/common.php";
fd4848e4 3
9c9d2cdf
BM
4if(session_status() !== PHP_SESSION_ACTIVE) session_start();
5
fd4848e4
BM
6if (!isset($_SESSION['id']))
7 die("Access denied");
8
9// Close the session now, otherwise other pages block
10session_write_close();
11
65b63bbe
BM
12// Apache w/FPM is shit because it doesn't have flushpackets=on
13// or not by default anyway, so we will fill up 4k buffers.
14// Yeah, really silly... I know.
15$fpm_workaround_needed = false;
16if (str_contains($_SERVER['SERVER_SOFTWARE'], 'Apache') &&
17 function_exists('fpm_get_status') &&
18 is_array(fpm_get_status()))
19{
20 $fpm_workaround_needed = true;
21}
22
fd4848e4 23// Only now make the connection (this can take a short while)
c06c1713 24include "../inc/connection.php";
fd4848e4
BM
25
26// Server Side Events
63026197
BM
27if (!defined('NO_EVENT_STREAM_HEADER'))
28 header('Content-Type: text/event-stream');
fd4848e4
BM
29
30// Explicitly disable caching so Varnish and other upstreams won't cache.
31header("Cache-Control: no-cache, must-revalidate");
32
33// Setting this header instructs Nginx to disable fastcgi_buffering and disable
34// gzip for this request.
35header('X-Accel-Buffering: no');
36
37// No time limit
38set_time_limit(0);
39
40// Send content immediately
41ob_implicit_flush(1);
42
f9558c92 43// Flush and stop output buffering (eg fastcgi w/NGINX)
65b63bbe 44function flush_completely()
3c5d6298 45{
65b63bbe 46 while (1)
3c5d6298 47 {
65b63bbe
BM
48 try {
49 $ret = @ob_end_flush();
50 if ($ret === false)
51 break;
52 } catch(Exception $e)
53 {
54 break;
55 }
3c5d6298 56 }
65b63bbe
BM
57}
58
59flush_completely();
fd4848e4
BM
60
61/* Send server-sent events (SSE) message */
62function send_sse($json)
63{
65b63bbe
BM
64 GLOBAL $fpm_workaround_needed;
65 $str = "data: ".json_encode($json)."\n\n";
66 if ($fpm_workaround_needed)
67 $str .= str_repeat(" ", 4096 - ((strlen($str)+1) % 4096))."\n";
68 echo $str;
fd4848e4
BM
69}
70
71function api_log_loop($sources)
72{
73 GLOBAL $rpc;
65b63bbe 74 GLOBAL $fpm_workaround_needed;
fd4848e4
BM
75
76 $rpc->log()->subscribe($sources);
77 if ($rpc->error)
78 {
79 echo $rpc->error;
80 die;
81 }
82
83 for(;;)
84 {
85 $res = $rpc->eventloop();
86 if (!$res)
0a2b3443
BM
87 {
88 /* Output at least something every timeout (10) seconds,
89 * otherwise PHP may not
90 * notice when the webclient is gone.
91 */
65b63bbe
BM
92 if ($fpm_workaround_needed)
93 echo str_repeat(" ", 4095)."\n";
94 else
95 echo "\n";
fd4848e4 96 continue;
0a2b3443 97 }
fd4848e4
BM
98 send_sse($res);
99 }
100}
101
102function api_timer_loop(int $every_msec, string $method, array|null $params = null)
103{
104 GLOBAL $rpc;
105
c16c239b
BM
106 /* First, execute it immediately */
107 $res = $rpc->query($method, $params);
108 if (!$res)
109 die;
110 send_sse($res);
fd4848e4
BM
111 $rpc->rpc()->add_timer("timer", $every_msec, $method, $params);
112 if ($rpc->error)
113 {
69e00a0c
BM
114 /* Have to resort to old style: client-side timer */
115 while(1)
116 {
117 $res = $rpc->query($method, $params);
118 if (!$res)
119 die;
120 send_sse($res);
563ebce7 121 usleep($every_msec * 1000);
69e00a0c 122 }
fd4848e4
BM
123 }
124
69e00a0c 125 /* New style: use server-side timers */
c16c239b
BM
126 /* - First, execute it immediately */
127 $res = $rpc->query($method, $params);
128 if (!$res)
129 die;
130 send_sse($res);
131 /* - Then add the timer */
fd4848e4
BM
132 for(;;)
133 {
134 $res = $rpc->eventloop();
135 if (!$res)
0a2b3443
BM
136 {
137 /* Output at least something every timeout (10) seconds,
138 * otherwise PHP may not
139 * notice when the webclient is gone.
140 */
65b63bbe
BM
141 if ($fpm_workaround_needed)
142 echo str_repeat(" ", 4095)."\n";
143 else
144 echo "\n";
fd4848e4 145 continue;
0a2b3443 146 }
fd4848e4
BM
147 send_sse($res);
148 }
149}