Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 1 | /******************************************************************************* |
| 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 | *******************************************************************************/ |
| 11 | using BaSyx.API.Components; |
| 12 | using BaSyx.API.Http.Controllers; |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 13 | using BaSyx.Components.Common; |
| 14 | using BaSyx.Utils.DependencyInjection; |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 15 | using BaSyx.Utils.Settings; |
| 16 | using BaSyx.Utils.Settings.Types; |
| 17 | using Microsoft.AspNetCore.Builder; |
| 18 | using Microsoft.AspNetCore.Hosting; |
| 19 | using Microsoft.AspNetCore.Http; |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 20 | using Microsoft.AspNetCore.Rewrite; |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 21 | using Microsoft.Extensions.Configuration; |
| 22 | using Microsoft.Extensions.DependencyInjection; |
| 23 | using Microsoft.Extensions.FileProviders; |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 24 | using Microsoft.Extensions.Hosting; |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 25 | using Microsoft.Extensions.Logging; |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 26 | using Microsoft.OpenApi.Models; |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 27 | using NLog; |
| 28 | using NLog.Web; |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 29 | using System; |
| 30 | using System.Diagnostics; |
| 31 | using System.IO; |
| 32 | using System.Reflection; |
| 33 | |
| 34 | namespace BaSyx.AAS.Server.Http |
| 35 | { |
| 36 | public class MultiStartup |
| 37 | { |
| 38 | private static readonly Logger logger = NLogBuilder.ConfigureNLog("NLog.config").GetCurrentClassLogger(); |
| 39 | private const string ControllerAssemblyName = "BaSyx.API.Http.Controllers"; |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 40 | |
| 41 | private const string UI_RELATIVE_PATH = "/multiui"; |
| 42 | |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 43 | public IConfiguration Configuration { get; } |
| 44 | public IServerApplicationLifetime ServerApplicationLifetime { get; } |
| 45 | public static ServerSettings ServerSettings { get; set; } |
| 46 | |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 47 | private string submodelId = string.Empty; |
| 48 | private string aasId = string.Empty; |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 49 | |
| 50 | public MultiStartup(IConfiguration configuration, ServerSettings serverSettings, IServerApplicationLifetime serverApplicationLifetime) |
| 51 | { |
| 52 | Configuration = configuration; |
| 53 | ServerSettings = serverSettings; |
| 54 | ServerApplicationLifetime = serverApplicationLifetime; |
| 55 | } |
| 56 | |
| 57 | |
| 58 | // This method gets called by the runtime. Use this method to add services to the container. |
| 59 | public void ConfigureServices(IServiceCollection services) |
| 60 | { |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 61 | services.AddStandardImplementation(); |
| 62 | |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 63 | Assembly controllerAssembly = Assembly.Load(ControllerAssemblyName); |
| 64 | services.AddCors(); |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 65 | services.AddMvc() |
| 66 | .AddApplicationPart(controllerAssembly) |
| 67 | .AddControllersAsServices() |
| 68 | .AddNewtonsoftJson(options => options.GetDefaultMvcJsonOptions(services)); |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 69 | services.AddRazorPages(options => options.Conventions.AddPageRoute("/MultiIndex", "/multiui")); |
Constantin Ziesche | 635c2e3 | 2020-02-27 18:11:07 +0100 | [diff] [blame] | 70 | |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 71 | //Check whether Asset Administration Shell Service Provider exists and bind it to the AssetAdministrationShell-Services-Controller |
Constantin Ziesche | 7ab66d1 | 2020-07-15 15:01:16 +0200 | [diff] [blame] | 72 | services.AddTransient<IAssetAdministrationShellServiceProvider>(ctx => |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 73 | { |
| 74 | IAssetAdministrationShellServiceProvider aasServiceProvider = ctx |
Constantin Ziesche | 8b4a64d | 2020-06-25 11:52:09 +0200 | [diff] [blame] | 75 | .GetRequiredService<IAssetAdministrationShellRepositoryServiceProvider>() |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 76 | .GetAssetAdministrationShellServiceProvider(aasId); |
| 77 | |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 78 | return aasServiceProvider;//new AssetAdministrationShellServices(aasServiceProvider); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 79 | }); |
| 80 | |
| 81 | |
| 82 | //Check whether Submodel Service Provider exists and bind it to the Submodel-Services-Controller |
Constantin Ziesche | 7ab66d1 | 2020-07-15 15:01:16 +0200 | [diff] [blame] | 83 | services.AddTransient<ISubmodelServiceProvider>(ctx => |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 84 | { |
| 85 | IAssetAdministrationShellServiceProvider aasServiceProvider = ctx |
Constantin Ziesche | 8b4a64d | 2020-06-25 11:52:09 +0200 | [diff] [blame] | 86 | .GetRequiredService<IAssetAdministrationShellRepositoryServiceProvider>() |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 87 | .GetAssetAdministrationShellServiceProvider(aasId); |
| 88 | |
| 89 | var submodelServiceProvider = aasServiceProvider.SubmodelRegistry.GetSubmodelServiceProvider(submodelId); |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 90 | if (!submodelServiceProvider.Success || submodelServiceProvider.Entity == null) |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 91 | { |
| 92 | SubmodelServiceProvider cssp = new SubmodelServiceProvider(); |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 93 | return cssp;//new SubmodelServices(cssp); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 94 | } |
| 95 | else |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 96 | return submodelServiceProvider.Entity;//new SubmodelServices(submodelServiceProvider.Entity); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 97 | }); |
| 98 | |
| 99 | // Register the Swagger generator, defining one or more Swagger documents |
| 100 | services.AddSwaggerGen(c => |
| 101 | { |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 102 | c.SwaggerDoc("v1", new OpenApiInfo |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 103 | { |
| 104 | Version = "v1", |
Constantin Ziesche | 8b4a64d | 2020-06-25 11:52:09 +0200 | [diff] [blame] | 105 | Title = "BaSyx Asset Administration Shell Repository HTTP REST-API", |
| 106 | Description = "The full description of the generic BaSyx Asset Administration Shell Repository HTTP REST-API", |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 107 | Contact = new OpenApiContact { Name = "Constantin Ziesche", Email = "constantin.ziesche@bosch.com", Url = new Uri("https://www.bosch.com/de/") }, |
| 108 | License = new OpenApiLicense { Name = "EPL-2.0", Url = new Uri("https://www.eclipse.org/legal/epl-2.0/") } |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 109 | }); |
| 110 | |
| 111 | // Set the comments path for the Swagger JSON and UI. |
| 112 | var xmlFile = $"{controllerAssembly.GetName().Name}.xml"; |
| 113 | var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); |
| 114 | if (ResourceChecker.CheckResourceAvailability(controllerAssembly, ControllerAssemblyName, xmlFile, true)) |
| 115 | c.IncludeXmlComments(xmlPath); |
| 116 | }); |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 117 | services.AddSwaggerGenNewtonsoftSupport(); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 121 | public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider, IWebHostEnvironment env, ILoggerFactory loggerFactory, IHostApplicationLifetime applicationLifetime) |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 122 | { |
| 123 | if (env.IsDevelopment() || Debugger.IsAttached) |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 124 | { |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 125 | app.UseDeveloperExceptionPage(); |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 126 | } |
| 127 | else |
| 128 | { |
| 129 | app.UseExceptionHandler("/error"); |
| 130 | //app.UseHsts(); |
| 131 | } |
| 132 | //app.UseHttpsRedirection(); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 133 | app.UseStaticFiles(); //necessary for the wwwroot folder |
| 134 | |
| 135 | string path = Path.Combine(env.ContentRootPath, ServerSettings.ServerConfig.Hosting.ContentPath); |
| 136 | if (Directory.Exists(path)) |
| 137 | { |
| 138 | app.UseStaticFiles(new StaticFileOptions() |
| 139 | { |
| 140 | FileProvider = new PhysicalFileProvider(@path), |
| 141 | RequestPath = new PathString("") |
| 142 | }); |
| 143 | |
| 144 | app.UseDirectoryBrowser(new DirectoryBrowserOptions |
| 145 | { |
| 146 | FileProvider = new PhysicalFileProvider(@path), |
| 147 | RequestPath = new PathString("/browse") |
| 148 | }); |
| 149 | } |
| 150 | |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 151 | app.Use((context, next) => |
| 152 | { |
| 153 | string[] pathElements = context.Request.Path.ToUriComponent()?.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 154 | if (pathElements.Length >= 2) |
| 155 | { |
| 156 | aasId = pathElements[1]; |
| 157 | if (pathElements.Length == 2) |
| 158 | { |
| 159 | context.Request.Path = new PathString("/shells/" + aasId); |
| 160 | } |
| 161 | else if (pathElements.Length == 3 && pathElements[2] == "aas") |
| 162 | { |
| 163 | context.Request.Path = new PathString("/aas"); |
| 164 | } |
| 165 | else if (pathElements.Length == 4 && pathElements[3] == "submodels") |
| 166 | { |
| 167 | context.Request.Path = new PathString("/aas/submodels"); |
| 168 | } |
| 169 | else if (pathElements.Length == 5) |
| 170 | { |
| 171 | submodelId = pathElements[4]; |
| 172 | context.Request.Path = new PathString("/aas/submodels/" + submodelId); |
| 173 | } |
| 174 | else if (pathElements.Length > 5) |
| 175 | { |
| 176 | submodelId = pathElements[4]; |
| 177 | string[] restOfPathArray = new string[pathElements.Length - 5]; |
| 178 | Array.Copy(pathElements, 5, restOfPathArray, 0, pathElements.Length - 5); |
| 179 | string restOfPath = string.Join("/", restOfPathArray); |
| 180 | context.Request.Path = new PathString("/" + restOfPath); |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 181 | } |
| 182 | } |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 183 | return next(); |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 184 | }); |
| 185 | |
| 186 | app.UseRouting(); |
| 187 | |
| 188 | app.UseCors( |
| 189 | options => options |
| 190 | .AllowAnyHeader() |
| 191 | .AllowAnyMethod() |
| 192 | .AllowAnyOrigin() |
| 193 | ); |
| 194 | |
| 195 | app.UseEndpoints(endpoints => |
| 196 | { |
| 197 | endpoints.MapRazorPages(); |
| 198 | endpoints.MapControllers(); |
| 199 | }); |
| 200 | |
Constantin Ziesche | e837f99 | 2020-08-19 12:04:32 +0200 | [diff] [blame] | 201 | var options = new RewriteOptions().AddRedirect("^$", UI_RELATIVE_PATH); |
| 202 | app.UseRewriter(options); |
| 203 | |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 204 | if (ServerApplicationLifetime.ApplicationStarted != null) |
| 205 | applicationLifetime.ApplicationStarted.Register(ServerApplicationLifetime.ApplicationStarted); |
| 206 | if (ServerApplicationLifetime.ApplicationStopping != null) |
| 207 | applicationLifetime.ApplicationStopping.Register(ServerApplicationLifetime.ApplicationStopping); |
| 208 | if (ServerApplicationLifetime.ApplicationStopped != null) |
| 209 | applicationLifetime.ApplicationStopped.Register(ServerApplicationLifetime.ApplicationStopped); |
| 210 | |
| 211 | // Enable middleware to serve generated Swagger as a JSON endpoint. |
| 212 | app.UseSwagger(); |
| 213 | |
| 214 | // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint. |
| 215 | app.UseSwaggerUI(c => |
| 216 | { |
Constantin Ziesche | 8b4a64d | 2020-06-25 11:52:09 +0200 | [diff] [blame] | 217 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "BaSyx Asset Administration Shell Repository HTTP REST-API"); |
Constantin Ziesche | fa61208 | 2020-04-03 09:54:56 +0200 | [diff] [blame] | 218 | }); |
Constantin Ziesche | 857c7ab | 2020-02-25 11:24:51 +0100 | [diff] [blame] | 219 | } |
| 220 | } |
| 221 | } |