Files
servtex/frontend/webserver.go

112 lines
2.8 KiB
Go

package frontend
import (
"fmt"
"time"
"embed"
"strings"
"net/http"
"net/url"
"git.noctra.dev/noctra/servtex/backend"
"git.noctra.dev/noctra/servtex/globals"
)
//go:embed jscss/bootstrap.min.css
//go:embed jscss/custom-view.css
//go:embed jscss/htmx.min.js
//go:embed jscss/htmx-ext-sse.js
//go:embed templates/main.html
var WebFiles embed.FS
// Adds necessary Headers for SSE
func sseHeadersAdd(writer *http.ResponseWriter) {
(*writer).Header().Set("Content-Type", "text/event-stream")
(*writer).Header().Set("Cache-Control", "no-cache")
(*writer).Header().Set("Connection", "keep-alive")
}
// Sends a Ping to keep the connection alive
func ssePing(writer *http.ResponseWriter) {
sseHeadersAdd(writer)
fmt.Fprintf((*writer), ": ping\n\n")
(*writer).(http.Flusher).Flush()
}
// Sends new Event
//
// Reads globals.LatexExec
func sseStatusSend(writer *http.ResponseWriter) {
sseHeadersAdd(writer)
fmt.Fprintf((*writer), "event: status\n")
fmt.Fprintf((*writer), "data: Execution Time: %s\n", globals.LatexExec.Timestamp)
fmt.Fprintf((*writer), "data: Execution State: %s\n\n", globals.LatexExec.ExecutionState)
(*writer).(http.Flusher).Flush()
}
// Sends new Event
//
// Reads globals.LatexExec
func ssePDFSend(writer *http.ResponseWriter) {
sseHeadersAdd(writer)
fmt.Fprintf((*writer), "event: pdf\n")
iframe := fmt.Sprintf(
`<iframe class="pdf-frame" src="servetex.pdf?ts=%s" hx-sse="connect:/sse/pdf" hx-swap="outerHTML"></iframe>`,
url.QueryEscape(backend.GetLocalTimeRFC()),
)
fmt.Fprintf((*writer), "data: %s\n\n", iframe)
(*writer).(http.Flusher).Flush()
}
// Sends new Event
//
// Reads globals.LatexExec
func sseOutputSend(writer *http.ResponseWriter) {
sseHeadersAdd(writer)
fmt.Fprintf((*writer), "event: output\n")
lines := strings.SplitSeq(string(globals.LatexExec.Output), "\n")
for line := range lines {
fmt.Fprintf((*writer), "data: %s\n", line)
}
fmt.Fprintf((*writer), "\n")
(*writer).(http.Flusher).Flush()
}
// Server Side Event Handler
//
// Sends a Ping instead of actual data when no new data available to save bandwidth
func SSEventHandler(writer http.ResponseWriter, request *http.Request) {
lastExecution := ""
for range time.Tick(time.Second) {
if lastExecution == globals.LatexExec.Timestamp {
ssePing(&writer)
} else {
sseStatusSend(&writer)
ssePDFSend(&writer)
sseOutputSend(&writer)
// comment out for testing purposes
lastExecution = globals.LatexExec.Timestamp
}
}
}
func PDFHandler(writer http.ResponseWriter, request *http.Request) {
http.NotFound(writer, request)
}
// Serves the main page of ServTeX
func MainHandler(writer http.ResponseWriter, request *http.Request) {
writer.Header().Set("Content-Type", "text/html")
main, _ := WebFiles.ReadFile("templates/main.html")
writer.Write(main)
}