using System.Net; using System.Text.Json; using System.Threading.Tasks; using AutopilotMonitor.Functions.Helpers; using AutopilotMonitor.Functions.Services.Backup; using AutopilotMonitor.Shared.Models.Backup; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Backup { /// /// GET /api/global/backups/{backupId} — fetches the manifest JSON for a /// specific backup run. 404 if the manifest is missing (i.e. the prefix exists but /// the durability anchor never got written — treated as Incomplete per plan). /// GA-only. /// public class GetBackupManifestFunction { private readonly BlobBackupStore _store; public GetBackupManifestFunction(BlobBackupStore store) { _store = store; } [Function("GetBackupManifest")] public async Task Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/backups/{backupId}")] HttpRequestData req, string backupId) { var (payload, _) = await _store.ReadManifestAsync(backupId, req.FunctionContext.CancellationToken); if (payload is null) { return await req.NotFoundAsync($"Backup manifest {backupId} not found."); } // Stream the bytes verbatim — the manifest is already JSON, no need to deserialise + re-serialise. var response = req.CreateResponse(HttpStatusCode.OK); response.Headers.Add("Content-Type", "application/json; charset=utf-8"); await response.Body.WriteAsync(payload, req.FunctionContext.CancellationToken); return response; } } }