source: binary-improvements2/WebServer/src/WebAPI/AbsRestApi.cs@ 394

Last change on this file since 394 was 394, checked in by alloc, 2 years ago

SessionHandler cleanup + redirect to /app/error/:code
Some profiler usage cleanup

File size: 5.4 KB
Line 
1using System;
2using System.IO;
3using System.Net;
4using AllocsFixes.JSON;
5
6namespace Webserver.WebAPI {
7 public abstract class AbsRestApi : AbsWebAPI {
8 private static readonly UnityEngine.Profiling.CustomSampler jsonDeserializeSampler = UnityEngine.Profiling.CustomSampler.Create ("JSON_Deserialize");
9
10 public sealed override void HandleRequest (RequestContext _context) {
11 JsonNode jsonBody = null;
12
13 if (_context.Request.HasEntityBody) {
14 string body = new StreamReader (_context.Request.InputStream).ReadToEnd ();
15
16 if (!string.IsNullOrEmpty (body)) {
17 try {
18 jsonDeserializeSampler.Begin ();
19 jsonBody = Parser.Parse (body);
20 jsonDeserializeSampler.End ();
21 } catch (Exception e) {
22 jsonDeserializeSampler.End ();
23
24 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "INVALID_BODY", e);
25 return;
26 }
27 }
28 }
29
30 try {
31 switch (_context.Request.HttpMethod) {
32 case "GET":
33 if (jsonBody != null) {
34 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "GET_WITH_BODY");
35 return;
36 }
37
38 HandleRestGet (_context);
39 return;
40 case "POST":
41 if (!string.IsNullOrEmpty (_context.RequestPath)) {
42 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "POST_WITH_ID");
43 return;
44 }
45
46 if (jsonBody == null) {
47 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "POST_WITHOUT_BODY");
48 return;
49 }
50
51 HandleRestPost (_context, jsonBody);
52 return;
53 case "PUT":
54 if (string.IsNullOrEmpty (_context.RequestPath)) {
55 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "PUT_WITHOUT_ID");
56 return;
57 }
58
59 if (jsonBody == null) {
60 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "PUT_WITHOUT_BODY");
61 return;
62 }
63
64 HandleRestPut (_context, jsonBody);
65 return;
66 case "DELETE":
67 if (string.IsNullOrEmpty (_context.RequestPath)) {
68 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, jsonBody, "DELETE_WITHOUT_ID");
69 return;
70 }
71
72 if (jsonBody != null) {
73 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "DELETE_WITH_BODY");
74 return;
75 }
76
77 HandleRestDelete (_context);
78 return;
79 default:
80 SendEnvelopedResult (_context, null, HttpStatusCode.BadRequest, null, "INVALID_METHOD");
81 return;
82 }
83 } catch (Exception e) {
84 SendEnvelopedResult (_context, null, HttpStatusCode.InternalServerError, jsonBody, "ERROR_PROCESSING", e);
85 }
86 }
87
88 private static readonly JsonArray emptyData = new JsonArray ();
89
90 protected void SendEnvelopedResult (RequestContext _context, JsonNode _resultData, HttpStatusCode _statusCode = HttpStatusCode.OK,
91 JsonNode _jsonInputBody = null, string _errorCode = null, Exception _exception = null) {
92 JsonObject meta = new JsonObject ();
93
94 meta.Add ("serverTime", new JsonString (DateTime.Now.ToString ("o")));
95 if (!string.IsNullOrEmpty (_errorCode)) {
96 meta.Add ("requestMethod", new JsonString (_context.Request.HttpMethod));
97 meta.Add ("requestSubpath", new JsonString (_context.RequestPath));
98 meta.Add ("requestBody", new JsonString (_jsonInputBody?.ToString () ?? "-empty-"));
99 meta.Add ("errorCode", new JsonString (_errorCode));
100 if (_exception != null) {
101 meta.Add ("exceptionMessage", new JsonString (_exception.Message));
102 meta.Add ("exceptionTrace", new JsonString (_exception.StackTrace));
103 }
104 }
105
106 JsonObject envelope = new JsonObject ();
107 envelope.Add ("meta", meta);
108 envelope.Add ("data", _resultData ?? emptyData);
109
110 WebUtils.WriteJson (_context.Response, envelope, _statusCode);
111 }
112
113 protected bool TryGetJsonField (JsonObject _jsonObject, string _fieldName, out int _value) {
114 _value = default;
115
116 if (!_jsonObject.TryGetValue (_fieldName, out JsonNode fieldNode)) {
117 return false;
118 }
119
120 if (!(fieldNode is JsonValue valueField)) {
121 return false;
122 }
123
124 try {
125 _value = valueField.AsInt;
126 return true;
127 } catch (Exception) {
128 return false;
129 }
130 }
131
132 protected bool TryGetJsonField (JsonObject _jsonObject, string _fieldName, out double _value) {
133 _value = default;
134
135 if (!_jsonObject.TryGetValue (_fieldName, out JsonNode fieldNode)) {
136 return false;
137 }
138
139 if (!(fieldNode is JsonValue valueField)) {
140 return false;
141 }
142
143 try {
144 _value = valueField.AsDouble;
145 return true;
146 } catch (Exception) {
147 return false;
148 }
149 }
150
151 protected bool TryGetJsonField (JsonObject _jsonObject, string _fieldName, out string _value) {
152 _value = default;
153
154 if (!_jsonObject.TryGetValue (_fieldName, out JsonNode fieldNode)) {
155 return false;
156 }
157
158 if (!(fieldNode is JsonValue valueField)) {
159 return false;
160 }
161
162 try {
163 _value = valueField.AsString;
164 return true;
165 } catch (Exception) {
166 return false;
167 }
168 }
169
170 protected abstract void HandleRestGet (RequestContext _context);
171
172 protected abstract void HandleRestPost (RequestContext _context, JsonNode _jsonBody);
173
174 protected abstract void HandleRestPut (RequestContext _context, JsonNode _jsonBody);
175
176 protected abstract void HandleRestDelete (RequestContext _context);
177 }
178}
Note: See TracBrowser for help on using the repository browser.