blob: f0bdba6e777172d93ec9848e68cdcb15b5057cf5 [file] [log] [blame]
Constantin Ziesche857c7ab2020-02-25 11:24:51 +01001/*******************************************************************************
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*******************************************************************************/
11using BaSyx.API.Components;
12using BaSyx.API.Http.Controllers;
Constantin Zieschefa612082020-04-03 09:54:56 +020013using BaSyx.Components.Common;
14using BaSyx.Utils.DependencyInjection;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010015using BaSyx.Utils.Settings;
16using BaSyx.Utils.Settings.Types;
17using Microsoft.AspNetCore.Builder;
18using Microsoft.AspNetCore.Hosting;
19using Microsoft.AspNetCore.Http;
Constantin Zieschee837f992020-08-19 12:04:32 +020020using Microsoft.AspNetCore.Rewrite;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010021using Microsoft.Extensions.Configuration;
22using Microsoft.Extensions.DependencyInjection;
23using Microsoft.Extensions.FileProviders;
Constantin Zieschefa612082020-04-03 09:54:56 +020024using Microsoft.Extensions.Hosting;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010025using Microsoft.Extensions.Logging;
Constantin Zieschefa612082020-04-03 09:54:56 +020026using Microsoft.OpenApi.Models;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010027using NLog;
28using NLog.Web;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010029using System;
30using System.Diagnostics;
31using System.IO;
32using System.Reflection;
33
34namespace 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 Zieschee837f992020-08-19 12:04:32 +020040
41 private const string UI_RELATIVE_PATH = "/multiui";
42
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010043 public IConfiguration Configuration { get; }
44 public IServerApplicationLifetime ServerApplicationLifetime { get; }
45 public static ServerSettings ServerSettings { get; set; }
46
Constantin Zieschefa612082020-04-03 09:54:56 +020047 private string submodelId = string.Empty;
48 private string aasId = string.Empty;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010049
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 Zieschefa612082020-04-03 09:54:56 +020061 services.AddStandardImplementation();
62
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010063 Assembly controllerAssembly = Assembly.Load(ControllerAssemblyName);
64 services.AddCors();
Constantin Zieschefa612082020-04-03 09:54:56 +020065 services.AddMvc()
66 .AddApplicationPart(controllerAssembly)
67 .AddControllersAsServices()
68 .AddNewtonsoftJson(options => options.GetDefaultMvcJsonOptions(services));
Constantin Zieschee837f992020-08-19 12:04:32 +020069 services.AddRazorPages(options => options.Conventions.AddPageRoute("/MultiIndex", "/multiui"));
Constantin Ziesche635c2e32020-02-27 18:11:07 +010070
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010071 //Check whether Asset Administration Shell Service Provider exists and bind it to the AssetAdministrationShell-Services-Controller
Constantin Ziesche7ab66d12020-07-15 15:01:16 +020072 services.AddTransient<IAssetAdministrationShellServiceProvider>(ctx =>
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010073 {
74 IAssetAdministrationShellServiceProvider aasServiceProvider = ctx
Constantin Ziesche8b4a64d2020-06-25 11:52:09 +020075 .GetRequiredService<IAssetAdministrationShellRepositoryServiceProvider>()
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010076 .GetAssetAdministrationShellServiceProvider(aasId);
77
Constantin Zieschee837f992020-08-19 12:04:32 +020078 return aasServiceProvider;//new AssetAdministrationShellServices(aasServiceProvider);
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010079 });
80
81
82 //Check whether Submodel Service Provider exists and bind it to the Submodel-Services-Controller
Constantin Ziesche7ab66d12020-07-15 15:01:16 +020083 services.AddTransient<ISubmodelServiceProvider>(ctx =>
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010084 {
85 IAssetAdministrationShellServiceProvider aasServiceProvider = ctx
Constantin Ziesche8b4a64d2020-06-25 11:52:09 +020086 .GetRequiredService<IAssetAdministrationShellRepositoryServiceProvider>()
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010087 .GetAssetAdministrationShellServiceProvider(aasId);
88
89 var submodelServiceProvider = aasServiceProvider.SubmodelRegistry.GetSubmodelServiceProvider(submodelId);
Constantin Zieschee837f992020-08-19 12:04:32 +020090 if (!submodelServiceProvider.Success || submodelServiceProvider.Entity == null)
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010091 {
92 SubmodelServiceProvider cssp = new SubmodelServiceProvider();
Constantin Zieschee837f992020-08-19 12:04:32 +020093 return cssp;//new SubmodelServices(cssp);
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010094 }
95 else
Constantin Zieschee837f992020-08-19 12:04:32 +020096 return submodelServiceProvider.Entity;//new SubmodelServices(submodelServiceProvider.Entity);
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010097 });
98
99 // Register the Swagger generator, defining one or more Swagger documents
100 services.AddSwaggerGen(c =>
101 {
Constantin Zieschefa612082020-04-03 09:54:56 +0200102 c.SwaggerDoc("v1", new OpenApiInfo
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100103 {
104 Version = "v1",
Constantin Ziesche8b4a64d2020-06-25 11:52:09 +0200105 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 Zieschefa612082020-04-03 09:54:56 +0200107 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 Ziesche857c7ab2020-02-25 11:24:51 +0100109 });
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 Zieschefa612082020-04-03 09:54:56 +0200117 services.AddSwaggerGenNewtonsoftSupport();
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100118 }
119
120 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Constantin Zieschefa612082020-04-03 09:54:56 +0200121 public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider, IWebHostEnvironment env, ILoggerFactory loggerFactory, IHostApplicationLifetime applicationLifetime)
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100122 {
123 if (env.IsDevelopment() || Debugger.IsAttached)
Constantin Zieschefa612082020-04-03 09:54:56 +0200124 {
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100125 app.UseDeveloperExceptionPage();
Constantin Zieschefa612082020-04-03 09:54:56 +0200126 }
127 else
128 {
129 app.UseExceptionHandler("/error");
130 //app.UseHsts();
131 }
132 //app.UseHttpsRedirection();
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100133 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 Ziesche857c7ab2020-02-25 11:24:51 +0100151 app.Use((context, next) =>
152 {
153 string[] pathElements = context.Request.Path.ToUriComponent()?.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100154 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 Zieschefa612082020-04-03 09:54:56 +0200181 }
182 }
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100183 return next();
Constantin Zieschefa612082020-04-03 09:54:56 +0200184 });
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 Zieschee837f992020-08-19 12:04:32 +0200201 var options = new RewriteOptions().AddRedirect("^$", UI_RELATIVE_PATH);
202 app.UseRewriter(options);
203
Constantin Zieschefa612082020-04-03 09:54:56 +0200204 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 Ziesche8b4a64d2020-06-25 11:52:09 +0200217 c.SwaggerEndpoint("/swagger/v1/swagger.json", "BaSyx Asset Administration Shell Repository HTTP REST-API");
Constantin Zieschefa612082020-04-03 09:54:56 +0200218 });
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100219 }
220 }
221}