Add next broadcast timer and enhance web security
This commit is contained in:
parent
68ce2c88d2
commit
ae93557d15
@ -32,6 +32,8 @@ type DashboardData struct {
|
|||||||
TotalBroadcast int
|
TotalBroadcast int
|
||||||
NewInLastHour int
|
NewInLastHour int
|
||||||
UnsummarizedCount int
|
UnsummarizedCount int
|
||||||
|
NextBroadcastIn string // Time until the next broadcast attempt
|
||||||
|
LastBroadcastTime time.Time // When the last broadcast occurred
|
||||||
NextUp []Article
|
NextUp []Article
|
||||||
History []Article
|
History []Article
|
||||||
RecentLogs []LogEntry
|
RecentLogs []LogEntry
|
||||||
|
@ -186,6 +186,10 @@
|
|||||||
<div class="stat-label">Awaiting Summary</div>
|
<div class="stat-label">Awaiting Summary</div>
|
||||||
<div class="stat-number">{{.UnsummarizedCount}}</div>
|
<div class="stat-number">{{.UnsummarizedCount}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-box">
|
||||||
|
<div class="stat-label">Next Broadcast In</div>
|
||||||
|
<div class="stat-number">{{.NextBroadcastIn}}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
75
webserver.go
75
webserver.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -19,8 +20,30 @@ func webServer(shutdown chan struct{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define HTTP handlers
|
// Create a custom request handler with security headers
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Add security headers
|
||||||
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
|
w.Header().Set("X-Frame-Options", "DENY")
|
||||||
|
w.Header().Set("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'")
|
||||||
|
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||||
|
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
||||||
|
|
||||||
|
// Enforce request method
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit request body size (1MB)
|
||||||
|
r.Body = http.MaxBytesReader(w, r.Body, 1<<20)
|
||||||
|
|
||||||
|
// Only serve the index page
|
||||||
|
if r.URL.Path != "/" {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
data, err := getDashboardData()
|
data, err := getDashboardData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Error fetching data: "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "Error fetching data: "+err.Error(), http.StatusInternalServerError)
|
||||||
@ -42,10 +65,14 @@ func webServer(shutdown chan struct{}) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Start the server
|
// Configure server with appropriate timeouts
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: ":8080",
|
Addr: ":8080",
|
||||||
Handler: nil, // Use default mux
|
Handler: handler,
|
||||||
|
ReadTimeout: 10 * time.Second, // Time to read the request
|
||||||
|
WriteTimeout: 30 * time.Second, // Time to write the response
|
||||||
|
IdleTimeout: 60 * time.Second, // Keep-alive connections timeout
|
||||||
|
MaxHeaderBytes: 1 << 20, // 1MB max header size
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a goroutine for the server
|
// Create a goroutine for the server
|
||||||
@ -91,9 +118,15 @@ func getDashboardData() (DashboardData, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Count broadcast articles, recent articles, and unsummarized articles
|
// Count broadcast articles, recent articles, and unsummarized articles
|
||||||
|
var lastBroadcastTime time.Time
|
||||||
for _, a := range articles {
|
for _, a := range articles {
|
||||||
if !a.BroadcastTime.IsZero() && a.BroadcastTime.Unix() > 1 {
|
if !a.BroadcastTime.IsZero() && a.BroadcastTime.Unix() > 1 {
|
||||||
data.TotalBroadcast++
|
data.TotalBroadcast++
|
||||||
|
|
||||||
|
// Track the most recent broadcast time
|
||||||
|
if a.BroadcastTime.After(lastBroadcastTime) {
|
||||||
|
lastBroadcastTime = a.BroadcastTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.FirstSeen.After(hourAgo) {
|
if a.FirstSeen.After(hourAgo) {
|
||||||
@ -105,6 +138,38 @@ func getDashboardData() (DashboardData, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the last broadcast time
|
||||||
|
data.LastBroadcastTime = lastBroadcastTime
|
||||||
|
|
||||||
|
// Calculate time until next broadcast
|
||||||
|
if lastBroadcastTime.IsZero() {
|
||||||
|
data.NextBroadcastIn = "As soon as articles are summarized"
|
||||||
|
} else {
|
||||||
|
nextBroadcastTime := lastBroadcastTime.Add(BROADCAST_INTERVAL)
|
||||||
|
if now.After(nextBroadcastTime) {
|
||||||
|
// If we're past the interval but haven't broadcast yet,
|
||||||
|
// likely waiting for articles to be summarized
|
||||||
|
if data.UnsummarizedCount > 0 {
|
||||||
|
data.NextBroadcastIn = "Waiting for articles to be summarized"
|
||||||
|
} else {
|
||||||
|
data.NextBroadcastIn = "Pending (checking every " + BROADCAST_CHECK_INTERVAL.String() + ")"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We're still within the interval, calculate remaining time
|
||||||
|
timeUntilNextBroadcast := nextBroadcastTime.Sub(now)
|
||||||
|
|
||||||
|
// Format as hours and minutes
|
||||||
|
hours := int(timeUntilNextBroadcast.Hours())
|
||||||
|
minutes := int(timeUntilNextBroadcast.Minutes()) % 60
|
||||||
|
|
||||||
|
if hours > 0 {
|
||||||
|
data.NextBroadcastIn = fmt.Sprintf("%dh %dm", hours, minutes)
|
||||||
|
} else {
|
||||||
|
data.NextBroadcastIn = fmt.Sprintf("%dm", minutes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get broadcast history (last 100)
|
// Get broadcast history (last 100)
|
||||||
history, err := getBroadcastHistory(100)
|
history, err := getBroadcastHistory(100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user