using System; using System.IO; using System.Net; using AllocsFixes.JSON; namespace AllocsFixes.NetConnections.Servers.Web.API { public abstract class AbsRestApi : AbsWebAPI { public sealed override void HandleRequest (RequestContext _context) { JSONNode jsonBody = null; if (_context.Request.HasEntityBody) { string body = new StreamReader (_context.Request.InputStream).ReadToEnd (); if (!string.IsNullOrEmpty (body)) { try { jsonBody = Parser.Parse (body); } catch (Exception e) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "INVALID_BODY", e); return; } } } try { switch (_context.Request.HttpMethod) { case "GET": if (jsonBody != null) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "GET_WITH_BODY"); return; } HandleRestGet (_context); return; case "POST": if (!string.IsNullOrEmpty (_context.RequestPath)) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "POST_WITH_ID"); return; } if (jsonBody == null) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "POST_WITHOUT_BODY"); return; } HandleRestPost (_context, jsonBody); return; case "PUT": if (string.IsNullOrEmpty (_context.RequestPath)) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "PUT_WITHOUT_ID"); return; } if (jsonBody == null) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "PUT_WITHOUT_BODY"); return; } HandleRestPut (_context, jsonBody); return; case "DELETE": if (string.IsNullOrEmpty (_context.RequestPath)) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "DELETE_WITHOUT_ID"); return; } if (jsonBody != null) { SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "DELETE_WITH_BODY"); return; } HandleRestDelete (_context); return; default: SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "INVALID_METHOD"); return; } } catch (Exception e) { SendEnvelopedResult (_context, null, HttpStatusCode.InternalServerError, jsonBody, "ERROR_PROCESSING", _exception: e); } } private static readonly JSONArray emptyData = new JSONArray (); protected void SendEnvelopedResult (RequestContext _context, JSONNode _resultData, HttpStatusCode _statusCode = HttpStatusCode.OK, JSONNode _jsonInputBody = null, string _errorCode = null, Exception _exception = null) { JSONObject meta = new JSONObject (); meta.Add ("serverTime", new JSONString (DateTime.Now.ToString ("o"))); if (!string.IsNullOrEmpty (_errorCode)) { meta.Add ("requestMethod", new JSONString (_context.Request.HttpMethod)); meta.Add ("requestSubpath", new JSONString (_context.RequestPath)); meta.Add ("requestBody", new JSONString (_jsonInputBody?.ToString () ?? "-empty-")); meta.Add ("errorCode", new JSONString (_errorCode)); if (_exception != null) { meta.Add ("exceptionMessage", new JSONString (_exception.Message)); meta.Add ("exceptionTrace", new JSONString (_exception.StackTrace)); } } JSONObject envelope = new JSONObject (); envelope.Add ("meta", meta); envelope.Add ("data", _resultData ?? emptyData); WebUtils.WriteJson (_context.Response, envelope, _statusCode); } protected bool TryGetJsonField (JSONObject _body, string _fieldName, out int _value) { _value = default; if (!_body.TryGetValue (_fieldName, out JSONNode fieldNode)) { return false; } if (!(fieldNode is JSONValue valueField)) { return false; } try { _value = valueField.AsInt; return true; } catch (Exception) { return false; } } protected abstract void HandleRestGet (RequestContext _context); protected abstract void HandleRestPost (RequestContext _context, JSONNode _jsonBody); protected abstract void HandleRestPut (RequestContext _context, JSONNode _jsonBody); protected abstract void HandleRestDelete (RequestContext _context); } }