Merge pull request from safing/feature/ready-api

Ready API
This commit is contained in:
Daniel Hååvi 2024-04-23 10:56:20 +02:00 committed by GitHub
commit 4d48ea1844
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 32 additions and 2 deletions

View file

@ -381,7 +381,7 @@ func (e *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Wait for the owning module to be ready.
if !moduleIsReady(e.BelongsTo) {
http.Error(w, "The API endpoint is not ready yet or the its module is not enabled. Please try again later.", http.StatusServiceUnavailable)
http.Error(w, "The API endpoint is not ready yet or the its module is not enabled. Reload (F5) to try again.", http.StatusServiceUnavailable)
return
}

View file

@ -3,6 +3,7 @@ package api
import (
"bytes"
"context"
"errors"
"fmt"
"net/http"
"os"
@ -11,6 +12,7 @@ import (
"time"
"github.com/safing/portbase/info"
"github.com/safing/portbase/modules"
"github.com/safing/portbase/utils/debug"
)
@ -25,6 +27,16 @@ func registerDebugEndpoints() error {
return err
}
if err := RegisterEndpoint(Endpoint{
Path: "ready",
Read: PermitAnyone,
ActionFunc: ready,
Name: "Ready",
Description: "Check if Portmaster has completed starting and is ready.",
}); err != nil {
return err
}
if err := RegisterEndpoint(Endpoint{
Path: "debug/stack",
Read: PermitAnyone,
@ -118,9 +130,22 @@ You can easily view this data in your browser with this command (with Go install
// ping responds with pong.
func ping(ar *Request) (msg string, err error) {
// TODO: Remove upgrade to "ready" when all UI components have transitioned.
if modules.IsStarting() || modules.IsShuttingDown() {
return "", ErrorWithStatus(errors.New("portmaster is not ready, reload (F5) to try again"), http.StatusTooEarly)
}
return "Pong.", nil
}
// ready checks if Portmaster has completed starting.
func ready(ar *Request) (msg string, err error) {
if modules.IsStarting() || modules.IsShuttingDown() {
return "", ErrorWithStatus(errors.New("portmaster is not ready, reload (F5) to try again"), http.StatusTooEarly)
}
return "Portmaster is ready.", nil
}
// getStack returns the current goroutine stack.
func getStack(_ *Request) (data []byte, err error) {
buf := &bytes.Buffer{}

View file

@ -271,7 +271,7 @@ func (mh *mainHandler) handle(w http.ResponseWriter, r *http.Request) error {
// Wait for the owning module to be ready.
if moduleHandler, ok := handler.(ModuleHandler); ok {
if !moduleIsReady(moduleHandler.BelongsTo()) {
http.Error(lrw, "The API endpoint is not ready yet. Please try again later.", http.StatusServiceUnavailable)
http.Error(lrw, "The API endpoint is not ready yet. Reload (F5) to try again.", http.StatusServiceUnavailable)
return nil
}
}

View file

@ -24,6 +24,11 @@ func SetGlobalPrepFn(fn func() error) {
}
}
// IsStarting returns whether the initial global start is still in progress.
func IsStarting() bool {
return !initialStartCompleted.IsSet()
}
// Start starts all modules in the correct order. In case of an error, it will automatically shutdown again.
func Start() error {
if !modulesLocked.SetToIf(false, true) {