diff --git a/BTCPayServer.Client/BTCPayServerClient.Health.cs b/BTCPayServer.Client/BTCPayServerClient.Health.cs new file mode 100644 index 000000000..2a9c70833 --- /dev/null +++ b/BTCPayServer.Client/BTCPayServerClient.Health.cs @@ -0,0 +1,16 @@ +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using BTCPayServer.Client.Models; + +namespace BTCPayServer.Client +{ + public partial class BTCPayServerClient + { + public virtual async Task GetHealth(CancellationToken token = default) + { + var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/health"), token); + return await HandleResponse(response); + } + } +} diff --git a/BTCPayServer.Client/Models/ApiHealthData.cs b/BTCPayServer.Client/Models/ApiHealthData.cs new file mode 100644 index 000000000..1f9f50663 --- /dev/null +++ b/BTCPayServer.Client/Models/ApiHealthData.cs @@ -0,0 +1,10 @@ +using BTCPayServer.Client.JsonConverters; +using Newtonsoft.Json; + +namespace BTCPayServer.Client.Models +{ + public class ApiHealthData + { + public bool Synchronized { get; set; } + } +} diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index faf2221e1..3451913e7 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -272,5 +272,20 @@ namespace BTCPayServer.Tests } } + + [Fact(Timeout = TestTimeout)] + [Trait("Integration", "Integration")] + public async Task HealthControllerTests() + { + using (var tester = ServerTester.Create()) + { + await tester.StartAsync(); + var unauthClient = new BTCPayServerClient(tester.PayTester.ServerUri); + + var apiHealthData = await unauthClient.GetHealth(); + Assert.NotNull(apiHealthData); + Assert.True(apiHealthData.Synchronized); + } + } } } diff --git a/BTCPayServer/Controllers/GreenField/HealthController.cs b/BTCPayServer/Controllers/GreenField/HealthController.cs new file mode 100644 index 000000000..843facf1a --- /dev/null +++ b/BTCPayServer/Controllers/GreenField/HealthController.cs @@ -0,0 +1,22 @@ +using BTCPayServer.HostedServices; +using BTCPayServer.Client.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace BTCPayServer.Controllers.GreenField +{ + [Controller] + public class HealthController : ControllerBase + { + [AllowAnonymous] + [HttpGet("~/api/v1/health")] + public ActionResult GetHealth(NBXplorerDashboard dashBoard) + { + ApiHealthData model = new ApiHealthData() + { + Synchronized = dashBoard.IsFullySynched() + }; + return Ok(model); + } + } +} diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.health.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.health.json new file mode 100644 index 000000000..beaa5be9c --- /dev/null +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.health.json @@ -0,0 +1,46 @@ +{ + "paths": { + "/api/v1/health": { + "get": { + "tags": [ + "Health" + ], + "summary": "Get health status", + "description": "Check the instance health status", + "operationId": "Health_GetHealth", + "responses": { + "200": { + "description": "Instance is up", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApplicationHealthData" + } + } + } + } + }, + "security": [] + } + } + }, + "components": { + "schemas": { + "ApplicationHealthData": { + "type": "object", + "additionalProperties": false, + "properties": { + "synchronized": { + "type": "boolean", + "description": "True if the instance is fully synchronized, according to NBXplorer" + } + } + } + } + }, + "tags": [ + { + "name": "Health" + } + ] +}