104 строки
2.3 KiB
Go
104 строки
2.3 KiB
Go
package webapp
|
|
|
|
import "net/http"
|
|
|
|
// handleApps lists the inventory rows the most recent refresh loop
|
|
// persisted. Each row links to the detail view at /apps/:id, which
|
|
// Phase 1 implements as a single-process summary (comm, cmdline,
|
|
// cwd, ports, uptime).
|
|
func (s *Server) handleApps(w http.ResponseWriter, r *http.Request) {
|
|
writeNoStore(w)
|
|
sess, _ := sessionFromContext(r.Context())
|
|
apps := s.inventory.Snapshot()
|
|
data := appsPageData{
|
|
basePageData: s.newBasePage(r, "Discovered apps", sess),
|
|
Apps: apps,
|
|
}
|
|
if err := s.templates.Execute(w, "apps.html", data); err != nil {
|
|
s.deps.Logger.Printf("render apps: %v", err)
|
|
http.Error(w, "template error", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
// handleAppDetail renders the detail page for a single inventory
|
|
// row. Phase 1 has no grouping, so :id is the row index in the
|
|
// snapshot (matching the table id column).
|
|
func (s *Server) handleAppDetail(w http.ResponseWriter, r *http.Request) {
|
|
writeNoStore(w)
|
|
sess, _ := sessionFromContext(r.Context())
|
|
id := r.PathValue("id")
|
|
apps := s.inventory.Snapshot()
|
|
var found *DiscoveredApp
|
|
for i := range apps {
|
|
if idMatch(&apps[i], id, i) {
|
|
found = &apps[i]
|
|
break
|
|
}
|
|
}
|
|
if found == nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
data := appDetailPageData{
|
|
basePageData: s.newBasePage(r, "App: "+found.Name, sess),
|
|
App: *found,
|
|
}
|
|
if err := s.templates.Execute(w, "app_detail.html", data); err != nil {
|
|
s.deps.Logger.Printf("render app detail: %v", err)
|
|
http.Error(w, "template error", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
// idMatch matches either by pid (when id is a positive integer) or
|
|
// by name (otherwise). Keeps URLs short and avoids leaking pids to
|
|
// browser history.
|
|
func idMatch(a *DiscoveredApp, id string, idx int) bool {
|
|
if a.Name == id {
|
|
return true
|
|
}
|
|
if id == pidOrIndex(a, idx) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func pidOrIndex(a *DiscoveredApp, idx int) string {
|
|
if a.PID > 0 {
|
|
return itoa(a.PID)
|
|
}
|
|
return itoa(idx)
|
|
}
|
|
|
|
func itoa(n int) string {
|
|
const digits = "0123456789"
|
|
if n == 0 {
|
|
return "0"
|
|
}
|
|
neg := n < 0
|
|
if neg {
|
|
n = -n
|
|
}
|
|
var buf [20]byte
|
|
i := len(buf)
|
|
for n > 0 {
|
|
i--
|
|
buf[i] = digits[n%10]
|
|
n /= 10
|
|
}
|
|
if neg {
|
|
i--
|
|
buf[i] = '-'
|
|
}
|
|
return string(buf[i:])
|
|
}
|
|
|
|
type appsPageData struct {
|
|
basePageData
|
|
Apps []DiscoveredApp
|
|
}
|
|
|
|
type appDetailPageData struct {
|
|
basePageData
|
|
App DiscoveredApp
|
|
}
|