diff --git a/api/common/api.go b/api/common/api.go index 9990b199..05f744fe 100644 --- a/api/common/api.go +++ b/api/common/api.go @@ -302,7 +302,7 @@ func (api *API) authHandler(h http.Handler, lggr *logging.ZapEventLogger) http.H wrap := func(w http.ResponseWriter, r *http.Request) { // We let CORS preflight requests pass through the next // handler. - if r.Method == http.MethodOptions { + if r.Method == http.MethodOptions || r.URL.Path == "/health" { h.ServeHTTP(w, r) return } @@ -853,3 +853,8 @@ func (api *API) Headers() map[string][]string { func (api *API) SetKeepAlivesEnabled(b bool) { api.server.SetKeepAlivesEnabled(b) } + + +func (api *API) HealthHandler(w http.ResponseWriter, r *http.Request){ + api.SendResponse(w,http.StatusNoContent,nil,nil) +} \ No newline at end of file diff --git a/api/pinsvcapi/pinsvcapi.go b/api/pinsvcapi/pinsvcapi.go index 127d1672..23a98961 100644 --- a/api/pinsvcapi/pinsvcapi.go +++ b/api/pinsvcapi/pinsvcapi.go @@ -22,9 +22,9 @@ import ( "go.uber.org/multierr" logging "github.com/ipfs/go-log/v2" + rpc "github.com/libp2p/go-libp2p-gorpc" "github.com/libp2p/go-libp2p/core/host" peer "github.com/libp2p/go-libp2p/core/peer" - rpc "github.com/libp2p/go-libp2p-gorpc" ) var ( @@ -178,6 +178,12 @@ func (api *API) routes(c *rpc.Client) []common.Route { Pattern: "/token", HandlerFunc: api.GenerateTokenHandler, }, + { + Name: "Health", + Method: "GET", + Pattern: "/health", + HandlerFunc: api.HealthHandler, + }, } } diff --git a/api/pinsvcapi/pinsvcapi_test.go b/api/pinsvcapi/pinsvcapi_test.go index 545c4e7c..dc787fd1 100644 --- a/api/pinsvcapi/pinsvcapi_test.go +++ b/api/pinsvcapi/pinsvcapi_test.go @@ -251,3 +251,19 @@ func TestAPIRemovePinEndpoint(t *testing.T) { test.BothEndpoints(t, tf) } + +func TestHealthEndpoint(t *testing.T) { + ctx := context.Background() + svcapi := testAPI(t) + defer svcapi.Shutdown(ctx) + + tf := func(t *testing.T, url test.URLFunc) { + errResp := api.Error{} + test.MakeGet(t, svcapi, url(svcapi)+"/health", &errResp) + if errResp.Code != 0 || errResp.Message != "" { + t.Error("expected no errors") + } + } + + test.BothEndpoints(t, tf) +} \ No newline at end of file diff --git a/api/rest/client/client.go b/api/rest/client/client.go index d9780c3c..c9a74290 100644 --- a/api/rest/client/client.go +++ b/api/rest/client/client.go @@ -122,6 +122,9 @@ type Client interface { // returns collected CIDs. If local is true, it would garbage collect // only on contacted peer, otherwise on all peers' IPFS daemons. RepoGC(ctx context.Context, local bool) (api.GlobalRepoGC, error) + + // Health returns no content when everything is ok, and an error otherwise + Health(ctx context.Context) (error) } // Config allows to configure the parameters to connect diff --git a/api/rest/client/methods.go b/api/rest/client/methods.go index 3fd51c25..28b2247b 100644 --- a/api/rest/client/methods.go +++ b/api/rest/client/methods.go @@ -697,3 +697,10 @@ func (c *defaultClient) AddMultiFile( ) return err } + +func (c *defaultClient) Health(ctx context.Context) (error) { + ctx, span := trace.StartSpan(ctx, "client/Health") + defer span.End() + err := c.do(ctx, "GET", "/health", nil, nil, nil) + return err +} diff --git a/api/rest/restapi.go b/api/rest/restapi.go index 14afc2e9..e6adeb44 100644 --- a/api/rest/restapi.go +++ b/api/rest/restapi.go @@ -204,6 +204,12 @@ func (api *API) routes(c *rpc.Client) []common.Route { Pattern: "/token", HandlerFunc: api.GenerateTokenHandler, }, + { + Name: "Health", + Method: "GET", + Pattern: "/health", + HandlerFunc: api.HealthHandler, + }, } } diff --git a/api/rest/restapi_test.go b/api/rest/restapi_test.go index d338d042..cad5f367 100644 --- a/api/rest/restapi_test.go +++ b/api/rest/restapi_test.go @@ -844,3 +844,20 @@ func TestAPIIPFSGCEndpoint(t *testing.T) { test.BothEndpoints(t, tf) } + + +func TestHealthEndpoint(t *testing.T) { + ctx := context.Background() + rest := testAPI(t) + defer rest.Shutdown(ctx) + + tf := func(t *testing.T, url test.URLFunc) { + errResp := api.Error{} + test.MakeGet(t, rest, url(rest)+"/health", &errResp) + if errResp.Code != 0 || errResp.Message != "" { + t.Error("expected no errors") + } + } + + test.BothEndpoints(t, tf) +} \ No newline at end of file