using System; using System.Text.Json; using System.Threading.Tasks; using GenHTTP.Api.Protocol; using GenHTTP.Modules.Conversion.Serializers.Json; using GenHTTP.Modules.IO; namespace Artemis.Core.Services; /// /// Represents a plugin web endpoint receiving an object of type and returning any /// or . /// Note: Both will be deserialized and serialized respectively using JSON. /// public class JsonPluginEndPoint : PluginEndPoint { private readonly Action? _requestHandler; private readonly Func? _responseRequestHandler; internal JsonPluginEndPoint(PluginFeature pluginFeature, string name, PluginsHandler pluginsHandler, Action requestHandler) : base(pluginFeature, name, pluginsHandler) { _requestHandler = requestHandler; ThrowOnFail = true; Accepts = FlexibleContentType.Get(ContentType.ApplicationJson); } internal JsonPluginEndPoint(PluginFeature pluginFeature, string name, PluginsHandler pluginsHandler, Func responseRequestHandler) : base(pluginFeature, name, pluginsHandler) { _responseRequestHandler = responseRequestHandler; ThrowOnFail = true; Accepts = FlexibleContentType.Get(ContentType.ApplicationJson); Returns = FlexibleContentType.Get(ContentType.ApplicationJson); } /// /// Whether or not the end point should throw an exception if deserializing the received JSON fails. /// If set to malformed JSON is silently ignored; if set to malformed /// JSON throws a . /// public bool ThrowOnFail { get; set; } #region Overrides of PluginEndPoint /// protected override async Task ProcessRequest(IRequest request) { if (request.Method != RequestMethod.Post && request.Method != RequestMethod.Put) return request.Respond().Status(ResponseStatus.MethodNotAllowed).Build(); if (request.Content == null) return request.Respond().Status(ResponseStatus.BadRequest).Build(); object? response = null; try { T? deserialized = await JsonSerializer.DeserializeAsync(request.Content, WebServerService.JsonOptions); if (deserialized == null) throw new JsonException("Deserialization returned null"); if (_requestHandler != null) { _requestHandler(deserialized); return request.Respond().Status(ResponseStatus.NoContent).Build(); } if (_responseRequestHandler != null) response = _responseRequestHandler(deserialized); else throw new ArtemisCoreException("JSON plugin end point has no request handler"); } catch (JsonException) { if (ThrowOnFail) throw; } // TODO: Cache options if (response == null) return request.Respond().Status(ResponseStatus.NoContent).Build(); return request.Respond() .Status(ResponseStatus.Ok) .Content(new JsonContent(response, WebServerService.JsonOptions)) .Type(ContentType.ApplicationJson) .Build(); } #endregion }