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

Last change on this file since 410 was 410, checked in by alloc, 21 months ago

Base API class improvements

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