nandi/oripublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

health.go · 77 lines · 2.5 KBGo Blame HistoryRaw
✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme 76d62ac k33g yesterday1// Package health probes an ori server's GET /healthz endpoint. It is pure Go
2// (no GUI dependency) so the connection logic of the desktop client can be
3// unit-tested against an httptest server.
4package health
5
6import (
7 "context"
8 "encoding/json"
9 "fmt"
10 "io"
11 "net/http"
12 "time"
13)
14
15// DefaultTimeout bounds a single probe; a desktop connection screen must fail
16// fast when the server is down.
17const DefaultTimeout = 3 * time.Second
18
19// Report is the outcome of one probe, shaped to cross the Wails bridge as a
20// plain JSON object (no error type, so the JavaScript side never has to
21// distinguish a rejected promise from a negative answer).
22type Report struct {
23 // OK is true when /healthz answered with a 2xx status.
24 OK bool `json:"ok"`
25 // URL is the exact URL that was probed.
26 URL string `json:"url"`
27 // StatusCode is the HTTP status received, or 0 when no response arrived.
28 StatusCode int `json:"statusCode"`
29 // Detail is a short human-readable explanation ("ori is reachable",
30 // the transport error, or the unexpected status).
31 Detail string `json:"detail"`
32}
33
34// Check performs GET <baseURL>/healthz. baseURL must already be normalised
35// (scheme + host, no trailing slash). A nil client uses http.DefaultTransport
36// with DefaultTimeout.
37func Check(ctx context.Context, client *http.Client, baseURL string) Report {
38 if client == nil {
39 client = &http.Client{Timeout: DefaultTimeout}
40 }
41 target := baseURL + "/healthz"
42 rep := Report{URL: target}
43
44 req, err := http.NewRequestWithContext(ctx, http.MethodGet, target, nil)
45 if err != nil {
46 rep.Detail = fmt.Sprintf("invalid URL: %v", err)
47 return rep
48 }
49 resp, err := client.Do(req)
50 if err != nil {
51 rep.Detail = fmt.Sprintf("cannot reach ori: %v", err)
52 return rep
53 }
54 defer resp.Body.Close()
55 rep.StatusCode = resp.StatusCode
56
57 body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
58 if resp.StatusCode < 200 || resp.StatusCode > 299 {
59 rep.Detail = fmt.Sprintf("unexpected status %s from /healthz (is this really an ori server?)", resp.Status)
60 return rep
61 }
62 rep.OK = true
63 rep.Detail = describe(body)
64 return rep
65}
66
67// describe turns ori's `{"status":"ok"}` body into a one-liner, tolerating
68// any other 2xx body so a future ori version cannot break the client.
69func describe(body []byte) string {
70 var payload struct {
71 Status string `json:"status"`
72 }
73 if err := json.Unmarshal(body, &payload); err == nil && payload.Status != "" {
74 return "ori is reachable (status: " + payload.Status + ")"
75 }
76 return "ori is reachable"
77}