source: binary-improvements2/MapRendering/Web/Handlers/ApiHandler.cs@ 387

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

Big refactoring in Web to pass around a Context instead of a bunch of individual arguments all the time

File size: 3.3 KB
RevLine 
[230]1using System;
2using System.Collections.Generic;
3using System.Net;
[250]4using System.Reflection;
[325]5using AllocsFixes.NetConnections.Servers.Web.API;
[230]6
[325]7namespace AllocsFixes.NetConnections.Servers.Web.Handlers {
[382]8 public class ApiHandler : AbsHandler {
[387]9 private readonly Dictionary<string, AbsWebAPI> apis = new CaseInsensitiveStringDictionary<AbsWebAPI> ();
[230]10
[384]11 public ApiHandler () : base (null) {
[250]12
[384]13 }
14
15 public override void SetBasePathAndParent (Web _parent, string _relativePath) {
16 base.SetBasePathAndParent (_parent, _relativePath);
17
18 Type[] apiWithParentCtorTypes = { typeof (Web) };
19 Object[] apiWithParentCtorArgs = { _parent };
20
21 Type[] apiEmptyCtorTypes = { };
22 Object[] apiEmptyCtorArgs = { };
23
[250]24 foreach (Type t in Assembly.GetExecutingAssembly ().GetTypes ()) {
[387]25 if (!t.IsAbstract && t.IsSubclassOf (typeof (AbsWebAPI))) {
[384]26 ConstructorInfo ctor = t.GetConstructor (apiWithParentCtorTypes);
[250]27 if (ctor != null) {
[387]28 AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiWithParentCtorArgs);
[367]29 addApi (apiInstance);
[384]30 continue;
[250]31 }
[384]32
33 ctor = t.GetConstructor (apiEmptyCtorTypes);
34 if (ctor != null) {
[387]35 AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiEmptyCtorArgs);
[384]36 addApi (apiInstance);
37 }
[250]38 }
[325]39 }
40
[367]41 // Permissions that don't map to a real API
42 addApi (new Null ("viewallclaims"));
43 addApi (new Null ("viewallplayers"));
[230]44 }
45
[387]46 private void addApi (AbsWebAPI _api) {
[367]47 apis.Add (_api.Name, _api);
48 WebPermissions.Instance.AddKnownModule ("webapi." + _api.Name, _api.DefaultPermissionLevel ());
[244]49 }
50
[332]51#if ENABLE_PROFILER
[367]52 private static readonly UnityEngine.Profiling.CustomSampler apiHandlerSampler = UnityEngine.Profiling.CustomSampler.Create ("API_Handler");
[332]53#endif
54
[387]55 public override void HandleRequest (RequestContext _context) {
[351]56
[387]57 string apiName;
58 string subPath = null;
59
60 int pathSeparatorIndex = _context.RequestPath.IndexOf ('/', urlBasePath.Length);
61 if (pathSeparatorIndex >= 0) {
62 apiName = _context.RequestPath.Substring (urlBasePath.Length, pathSeparatorIndex - urlBasePath.Length);
63 subPath = _context.RequestPath.Substring (pathSeparatorIndex + 1);
64 } else {
65 apiName = _context.RequestPath.Substring (urlBasePath.Length);
66 }
67
68 if (!apis.TryGetValue (apiName, out AbsWebAPI api)) {
[367]69 Log.Out ($"Error in {nameof(ApiHandler)}.HandleRequest(): No handler found for API \"{apiName}\"");
[387]70 _context.Response.StatusCode = (int) HttpStatusCode.NotFound;
[351]71 return;
72 }
73
[387]74 if (!AuthorizeForApi (apiName, _context.PermissionLevel)) {
75 _context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
76 if (_context.Connection != null) {
[367]77 //Log.Out ($"{nameof(ApiHandler)}: user '{user.SteamID}' not allowed to execute '{apiName}'");
[244]78 }
[325]79
[244]80 return;
[325]81 }
82
[387]83 _context.RequestPath = subPath;
84
[351]85 try {
[332]86#if ENABLE_PROFILER
[351]87 apiHandlerSampler.Begin ();
[332]88#endif
[387]89 api.HandleRequest (_context);
[332]90#if ENABLE_PROFILER
[351]91 apiHandlerSampler.End ();
[332]92#endif
[351]93 } catch (Exception e) {
[367]94 Log.Error ($"Error in {nameof(ApiHandler)}.HandleRequest(): Handler {api.Name} threw an exception:");
[351]95 Log.Exception (e);
[387]96 _context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
[230]97 }
98 }
99
[367]100 private bool AuthorizeForApi (string _apiName, int _permissionLevel) {
[351]101 return WebPermissions.Instance.ModuleAllowedWithLevel ("webapi." + _apiName, _permissionLevel);
[230]102 }
103 }
[325]104}
Note: See TracBrowser for help on using the repository browser.