opds-explorer/cmd/server/main.go
Vibe Kanban d41f6859f4 OPDS-PS Explorer (vibe-kanban 1dc76aea)
Create a server (go) and webapp (vue) development tool to explore OPDS-PS capable servers. This tool is intended for development purposes only, it should allow to navigate the server, view raw requests and responses and interact with the API in a general way. I think it's best if we provide a columns layout to navigate the OPDS-PS server much like the macos finder does, with a panel with details to the far right for technical information.

Here's the SPEC: https://specs.opds.io/
2026-02-11 09:36:23 +01:00

65 lines
1.8 KiB
Go

package main
import (
"log"
"net/http"
"os"
"path/filepath"
"opds-explorer/internal/handlers"
"opds-explorer/internal/proxy"
)
func main() {
proxyClient := proxy.NewClient()
h := handlers.New(proxyClient)
mux := http.NewServeMux()
// API: fetch OPDS feed (proxies request, returns parsed + raw)
mux.HandleFunc("GET /api/fetch", h.FetchFeed)
mux.HandleFunc("POST /api/fetch", h.FetchFeed)
// API: stream a URL through the server (e.g. for images to avoid CORS)
mux.HandleFunc("GET /api/proxy", h.ProxyResource)
// Serve Vue SPA from dist (or embedded)
dist := os.Getenv("OPDS_DIST")
if dist == "" {
dist = filepath.Join(".", "dist")
}
if info, err := os.Stat(dist); err == nil && info.IsDir() {
mux.Handle("/", http.FileServer(http.Dir(dist)))
} else {
// Dev: serve a simple message if dist missing
mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(`<h1>OPDS-PS Explorer</h1><p>Build the Vue app: <code>cd webapp && bun run build</code>, then run the server from repo root.</p>`))
})
}
addr := ":8080"
if p := os.Getenv("PORT"); p != "" {
addr = ":" + p
}
log.Printf("OPDS-PS Explorer server listening on %s", addr)
if err := http.ListenAndServe(addr, cors(mux)); err != nil {
log.Fatal(err)
}
}
func cors(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusNoContent)
return
}
next.ServeHTTP(w, r)
})
}