using Invercargill; using Invercargill.DataStructures; using Astralis; namespace Statum { /** * Helpers for rendering Statum directive responses. */ public class StatumDirectives : Object { /** The content type that distinguishes a Statum directive response. */ public const string CONTENT_TYPE = "application/vnd.statum+json"; /** * Builds the short-circuit response an endpoint returns when the request * carried slots the server does not have in memory: a `transmit(retry)` * per missing key (plus an `invalidate` per untrustworthy frame * signature). The client re-sends the frames to the slot post endpoint, * drops any that fail verification, then re-issues the original request. */ public static HttpResult transmit_result(Lot transmit_keys, Lot? invalid_signatures = null) throws GLib.Error { var directives = new Series(); foreach (var key in transmit_keys) { directives.add(new Model.TransmitDirectiveDto.with(key, true)); } return to_result(directives, invalid_signatures); } /** * Renders a lot of directives as the JSON array response served by every * directive-returning endpoint, with the Statum content type and * `Cache-Control: no-store`. * * Any invalid frame `signature`s are appended as `invalidate` directives * so the client drops slots whose frames the server could not trust. * Stale slot keys are auto-signed and appended as `set` directives so the * client refreshes outdated snapshots. */ public static HttpResult to_result( Lot directives, Lot? invalid_signatures = null, StateService? state_service = null, Lot? stale_keys = null) throws GLib.Error { var rendered = new Series(); foreach (var directive in directives) { rendered.add(directive); } if (invalid_signatures != null) { foreach (var signature in (!)invalid_signatures) { rendered.add(new Model.InvalidateDirectiveDto.with_signature(signature)); } } if (state_service != null && stale_keys != null) { foreach (var key in (!)stale_keys) { var frame = state_service.sign_slot(key); if (frame != null) { rendered.add(new Model.SetDirectiveDto.with_frame((!)frame)); } } } var json = Model.DirectiveDto.serialize_array(rendered); var result = new HttpStringResult(json.stringify()); result.set_header("Content-Type", CONTENT_TYPE); result.set_header("Cache-Control", "no-store"); return result; } } }