Files
zoraxy/example/plugins/event-subscriber-example/main.go
Anthony Rubick 2f98ecd0c6 fix(event-subscriber-example): remove event.go
the file was removed from zoraxy_plugin, but since `build_all.sh` works
by copying the module to the plugins this change wasn't propagated. This
fix removed the leftover file and updates `build_all.sh` to delete the
existing `zoraxy_plugin` module of the plugins before copying over the
updated code.
2025-09-07 17:10:02 -05:00

106 lines
3.4 KiB
Go

package main
import (
"bytes"
"fmt"
"net/http"
"sync"
plugin "aroz.org/zoraxy/event-subscriber-example/mod/zoraxy_plugin"
"aroz.org/zoraxy/event-subscriber-example/mod/zoraxy_plugin/events"
)
const (
PLUGIN_ID = "org.aroz.zoraxy.event_subscriber_example"
UI_PATH = "/ui"
EVENT_PATH = "/notifyme/"
)
var (
EventLog = make([]events.Event, 0) // A slice to store events
EventLogMutex = &sync.Mutex{} // Mutex to protect access to the event log
)
func main() {
// Serve the plugin intro spect
// This will print the plugin intro spect and exit if the -introspect flag is provided
runtimeCfg, err := plugin.ServeAndRecvSpec(&plugin.IntroSpect{
ID: PLUGIN_ID,
Name: "Event Subscriber Example Plugin",
Author: "Anthony Rubick",
AuthorContact: "",
Description: "An example plugin for event subscriptions, will display all events in the UI",
Type: plugin.PluginType_Utilities,
VersionMajor: 1,
VersionMinor: 0,
VersionPatch: 0,
UIPath: UI_PATH,
/* Subscriptions Settings */
SubscriptionPath: "/notifyme",
SubscriptionsEvents: map[string]string{
// for this example, we will subscribe to all events that exist at time of writing
string(events.EventBlacklistedIPBlocked): "This event is triggered when a blacklisted IP is blocked",
string(events.EventBlacklistToggled): "This event is triggered when the blacklist is toggled for an access rule",
string(events.EventAccessRuleCreated): "This event is triggered when a new access ruleset is created",
},
})
if err != nil {
fmt.Printf("Error serving introspect: %v\n", err)
return
}
// Start the HTTP server
http.HandleFunc(UI_PATH+"/", func(w http.ResponseWriter, r *http.Request) {
RenderUI(runtimeCfg, w, r)
})
http.HandleFunc(EVENT_PATH, func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
var event events.Event
// read the request body
if r.Body == nil || r.ContentLength == 0 {
http.Error(w, "Request body is empty", http.StatusBadRequest)
return
}
defer r.Body.Close()
buffer := bytes.NewBuffer(make([]byte, 0, r.ContentLength))
if _, err := buffer.ReadFrom(r.Body); err != nil {
http.Error(w, fmt.Sprintf("Failed to read request body: %v", err), http.StatusBadRequest)
return
}
// parse the event from the request body
if err := events.ParseEvent(buffer.Bytes(), &event); err != nil {
http.Error(w, fmt.Sprintf("Failed to parse event: %v", err), http.StatusBadRequest)
return
}
// Typically, at this point you would use a switch statement on the event.Name
// to route the event to the appropriate handler.
//
// For this example, we will just store the event and return a success message.
EventLogMutex.Lock()
defer EventLogMutex.Unlock()
if len(EventLog) >= 100 { // Limit the log size to 100 events
EventLog = EventLog[1:] // Remove the oldest event
}
EventLog = append(EventLog, event) // Store the event in the log
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
fmt.Fprintf(w, "Event received: %s", event.Name)
} else {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
serverAddr := fmt.Sprintf("127.0.0.1:%d", runtimeCfg.Port)
fmt.Printf("Starting API Call Example Plugin on %s\n", serverAddr)
http.ListenAndServe(serverAddr, nil)
}