Ignore:
Timestamp:
Aug 11, 2023, 6:29:09 PM (15 months ago)
Author:
alloc
Message:

More OpenAPI specs added
OpenAPI specs cleanup to have everything validate fine
Added CORS support to API endpoints

File:
1 edited

Legend:

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

    r459 r460  
    33using System.Reflection;
    44using System.Text;
     5using System.Text.RegularExpressions;
    56
    67namespace Webserver.WebAPI {
     
    1213                private const string masterDocRefLineEnd = "#/paths";
    1314
    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> ();
    1526
    1627                public OpenApiHelpers () {
     
    3041                        }
    3142
    32                         specs.Add (masterDocName, specText);
     43                        specs.Add (masterDocName, new OpenApiSpec(specText));
    3344                        Log.Out ($"[Web] Loaded main OpenAPI spec");
    3445                }
     
    4152                        StringBuilder sb = new StringBuilder (mainSpec);
    4253                       
    43                         foreach ((string apiSpecName, _) in specs) {
     54                        foreach ((string apiSpecName, OpenApiSpec spec) in specs) {
    4455                                if (apiSpecName.Equals (masterDocName)) {
    4556                                        continue;
    4657                                }
    4758
    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 ());
    5269                       
    5370                        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 ("'");
    54199                }
    55200
     
    65210
    66211                        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;
    68242                }
    69243
     
    73247                        }
    74248
    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;
    76256                }
    77257        }
Note: See TracChangeset for help on using the changeset viewer.