blob: 839c075193f09493c468e658f6aaf262fdb19ebb [file] [log] [blame]
Constantin Zieschefa612082020-04-03 09:54:56 +02001/*******************************************************************************
2* Copyright (c) 2020 Robert Bosch GmbH
3* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
4*
5* This program and the accompanying materials are made available under the
6* terms of the Eclipse Public License 2.0 which is available at
7* http://www.eclipse.org/legal/epl-2.0
8*
9* SPDX-License-Identifier: EPL-2.0
10*******************************************************************************/
Constantin Zieschece276602020-10-27 09:36:00 +010011using BaSyx.Components.Common.Abstractions;
Constantin Ziesche0399d412020-09-24 14:31:15 +020012using BaSyx.Utils.AssemblyHandling;
Constantin Ziesche687f8882020-10-02 16:17:44 +020013using BaSyx.Utils.DependencyInjection;
Constantin Ziesche220223d2020-12-03 11:27:54 +010014using BaSyx.Utils.JsonHandling;
15using BaSyx.Utils.ResultHandling;
Constantin Zieschefa612082020-04-03 09:54:56 +020016using BaSyx.Utils.Settings.Types;
17using Microsoft.AspNetCore.Builder;
18using Microsoft.AspNetCore.Hosting;
Constantin Ziesche687f8882020-10-02 16:17:44 +020019using Microsoft.AspNetCore.Http;
Constantin Ziesche220223d2020-12-03 11:27:54 +010020using Microsoft.AspNetCore.Mvc;
Constantin Ziesche687f8882020-10-02 16:17:44 +020021using Microsoft.AspNetCore.Rewrite;
Constantin Zieschefa612082020-04-03 09:54:56 +020022using Microsoft.Extensions.DependencyInjection;
Constantin Ziesche0399d412020-09-24 14:31:15 +020023using Microsoft.Extensions.FileProviders;
24using Microsoft.Extensions.Hosting;
Constantin Zieschefa612082020-04-03 09:54:56 +020025using Microsoft.Extensions.Logging;
Constantin Ziesche220223d2020-12-03 11:27:54 +010026using Newtonsoft.Json;
27using Newtonsoft.Json.Serialization;
Constantin Zieschefa612082020-04-03 09:54:56 +020028using NLog;
29using NLog.Web;
30using System;
Constantin Ziesche687f8882020-10-02 16:17:44 +020031using System.Collections.Generic;
Constantin Zieschefa612082020-04-03 09:54:56 +020032using System.IO;
33using System.Linq;
Constantin Ziesche02817f12020-08-04 21:40:43 +020034using System.Reflection;
Constantin Ziesche687f8882020-10-02 16:17:44 +020035using System.Text.RegularExpressions;
Constantin Zieschefa612082020-04-03 09:54:56 +020036using System.Threading;
37using System.Threading.Tasks;
Constantin Ziesche687f8882020-10-02 16:17:44 +020038using System.Web;
Constantin Ziesche02817f12020-08-04 21:40:43 +020039using static BaSyx.Utils.Settings.Types.ServerSettings;
Constantin Zieschefa612082020-04-03 09:54:56 +020040
41namespace BaSyx.Components.Common
42{
Constantin Zieschece276602020-10-27 09:36:00 +010043 public abstract class ServerApplication : IServerApplication
Constantin Zieschefa612082020-04-03 09:54:56 +020044 {
Constantin Ziesche220223d2020-12-03 11:27:54 +010045 private static readonly Logger logger = NLogBuilder.ConfigureNLog("NLog.config").GetCurrentClassLogger();
Constantin Zieschefa612082020-04-03 09:54:56 +020046
Constantin Ziesche0399d412020-09-24 14:31:15 +020047 private string _contentRoot;
48 private string _webRoot;
Constantin Ziesche687f8882020-10-02 16:17:44 +020049 private bool _secure = false;
50
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +020051 private readonly List<Action<IApplicationBuilder>> AppBuilderPipeline;
52 private readonly List<Action<IServiceCollection>> ServiceBuilderPipeline;
Constantin Ziesche0399d412020-09-24 14:31:15 +020053
54 public const string DEFAULT_CONTENT_ROOT = "Content";
55 public const string DEFAULT_WEB_ROOT = "wwwroot";
Constantin Ziesche687f8882020-10-02 16:17:44 +020056 public const string UI_RELATIVE_PATH = "/ui";
Constantin Ziescheb10014d2021-01-24 11:57:29 +010057 public const string FILES_PATH = "/files";
Constantin Ziesche220223d2020-12-03 11:27:54 +010058 public const string ERROR_PATH = "/error";
Constantin Ziesche687f8882020-10-02 16:17:44 +020059 public const string CONTROLLER_ASSEMBLY_NAME = "BaSyx.API.Http.Controllers";
Constantin Ziesche0399d412020-09-24 14:31:15 +020060
Constantin Ziesche687f8882020-10-02 16:17:44 +020061 public Assembly ControllerAssembly { get; private set; }
Constantin Zieschefa612082020-04-03 09:54:56 +020062 public ServerSettings Settings { get; protected set; }
63 public IWebHostBuilder WebHostBuilder { get; protected set; }
Constantin Ziesche687f8882020-10-02 16:17:44 +020064
Constantin Ziesche0399d412020-09-24 14:31:15 +020065 public string ExecutionPath { get; }
Constantin Zieschefa612082020-04-03 09:54:56 +020066
67 public Action ApplicationStarted { get; set; }
68
69 public Action ApplicationStopping { get; set; }
70
71 public Action ApplicationStopped { get; set; }
72
Constantin Ziesche687f8882020-10-02 16:17:44 +020073 protected ServerApplication() : this(null, null)
Constantin Zieschefa612082020-04-03 09:54:56 +020074 { }
Constantin Ziesche687f8882020-10-02 16:17:44 +020075 protected ServerApplication(ServerSettings settings) : this(settings, null)
Constantin Zieschefa612082020-04-03 09:54:56 +020076 { }
Constantin Ziesche687f8882020-10-02 16:17:44 +020077 protected ServerApplication(ServerSettings settings, string[] webHostBuilderArgs)
Constantin Zieschefa612082020-04-03 09:54:56 +020078 {
Constantin Ziesche0399d412020-09-24 14:31:15 +020079 ExecutionPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Constantin Ziesche687f8882020-10-02 16:17:44 +020080 ControllerAssembly = Assembly.Load(CONTROLLER_ASSEMBLY_NAME);
Constantin Ziesche0399d412020-09-24 14:31:15 +020081
Constantin Ziesche687f8882020-10-02 16:17:44 +020082 if (!EmbeddedResource.CheckOrWriteRessourceToFile(typeof(ServerApplication).Assembly, Path.Combine(ExecutionPath, "NLog.config")))
Constantin Ziesche0399d412020-09-24 14:31:15 +020083 logger.Error("NLog.config cannot be loaded or written");
84
Constantin Ziesche687f8882020-10-02 16:17:44 +020085 if (settings == null && !EmbeddedResource.CheckOrWriteRessourceToFile(typeof(ServerApplication).Assembly, Path.Combine(ExecutionPath, "ServerSettings.xml")))
Constantin Ziesche0399d412020-09-24 14:31:15 +020086 logger.Error("ServerSettings.xml cannot be loaded or written");
87
88 Settings = settings ?? ServerSettings.LoadSettingsFromFile("ServerSettings.xml") ?? throw new ArgumentNullException(nameof(settings));
89
Constantin Ziesche687f8882020-10-02 16:17:44 +020090 WebHostBuilder = DefaultWebHostBuilder.CreateWebHostBuilder(webHostBuilderArgs, Settings);
91 AppBuilderPipeline = new List<Action<IApplicationBuilder>>();
92 ServiceBuilderPipeline = new List<Action<IServiceCollection>>();
93
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +020094 WebHostBuilder.ConfigureServices( (context, services) =>
Constantin Ziesche687f8882020-10-02 16:17:44 +020095 {
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +020096 ConfigureServices(context, services);
Constantin Ziesche687f8882020-10-02 16:17:44 +020097 });
98
99 WebHostBuilder.Configure(app =>
100 {
101 Configure(app);
102 });
103
104 WebHostBuilder.UseNLog();
105 ConfigureLogging(logger.GetLogLevel());
106
Constantin Ziesche0399d412020-09-24 14:31:15 +0200107 if (string.IsNullOrEmpty(Settings.ServerConfig.Hosting.ContentPath))
108 _contentRoot = Path.Join(ExecutionPath, DEFAULT_CONTENT_ROOT);
109 else if (Path.IsPathRooted(Settings.ServerConfig.Hosting.ContentPath))
110 _contentRoot = Settings.ServerConfig.Hosting.ContentPath;
111 else
112 _contentRoot = Path.Join(ExecutionPath, Settings.ServerConfig.Hosting.ContentPath);
113
Constantin Ziesche0399d412020-09-24 14:31:15 +0200114 try
115 {
116 if (!Directory.Exists(_contentRoot))
117 Directory.CreateDirectory(_contentRoot);
118 WebHostBuilder.UseContentRoot(_contentRoot);
119 }
120 catch (Exception e)
121 {
122 logger.Error(e, $"ContentRoot path {_contentRoot} cannot be created ");
123 }
124
Constantin Ziesche687f8882020-10-02 16:17:44 +0200125 _webRoot = Path.Join(ExecutionPath, DEFAULT_WEB_ROOT);
Constantin Ziesche0399d412020-09-24 14:31:15 +0200126
127 try
128 {
129 if (!Directory.Exists(_webRoot))
130 Directory.CreateDirectory(_webRoot);
131 WebHostBuilder.UseWebRoot(_webRoot);
Constantin Ziesche687f8882020-10-02 16:17:44 +0200132 logger.Info($"wwwroot-Path: {_webRoot}");
Constantin Ziesche0399d412020-09-24 14:31:15 +0200133 }
134 catch (Exception e)
135 {
136 logger.Error(e, $"WebRoot path {_webRoot} cannot be created ");
Constantin Ziesche687f8882020-10-02 16:17:44 +0200137 }
Constantin Zieschefa612082020-04-03 09:54:56 +0200138 }
139
140 public virtual void Run()
141 {
Constantin Ziesche687f8882020-10-02 16:17:44 +0200142 logger.Info("Starting Server...");
Constantin Zieschefa612082020-04-03 09:54:56 +0200143
Constantin Ziesche0399d412020-09-24 14:31:15 +0200144 WebHostBuilder.Build().Run();
Constantin Zieschefa612082020-04-03 09:54:56 +0200145 }
Constantin Zieschefa612082020-04-03 09:54:56 +0200146 public virtual async Task RunAsync(CancellationToken cancellationToken = default)
147 {
Constantin Ziesche687f8882020-10-02 16:17:44 +0200148 logger.Info("Starting Server asynchronously...");
Constantin Zieschefa612082020-04-03 09:54:56 +0200149
150 await WebHostBuilder.Build().RunAsync(cancellationToken);
151 }
Constantin Zieschefa612082020-04-03 09:54:56 +0200152 public virtual void ConfigureLogging(Microsoft.Extensions.Logging.LogLevel logLevel)
153 {
154 WebHostBuilder.ConfigureLogging(logging =>
Constantin Ziesche0399d412020-09-24 14:31:15 +0200155 {
156 logging.ClearProviders();
157 logging.SetMinimumLevel(logLevel);
158 });
Constantin Zieschefa612082020-04-03 09:54:56 +0200159 }
Constantin Ziesche687f8882020-10-02 16:17:44 +0200160 public virtual void Configure(Action<IApplicationBuilder> app) => AppBuilderPipeline.Add(app);
161 public virtual void ConfigureServices(Action<IServiceCollection> services) => ServiceBuilderPipeline.Add(services);
Constantin Ziesche0399d412020-09-24 14:31:15 +0200162 public virtual void UseContentRoot(string contentRoot)
163 {
164 _contentRoot = contentRoot;
165 WebHostBuilder.UseContentRoot(contentRoot);
166 }
167 public virtual void UseWebRoot(string webRoot)
168 {
169 _webRoot = webRoot;
170 WebHostBuilder.UseWebRoot(webRoot);
171 }
Constantin Zieschefa612082020-04-03 09:54:56 +0200172 public virtual void UseUrls(params string[] urls)
173 {
174 WebHostBuilder.UseUrls(urls);
175 if (Settings?.ServerConfig?.Hosting != null)
176 Settings.ServerConfig.Hosting.Urls = urls?.ToList();
177 }
Constantin Zieschefa612082020-04-03 09:54:56 +0200178 public virtual void ProvideContent(Uri relativeUri, Stream content)
179 {
180 try
181 {
182 using (Stream stream = content)
183 {
184 string fileName = Path.GetFileName(relativeUri.ToString());
Constantin Zieschee837f992020-08-19 12:04:32 +0200185 logger.Info("FileName: " + fileName);
186 string directory = Path.GetDirectoryName(relativeUri.ToString()).TrimStart('\\');
187 logger.Info("Directory: " + directory);
188
Constantin Ziesche0399d412020-09-24 14:31:15 +0200189 string hostingDirectory = Path.Join(_contentRoot, directory);
Constantin Zieschee837f992020-08-19 12:04:32 +0200190
191 logger.Info($"Try creating hosting directory if not existing: {hostingDirectory}");
Constantin Zieschefa612082020-04-03 09:54:56 +0200192 Directory.CreateDirectory(hostingDirectory);
193
Constantin Zieschee837f992020-08-19 12:04:32 +0200194 string filePath = Path.Join(hostingDirectory, fileName);
195 logger.Info($"Try writing file: {filePath}");
Constantin Zieschefa612082020-04-03 09:54:56 +0200196
197 using (FileStream fileStream = File.OpenWrite(filePath))
198 {
199 stream.CopyTo(fileStream);
200 }
201 }
202 }
203 catch (Exception e)
204 {
205 logger.Error(e, $"Error providing content {relativeUri}");
206 }
207 }
Constantin Ziesche02817f12020-08-04 21:40:43 +0200208 public virtual void MapControllers(ControllerConfiguration controllerConfig)
209 {
210 this.ConfigureServices(services =>
211 {
212 if (controllerConfig?.Controllers?.Count > 0)
213 {
214 var mvcBuilder = services.AddMvc();
Constantin Ziesche0399d412020-09-24 14:31:15 +0200215 foreach (var controllerAssemblyString in controllerConfig.Controllers)
Constantin Ziesche02817f12020-08-04 21:40:43 +0200216 {
Constantin Ziesche181770b2020-08-20 20:32:39 +0200217 Assembly controllerAssembly = null;
218 try
219 {
Constantin Ziesche0399d412020-09-24 14:31:15 +0200220 controllerAssembly = Assembly.Load(controllerAssemblyString);
Constantin Ziesche181770b2020-08-20 20:32:39 +0200221 }
222 catch (Exception e)
223 {
Constantin Ziesche0399d412020-09-24 14:31:15 +0200224 logger.Warn(e, $"Assembly {controllerAssemblyString} cannot be loaded - maybe it is not referenced. Try reading from file...");
Constantin Ziesche181770b2020-08-20 20:32:39 +0200225 try
226 {
Constantin Ziesche0399d412020-09-24 14:31:15 +0200227 if (File.Exists(controllerAssemblyString))
228 controllerAssembly = Assembly.LoadFile(controllerAssemblyString);
229 else if (File.Exists(controllerAssemblyString + ".dll"))
230 controllerAssembly = Assembly.LoadFile(controllerAssemblyString + ".dll");
Constantin Ziesche181770b2020-08-20 20:32:39 +0200231 else
Constantin Ziesche0399d412020-09-24 14:31:15 +0200232 controllerAssembly = Assembly.LoadFrom(controllerAssemblyString);
Constantin Ziesche181770b2020-08-20 20:32:39 +0200233 }
234 catch (Exception exp)
235 {
Constantin Ziesche0399d412020-09-24 14:31:15 +0200236 logger.Warn(exp, $"Assembly {controllerAssemblyString} can finally not be loaded");
237 }
Constantin Ziesche181770b2020-08-20 20:32:39 +0200238 }
Constantin Ziesche08215502020-09-21 19:08:32 +0200239 if (controllerAssembly != null)
240 {
Constantin Ziesche181770b2020-08-20 20:32:39 +0200241 mvcBuilder.AddApplicationPart(controllerAssembly);
Constantin Ziesche0399d412020-09-24 14:31:15 +0200242 string controllerAssemblyName = controllerAssembly.GetName().Name;
243 string xmlDocFile = $"{controllerAssemblyName}.xml";
244 string xmlDocFilePath = Path.Combine(ExecutionPath, xmlDocFile);
245
246 if (File.Exists(xmlDocFilePath))
247 continue;
248
249 try
250 {
251 ManifestEmbeddedFileProvider embeddedFileProvider = new ManifestEmbeddedFileProvider(controllerAssembly);
252 IFileInfo fileInfo = embeddedFileProvider.GetFileInfo(xmlDocFile);
253 if (fileInfo == null)
254 {
255 logger.Warn($"{xmlDocFile} of Assembly {controllerAssemblyName} not found");
256 continue;
257 }
258 using (Stream stream = fileInfo.CreateReadStream())
259 {
260 using (FileStream fileStream = File.OpenWrite(xmlDocFilePath))
261 {
262 stream.CopyTo(fileStream);
263 }
264 }
265 logger.Info($"{xmlDocFile} of Assembly {controllerAssemblyName} has been created successfully");
266 }
267 catch (Exception e)
268 {
269 logger.Warn(e, $"{xmlDocFile} of Assembly {controllerAssemblyName} cannot be read");
270 }
Constantin Ziesche08215502020-09-21 19:08:32 +0200271 }
Constantin Ziesche02817f12020-08-04 21:40:43 +0200272 }
273 mvcBuilder.AddControllersAsServices();
274 }
275 });
276 }
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +0200277 protected virtual void ConfigureServices(WebHostBuilderContext context, IServiceCollection services)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200278 {
279 services.AddSingleton(typeof(ServerSettings), Settings);
280 services.AddSingleton<IServerApplicationLifetime>(this);
281
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +0200282
Constantin Ziesche687f8882020-10-02 16:17:44 +0200283 var urls = Settings.ServerConfig.Hosting.Urls;
284 var secureUrl = urls.Find(s => s.StartsWith("https"));
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +0200285 if (!string.IsNullOrEmpty(secureUrl) && !context.HostingEnvironment.IsDevelopment())
Constantin Ziesche687f8882020-10-02 16:17:44 +0200286 {
287 secureUrl = secureUrl.Replace("+", "0.0.0.0");
288 Uri secureUri = new Uri(secureUrl);
289 _secure = true;
290 services.AddHttpsRedirection(opts =>
291 {
292 opts.HttpsPort = secureUri.Port;
293 });
294 }
295
296 services.AddStandardImplementation();
297
298 services.AddCors();
299 services.AddMvc()
300 .AddApplicationPart(ControllerAssembly)
301 .AddControllersAsServices()
302 .AddNewtonsoftJson(options => options.GetDefaultMvcJsonOptions(services));
303
304 services.AddRazorPages(opts =>
305 {
306 logger.Info("Pages-RootDirectory: " + opts.RootDirectory);
307 });
308
309 services.AddDirectoryBrowser();
310
Constantin Ziesche220223d2020-12-03 11:27:54 +0100311 services.PostConfigure<ApiBehaviorOptions>(options =>
312 {
313 options.InvalidModelStateResponseFactory = actionContext =>
314 {
315 ValidationProblemDetails error = actionContext.ModelState
316 .Where(e => e.Value.Errors.Count > 0)
317 .Select(e => new ValidationProblemDetails(actionContext.ModelState)).FirstOrDefault();
318
319 Result result = new Result(false,
320 new Message(
321 MessageType.Error,
322 $"Path '{actionContext.HttpContext.Request.Path.Value}' received invalid or malformed request: {error.Errors.Values}",
323 actionContext.HttpContext.Response.StatusCode.ToString()));
324
325 return new BadRequestObjectResult(result);
326 };
327 });
328
Constantin Ziesche687f8882020-10-02 16:17:44 +0200329 foreach (var serviceBuider in ServiceBuilderPipeline)
330 {
331 serviceBuider.Invoke(services);
332 }
333 }
Constantin Ziesche687f8882020-10-02 16:17:44 +0200334 protected virtual void Configure(IApplicationBuilder app)
335 {
336 var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
337 var applicationLifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
338
Constantin Ziesche220223d2020-12-03 11:27:54 +0100339 if (env.IsProduction())
Constantin Ziesche687f8882020-10-02 16:17:44 +0200340 app.UseHsts();
Constantin Ziesche220223d2020-12-03 11:27:54 +0100341
342 app.UseExceptionHandler(ERROR_PATH);
343
344 app.UseStatusCodePages(async context =>
345 {
346 context.HttpContext.Response.ContentType = "application/json";
347
348 JsonSerializerSettings settings;
349 var options = context.HttpContext.RequestServices.GetService<MvcNewtonsoftJsonOptions>();
350 if (options == null)
351 settings = new DefaultJsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
352 else
353 settings = options.SerializerSettings;
354
355 Result result = new Result(false,
356 new Message(MessageType.Error, "Path: " + context.HttpContext.Request.Path.Value,
357 context.HttpContext.Response.StatusCode.ToString()));
358
359 string resultMessage = JsonConvert.SerializeObject(result, settings);
360
361 await context.HttpContext.Response.WriteAsync(resultMessage);
362 });
Constantin Ziesche687f8882020-10-02 16:17:44 +0200363
Constantin Ziesche09dcb6b2020-10-07 13:47:39 +0200364 if(_secure && !env.IsDevelopment())
Constantin Ziesche687f8882020-10-02 16:17:44 +0200365 app.UseHttpsRedirection();
366
367 app.UseStaticFiles();
368
369 string path = env.ContentRootPath;
370 if (Directory.Exists(path))
371 {
372 app.UseStaticFiles(new StaticFileOptions()
373 {
374 FileProvider = new PhysicalFileProvider(@path),
Constantin Ziescheb10014d2021-01-24 11:57:29 +0100375 RequestPath = new PathString(FILES_PATH),
376 ServeUnknownFileTypes = true
Constantin Ziesche687f8882020-10-02 16:17:44 +0200377 });
378
379 app.UseDirectoryBrowser(new DirectoryBrowserOptions
380 {
381 FileProvider = new PhysicalFileProvider(@path),
Constantin Ziescheb10014d2021-01-24 11:57:29 +0100382 RequestPath = new PathString(FILES_PATH)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200383 });
384 }
385
386 app.Use((context, next) =>
387 {
Constantin Ziesche77977502020-12-04 14:05:52 +0100388 var url = context.GetServerVariable("UNENCODED_URL");
389 if (!string.IsNullOrEmpty(url))
390 context.Request.Path = new PathString(url);
391
392 return next();
393 });
394
395 app.Use((context, next) =>
396 {
Constantin Ziesche687f8882020-10-02 16:17:44 +0200397 string requestPath = context.Request.Path.ToUriComponent();
398
399 if (requestPath.Contains("submodelElements/"))
400 {
401 Match valueMatch = Regex.Match(requestPath, "(?<=submodelElements/)(.*)(?=/value|/invoke|/invocationList)");
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100402 if(valueMatch.Success && !string.IsNullOrEmpty(valueMatch.Value))
Constantin Ziesche687f8882020-10-02 16:17:44 +0200403 {
404 string elementPath = HttpUtility.UrlEncode(valueMatch.Value);
405 requestPath = requestPath.Replace(valueMatch.Value, elementPath);
406 context.Request.Path = new PathString(requestPath);
407 }
408 else
409 {
410 Match baseMatch = Regex.Match(requestPath, "(?<=submodelElements/)(.*)");
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100411 if(baseMatch.Success && !string.IsNullOrEmpty(baseMatch.Value))
Constantin Ziesche687f8882020-10-02 16:17:44 +0200412 {
413 string elementPath = HttpUtility.UrlEncode(baseMatch.Value);
414 requestPath = requestPath.Replace(baseMatch.Value, elementPath);
415 context.Request.Path = new PathString(requestPath);
416 }
417 }
418 }
419 return next();
420 });
421
422 app.UseRouting();
423
424 app.UseCors(
425 options => options
426 .AllowAnyHeader()
427 .AllowAnyMethod()
428 .AllowAnyOrigin()
429 );
430 app.UseAuthorization();
431
432 app.UseEndpoints(endpoints =>
433 {
434 endpoints.MapRazorPages();
435 endpoints.MapControllers();
436 });
437
438 var options = new RewriteOptions().AddRedirect("^$", UI_RELATIVE_PATH);
439 app.UseRewriter(options);
440
441 if (ApplicationStarted != null)
442 applicationLifetime.ApplicationStarted.Register(ApplicationStarted);
443 if (ApplicationStopping != null)
444 applicationLifetime.ApplicationStopping.Register(ApplicationStopping);
445 if (ApplicationStopped != null)
446 applicationLifetime.ApplicationStopped.Register(ApplicationStopped);
447
448 foreach (var appBuilder in AppBuilderPipeline)
449 {
450 appBuilder.Invoke(app);
451 }
452 }
Constantin Zieschefa612082020-04-03 09:54:56 +0200453 }
454}