Ignore:
Timestamp:
Aug 17, 2023, 4:57:23 PM (15 months ago)
Author:
alloc
Message:

21.1.16.0 release
Completed OpenAPI specs
Add support to path handlers to register OpenAPI specs
Fixed ItemIconHandler throwing error when requested path contains no dot

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TFP-WebServer/WebServer/src/WebAPI/OpenApiHelpers.cs

    r460 r463  
    44using System.Text;
    55using System.Text.RegularExpressions;
     6using Webserver.UrlHandlers;
    67
    78namespace Webserver.WebAPI {
     
    1011                private const string masterDocName = "openapi.yaml";
    1112
    12                 private const string masterDocRefLineBegin = "    - $ref: ";
    13                 private const string masterDocRefLineEnd = "#/paths";
    14 
    1513                private struct OpenApiSpec {
    16                         public readonly List<string> ExportedPaths;
     14                        public readonly Dictionary<string, string> ExportedPaths;
    1715                        public readonly string Spec;
    1816
    19                         public OpenApiSpec (string _spec, List<string> _exportedPaths = null) {
     17                        public OpenApiSpec (string _spec, Dictionary<string, string> _exportedPaths = null) {
    2018                                ExportedPaths = _exportedPaths;
    2119                                Spec = _spec;
     
    5755                                }
    5856
    59                                 if ((spec.ExportedPaths?.Count ?? 0) < 1) {
     57                                if (spec.ExportedPaths == null || spec.ExportedPaths.Count < 1) {
    6058                                        continue;
    6159                                }
    6260
    63                                 foreach (string exportedPath in spec.ExportedPaths) {
    64                                         writePath (sb, apiSpecName, exportedPath);
     61                                foreach ((string exportedPath, string rebasedPath) in spec.ExportedPaths) {
     62                                        writePath (sb, apiSpecName, exportedPath, rebasedPath);
    6563                                }
    6664                        }
     
    7169                }
    7270
    73                 private void writePath (StringBuilder _sb, string _apiSpecName, string _exportedPath) {
    74                         _sb.AppendLine ($"  {_exportedPath}:");
     71                private void writePath (StringBuilder _sb, string _apiSpecName, string _exportedPath, string _rebasedPath) {
     72                        _sb.AppendLine ($"  {_rebasedPath ?? _exportedPath}:");
    7573                        _sb.Append ($"    $ref: './{_apiSpecName}#/paths/");
    7674
    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                         }
     75                        writeJsonPointerEncodedPath (_sb, _exportedPath);
    19776                       
    19877                        _sb.AppendLine ("'");
     
    21493                }
    21594
     95                public void LoadOpenApiSpec (AbsHandler _pathHandler) {
     96                        Assembly apiAssembly = _pathHandler.GetType ().Assembly;
     97                        string apiName = _pathHandler.GetType ().Name;
     98                        string apiSpecName = $"{apiName}.openapi.yaml";
     99
     100                        string specText = ResourceHelpers.GetManifestResourceText (apiAssembly, apiSpecName, true);
     101                        if (specText == null) {
     102                                return;
     103                        }
     104
     105                        Log.Out ($"[Web] Loaded OpenAPI spec for '{apiName}'");
     106                        OpenApiSpec spec = new OpenApiSpec (specText, findExportedPaths (specText, _pathHandler.UrlBasePath));
     107                        specs.Add (apiSpecName, spec);
     108                }
     109
     110                public void RegisterCustomSpec (Assembly _assembly, string _apiSpecName, string _replaceBasePath = null) {
     111                        string apiSpecName = $"{_apiSpecName}.openapi.yaml";
     112
     113                        string specText = ResourceHelpers.GetManifestResourceText (_assembly, apiSpecName, true);
     114                        if (specText == null) {
     115                                return;
     116                        }
     117
     118                        Log.Out ($"[Web] Loaded OpenAPI spec for '{_apiSpecName}'");
     119                        OpenApiSpec spec = new OpenApiSpec (specText, findExportedPaths (specText, _replaceBasePath));
     120                        specs.Add (apiSpecName, spec);
     121                }
     122
    216123                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> ();
     124                private Dictionary<string, string> findExportedPaths (string _spec, string _replaceBasePath = null) {
     125                        Dictionary<string, string> result = new Dictionary<string, string> ();
    219126
    220127                        using TextReader tr = new StringReader (_spec);
     
    234141
    235142                                        string path = match.Groups [1].Value;
     143                                        string rebasedPath = null;
    236144                                        Log.Out ($"[Web]   Exports: {path}");
    237                                         result.Add (path);
     145                                        if (_replaceBasePath != null) {
     146                                                rebasedPath = path.Replace ("/BASEPATH/", _replaceBasePath);
     147                                        }
     148                                        result [path] = rebasedPath;
    238149                                }
    239150                        }
     
    255166                        return true;
    256167                }
     168
     169                private void writeJsonPointerEncodedPath (StringBuilder _targetSb, string _path) {
     170                        for (int i = 0; i < _path.Length; i++) {
     171                                char c = _path[i];
     172
     173                                switch (c) {
     174                                        // JSON string escaped characters
     175                                        case '"':
     176                                                _targetSb.Append ("\\\"");
     177                                                break;
     178                                        case '\\':
     179                                                _targetSb.Append ("\\\\");
     180                                                break;
     181                                        case '\b':
     182                                                _targetSb.Append ("\\b");
     183                                                break;
     184                                        case '\f':
     185                                                _targetSb.Append ("\\f");
     186                                                break;
     187                                        case '\n':
     188                                                _targetSb.Append ("\\n");
     189                                                break;
     190                                        case '\r':
     191                                                _targetSb.Append ("\\r");
     192                                                break;
     193                                        case '\t':
     194                                                _targetSb.Append ("\\t");
     195                                                break;
     196                                        case (char)0x00:
     197                                                _targetSb.Append ("\\u0000");
     198                                                break;
     199                                        case (char)0x01:
     200                                                _targetSb.Append ("\\u0001");
     201                                                break;
     202                                        case (char)0x02:
     203                                                _targetSb.Append ("\\u0002");
     204                                                break;
     205                                        case (char)0x03:
     206                                                _targetSb.Append ("\\u0003");
     207                                                break;
     208                                        case (char)0x04:
     209                                                _targetSb.Append ("\\u0004");
     210                                                break;
     211                                        case (char)0x05:
     212                                                _targetSb.Append ("\\u0005");
     213                                                break;
     214                                        case (char)0x06:
     215                                                _targetSb.Append ("\\u0006");
     216                                                break;
     217                                        case (char)0x07:
     218                                                _targetSb.Append ("\\u0007");
     219                                                break;
     220                                        case (char)0x0b:
     221                                                _targetSb.Append ("\\u000b");
     222                                                break;
     223                                        case (char)0x0e:
     224                                                _targetSb.Append ("\\u000e");
     225                                                break;
     226                                        case (char)0x0f:
     227                                                _targetSb.Append ("\\u000f");
     228                                                break;
     229                                        case (char)0x10:
     230                                                _targetSb.Append ("\\u0010");
     231                                                break;
     232                                        case (char)0x11:
     233                                                _targetSb.Append ("\\u0011");
     234                                                break;
     235                                        case (char)0x12:
     236                                                _targetSb.Append ("\\u0012");
     237                                                break;
     238                                        case (char)0x13:
     239                                                _targetSb.Append ("\\u0013");
     240                                                break;
     241                                        case (char)0x14:
     242                                                _targetSb.Append ("\\u0014");
     243                                                break;
     244                                        case (char)0x15:
     245                                                _targetSb.Append ("\\u0015");
     246                                                break;
     247                                        case (char)0x16:
     248                                                _targetSb.Append ("\\u0016");
     249                                                break;
     250                                        case (char)0x17:
     251                                                _targetSb.Append ("\\u0017");
     252                                                break;
     253                                        case (char)0x18:
     254                                                _targetSb.Append ("\\u0018");
     255                                                break;
     256                                        case (char)0x19:
     257                                                _targetSb.Append ("\\u0019");
     258                                                break;
     259                                        case (char)0x1a:
     260                                                _targetSb.Append ("\\u001a");
     261                                                break;
     262                                        case (char)0x1b:
     263                                                _targetSb.Append ("\\u001b");
     264                                                break;
     265                                        case (char)0x1c:
     266                                                _targetSb.Append ("\\u001c");
     267                                                break;
     268                                        case (char)0x1d:
     269                                                _targetSb.Append ("\\u001d");
     270                                                break;
     271                                        case (char)0x1e:
     272                                                _targetSb.Append ("\\u001e");
     273                                                break;
     274                                        case (char)0x1f:
     275                                                _targetSb.Append ("\\u001f");
     276                                                break;
     277                                        // JSON Pointer specific
     278                                        case '/':
     279                                                _targetSb.Append ("~1");
     280                                                break;
     281                                        case '~':
     282                                                _targetSb.Append ("~0");
     283                                                break;
     284                                        // Non escaped characters
     285                                        default:
     286                                                _targetSb.Append (c);
     287                                                break;
     288                                }
     289                        }
     290                }
     291
    257292        }
    258293}
Note: See TracChangeset for help on using the changeset viewer.