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

Last change on this file since 406 was 404, checked in by alloc, 22 months ago

Latest state including reworking to the permissions system

File size: 6.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Net;
5using Utf8Json;
6
7namespace Webserver.WebAPI {
8 public abstract class AbsRestApi : AbsWebAPI {
9 private static readonly UnityEngine.Profiling.CustomSampler jsonDeserializeSampler = UnityEngine.Profiling.CustomSampler.Create ("JSON_Deserialize");
10
11 public sealed override void HandleRequest (RequestContext _context) {
12 IDictionary<string, object> inputJson = null;
13 byte[] jsonInputData = null;
14
15 if (_context.Request.HasEntityBody) {
16 Stream requestInputStream = _context.Request.InputStream;
17
18 jsonInputData = new byte[_context.Request.ContentLength64];
19 requestInputStream.Read (jsonInputData, 0, (int)_context.Request.ContentLength64);
20
21 try {
22 jsonDeserializeSampler.Begin ();
23 inputJson = JsonSerializer.Deserialize<IDictionary<string, object>> (jsonInputData);
24
25 // Log.Out ("JSON body:");
26 // foreach ((string key, object value) in inputJson) {
27 // Log.Out ($" - {key} = {value} ({value.GetType ()})");
28 // }
29
30 jsonDeserializeSampler.End ();
31 } catch (Exception e) {
32 jsonDeserializeSampler.End ();
33
34 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "INVALID_BODY", e);
35 return;
36 }
37 }
38
39 try {
40 switch (_context.Request.HttpMethod) {
41 case "GET":
42 if (inputJson != null) {
43 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "GET_WITH_BODY");
44 return;
45 }
46
47 HandleRestGet (_context);
48 return;
49 case "POST":
50 if (!string.IsNullOrEmpty (_context.RequestPath)) {
51 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "POST_WITH_ID");
52 return;
53 }
54
55 if (inputJson == null) {
56 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "POST_WITHOUT_BODY");
57 return;
58 }
59
60 HandleRestPost (_context, inputJson, jsonInputData);
61 return;
62 case "PUT":
63 if (string.IsNullOrEmpty (_context.RequestPath)) {
64 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "PUT_WITHOUT_ID");
65 return;
66 }
67
68 if (inputJson == null) {
69 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "PUT_WITHOUT_BODY");
70 return;
71 }
72
73 HandleRestPut (_context, inputJson, jsonInputData);
74 return;
75 case "DELETE":
76 if (string.IsNullOrEmpty (_context.RequestPath)) {
77 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "DELETE_WITHOUT_ID");
78 return;
79 }
80
81 if (inputJson != null) {
82 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "DELETE_WITH_BODY");
83 return;
84 }
85
86 HandleRestDelete (_context);
87 return;
88 default:
89 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "INVALID_METHOD");
90 return;
91 }
92 } catch (Exception e) {
93 SendErrorResult (_context, HttpStatusCode.InternalServerError, jsonInputData, "ERROR_PROCESSING", e);
94 }
95 }
96
97 static AbsRestApi () {
98 JsonWriter writer = new JsonWriter ();
99 writer.WriteBeginArray ();
100 writer.WriteEndArray ();
101 JsonEmptyData = writer.ToUtf8ByteArray ();
102 }
103
104 protected virtual void HandleRestGet (RequestContext _context) {
105 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, null, "Unsupported");
106 }
107
108 protected virtual void HandleRestPost (RequestContext _context, IDictionary<string, object> _jsonInput, byte[] _jsonInputData) {
109 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, _jsonInputData, "Unsupported");
110 }
111
112 protected virtual void HandleRestPut (RequestContext _context, IDictionary<string, object> _jsonInput, byte[] _jsonInputData) {
113 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, _jsonInputData, "Unsupported");
114 }
115
116 protected virtual void HandleRestDelete (RequestContext _context) {
117 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, null, "Unsupported");
118 }
119
120
121#region Helpers
122
123 protected static readonly byte[] JsonEmptyData;
124
125 protected static void PrepareEnvelopedResult (out JsonWriter _writer) {
126 WebUtils.PrepareEnvelopedResult (out _writer);
127 }
128
129 protected static void SendEnvelopedResult (RequestContext _context, ref JsonWriter _writer, HttpStatusCode _statusCode = HttpStatusCode.OK,
130 byte[] _jsonInputData = null, string _errorCode = null, Exception _exception = null) {
131
132 WebUtils.SendEnvelopedResult (_context, ref _writer, _statusCode, _jsonInputData, _errorCode, _exception);
133 }
134
135 protected static void SendErrorResult (RequestContext _context, HttpStatusCode _statusCode, byte[] _jsonInputData = null, string _errorCode = null, Exception _exception = null) {
136 PrepareEnvelopedResult (out JsonWriter writer);
137 writer.WriteRaw (JsonEmptyData);
138 SendEnvelopedResult (_context, ref writer, _statusCode, _jsonInputData, _errorCode, _exception);
139 }
140
141 protected static bool TryGetJsonField (IDictionary<string, object> _jsonObject, string _fieldName, out int _value) {
142 _value = default;
143
144 if (!_jsonObject.TryGetValue (_fieldName, out object fieldNode)) {
145 return false;
146 }
147
148 if (fieldNode is not double value) {
149 return false;
150 }
151
152 try {
153 _value = (int)value;
154 return true;
155 } catch (Exception) {
156 return false;
157 }
158 }
159
160 protected static bool TryGetJsonField (IDictionary<string, object> _jsonObject, string _fieldName, out double _value) {
161 _value = default;
162
163 if (!_jsonObject.TryGetValue (_fieldName, out object fieldNode)) {
164 return false;
165 }
166
167 if (fieldNode is not double value) {
168 return false;
169 }
170
171 try {
172 _value = value;
173 return true;
174 } catch (Exception) {
175 return false;
176 }
177 }
178
179 protected static bool TryGetJsonField (IDictionary<string, object> _jsonObject, string _fieldName, out string _value) {
180 _value = default;
181
182 if (!_jsonObject.TryGetValue (_fieldName, out object fieldNode)) {
183 return false;
184 }
185
186 if (fieldNode is not string value) {
187 return false;
188 }
189
190 try {
191 _value = value;
192 return true;
193 } catch (Exception) {
194 return false;
195 }
196 }
197
198
199#endregion
200 }
201}
Note: See TracBrowser for help on using the repository browser.