telegram-notifier/notifier/listener/listener.go

87 lines
1.8 KiB
Go

package listener
import (
"context"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
)
type Listener struct {
ctx context.Context
cancel context.CancelFunc
httpSrv *http.Server
exportChan chan string
errorChan chan error
listener net.Listener
handler *http.ServeMux
}
func New(sockPath string) (*Listener, error) {
if err := os.Remove(sockPath); err != nil && !errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("failed to cleanup previously existing socket: %w", err)
}
sock, err := net.Listen("unix", sockPath)
if err != nil {
return nil, fmt.Errorf("failed to create unix socket: %w", err)
}
m := http.NewServeMux()
return &Listener{
handler: m,
httpSrv: &http.Server{
Handler: m,
},
listener: sock,
exportChan: make(chan string, 10),
errorChan: make(chan error, 10),
}, nil
}
func (l *Listener) initMux() {
l.handler.HandleFunc("/", l.sendMessageHandler)
}
func (l *Listener) Run(ctx context.Context) {
l.ctx, l.cancel = context.WithCancel(ctx)
l.initMux()
if err := l.httpSrv.Serve(l.listener); err != nil {
l.errorChan <- fmt.Errorf("failed to serve HTTP server: %w", err)
}
}
func (l *Listener) sendMessage(message string) {
l.exportChan <- message
}
func (l *Listener) sendMessageHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
// TODO: use max length instead of writing everything
bod, err := ioutil.ReadAll(r.Body)
if err != nil {
l.errorChan <- fmt.Errorf("failed to read body: %w", err)
w.WriteHeader(http.StatusBadRequest)
return
}
l.sendMessage(string(bod))
w.WriteHeader(http.StatusOK)
}
func (l *Listener) ExportChan() <-chan string {
return l.exportChan
}
func (l *Listener) ErrorChan() <-chan error {
return l.errorChan
}