Changeset 460
- Timestamp:
- Aug 11, 2023, 6:29:09 PM (16 months ago)
- Location:
- TFP-WebServer
- Files:
-
- 6 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
TFP-WebServer/MarkersMod/src/Markers.openapi.yaml
r459 r460 2 2 info: 3 3 title: Markers 4 version: 14 version: '1' 5 5 6 6 components: … … 80 80 $ref: '#/components/schemas/MarkersList' 81 81 meta: 82 $ref: ' #/components/schemas/ResultEnvelopeMeta'82 $ref: './openapi.yaml#/components/schemas/ResultEnvelopeMeta' 83 83 required: 84 84 - data … … 96 96 format: uuid 97 97 meta: 98 $ref: ' #/components/schemas/ResultEnvelopeMeta'98 $ref: './openapi.yaml#/components/schemas/ResultEnvelopeMeta' 99 99 required: 100 100 - data … … 110 110 type: string 111 111 format: uuid 112 description: ID of marker to fetch 112 113 113 114 … … 118 119 - Map 119 120 summary: Markers list 120 description: Fetch a list of theall defined map markers121 description: Fetch a list of all defined map markers 121 122 operationId: markers.get 122 123 responses: … … 141 142 Invalid request body, errorCode will be one of 'NO_OR_INVALID_X', 142 143 'NO_OR_INVALID_Y' 143 $ref: ' #/components/responses/HttpEmptyEnvelopedResponse'144 $ref: './openapi.yaml#/components/responses/HttpEmptyEnvelopedResponse' 144 145 403: 145 $ref: ' #/components/responses/Unauthorized'146 $ref: './openapi.yaml#/components/responses/Unauthorized' 146 147 security: 147 148 - apiTokenName: [] … … 164 165 404: 165 166 description: Marker ID not found, errorCode will be 'ID_NOT_FOUND' 166 $ref: ' #/components/responses/HttpEmptyEnvelopedResponse'167 $ref: './openapi.yaml#/components/responses/HttpEmptyEnvelopedResponse' 167 168 168 169 put: … … 184 185 Invalid request body, errorCode will be one of 'NO_OR_INVALID_X', 185 186 'NO_OR_INVALID_Y' 186 $ref: ' #/components/responses/HttpEmptyEnvelopedResponse'187 $ref: './openapi.yaml#/components/responses/HttpEmptyEnvelopedResponse' 187 188 404: 188 189 description: Marker ID not found, errorCode will be 'ID_NOT_FOUND' 189 $ref: ' #/components/responses/HttpEmptyEnvelopedResponse'190 $ref: './openapi.yaml#/components/responses/HttpEmptyEnvelopedResponse' 190 191 403: 191 $ref: ' #/components/responses/Unauthorized'192 $ref: './openapi.yaml#/components/responses/Unauthorized' 192 193 security: 193 194 - apiTokenName: [] … … 206 207 204: 207 208 description: Deleted marker 208 $ref: ' #/components/responses/HttpEmptyEnvelopedResponse'209 $ref: './openapi.yaml#/components/responses/HttpEmptyEnvelopedResponse' 209 210 404: 210 211 description: Marker ID not found 211 $ref: ' #/components/responses/HttpEmptyEnvelopedResponse'212 $ref: './openapi.yaml#/components/responses/HttpEmptyEnvelopedResponse' 212 213 403: 213 $ref: ' #/components/responses/Unauthorized'214 $ref: './openapi.yaml#/components/responses/Unauthorized' 214 215 security: 215 216 - apiTokenName: [] -
TFP-WebServer/WebServer/WebServer.csproj
r459 r460 198 198 </ItemGroup> 199 199 <ItemGroup> 200 <EmbeddedResource Include="src\WebAPI\APIs\GameData\Item.openapi.yaml" /> 201 <EmbeddedResource Include="src\WebAPI\APIs\GameData\Mods.openapi.yaml" /> 202 <EmbeddedResource Include="src\WebAPI\APIs\Log.openapi.yaml" /> 203 <EmbeddedResource Include="src\WebAPI\APIs\Command.openapi.yaml" /> 204 <EmbeddedResource Include="src\WebAPI\APIs\Permissions\Blacklist.openapi.yaml" /> 200 205 <EmbeddedResource Include="src\WebAPI\APIs\WorldState\Animal.openapi.yaml" /> 201 206 <EmbeddedResource Include="src\WebAPI\OpenAPI.master.yaml" /> -
TFP-WebServer/WebServer/src/UrlHandlers/ApiHandler.cs
r459 r460 53 53 private static readonly UnityEngine.Profiling.CustomSampler apiHandlerSampler = UnityEngine.Profiling.CustomSampler.Create ("API_Handler"); 54 54 55 private bool HandleCors (RequestContext _context) { 56 _context.Request.Headers.TryGetValue ("Origin", out string origin); 57 _context.Response.AddHeader ("Access-Control-Allow-Origin", origin ?? "*"); 58 59 if (_context.Method != ERequestMethod.OPTIONS) { 60 return false; 61 } 62 63 if (!_context.Request.Headers.TryGetValue ("Access-Control-Request-Method", out _)) { 64 return false; 65 } 66 67 _context.Response.AddHeader ("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS, HEAD"); 68 _context.Response.AddHeader ("Access-Control-Allow-Headers", "X-SDTD-API-TOKENNAME, X-SDTD-API-SECRET"); 69 _context.Response.AddHeader ("Access-Control-Allow-Credentials", "true"); 70 return true; 71 } 72 55 73 public override void HandleRequest (RequestContext _context) { 56 74 … … 72 90 } 73 91 92 // CORS specific stuff 93 if (HandleCors (_context)) { 94 return; 95 } 96 // CORS end 97 74 98 _context.RequestPath = subPath; 75 99 -
TFP-WebServer/WebServer/src/WebAPI/APIs/OpenAPI.openapi.yaml
r459 r460 2 2 info: 3 3 title: OpenAPI 4 version: 14 version: '1' 5 5 6 6 … … 8 8 /api/OpenAPI/openapi.yaml: 9 9 get: 10 tags: 11 - Meta 12 summary: OpenAPI master document 13 description: Fetch the OpenAPI master document, referencing all the individual WebAPI specs 10 14 operationId: OpenAPI.openapi 11 15 responses: … … 14 18 application/json: {} 15 19 description: OpenAPI master document 20 /api/OpenAPI/{name}.openapi.yaml: 21 get: 16 22 tags: 17 23 - Meta 18 /api/OpenAPI/{name}.openapi.yaml:19 get:24 summary: OpenAPI spec for single API 25 description: Fetch the OpenAPI spec of a single WebAPI 20 26 operationId: OpenAPI.getAPI 21 27 parameters: … … 35 41 application/json: {} 36 42 description: No OpenAPI spec found for the API name 37 tags:38 - Meta -
TFP-WebServer/WebServer/src/WebAPI/APIs/Permissions/Blacklist.cs
r434 r460 100 100 } 101 101 102 bool validId = PlatformUserIdentifierAbs.TryFromCombinedString (id, out _userId); 103 if (!validId) { 102 if (PlatformUserIdentifierAbs.TryFromCombinedString (id, out _userId)) { 104 103 SendEmptyResponse (_context, HttpStatusCode.BadRequest, _jsonInputData, "INVALID_USER"); 104 return false; 105 105 } 106 106 107 return validId;107 return true; 108 108 } 109 109 -
TFP-WebServer/WebServer/src/WebAPI/APIs/WorldState/Animal.openapi.yaml
r459 r460 2 2 info: 3 3 title: Animal 4 version: 14 version: '1' 5 5 6 6 components: … … 10 10 properties: 11 11 id: 12 $ref: ' #/components/schemas/TypeEntityId'12 $ref: './openapi.yaml#/components/schemas/TypeEntityId' 13 13 name: 14 14 type: string … … 16 16 - animalStag 17 17 position: 18 $ref: ' #/components/schemas/TypeVector3i'18 $ref: './openapi.yaml#/components/schemas/TypeVector3i' 19 19 required: 20 20 - id … … 47 47 $ref: '#/components/schemas/AnimalList' 48 48 meta: 49 $ref: ' #/components/schemas/ResultEnvelopeMeta'49 $ref: './openapi.yaml#/components/schemas/ResultEnvelopeMeta' 50 50 required: 51 51 - data 52 52 - meta 53 53 403: 54 $ref: ' #/components/responses/Unauthorized'54 $ref: './openapi.yaml#/components/responses/Unauthorized' 55 55 security: 56 56 - apiTokenName: [] -
TFP-WebServer/WebServer/src/WebAPI/OpenAPI.master.yaml
r459 r460 1 openapi: 3.1.0 1 2 info: 2 3 title: 7 Days To Die WebAPI 3 version: 1.0.0 4 openapi: 3.1.0 4 version: '1.0.0' 5 5 servers: 6 6 - url: / … … 81 81 description: 3D vector in full blocks 82 82 83 TypeUserIdString: 84 type: string 85 pattern: '^\[a-zA-Z]+_[\w]+$' 86 examples: 87 - 'Steam_76561198021925107' 88 description: User ID including platform 89 90 TypeUserIdObject: 91 anyOf: 92 - type: object 93 properties: 94 combinedString: 95 $ref: '#/components/schemas/TypeUserIdString' 96 platformId: 97 type: string 98 examples: 99 - Steam 100 - XBL 101 description: Gaming platform the ID references 102 userId: 103 type: string 104 examples: 105 - '76561198021925107' 106 description: Unique ID of the user within the given gaming platform 107 required: 108 - combinedString 109 - platformId 110 - userId 111 description: User ID 112 - type: 'null' 113 83 114 84 115 responses: … … 126 157 127 158 paths: 128 allOf: -
TFP-WebServer/WebServer/src/WebAPI/OpenApiHelpers.cs
r459 r460 3 3 using System.Reflection; 4 4 using System.Text; 5 using System.Text.RegularExpressions; 5 6 6 7 namespace Webserver.WebAPI { … … 12 13 private const string masterDocRefLineEnd = "#/paths"; 13 14 14 private readonly Dictionary<string, string> specs = new CaseInsensitiveStringDictionary<string> (); 15 private struct OpenApiSpec { 16 public readonly List<string> ExportedPaths; 17 public readonly string Spec; 18 19 public OpenApiSpec (string _spec, List<string> _exportedPaths = null) { 20 ExportedPaths = _exportedPaths; 21 Spec = _spec; 22 } 23 } 24 25 private readonly Dictionary<string, OpenApiSpec> specs = new CaseInsensitiveStringDictionary<OpenApiSpec> (); 15 26 16 27 public OpenApiHelpers () { … … 30 41 } 31 42 32 specs.Add (masterDocName, specText);43 specs.Add (masterDocName, new OpenApiSpec(specText)); 33 44 Log.Out ($"[Web] Loaded main OpenAPI spec"); 34 45 } … … 41 52 StringBuilder sb = new StringBuilder (mainSpec); 42 53 43 foreach ((string apiSpecName, _) in specs) {54 foreach ((string apiSpecName, OpenApiSpec spec) in specs) { 44 55 if (apiSpecName.Equals (masterDocName)) { 45 56 continue; 46 57 } 47 58 48 sb.AppendLine ($"{masterDocRefLineBegin}./{apiSpecName}{masterDocRefLineEnd}"); 49 } 50 51 specs[masterDocName] = sb.ToString (); 59 if ((spec.ExportedPaths?.Count ?? 0) < 1) { 60 continue; 61 } 62 63 foreach (string exportedPath in spec.ExportedPaths) { 64 writePath (sb, apiSpecName, exportedPath); 65 } 66 } 67 68 specs[masterDocName] = new OpenApiSpec(sb.ToString ()); 52 69 53 70 Log.Out ("[Web] OpenAPI preparation done"); 71 } 72 73 private void writePath (StringBuilder _sb, string _apiSpecName, string _exportedPath) { 74 _sb.AppendLine ($" {_exportedPath}:"); 75 _sb.Append ($" $ref: './{_apiSpecName}#/paths/"); 76 77 for (int i = 0; i < _exportedPath.Length; i++) { 78 char c = _exportedPath[i]; 79 80 switch (c) { 81 // JSON string escaped characters 82 case '"': 83 _sb.Append ("\\\""); 84 break; 85 case '\\': 86 _sb.Append ("\\\\"); 87 break; 88 case '\b': 89 _sb.Append ("\\b"); 90 break; 91 case '\f': 92 _sb.Append ("\\f"); 93 break; 94 case '\n': 95 _sb.Append ("\\n"); 96 break; 97 case '\r': 98 _sb.Append ("\\r"); 99 break; 100 case '\t': 101 _sb.Append ("\\t"); 102 break; 103 case (char)0x00: 104 _sb.Append ("\\u0000"); 105 break; 106 case (char)0x01: 107 _sb.Append ("\\u0001"); 108 break; 109 case (char)0x02: 110 _sb.Append ("\\u0002"); 111 break; 112 case (char)0x03: 113 _sb.Append ("\\u0003"); 114 break; 115 case (char)0x04: 116 _sb.Append ("\\u0004"); 117 break; 118 case (char)0x05: 119 _sb.Append ("\\u0005"); 120 break; 121 case (char)0x06: 122 _sb.Append ("\\u0006"); 123 break; 124 case (char)0x07: 125 _sb.Append ("\\u0007"); 126 break; 127 case (char)0x0b: 128 _sb.Append ("\\u000b"); 129 break; 130 case (char)0x0e: 131 _sb.Append ("\\u000e"); 132 break; 133 case (char)0x0f: 134 _sb.Append ("\\u000f"); 135 break; 136 case (char)0x10: 137 _sb.Append ("\\u0010"); 138 break; 139 case (char)0x11: 140 _sb.Append ("\\u0011"); 141 break; 142 case (char)0x12: 143 _sb.Append ("\\u0012"); 144 break; 145 case (char)0x13: 146 _sb.Append ("\\u0013"); 147 break; 148 case (char)0x14: 149 _sb.Append ("\\u0014"); 150 break; 151 case (char)0x15: 152 _sb.Append ("\\u0015"); 153 break; 154 case (char)0x16: 155 _sb.Append ("\\u0016"); 156 break; 157 case (char)0x17: 158 _sb.Append ("\\u0017"); 159 break; 160 case (char)0x18: 161 _sb.Append ("\\u0018"); 162 break; 163 case (char)0x19: 164 _sb.Append ("\\u0019"); 165 break; 166 case (char)0x1a: 167 _sb.Append ("\\u001a"); 168 break; 169 case (char)0x1b: 170 _sb.Append ("\\u001b"); 171 break; 172 case (char)0x1c: 173 _sb.Append ("\\u001c"); 174 break; 175 case (char)0x1d: 176 _sb.Append ("\\u001d"); 177 break; 178 case (char)0x1e: 179 _sb.Append ("\\u001e"); 180 break; 181 case (char)0x1f: 182 _sb.Append ("\\u001f"); 183 break; 184 // JSON Pointer specific 185 case '/': 186 _sb.Append ("~1"); 187 break; 188 case '~': 189 _sb.Append ("~0"); 190 break; 191 // Non escaped characters 192 default: 193 _sb.Append (c); 194 break; 195 } 196 } 197 198 _sb.AppendLine ("'"); 54 199 } 55 200 … … 65 210 66 211 Log.Out ($"[Web] Loaded OpenAPI spec for '{apiName}'"); 67 specs.Add (apiSpecName, specText); 212 OpenApiSpec spec = new OpenApiSpec (specText, findExportedPaths (specText)); 213 specs.Add (apiSpecName, spec); 214 } 215 216 private static readonly Regex pathMatcher = new Regex ("^\\s{1,2}(/\\S+):.*$", RegexOptions.Compiled | RegexOptions.CultureInvariant); 217 private List<string> findExportedPaths (string _spec) { 218 List<string> result = new List<string> (); 219 220 using TextReader tr = new StringReader (_spec); 221 222 string line; 223 bool inPaths = false; 224 while ((line = tr.ReadLine ()) != null) { 225 if (!inPaths) { 226 if (line.StartsWith ("paths:")) { 227 inPaths = true; 228 } 229 } else { 230 Match match = pathMatcher.Match (line); 231 if (!match.Success) { 232 continue; 233 } 234 235 string path = match.Groups [1].Value; 236 Log.Out ($"[Web] Exports: {path}"); 237 result.Add (path); 238 } 239 } 240 241 return result; 68 242 } 69 243 … … 73 247 } 74 248 75 return specs.TryGetValue (_name, out _specText); 249 if (!specs.TryGetValue (_name, out OpenApiSpec spec)) { 250 _specText = null; 251 return false; 252 } 253 254 _specText = spec.Spec; 255 return true; 76 256 } 77 257 } -
TFP-WebServer/WebServer/webroot/rapidoc.html
r459 r460 7 7 </head> 8 8 <body> 9 <rapi-doc spec-url="/api/openapi/openapi.yaml" render-style="focused" show-header="false" show-method-in-nav-bar="as-colored-block" > </rapi-doc>9 <rapi-doc spec-url="/api/openapi/openapi.yaml" render-style="focused" show-header="false" show-method-in-nav-bar="as-colored-block" sort-tags="true" schema-description-expanded="true" > </rapi-doc> 10 10 </body> 11 11 </html>
Note:
See TracChangeset
for help on using the changeset viewer.