Skip to content

Commit 4d48ea1

Browse files
authored
Merge pull request #229 from safing/feature/ready-api
Ready API
2 parents c4a6f2e + e35d320 commit 4d48ea1

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

api/endpoints.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ func (e *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
381381

382382
// Wait for the owning module to be ready.
383383
if !moduleIsReady(e.BelongsTo) {
384-
http.Error(w, "The API endpoint is not ready yet or the its module is not enabled. Please try again later.", http.StatusServiceUnavailable)
384+
http.Error(w, "The API endpoint is not ready yet or the its module is not enabled. Reload (F5) to try again.", http.StatusServiceUnavailable)
385385
return
386386
}
387387

api/endpoints_debug.go

+25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package api
33
import (
44
"bytes"
55
"context"
6+
"errors"
67
"fmt"
78
"net/http"
89
"os"
@@ -11,6 +12,7 @@ import (
1112
"time"
1213

1314
"github.com/safing/portbase/info"
15+
"github.com/safing/portbase/modules"
1416
"github.com/safing/portbase/utils/debug"
1517
)
1618

@@ -25,6 +27,16 @@ func registerDebugEndpoints() error {
2527
return err
2628
}
2729

30+
if err := RegisterEndpoint(Endpoint{
31+
Path: "ready",
32+
Read: PermitAnyone,
33+
ActionFunc: ready,
34+
Name: "Ready",
35+
Description: "Check if Portmaster has completed starting and is ready.",
36+
}); err != nil {
37+
return err
38+
}
39+
2840
if err := RegisterEndpoint(Endpoint{
2941
Path: "debug/stack",
3042
Read: PermitAnyone,
@@ -118,9 +130,22 @@ You can easily view this data in your browser with this command (with Go install
118130

119131
// ping responds with pong.
120132
func ping(ar *Request) (msg string, err error) {
133+
// TODO: Remove upgrade to "ready" when all UI components have transitioned.
134+
if modules.IsStarting() || modules.IsShuttingDown() {
135+
return "", ErrorWithStatus(errors.New("portmaster is not ready, reload (F5) to try again"), http.StatusTooEarly)
136+
}
137+
121138
return "Pong.", nil
122139
}
123140

141+
// ready checks if Portmaster has completed starting.
142+
func ready(ar *Request) (msg string, err error) {
143+
if modules.IsStarting() || modules.IsShuttingDown() {
144+
return "", ErrorWithStatus(errors.New("portmaster is not ready, reload (F5) to try again"), http.StatusTooEarly)
145+
}
146+
return "Portmaster is ready.", nil
147+
}
148+
124149
// getStack returns the current goroutine stack.
125150
func getStack(_ *Request) (data []byte, err error) {
126151
buf := &bytes.Buffer{}

api/router.go

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

modules/start.go

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ func SetGlobalPrepFn(fn func() error) {
2424
}
2525
}
2626

27+
// IsStarting returns whether the initial global start is still in progress.
28+
func IsStarting() bool {
29+
return !initialStartCompleted.IsSet()
30+
}
31+
2732
// Start starts all modules in the correct order. In case of an error, it will automatically shutdown again.
2833
func Start() error {
2934
if !modulesLocked.SetToIf(false, true) {

0 commit comments

Comments
 (0)