mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-06-18 18:16:26 +00:00
Certificates Renewal + SSE
- Certificate renewal is just a re-request as it's forced already - Rejig the routes for readability - Added Server Side Events so that the UI would invalidate the cache when changes happen on the backend, such as certs being provided or failing - Added a SSE Token, which has the same shelf life as normal token but can't be used interchangeably. The reason for this is, the SSE endpoint needs a token for auth as a Query param, so it would be stored in log files. If someone where to get a hold of that, it's pretty useless as it can't be used to change anything, only to listen for events until it expires - Added test endpoint for SSE testing only availabe in debug mode
This commit is contained in:
74
backend/internal/serverevents/sse.go
Normal file
74
backend/internal/serverevents/sse.go
Normal file
@ -0,0 +1,74 @@
|
||||
package serverevents
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"npm/internal/logger"
|
||||
|
||||
"github.com/jc21/go-sse"
|
||||
)
|
||||
|
||||
var instance *sse.Server
|
||||
|
||||
const defaultChannel = "changes"
|
||||
|
||||
// Message is how we're going to send the data
|
||||
type Message struct {
|
||||
Lang string `json:"lang,omitempty"`
|
||||
LangParams map[string]string `json:"lang_params,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Affects string `json:"affects,omitempty"`
|
||||
}
|
||||
|
||||
// Get will return a sse server
|
||||
func Get() *sse.Server {
|
||||
if instance == nil {
|
||||
instance = sse.NewServer(&sse.Options{
|
||||
Logger: logger.Get(),
|
||||
ChannelNameFunc: func(request *http.Request) string {
|
||||
return defaultChannel // This is the channel for all updates regardless of visibility
|
||||
},
|
||||
})
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
// Shutdown will shutdown the server
|
||||
func Shutdown() {
|
||||
if instance != nil {
|
||||
instance.Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// SendChange will send a specific change
|
||||
func SendChange(affects string) {
|
||||
Send(Message{Affects: affects}, "")
|
||||
}
|
||||
|
||||
// SendMessage will construct a message for the UI
|
||||
func SendMessage(typ, lang string, langParams map[string]string) {
|
||||
Send(Message{
|
||||
Type: typ,
|
||||
Lang: lang,
|
||||
LangParams: langParams,
|
||||
}, "")
|
||||
}
|
||||
|
||||
// Send will send a message
|
||||
func Send(msg Message, channel string) {
|
||||
if channel == "" {
|
||||
channel = defaultChannel
|
||||
}
|
||||
logger.Debug("SSE Sending: %+v", msg)
|
||||
if data, err := json.Marshal(msg); err != nil {
|
||||
logger.Error("SSEError", err)
|
||||
} else {
|
||||
Get().SendMessage(channel, sse.SimpleMessage(string(data)))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: if we end up implementing user visibility,
|
||||
// then we'll have to subscribe people to their own
|
||||
// channels and publish to all or some depending on visibility.
|
||||
// This means using a specific ChannelNameFunc that revolves
|
||||
// around the user and their visibility.
|
Reference in New Issue
Block a user