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

Last change on this file since 402 was 402, checked in by alloc, 22 months ago
  • Major refactoring
  • Using Utf8Json for (de)serialization
  • Moving APIs to REST
  • Removing dependencies from WebServer and MapRenderer to ServerFixes
File size: 6.1 KB
RevLine 
[391]1using System;
[402]2using System.Collections.Generic;
[391]3using System.IO;
4using System.Net;
[402]5using Utf8Json;
[391]6
7namespace Webserver.WebAPI {
8 public abstract class AbsRestApi : AbsWebAPI {
[394]9 private static readonly UnityEngine.Profiling.CustomSampler jsonDeserializeSampler = UnityEngine.Profiling.CustomSampler.Create ("JSON_Deserialize");
10
[391]11 public sealed override void HandleRequest (RequestContext _context) {
[402]12 IDictionary<string, object> inputJson = null;
13 byte[] jsonInputData = null;
14
[391]15 if (_context.Request.HasEntityBody) {
[402]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 ();
[391]33
[402]34 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "INVALID_BODY", e);
35 return;
[391]36 }
37 }
38
39 try {
40 switch (_context.Request.HttpMethod) {
41 case "GET":
[402]42 if (inputJson != null) {
43 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "GET_WITH_BODY");
[391]44 return;
45 }
46
47 HandleRestGet (_context);
48 return;
49 case "POST":
50 if (!string.IsNullOrEmpty (_context.RequestPath)) {
[402]51 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "POST_WITH_ID");
[391]52 return;
53 }
54
[402]55 if (inputJson == null) {
56 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "POST_WITHOUT_BODY");
[391]57 return;
58 }
59
[402]60 HandleRestPost (_context, inputJson, jsonInputData);
[391]61 return;
62 case "PUT":
63 if (string.IsNullOrEmpty (_context.RequestPath)) {
[402]64 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "PUT_WITHOUT_ID");
[391]65 return;
66 }
67
[402]68 if (inputJson == null) {
69 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "PUT_WITHOUT_BODY");
[391]70 return;
71 }
72
[402]73 HandleRestPut (_context, inputJson, jsonInputData);
[391]74 return;
75 case "DELETE":
76 if (string.IsNullOrEmpty (_context.RequestPath)) {
[402]77 SendErrorResult (_context, HttpStatusCode.BadRequest, jsonInputData, "DELETE_WITHOUT_ID");
[391]78 return;
79 }
80
[402]81 if (inputJson != null) {
82 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "DELETE_WITH_BODY");
[391]83 return;
84 }
85
86 HandleRestDelete (_context);
87 return;
88 default:
[402]89 SendErrorResult (_context, HttpStatusCode.BadRequest, null, "INVALID_METHOD");
[391]90 return;
91 }
92 } catch (Exception e) {
[402]93 SendErrorResult (_context, HttpStatusCode.InternalServerError, jsonInputData, "ERROR_PROCESSING", e);
[391]94 }
95 }
96
[402]97 protected void SendErrorResult (RequestContext _context, HttpStatusCode _statusCode, byte[] _jsonInputData = null, string _errorCode = null, Exception _exception = null) {
98 PrepareEnvelopedResult (out JsonWriter writer);
99 writer.WriteRaw (JsonEmptyData);
100 SendEnvelopedResult (_context, ref writer, _statusCode, _jsonInputData, _errorCode, _exception);
101 }
[391]102
[402]103 static AbsRestApi () {
104 JsonWriter writer = new JsonWriter ();
105 writer.WriteBeginArray ();
106 writer.WriteEndArray ();
107 JsonEmptyData = writer.ToUtf8ByteArray ();
108 }
[391]109
[402]110 protected static readonly byte[] JsonEmptyData;
111
112 protected void PrepareEnvelopedResult (out JsonWriter _writer) {
113 WebUtils.PrepareEnvelopedResult (out _writer);
114 }
[391]115
[402]116 protected void SendEnvelopedResult (RequestContext _context, ref JsonWriter _writer, HttpStatusCode _statusCode = HttpStatusCode.OK,
117 byte[] _jsonInputData = null, string _errorCode = null, Exception _exception = null) {
118
119 WebUtils.SendEnvelopedResult (_context, ref _writer, _statusCode, _jsonInputData, _errorCode, _exception);
[391]120 }
121
[402]122 protected bool TryGetJsonField (IDictionary<string, object> _jsonObject, string _fieldName, out int _value) {
[391]123 _value = default;
124
[402]125 if (!_jsonObject.TryGetValue (_fieldName, out object fieldNode)) {
[391]126 return false;
127 }
128
[402]129 if (fieldNode is not double value) {
[391]130 return false;
131 }
132
133 try {
[402]134 _value = (int)value;
[391]135 return true;
136 } catch (Exception) {
137 return false;
138 }
139 }
140
[402]141 protected bool TryGetJsonField (IDictionary<string, object> _jsonObject, string _fieldName, out double _value) {
[391]142 _value = default;
143
[402]144 if (!_jsonObject.TryGetValue (_fieldName, out object fieldNode)) {
[391]145 return false;
146 }
147
[402]148 if (fieldNode is not double value) {
[391]149 return false;
150 }
151
152 try {
[402]153 _value = value;
[391]154 return true;
155 } catch (Exception) {
156 return false;
157 }
158 }
159
[402]160 protected bool TryGetJsonField (IDictionary<string, object> _jsonObject, string _fieldName, out string _value) {
[391]161 _value = default;
162
[402]163 if (!_jsonObject.TryGetValue (_fieldName, out object fieldNode)) {
[391]164 return false;
165 }
166
[402]167 if (fieldNode is not string value) {
[391]168 return false;
169 }
170
171 try {
[402]172 _value = value;
[391]173 return true;
174 } catch (Exception) {
175 return false;
176 }
177 }
178
[402]179 protected virtual void HandleRestGet (RequestContext _context) {
180 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, null, "Unsupported");
181 }
[391]182
[402]183 protected virtual void HandleRestPost (RequestContext _context, IDictionary<string, object> _jsonInput, byte[] _jsonInputData) {
184 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, _jsonInputData, "Unsupported");
185 }
[391]186
[402]187 protected virtual void HandleRestPut (RequestContext _context, IDictionary<string, object> _jsonInput, byte[] _jsonInputData) {
188 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, _jsonInputData, "Unsupported");
189 }
[391]190
[402]191 protected virtual void HandleRestDelete (RequestContext _context) {
192 SendErrorResult (_context, HttpStatusCode.MethodNotAllowed, null, "Unsupported");
193 }
[391]194 }
195}
Note: See TracBrowser for help on using the repository browser.