142 lines
3.9 KiB
Go
142 lines
3.9 KiB
Go
package frontend
|
|
|
|
import (
|
|
"embed"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"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
|
|
//go:embed media/favicon.ico
|
|
var WebFiles embed.FS
|
|
|
|
// Sends a Ping to keep the connection alive
|
|
func ssePing(writer *http.ResponseWriter) {
|
|
fmt.Fprintf((*writer), ": ping\n\n")
|
|
|
|
(*writer).(http.Flusher).Flush()
|
|
}
|
|
|
|
// Sends new Event
|
|
//
|
|
// Reads globals.LatexExec
|
|
func sseStatusSend(writer *http.ResponseWriter) {
|
|
fmt.Fprintf((*writer), "event: status\n")
|
|
fmt.Fprintf((*writer), "data: Execution Time:<br>%s<br><br>\n", globals.LatexExec.Timestamp)
|
|
fmt.Fprintf((*writer), "data: Execution State:<br>%s<br>\n\n", globals.LatexExec.ExecutionState)
|
|
|
|
(*writer).(http.Flusher).Flush()
|
|
backend.LogLine("Status Event has been sent", 1)
|
|
}
|
|
|
|
// Sends new Event
|
|
//
|
|
// Reads globals.LatexExec
|
|
func ssePDFSend(writer *http.ResponseWriter) {
|
|
fmt.Fprintf((*writer), "event: pdf\n")
|
|
iframe := fmt.Sprintf(
|
|
`<iframe class="pdf-frame" src="/pdf?ts=%s"></iframe>`,
|
|
url.QueryEscape(backend.GetLocalTimeRFC()),
|
|
)
|
|
fmt.Fprintf((*writer), "data: %s\n\n", iframe)
|
|
|
|
(*writer).(http.Flusher).Flush()
|
|
backend.LogLine("PDF Event has been sent", 1)
|
|
}
|
|
|
|
// Sends new Event
|
|
//
|
|
// Reads globals.LatexExec
|
|
func sseOutputSend(writer *http.ResponseWriter) {
|
|
fmt.Fprintf((*writer), "event: output\n")
|
|
lines := strings.SplitSeq(string(globals.LatexExec.Output), "\n")
|
|
for line := range lines {
|
|
fmt.Fprintf((*writer), "data: %s<br>\n", line)
|
|
}
|
|
fmt.Fprintf((*writer), "\n")
|
|
|
|
(*writer).(http.Flusher).Flush()
|
|
backend.LogLine("Output Event has been sent", 1)
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
|
if err := backend.VerifyLogRequest(request); err != nil { http.Error(writer, "Bad Request", http.StatusBadRequest) }
|
|
|
|
writer.Header().Set("Content-Type", "text/event-stream")
|
|
writer.Header().Set("Cache-Control", "no-cache")
|
|
writer.Header().Set("Connection", "keep-alive")
|
|
ssePing(&writer)
|
|
|
|
|
|
lastExecution := &globals.LatexExecution{}
|
|
for range time.Tick(time.Second) {
|
|
select {
|
|
case <-request.Context().Done():
|
|
return
|
|
default:
|
|
if lastExecution.Equal(&globals.LatexExec) {
|
|
ssePing(&writer)
|
|
} else {
|
|
sseStatusSend(&writer)
|
|
if globals.LatexExec.ExecutionState != globals.LatexExecutionStateRunning {
|
|
sseOutputSend(&writer)
|
|
}
|
|
if globals.LatexExec.ExecutionState != globals.LatexExecutionStateFailure {
|
|
ssePDFSend(&writer)
|
|
}
|
|
lastExecution = globals.LatexExec.Copy()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Serves the compiled PDF file
|
|
func PDFHandler(writer http.ResponseWriter, request *http.Request) {
|
|
if err := backend.VerifyLogRequest(request); err != nil { http.Error(writer, "Bad Request", http.StatusBadRequest) }
|
|
|
|
pdfPath := filepath.Join(globals.AppConfig.LatexOutputPath, "servtex.pdf")
|
|
pdf, err := os.Open(pdfPath)
|
|
if err != nil {
|
|
backend.LogLine("PDF file could not be found or read", 1)
|
|
http.NotFound(writer, request)
|
|
return
|
|
}
|
|
defer pdf.Close()
|
|
|
|
writer.Header().Set("Content-Type", "application/pdf")
|
|
http.ServeFile(writer, request, pdfPath)
|
|
}
|
|
|
|
// Serves the main page of ServTeX
|
|
func MainHandler(writer http.ResponseWriter, request *http.Request) {
|
|
if err := backend.VerifyLogRequest(request); err != nil { http.Error(writer, "Bad Request", http.StatusBadRequest) }
|
|
|
|
writer.Header().Set("Content-Type", "text/html")
|
|
main, _ := WebFiles.ReadFile("templates/main.html")
|
|
writer.Write(main)
|
|
}
|
|
|
|
func PDFCompile(writer http.ResponseWriter, request *http.Request) {
|
|
if err := backend.VerifyLogRequest(request); err != nil { http.Error(writer, "Bad Request", http.StatusBadRequest) }
|
|
|
|
backend.LatexCompile()
|
|
}
|
|
|