This repository has been archived on 2025-08-23. You can view files and clone it, but cannot push or open issues or pull requests.
Files
GreenCoast/internal/api/static.go
Dani d87e9322b5 Added example/dropin replacements for .env.example
Fixed the issue with PlainText (Complete Anon) posting
Need to fix device sign on issues.
Need to make it so that the non-signed in devices can only see their equalivant level of posts. (i.e. plaintext, public-encrypted, private-encrypted)
2025-08-22 22:59:05 -04:00

77 lines
2.2 KiB
Go

package api
import (
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
// ListenFrontend serves the static client from s.StaticDir on a separate port (e.g. :9082).
func (s *Server) ListenFrontend(addr string) error {
root := s.StaticDir
if root == "" {
root = "./client"
}
// Basic security/CSP headers for static content.
addCommonHeaders := func(w http.ResponseWriter) {
// CORS: static site can be embedded by any origin if you want, keep strict by default
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
w.Header().Set("Cross-Origin-Resource-Policy", "same-site")
w.Header().Set("Referrer-Policy", "no-referrer")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
// Cache: avoid caching during test
w.Header().Set("Cache-Control", "no-store")
// CSP: no inline scripts/styles; allow XHR/SSE/Ws to any (tunnel/api) host
w.Header().Set("Content-Security-Policy",
strings.Join([]string{
"default-src 'self'",
"script-src 'self'",
"style-src 'self'",
"img-src 'self' data:",
"font-src 'self'",
"connect-src *",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
}, "; "),
)
}
// File handler with index.html fallback for “/”.
fileServer := http.FileServer(http.Dir(root))
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
addCommonHeaders(w)
// Serve index.html at root or when requesting a directory.
p := r.URL.Path
if p == "/" || p == "" {
http.ServeFile(w, r, filepath.Join(root, "index.html"))
return
}
// If path maps to a directory, try its index.html.
full := filepath.Join(root, filepath.Clean(strings.TrimPrefix(p, "/")))
if st, err := os.Stat(full); err == nil && st.IsDir() {
indexFile := filepath.Join(full, "index.html")
if _, err := os.Stat(indexFile); err == nil {
http.ServeFile(w, r, indexFile)
return
}
}
// Normal static file.
fileServer.ServeHTTP(w, r)
})
srv := &http.Server{
Addr: addr,
Handler: handler,
ReadHeaderTimeout: 5 * time.Second,
}
return srv.ListenAndServe()
}