25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Startup.cs 7.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using Microsoft.AspNetCore.Authentication;
  6. using Microsoft.AspNetCore.Builder;
  7. using Microsoft.AspNetCore.Hosting;
  8. using Microsoft.AspNetCore.Mvc;
  9. using Microsoft.Extensions.Configuration;
  10. using Microsoft.Extensions.DependencyInjection;
  11. using Microsoft.Net.Http.Headers;
  12. using Microsoft.OpenApi.Models;
  13. using Microsoft.Scripting.Utils;
  14. using MQTTnet.Server.Configuration;
  15. using MQTTnet.Server.Logging;
  16. using MQTTnet.Server.Mqtt;
  17. using MQTTnet.Server.Scripting;
  18. using MQTTnet.Server.Scripting.DataSharing;
  19. using Swashbuckle.AspNetCore.SwaggerUI;
  20. namespace MQTTnet.Server.Web
  21. {
  22. public class Startup
  23. {
  24. public Startup(IConfiguration configuration)
  25. {
  26. var builder = new ConfigurationBuilder()
  27. .AddJsonFile("appsettings.json")
  28. .AddEnvironmentVariables();
  29. Configuration = builder.Build();
  30. }
  31. public IConfigurationRoot Configuration { get; }
  32. public void Configure(
  33. IApplicationBuilder application,
  34. IHostingEnvironment environment,
  35. MqttServerService mqttServerService,
  36. PythonScriptHostService pythonScriptHostService,
  37. DataSharingService dataSharingService,
  38. MqttSettingsModel mqttSettings)
  39. {
  40. if (environment.IsDevelopment())
  41. {
  42. application.UseDeveloperExceptionPage();
  43. }
  44. else
  45. {
  46. application.UseHsts();
  47. }
  48. application.UseCors(x => x
  49. .AllowAnyOrigin()
  50. .AllowAnyMethod()
  51. .AllowAnyHeader()
  52. .AllowCredentials());
  53. application.UseAuthentication();
  54. application.UseStaticFiles();
  55. application.UseHttpsRedirection();
  56. application.UseMvc();
  57. ConfigureWebSocketEndpoint(application, mqttServerService, mqttSettings);
  58. dataSharingService.Configure();
  59. pythonScriptHostService.Configure();
  60. mqttServerService.Configure();
  61. application.UseSwagger(o => o.RouteTemplate = "/api/{documentName}/swagger.json");
  62. application.UseSwaggerUI(o =>
  63. {
  64. o.RoutePrefix = "api";
  65. o.DocumentTitle = "MQTTnet.Server API";
  66. o.SwaggerEndpoint("/api/v1/swagger.json", "MQTTnet.Server API v1");
  67. o.DisplayRequestDuration();
  68. o.DocExpansion(DocExpansion.List);
  69. o.DefaultModelRendering(ModelRendering.Model);
  70. });
  71. }
  72. public void ConfigureServices(IServiceCollection services)
  73. {
  74. services.AddCors();
  75. services.AddMvc()
  76. .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
  77. .AddJsonOptions(options =>
  78. {
  79. options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
  80. });
  81. ReadMqttSettings(services);
  82. services.AddSingleton<PythonIOStream>();
  83. services.AddSingleton<PythonScriptHostService>();
  84. services.AddSingleton<DataSharingService>();
  85. services.AddSingleton<MqttNetLoggerWrapper>();
  86. services.AddSingleton<CustomMqttFactory>();
  87. services.AddSingleton<MqttServerService>();
  88. services.AddSingleton<MqttServerStorage>();
  89. services.AddSingleton<MqttClientConnectedHandler>();
  90. services.AddSingleton<MqttClientDisconnectedHandler>();
  91. services.AddSingleton<MqttClientSubscribedTopicHandler>();
  92. services.AddSingleton<MqttClientUnsubscribedTopicHandler>();
  93. services.AddSingleton<MqttServerConnectionValidator>();
  94. services.AddSingleton<MqttSubscriptionInterceptor>();
  95. services.AddSingleton<MqttApplicationMessageInterceptor>();
  96. services.AddSwaggerGen(c =>
  97. {
  98. c.DescribeAllEnumsAsStrings();
  99. var securityScheme = new OpenApiSecurityScheme
  100. {
  101. Scheme = "Basic",
  102. Name = HeaderNames.Authorization,
  103. Type = SecuritySchemeType.Http,
  104. In = ParameterLocation.Header
  105. };
  106. c.AddSecurityDefinition("Swagger", securityScheme);
  107. c.AddSecurityRequirement(new OpenApiSecurityRequirement
  108. {
  109. [securityScheme] = new List<string>()
  110. });
  111. c.SwaggerDoc("v1", new OpenApiInfo
  112. {
  113. Title = "MQTTnet.Server API",
  114. Version = "v1",
  115. Description = "The public API for the MQTT broker MQTTnet.Server.",
  116. License = new OpenApiLicense
  117. {
  118. Name = "MIT",
  119. Url = new Uri("https://github.com/chkr1011/MQTTnet/blob/master/README.md")
  120. },
  121. Contact = new OpenApiContact
  122. {
  123. Name = "MQTTnet.Server",
  124. Email = string.Empty,
  125. Url = new Uri("https://github.com/chkr1011/MQTTnet")
  126. },
  127. });
  128. });
  129. services.AddAuthentication("Basic")
  130. .AddScheme<AuthenticationSchemeOptions, AuthenticationHandler>("Basic", null)
  131. .AddCookie();
  132. }
  133. private void ReadMqttSettings(IServiceCollection services)
  134. {
  135. var mqttSettings = new MqttSettingsModel();
  136. Configuration.Bind("MQTT", mqttSettings);
  137. services.AddSingleton(mqttSettings);
  138. var scriptingSettings = new ScriptingSettingsModel();
  139. Configuration.Bind("Scripting", scriptingSettings);
  140. services.AddSingleton(scriptingSettings);
  141. }
  142. private static void ConfigureWebSocketEndpoint(
  143. IApplicationBuilder application,
  144. MqttServerService mqttServerService,
  145. MqttSettingsModel mqttSettings)
  146. {
  147. if (mqttSettings?.WebSocketEndPoint?.Enabled != true)
  148. {
  149. return;
  150. }
  151. if (string.IsNullOrEmpty(mqttSettings.WebSocketEndPoint.Path))
  152. {
  153. return;
  154. }
  155. var webSocketOptions = new WebSocketOptions
  156. {
  157. KeepAliveInterval = TimeSpan.FromSeconds(mqttSettings.WebSocketEndPoint.KeepAliveInterval),
  158. ReceiveBufferSize = mqttSettings.WebSocketEndPoint.ReceiveBufferSize
  159. };
  160. if (mqttSettings.WebSocketEndPoint.AllowedOrigins?.Any() == true)
  161. {
  162. webSocketOptions.AllowedOrigins.AddRange(mqttSettings.WebSocketEndPoint.AllowedOrigins);
  163. }
  164. application.UseWebSockets(webSocketOptions);
  165. application.Use(async (context, next) =>
  166. {
  167. if (context.Request.Path == mqttSettings.WebSocketEndPoint.Path)
  168. {
  169. if (context.WebSockets.IsWebSocketRequest)
  170. {
  171. using (var webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false))
  172. {
  173. await mqttServerService.RunWebSocketConnectionAsync(webSocket, context).ConfigureAwait(false);
  174. }
  175. }
  176. else
  177. {
  178. context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
  179. }
  180. }
  181. else
  182. {
  183. await next().ConfigureAwait(false);
  184. }
  185. });
  186. }
  187. }
  188. }