server-protocol.ts 1.4 KB

1234567891011121314151617181920212223242526272829303132333435
  1. import type { ServerConnection } from "@/context/server"
  2. import { authTokenFromCredentials } from "./server"
  3. export type ServerProtocol = "v1" | "v2"
  4. function headers(server: ServerConnection.HttpBase) {
  5. if (!server.password) return
  6. return {
  7. Authorization: `Basic ${authTokenFromCredentials({ username: server.username, password: server.password })}`,
  8. }
  9. }
  10. async function probe(server: ServerConnection.HttpBase, fetch: typeof globalThis.fetch, path: string) {
  11. const response = await fetch(new URL(path, server.url), {
  12. headers: headers(server),
  13. signal: AbortSignal.timeout(5_000),
  14. })
  15. if (!response.ok || !response.headers.get("content-type")?.includes("application/json")) return
  16. const value: unknown = await response.json()
  17. if (!value || typeof value !== "object") return
  18. return value
  19. }
  20. export async function detectServerProtocol(
  21. server: ServerConnection.HttpBase,
  22. fetch: typeof globalThis.fetch,
  23. ): Promise<ServerProtocol> {
  24. const legacy = await probe(server, fetch, "/global/health").catch(() => undefined)
  25. if (legacy && "healthy" in legacy && legacy.healthy === true) return "v1"
  26. const current = await probe(server, fetch, "/api/health").catch(() => undefined)
  27. if (current && "pid" in current && typeof current.pid === "number") return "v2"
  28. if (current && "healthy" in current && current.healthy === true) return "v1"
  29. return "v2"
  30. }