Diff -- /var/www/vhosts/3dshawn.com/site1/alert_test_catcher.cgi
Diff
/var/www/vhosts/3dshawn.com/site1/alert_test_catcher.cgi
modified on local at 2026-07-11 18:57:53
Added
+12
lines
Removed
-2
lines
Context
83
unchanged
Blobs
from 0c1ec2c322e7
to 215f8f105f61
to 215f8f105f61
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.| 1 | 1 | #!/usr/bin/perl |
| 2 | 2 | #====================================================================== |
| 3 | 3 | # DriftSense -- /alert_test_catcher.cgi |
| 4 | 4 | # |
| 5 | 5 | # Tiny endpoint that accepts POSTs from the alert dispatcher and appends |
| 6 | 6 | # the raw body + headers to /var/log/drift_sense/test_catcher.log. Used |
| 7 | 7 | # for end-to-end alert testing without needing an external webhook. |
| 8 | 8 | # |
| 9 | 9 | # GET /alert_test_catcher.cgi -> HTML view of the last N events |
| 10 | 10 | # POST anything -> log it, return 200 JSON |
| 11 | 11 | # GET /alert_test_catcher.cgi?raw=1 -> tail the log as text/plain |
| 12 | 12 | #====================================================================== |
| 13 | 13 | use strict; |
| 14 | 14 | use warnings; |
| 15 | 15 | use CGI (); |
| 16 | 16 | use POSIX (); |
| 17 | 17 | |
| 18 | 18 | my $LOG = '/var/log/drift_sense/test_catcher.log'; |
| 19 | 19 | |
| 20 | 20 | $|=1; |
| 21 | 21 | my $cgi = CGI->new; |
| 22 | 22 | my $method = $ENV{REQUEST_METHOD} || 'GET'; |
| 23 | 23 | |
| 24 | 24 | if ($method eq 'POST') { |
| 25 | 25 | my $body = ''; |
| 26 | if (defined $ENV{CONTENT_LENGTH} && $ENV{CONTENT_LENGTH} > 0) { | |
| 27 | read(STDIN, $body, $ENV{CONTENT_LENGTH}); | |
| 26 | # Prefer CGI.pm's POSTDATA -- handles Plesk/nginx buffering + suEXEC | |
| 27 | # STDIN quirks reliably; fall back to sysread if that returns empty. | |
| 28 | $body = $cgi->param('POSTDATA') // ''; | |
| 29 | if ($body eq '' && defined $ENV{CONTENT_LENGTH} && $ENV{CONTENT_LENGTH} > 0) { | |
| 30 | binmode STDIN; | |
| 31 | my $want = int($ENV{CONTENT_LENGTH}); | |
| 32 | while (length($body) < $want) { | |
| 33 | my $chunk = ''; | |
| 34 | my $n = sysread(STDIN, $chunk, $want - length($body)); | |
| 35 | last unless $n; | |
| 36 | $body .= $chunk; | |
| 37 | } | |
| 28 | 38 | } |
| 29 | 39 | my $stamp = POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime); |
| 30 | 40 | my @hdrs; |
| 31 | 41 | foreach my $k (sort keys %ENV) { |
| 32 | 42 | next unless $k =~ /^(HTTP_|CONTENT_|REQUEST_|REMOTE_)/; |
| 33 | 43 | push @hdrs, " $k = $ENV{$k}"; |
| 34 | 44 | } |
| 35 | 45 | if (open(my $fh, '>>', $LOG)) { |
| 36 | 46 | print $fh "==================================================\n"; |
| 37 | 47 | print $fh "[$stamp] delivery received\n"; |
| 38 | 48 | print $fh join("\n", @hdrs), "\n"; |
| 39 | 49 | print $fh "-- body ($ENV{CONTENT_LENGTH} bytes) --\n"; |
| 40 | 50 | print $fh $body, "\n"; |
| 41 | 51 | close($fh); |
| 42 | 52 | } |
| 43 | 53 | print "Content-Type: application/json\n\n"; |
| 44 | 54 | print '{"ok":true,"received_bytes":' . length($body) . '}'; |
| 45 | 55 | exit 0; |
| 46 | 56 | } |
| 47 | 57 | |
| 48 | 58 | # GET modes |
| 49 | 59 | if ($cgi->param('raw')) { |
| 50 | 60 | print "Content-Type: text/plain; charset=utf-8\nCache-Control: no-cache\n\n"; |
| 51 | 61 | if (open(my $fh, '<', $LOG)) { |
| 52 | 62 | my @lines = <$fh>; close($fh); |
| 53 | 63 | # tail last 500 lines |
| 54 | 64 | my $start = @lines > 500 ? scalar(@lines) - 500 : 0; |
| 55 | 65 | print join('', @lines[$start .. $#lines]); |
| 56 | 66 | } else { |
| 57 | 67 | print "(no deliveries yet)\n"; |
| 58 | 68 | } |
| 59 | 69 | exit 0; |
| 60 | 70 | } |
| 61 | 71 | |
| 62 | 72 | # HTML view |
| 63 | 73 | print "Content-Type: text/html; charset=utf-8\nCache-Control: no-cache\n\n"; |
| 64 | 74 | my $body = ''; |
| 65 | 75 | if (open(my $fh, '<', $LOG)) { |
| 66 | 76 | local $/; $body = <$fh>; close($fh); |
| 67 | 77 | } |
| 68 | 78 | my $entries = 0; |
| 69 | 79 | $entries++ while $body =~ /===+/g; |
| 70 | 80 | |
| 71 | 81 | my $esc = $body // ''; |
| 72 | 82 | $esc =~ s/&/&/g; $esc =~ s/</</g; $esc =~ s/>/>/g; |
| 73 | 83 | |
| 74 | 84 | print <<"HTML"; |
| 75 | 85 | <!doctype html><html><head><meta charset="utf-8"><title>Alert catcher -- DriftSense</title> |
| 76 | 86 | <link rel="stylesheet" href="/assets/styles/drift_sense.css"> |
| 77 | 87 | <meta http-equiv="refresh" content="10"> |
| 78 | 88 | </head><body> |
| 79 | 89 | <div style="padding:24px;max-width:1200px;margin:0 auto"> |
| 80 | 90 | <h1 style="color:var(--accent);font-family:var(--sans)">Alert test catcher</h1> |
| 81 | 91 | <p style="color:var(--text-dim)">POST anything here and it gets appended to <code>$LOG</code>. Auto-refreshes every 10s. <a href="?raw=1" style="color:var(--accent-hi)">raw view</a></p> |
| 82 | 92 | <div style="color:var(--text);font-size:12.5px;font-family:var(--mono);background:var(--bg-2);border:1px solid var(--border);border-radius:12px;padding:14px 16px;white-space:pre-wrap;max-height:75vh;overflow:auto">$esc</div> |
| 83 | 93 | </div> |
| 84 | 94 | </body></html> |
| 85 | 95 | HTML |