From af9102188cb8924e30bcbbf74b83a8c4a94dc8cf Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 17:14:01 +0300 Subject: [PATCH 01/12] Improve Ocelot logger --- .../Middleware/AuthenticationMiddleware.cs | 2 +- .../Middleware/AuthorizationMiddleware.cs | 2 +- src/Ocelot/Configuration/DownstreamRoute.cs | 2 +- .../ConfigurationBuilderExtensions.cs | 14 ++++++++++ .../DownstreamRouteFinderMiddleware.cs | 4 +-- .../DownstreamUrlCreatorMiddleware.cs | 2 +- .../Middleware/ExceptionHandlerMiddleware.cs | 28 +++++++++++-------- .../Extensions/StringExtensions.cs | 3 ++ src/Ocelot/Logging/OcelotLogger.cs | 19 +++++++------ .../Middleware/RateLimitingMiddleware.cs | 2 +- .../Middleware/HttpRequesterMiddleware.cs | 4 +-- .../Middleware/ResponderMiddleware.cs | 2 +- 12 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs index a79008bab..bf8d6de9c 100644 --- a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs +++ b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs @@ -25,7 +25,7 @@ public async Task Invoke(HttpContext httpContext) // reducing nesting, returning early when no authentication is needed. if (request.Method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase) || !downstreamRoute.IsAuthenticated) { - Logger.LogInformation($"No authentication needed for path '{path}'."); + Logger.LogInformation($"No authentication needed for path: {path}"); await _next(httpContext); return; } diff --git a/src/Ocelot/Authorization/Middleware/AuthorizationMiddleware.cs b/src/Ocelot/Authorization/Middleware/AuthorizationMiddleware.cs index e795f6dca..9775d2c4a 100644 --- a/src/Ocelot/Authorization/Middleware/AuthorizationMiddleware.cs +++ b/src/Ocelot/Authorization/Middleware/AuthorizationMiddleware.cs @@ -82,7 +82,7 @@ public async Task Invoke(HttpContext httpContext) } else { - Logger.LogInformation(() => $"{downstreamRoute.DownstreamPathTemplate.Value} route does not require user to be authorized"); + Logger.LogInformation(() => $"Route to '{downstreamRoute.DownstreamPathTemplate.Value}' does not require user to be authorized"); await _next.Invoke(httpContext); } } diff --git a/src/Ocelot/Configuration/DownstreamRoute.cs b/src/Ocelot/Configuration/DownstreamRoute.cs index f1f8bc0c1..edd20baad 100644 --- a/src/Ocelot/Configuration/DownstreamRoute.cs +++ b/src/Ocelot/Configuration/DownstreamRoute.cs @@ -91,7 +91,7 @@ public DownstreamRoute( public string ServiceName { get; } public string ServiceNamespace { get; } public HttpHandlerOptions HttpHandlerOptions { get; } - public bool EnableEndpointEndpointRateLimiting { get; } + public bool EnableEndpointEndpointRateLimiting { get; } // TODO Naming mistyping public QoSOptions QosOptions { get; } public string DownstreamScheme { get; } public string RequestIdKey { get; } diff --git a/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs b/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs index f07baba1a..f78c4059b 100644 --- a/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs +++ b/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs @@ -204,4 +204,18 @@ private static IConfigurationBuilder AddOcelotJsonFile(IConfigurationBuilder bui File.WriteAllText(primary, json); return builder?.AddJsonFile(primary, optional ?? false, reloadOnChange ?? false); } + + /// + /// Adds Ocelot primary configuration file (aka ocelot.json) in read-only mode. + /// Adds the file as a JSON configuration provider via the extension. + /// + /// Use optional arguments for injections and overridings. + /// The builder to extend. + /// Primary config file path. + /// The 2nd argument of the AddJsonFile. + /// The 3rd argument of the AddJsonFile. + /// An object. + public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, + string primaryFile = null, bool? optional = null, bool? reloadOnChange = null) // optional injections + => builder.AddJsonFile(primaryFile ?? PrimaryConfigFile, optional ?? false, reloadOnChange ?? false); } diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index 25278c0b3..232a886ba 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -33,7 +33,7 @@ public async Task Invoke(HttpContext httpContext) var upstreamHeaders = httpContext.Request.Headers .ToDictionary(h => h.Key, h => string.Join(';', (IList)h.Value)); - Logger.LogDebug(() => $"Upstream URL path is '{upstreamUrlPath}'."); + Logger.LogDebug(() => $"Upstream URL path: {upstreamUrlPath}"); var provider = _factory.Get(internalConfiguration); var response = provider.Get(upstreamUrlPath, upstreamQueryString, httpContext.Request.Method, internalConfiguration, upstreamHost, upstreamHeaders); @@ -44,7 +44,7 @@ public async Task Invoke(HttpContext httpContext) return; } - Logger.LogDebug(() => $"downstream templates are {string.Join(", ", response.Data.Route.DownstreamRoute.Select(r => r.DownstreamPathTemplate.Value))}"); + Logger.LogDebug(() => $"Downstream templates: {string.Join(", ", response.Data.Route.DownstreamRoute.Select(r => r.DownstreamPathTemplate.Value))}"); // why set both of these on HttpContext httpContext.Items.UpsertTemplatePlaceholderNameAndValues(response.Data.TemplatePlaceholderNameAndValues); diff --git a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs index 428e764d3..e27ffd978 100644 --- a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -89,7 +89,7 @@ public async Task Invoke(HttpContext httpContext) } } - Logger.LogDebug(() => $"Downstream url is {downstreamRequest}"); + Logger.LogDebug(() => $"Downstream URL: {downstreamRequest}"); await _next.Invoke(httpContext); } diff --git a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs index c1e0b59b7..7c9a6b835 100644 --- a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs +++ b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Http; using Ocelot.Configuration; +using Ocelot.Infrastructure.Extensions; using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; using Ocelot.Middleware; @@ -33,13 +34,13 @@ public async Task Invoke(HttpContext httpContext) TrySetGlobalRequestId(httpContext, internalConfiguration); - Logger.LogDebug("ocelot pipeline started"); + Logger.LogDebug("Ocelot pipeline started"); await _next.Invoke(httpContext); } catch (OperationCanceledException) when (httpContext.RequestAborted.IsCancellationRequested) { - Logger.LogDebug("operation canceled"); + Logger.LogDebug("Operation canceled"); if (!httpContext.Response.HasStarted) { httpContext.Response.StatusCode = 499; @@ -47,13 +48,13 @@ public async Task Invoke(HttpContext httpContext) } catch (Exception e) { - Logger.LogDebug("error calling middleware"); + Logger.LogDebug("Error calling middleware"); Logger.LogError(() => CreateMessage(httpContext, e), e); SetInternalServerErrorOnResponse(httpContext); } - Logger.LogDebug("ocelot pipeline finished"); + Logger.LogDebug("Ocelot pipeline finished"); } private void TrySetGlobalRequestId(HttpContext httpContext, IInternalConfiguration configuration) @@ -76,17 +77,20 @@ private static void SetInternalServerErrorOnResponse(HttpContext httpContext) } } - private static string CreateMessage(HttpContext httpContext, Exception e) + private static string CreateMessage(HttpContext context, Exception e) { - var message = - $"Exception caught in global error handler, exception message: {e.Message}, exception stack: {e.StackTrace}"; - - if (e.InnerException != null) + var original = e; + var builder = new StringBuilder() + .AppendLine($"{e.GetType().Name} caught in global error handler!"); + int total = 0; + while (e.InnerException != null) { - message = - $"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}"; + builder.AppendLine(e.InnerException.ToString()); + e = e.InnerException; + total++; } - return $"{message} RequestId: {httpContext.TraceIdentifier}"; + builder.Append($"DONE reporting of a total {total} inner exception{total.Plural()} for request {context.TraceIdentifier} of the original {original.GetType().Name} below ->"); + return builder.ToString(); } } diff --git a/src/Ocelot/Infrastructure/Extensions/StringExtensions.cs b/src/Ocelot/Infrastructure/Extensions/StringExtensions.cs index a67d11f41..58222b377 100644 --- a/src/Ocelot/Infrastructure/Extensions/StringExtensions.cs +++ b/src/Ocelot/Infrastructure/Extensions/StringExtensions.cs @@ -30,4 +30,7 @@ public static string TrimPrefix(this string source, string prefix, StringCompari /// A witl the last forward slash. public static string LastCharAsForwardSlash(this string source) => source.EndsWith(Slash) ? source : source + Slash; + + public static string Plural(this int count) => count == 1 ? string.Empty : "s"; + public static string Plural(this string source, int count) => count == 1 ? source : string.Concat(source, "s"); } diff --git a/src/Ocelot/Logging/OcelotLogger.cs b/src/Ocelot/Logging/OcelotLogger.cs index 1528f3957..d165cc086 100644 --- a/src/Ocelot/Logging/OcelotLogger.cs +++ b/src/Ocelot/Logging/OcelotLogger.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using Ocelot.Infrastructure.RequestData; using Ocelot.RequestId.Middleware; +using System; namespace Ocelot.Logging; @@ -11,7 +12,6 @@ public class OcelotLogger : IOcelotLogger { private readonly ILogger _logger; private readonly IRequestScopedDataRepository _scopedDataRepository; - private readonly Func _func; /// /// Initializes a new instance of the class. @@ -28,7 +28,6 @@ public OcelotLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepos { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _scopedDataRepository = scopedDataRepository; - _func = (state, exception) => exception == null ? state : $"{state}, {nameof(exception)}: {exception}"; } public void LogTrace(string message) => WriteLog(LogLevel.Trace, message); @@ -52,13 +51,13 @@ public OcelotLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepos private string GetOcelotRequestId() { var requestId = _scopedDataRepository.Get(RequestIdMiddleware.RequestIdName); - return requestId?.IsError ?? true ? $"No {RequestIdMiddleware.RequestIdName}" : requestId.Data; + return requestId?.IsError ?? true ? "-" : requestId.Data; } private string GetOcelotPreviousRequestId() { var requestId = _scopedDataRepository.Get(RequestIdMiddleware.PreviousRequestIdName); - return requestId?.IsError ?? true ? $"No {RequestIdMiddleware.PreviousRequestIdName}" : requestId.Data; + return requestId?.IsError ?? true ? "-" : requestId.Data; } private void WriteLog(LogLevel logLevel, string message, Exception exception = null) @@ -86,10 +85,12 @@ private void WriteLog(LogLevel logLevel, Func messageFactory, string mes message = messageFactory.Invoke() ?? string.Empty; } - _logger.Log(logLevel, - default, - $"{nameof(requestId)}: {requestId}, {nameof(previousRequestId)}: {previousRequestId}, {nameof(message)}: '{message}'", - exception, - _func); + _logger.Log(logLevel, default, + $"{RequestIdMiddleware.RequestIdName}: {requestId}, {RequestIdMiddleware.PreviousRequestIdName}: {previousRequestId}{Environment.NewLine + message}", + exception, NoFormatter); } + + private static string NoFormatter(string state, Exception e) => state; + private static string ExceptionFormatter(string state, Exception e) + => e == null ? state : $"{state}, {Environment.NewLine + nameof(Exception)}: {e}"; } diff --git a/src/Ocelot/RateLimiting/Middleware/RateLimitingMiddleware.cs b/src/Ocelot/RateLimiting/Middleware/RateLimitingMiddleware.cs index 0efb86cee..93749ec80 100644 --- a/src/Ocelot/RateLimiting/Middleware/RateLimitingMiddleware.cs +++ b/src/Ocelot/RateLimiting/Middleware/RateLimitingMiddleware.cs @@ -34,7 +34,7 @@ public async Task Invoke(HttpContext httpContext) // check if rate limiting is enabled if (!downstreamRoute.EnableEndpointEndpointRateLimiting) { - Logger.LogInformation(() => $"EndpointRateLimiting is not enabled for {downstreamRoute.DownstreamPathTemplate.Value}"); + Logger.LogInformation(() => $"{nameof(DownstreamRoute.EnableEndpointEndpointRateLimiting)} is not enabled for downstream path: {downstreamRoute.DownstreamPathTemplate.Value}"); await _next.Invoke(httpContext); return; } diff --git a/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs b/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs index 9595bec4e..76c9b33bc 100644 --- a/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs +++ b/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs @@ -32,7 +32,7 @@ public async Task Invoke(HttpContext httpContext) return; } - Logger.LogDebug("setting http response message"); + Logger.LogDebug("Setting HTTP response message..."); httpContext.Items.UpsertDownstreamResponse(new DownstreamResponse(response.Data)); await _next.Invoke(httpContext); } @@ -43,7 +43,7 @@ private void CreateLogBasedOnResponse(Response response) var reason = response.Data?.ReasonPhrase ?? "unknown"; var uri = response.Data?.RequestMessage?.RequestUri?.ToString() ?? string.Empty; - string message() => $"{(int)status} ({reason}) status code of request URI: {uri}."; + string message() => $"{(int)status} {reason} status code of request URI: {uri}"; if (status < HttpStatusCode.BadRequest) { diff --git a/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs index 1815b5c61..f3ff6bb32 100644 --- a/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs +++ b/src/Ocelot/Responder/Middleware/ResponderMiddleware.cs @@ -51,7 +51,7 @@ public async Task Invoke(HttpContext httpContext) return; } - Logger.LogDebug("no pipeline errors, setting and returning completed response"); + Logger.LogDebug("No pipeline errors: setting and returning completed response..."); await _responder.SetResponseOnHttpContext(httpContext, downstreamResponse); } From 5cf758def4a51313960dd30f176a66d3329b1bf0 Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 18:47:41 +0300 Subject: [PATCH 02/12] Fix tests --- .../Logging/OcelotLoggerTests.cs | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test/Ocelot.UnitTests/Logging/OcelotLoggerTests.cs b/test/Ocelot.UnitTests/Logging/OcelotLoggerTests.cs index d93e43cae..1db2a5217 100644 --- a/test/Ocelot.UnitTests/Logging/OcelotLoggerTests.cs +++ b/test/Ocelot.UnitTests/Logging/OcelotLoggerTests.cs @@ -12,6 +12,7 @@ public class OcelotLoggerTests private static readonly string _a = "Tom"; private static readonly string _b = "Laura"; private static readonly Exception _ex = new("oh no"); + private static readonly string NL = Environment.NewLine; public OcelotLoggerTests() { @@ -28,8 +29,7 @@ public void Should_log_trace() _logger.LogTrace(() => $"a message from {_a} to {_b}"); // Assert - ThenLevelIsLogged( - "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'", + ThenLevelIsLogged($"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura", LogLevel.Trace); } @@ -40,8 +40,7 @@ public void Should_log_info() _logger.LogInformation(() => $"a message from {_a} to {_b}"); // Assert - ThenLevelIsLogged( - "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'", + ThenLevelIsLogged($"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura", LogLevel.Information); } @@ -52,8 +51,7 @@ public void Should_log_warning() _logger.LogWarning(() => $"a message from {_a} to {_b}"); // Assert - ThenLevelIsLogged( - "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'", + ThenLevelIsLogged($"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura", LogLevel.Warning); } @@ -64,8 +62,7 @@ public void Should_log_error() _logger.LogError(() => $"a message from {_a} to {_b}", _ex); // Assert - ThenLevelIsLogged( - "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'", + ThenLevelIsLogged($"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura", LogLevel.Error, _ex); } @@ -76,8 +73,7 @@ public void Should_log_critical() _logger.LogCritical(() => $"a message from {_a} to {_b}", _ex); // Assert - ThenLevelIsLogged( - "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'", + ThenLevelIsLogged($"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura", LogLevel.Critical, _ex); } @@ -120,7 +116,7 @@ public void If_minimum_log_level_not_set_then_log_is_called_for_information_and_ var currentLogger = new OcelotLogger(mockedILogger.Object, repo.Object); currentLogger.LogDebug(() => $"a message from {_a} to {_b}"); - var expected = "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'"; + var expected = $"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura"; ThenLevelIsNotLogged(mockedILogger, expected, LogLevel.Debug); @@ -194,7 +190,7 @@ public void If_minimum_log_level_set_to_trace_then_log_is_called_for_trace_and_a var currentLogger = new OcelotLogger(mockedILogger.Object, repo.Object); currentLogger.LogDebug(() => $"a message from {_a} to {_b}"); - var expected = "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'"; + var expected = $"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura"; ThenLevelIsLogged(mockedILogger, expected, LogLevel.Debug); @@ -265,7 +261,7 @@ public void If_minimum_log_level_set_to_debug_then_log_is_called_for_debug_and_a var currentLogger = new OcelotLogger(mockedILogger.Object, repo.Object); currentLogger.LogDebug(() => $"a message from {_a} to {_b}"); - var expected = "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'"; + var expected = $"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura"; ThenLevelIsLogged(mockedILogger, expected, LogLevel.Debug); @@ -302,7 +298,7 @@ public void If_minimum_log_level_set_to_warning_then_log_is_called_for_warning_a var currentLogger = new OcelotLogger(mockedILogger.Object, repo.Object); currentLogger.LogDebug(() => $"a message from {_a} to {_b}"); - var expected = "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'"; + var expected = $"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura"; ThenLevelIsNotLogged(mockedILogger, expected, LogLevel.Debug); @@ -339,7 +335,7 @@ public void If_minimum_log_level_set_to_error_then_log_is_called_for_error_and_a var currentLogger = new OcelotLogger(mockedILogger.Object, repo.Object); currentLogger.LogDebug(() => $"a message from {_a} to {_b}"); - var expected = "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'"; + var expected = $"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura"; ThenLevelIsNotLogged(mockedILogger, expected, LogLevel.Debug); @@ -376,7 +372,7 @@ public void If_minimum_log_level_set_to_critical_then_log_is_called_for_critical var currentLogger = new OcelotLogger(mockedILogger.Object, repo.Object); currentLogger.LogDebug(() => $"a message from {_a} to {_b}"); - var expected = "requestId: No RequestId, previousRequestId: No PreviousRequestId, message: 'a message from Tom to Laura'"; + var expected = $"RequestId: -, PreviousRequestId: -{NL}a message from Tom to Laura"; ThenLevelIsNotLogged(mockedILogger, expected, LogLevel.Debug); From 8472b85b88fde5b6eb26c838453f1f1e32f46b2f Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 18:53:03 +0300 Subject: [PATCH 03/12] Refactor Basic sample --- samples/Basic/API.http | 17 ++++++ ...way.csproj => Ocelot.Samples.Basic.csproj} | 12 ++--- samples/Basic/Program.cs | 52 +++++++------------ samples/Basic/Properties/launchSettings.json | 50 +++++++++++++----- samples/Basic/Startup.cs | 30 ----------- samples/Basic/ocelot.json | 32 ++++++++++-- samples/Web/Ocelot.Samples.Web.csproj | 5 +- samples/Web/Program.cs | 6 --- samples/Web/Properties/launchSettings.json | 4 +- 9 files changed, 110 insertions(+), 98 deletions(-) create mode 100644 samples/Basic/API.http rename samples/Basic/{Ocelot.Samples.Basic.ApiGateway.csproj => Ocelot.Samples.Basic.csproj} (51%) delete mode 100644 samples/Basic/Startup.cs delete mode 100644 samples/Web/Program.cs diff --git a/samples/Basic/API.http b/samples/Basic/API.http new file mode 100644 index 000000000..f082543bd --- /dev/null +++ b/samples/Basic/API.http @@ -0,0 +1,17 @@ +@OcelotHttp = http://localhost:5555 + +GET {{OcelotHttp}}/ocelot/posts/1 +Accept: application/json +### +GET {{OcelotHttp}}/ocelot/docs/ +Accept: text/html, */* +### + +@OcelotHttps = https://localhost:7777 + +GET {{OcelotHttps}}/ocelot/posts/3 +Accept: application/json +### +GET {{OcelotHttps}}/ocelot/docs/releasenotes.html +Accept: text/html, */* +### diff --git a/samples/Basic/Ocelot.Samples.Basic.ApiGateway.csproj b/samples/Basic/Ocelot.Samples.Basic.csproj similarity index 51% rename from samples/Basic/Ocelot.Samples.Basic.ApiGateway.csproj rename to samples/Basic/Ocelot.Samples.Basic.csproj index 845855aac..506065fa0 100644 --- a/samples/Basic/Ocelot.Samples.Basic.ApiGateway.csproj +++ b/samples/Basic/Ocelot.Samples.Basic.csproj @@ -1,13 +1,13 @@  net9.0 - disable - disable - InProcess + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals + 8104153a-d238-41dd-a5d1-fecb9b807923 - - - diff --git a/samples/Basic/Program.cs b/samples/Basic/Program.cs index 83d525fe0..6f2810d9e 100644 --- a/samples/Basic/Program.cs +++ b/samples/Basic/Program.cs @@ -1,38 +1,22 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Ocelot.Samples.Web; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; -namespace Ocelot.Samples.Basic.ApiGateway; +var builder = WebApplication.CreateBuilder(args); -public class Program +// Ocelot Basic setup +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); // single ocelot.json file in read-only mode +builder.Services + .AddOcelot(builder.Configuration); + +// Add your features +if (builder.Environment.IsDevelopment()) { - public static void Main(string[] args) - { - OcelotHostBuilder.BasicSetup() - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json") - .AddEnvironmentVariables(); - }) - .ConfigureLogging((hostingContext, logging) => - { - if (hostingContext.HostingEnvironment.IsDevelopment()) - { - logging.ClearProviders(); - logging.AddConsole(); - } - //add your logging - }) - .UseIISIntegration() - .UseStartup() - .Build() - .Run(); - } + builder.Logging.AddConsole(); } + +// Add middlewares aka app.Use*() +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/Basic/Properties/launchSettings.json b/samples/Basic/Properties/launchSettings.json index 924e292df..766f07824 100644 --- a/samples/Basic/Properties/launchSettings.json +++ b/samples/Basic/Properties/launchSettings.json @@ -1,29 +1,51 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:55029/", - "sslPort": 44390 - } - }, "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "ocelot/posts/1", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5555" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "ocelot/docs/", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7777;http://localhost:5555" + }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "posts/1", + "launchUrl": "ocelot/posts/1", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "ApiGateway": { - "commandName": "Project", + "WSL": { + "commandName": "WSL2", "launchBrowser": true, - "launchUrl": "posts/1", + "launchUrl": "https://localhost:7777/ocelot/docs/", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7777;http://localhost:5555" }, - "applicationUrl": "https://localhost:5001;http://localhost:5000" + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62555/", + "sslPort": 44355 } } } diff --git a/samples/Basic/Startup.cs b/samples/Basic/Startup.cs deleted file mode 100644 index c41456f27..000000000 --- a/samples/Basic/Startup.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Ocelot.DependencyInjection; -using Ocelot.Middleware; - -namespace Ocelot.Samples.Basic.ApiGateway; - -public class Startup -{ - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddOcelot(); - services.AddLogging(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseOcelot().Wait(); - } -} diff --git a/samples/Basic/ocelot.json b/samples/Basic/ocelot.json index 7cab02430..ee2ab9503 100644 --- a/samples/Basic/ocelot.json +++ b/samples/Basic/ocelot.json @@ -1,6 +1,8 @@ { "Routes": [ { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/ocelot/posts/{id}", "DownstreamPathTemplate": "/todos/{id}", "DownstreamScheme": "https", "DownstreamHostAndPorts": [ @@ -8,14 +10,34 @@ "Host": "jsonplaceholder.typicode.com", "Port": 443 } - ], - "UpstreamPathTemplate": "/posts/{id}", - "UpstreamHttpMethod": [ - "Get" + ] + }, + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/ocelot/docs/{everything}", + "DownstreamPathTemplate": "/en/latest/{everything}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "ocelot.readthedocs.io", + "Port": 443 + } + ] + }, + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/_/{BFF}", + "DownstreamPathTemplate": "/_/{BFF}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "ocelot.readthedocs.io", + "Port": 443 + } ] } ], "GlobalConfiguration": { - "BaseUrl": "https://localhost:5000" + "BaseUrl": "http://localhost:5555" // "https://localhost:7777" } } diff --git a/samples/Web/Ocelot.Samples.Web.csproj b/samples/Web/Ocelot.Samples.Web.csproj index 18257e423..1674b744b 100644 --- a/samples/Web/Ocelot.Samples.Web.csproj +++ b/samples/Web/Ocelot.Samples.Web.csproj @@ -1,10 +1,13 @@  - 0.0.0-dev net9.0 enable enable + Library + 24.0.0 + 24.0.0 + ThreeMammals diff --git a/samples/Web/Program.cs b/samples/Web/Program.cs deleted file mode 100644 index 40d9a78b7..000000000 --- a/samples/Web/Program.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Ocelot.Samples.Web; - -public class Program -{ - public static void Main(string[] args) { } -} diff --git a/samples/Web/Properties/launchSettings.json b/samples/Web/Properties/launchSettings.json index 4aac128b6..5178e6632 100644 --- a/samples/Web/Properties/launchSettings.json +++ b/samples/Web/Properties/launchSettings.json @@ -1,12 +1,12 @@ { "profiles": { - "Ocelot.Samples.Helpers": { + "Ocelot.Samples.Web": { "commandName": "Project", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "https://localhost:63629;http://localhost:63630" + "applicationUrl": "https://localhost:60184;http://localhost:60185" } } } \ No newline at end of file From 4daf150bab2b9d54073912422250a9ecf2833aac Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 18:54:35 +0300 Subject: [PATCH 04/12] Create Basic Configuration sample --- Ocelot.Release.sln | 13 ++++++++- samples/Configuration/API.http | 23 +++++++++++++++ .../Ocelot.Samples.Configuration.csproj | 16 +++++++++++ samples/Configuration/Program.cs | 23 +++++++++++++++ .../Properties/launchSettings.json | 23 +++++++++++++++ .../appsettings.Development.json | 11 ++++++++ samples/Configuration/appsettings.json | 9 ++++++ .../ocelot-configuration/ocelot.docs.json | 28 +++++++++++++++++++ .../ocelot-configuration/ocelot.global.json | 5 ++++ .../ocelot-configuration/ocelot.posts.json | 16 +++++++++++ .../ocelot-configuration/ocelot.weather.json | 16 +++++++++++ samples/Ocelot.Samples.sln | 18 ++++++++---- 12 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 samples/Configuration/API.http create mode 100644 samples/Configuration/Ocelot.Samples.Configuration.csproj create mode 100644 samples/Configuration/Program.cs create mode 100644 samples/Configuration/Properties/launchSettings.json create mode 100644 samples/Configuration/appsettings.Development.json create mode 100644 samples/Configuration/appsettings.json create mode 100644 samples/Configuration/ocelot-configuration/ocelot.docs.json create mode 100644 samples/Configuration/ocelot-configuration/ocelot.global.json create mode 100644 samples/Configuration/ocelot-configuration/ocelot.posts.json create mode 100644 samples/Configuration/ocelot-configuration/ocelot.weather.json diff --git a/Ocelot.Release.sln b/Ocelot.Release.sln index 1b69b6edc..19a876add 100644 --- a/Ocelot.Release.sln +++ b/Ocelot.Release.sln @@ -57,7 +57,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{8FA0 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.AdministrationApi", "samples\Administration\Ocelot.Samples.AdministrationApi.csproj", "{A7F0CAFA-AECB-43CA-BE89-5F5B728E7C22}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Basic.ApiGateway", "samples\Basic\Ocelot.Samples.Basic.ApiGateway.csproj", "{F00C73F4-019D-490D-8194-CA1754D717FA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Basic", "samples\Basic\Ocelot.Samples.Basic.csproj", "{F00C73F4-019D-490D-8194-CA1754D717FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ocelot.Samples.Configuration", "samples\Configuration\Ocelot.Samples.Configuration.csproj", "{A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Eureka.ApiGateway", "samples\Eureka\ApiGateway\Ocelot.Samples.Eureka.ApiGateway.csproj", "{FECB0C8B-5778-4441-B10E-0C815F5106D5}" EndProject @@ -313,6 +315,14 @@ Global {1A00E87D-2B0B-4D61-A606-3D747C1E43F8}.Release|Any CPU.Build.0 = Release|Any CPU {1A00E87D-2B0B-4D61-A606-3D747C1E43F8}.Release|x64.ActiveCfg = Release|Any CPU {1A00E87D-2B0B-4D61-A606-3D747C1E43F8}.Release|x64.Build.0 = Release|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Debug|x64.ActiveCfg = Debug|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Debug|x64.Build.0 = Debug|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Release|Any CPU.Build.0 = Release|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Release|x64.ActiveCfg = Release|Any CPU + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -346,6 +356,7 @@ Global {D991C694-01F0-4F04-8135-5C133DC8E029} = {8FA0CBA0-0338-48EB-B37F-83CA5022237C} {AD09D124-7DD7-4C9E-9BCC-782B579B1786} = {8FA0CBA0-0338-48EB-B37F-83CA5022237C} {1A00E87D-2B0B-4D61-A606-3D747C1E43F8} = {8FA0CBA0-0338-48EB-B37F-83CA5022237C} + {A33D6A6F-4FAB-4C22-A8AF-2B8C1DF122BA} = {8FA0CBA0-0338-48EB-B37F-83CA5022237C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {21476EFF-778A-4F97-8A56-D1AF1CEC0C48} diff --git a/samples/Configuration/API.http b/samples/Configuration/API.http new file mode 100644 index 000000000..b2d34a2a6 --- /dev/null +++ b/samples/Configuration/API.http @@ -0,0 +1,23 @@ +@HttpHost = http://localhost:5556 + +GET {{HttpHost}}/ocelot/posts/1 +Accept: application/json +### +GET {{HttpHost}}/ocelot/docs/ +Accept: text/html, */* +### +GET {{HttpHost}}/weather/current/London +Accept: application/json +### + +@HttpsHost = https://localhost:7778 + +GET {{HttpsHost}}/ocelot/posts/3 +Accept: application/json +### +GET {{HttpsHost}}/ocelot/docs/releasenotes.html +Accept: text/html, */* +### +GET {{HttpsHost}}/weather/current/Paris +Accept: application/json +### diff --git a/samples/Configuration/Ocelot.Samples.Configuration.csproj b/samples/Configuration/Ocelot.Samples.Configuration.csproj new file mode 100644 index 000000000..465db5c40 --- /dev/null +++ b/samples/Configuration/Ocelot.Samples.Configuration.csproj @@ -0,0 +1,16 @@ + + + + net9.0 + enable + enable + + + + + + + + + + diff --git a/samples/Configuration/Program.cs b/samples/Configuration/Program.cs new file mode 100644 index 000000000..c5e21fabf --- /dev/null +++ b/samples/Configuration/Program.cs @@ -0,0 +1,23 @@ +using Ocelot.DependencyInjection; +using Ocelot.Middleware; + +var builder = WebApplication.CreateBuilder(args); + +// Ocelot Basic setup +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot("ocelot-configuration", builder.Environment); // multiple environment files (ocelot.*.json) to be merged to ocelot.json file and write it back to disk + //.AddOcelot("ocelot-configuration", builder.Environment, MergeOcelotJson.ToMemory); // to be merged to ocelot.json JSON-data and keep it in memory +builder.Services + .AddOcelot(builder.Configuration); + +// Add your features +if (builder.Environment.IsDevelopment()) +{ + builder.Logging.AddConsole(); +} + +// Add middlewares aka app.Use*() +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/Configuration/Properties/launchSettings.json b/samples/Configuration/Properties/launchSettings.json new file mode 100644 index 000000000..81269dc33 --- /dev/null +++ b/samples/Configuration/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5556", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7778;http://localhost:5556", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/Configuration/appsettings.Development.json b/samples/Configuration/appsettings.Development.json new file mode 100644 index 000000000..77cdc8878 --- /dev/null +++ b/samples/Configuration/appsettings.Development.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" + } + } +} diff --git a/samples/Configuration/appsettings.json b/samples/Configuration/appsettings.json new file mode 100644 index 000000000..10f68b8c8 --- /dev/null +++ b/samples/Configuration/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/Configuration/ocelot-configuration/ocelot.docs.json b/samples/Configuration/ocelot-configuration/ocelot.docs.json new file mode 100644 index 000000000..cab1261d4 --- /dev/null +++ b/samples/Configuration/ocelot-configuration/ocelot.docs.json @@ -0,0 +1,28 @@ +{ + "Routes": [ + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/ocelot/docs/{everything}", + "DownstreamPathTemplate": "/en/latest/{everything}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "ocelot.readthedocs.io", + "Port": 443 + } + ] + }, + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/_/{BFF}", + "DownstreamPathTemplate": "/_/{BFF}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "ocelot.readthedocs.io", + "Port": 443 + } + ] + } + ] +} diff --git a/samples/Configuration/ocelot-configuration/ocelot.global.json b/samples/Configuration/ocelot-configuration/ocelot.global.json new file mode 100644 index 000000000..d7f7e570b --- /dev/null +++ b/samples/Configuration/ocelot-configuration/ocelot.global.json @@ -0,0 +1,5 @@ +{ + "GlobalConfiguration": { + "BaseUrl": "http://localhost:5556" // "https://localhost:7778" + } +} diff --git a/samples/Configuration/ocelot-configuration/ocelot.posts.json b/samples/Configuration/ocelot-configuration/ocelot.posts.json new file mode 100644 index 000000000..0b0ca7e5e --- /dev/null +++ b/samples/Configuration/ocelot-configuration/ocelot.posts.json @@ -0,0 +1,16 @@ +{ + "Routes": [ + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/ocelot/posts/{id}", + "DownstreamPathTemplate": "/todos/{id}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "jsonplaceholder.typicode.com", + "Port": 443 + } + ] + } + ] +} diff --git a/samples/Configuration/ocelot-configuration/ocelot.weather.json b/samples/Configuration/ocelot-configuration/ocelot.weather.json new file mode 100644 index 000000000..0d4c48e36 --- /dev/null +++ b/samples/Configuration/ocelot-configuration/ocelot.weather.json @@ -0,0 +1,16 @@ +{ + "Routes": [ + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/weather/current/{city}", + "DownstreamPathTemplate": "/v1/current.json?q={city}&key=4ea9a1d2aafe4e15bbd173615242312", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "api.weatherapi.com", + "Port": 443 + } + ] + } + ] +} diff --git a/samples/Ocelot.Samples.sln b/samples/Ocelot.Samples.sln index 4599cc5e7..37c9e40b0 100644 --- a/samples/Ocelot.Samples.sln +++ b/samples/Ocelot.Samples.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot", "..\src\Ocelot\Oce EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.AdministrationApi", "Administration\Ocelot.Samples.AdministrationApi.csproj", "{238467FE-19EE-4102-9AF7-51EB2C6F0354}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Basic.ApiGateway", "Basic\Ocelot.Samples.Basic.ApiGateway.csproj", "{A7D2C43A-E35C-4A89-AEE5-5C87052ECD89}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Eureka.ApiGateway", "Eureka\ApiGateway\Ocelot.Samples.Eureka.ApiGateway.csproj", "{EA0E146F-2C2B-4176-B6EC-F62A587F5077}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Eureka.DownstreamService", "Eureka\DownstreamService\Ocelot.Samples.Eureka.DownstreamService.csproj", "{B7317B64-2208-472D-90AC-F42B61956B79}" @@ -31,6 +29,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.ServiceFabri EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Samples.Web", "Web\Ocelot.Samples.Web.csproj", "{EA553F5C-4B94-4E4A-8C3E-0124C5EA5F6E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ocelot.Samples.Basic", "Basic\Ocelot.Samples.Basic.csproj", "{3225BD01-42ED-4362-9757-28CBFF6B2D70}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ocelot.Samples.Configuration", "Configuration\Ocelot.Samples.Configuration.csproj", "{FE091795-7FBF-4D82-ABD6-51405F210142}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,10 +47,6 @@ Global {238467FE-19EE-4102-9AF7-51EB2C6F0354}.Debug|Any CPU.Build.0 = Debug|Any CPU {238467FE-19EE-4102-9AF7-51EB2C6F0354}.Release|Any CPU.ActiveCfg = Release|Any CPU {238467FE-19EE-4102-9AF7-51EB2C6F0354}.Release|Any CPU.Build.0 = Release|Any CPU - {A7D2C43A-E35C-4A89-AEE5-5C87052ECD89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A7D2C43A-E35C-4A89-AEE5-5C87052ECD89}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A7D2C43A-E35C-4A89-AEE5-5C87052ECD89}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A7D2C43A-E35C-4A89-AEE5-5C87052ECD89}.Release|Any CPU.Build.0 = Release|Any CPU {EA0E146F-2C2B-4176-B6EC-F62A587F5077}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA0E146F-2C2B-4176-B6EC-F62A587F5077}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA0E146F-2C2B-4176-B6EC-F62A587F5077}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -93,6 +91,14 @@ Global {EA553F5C-4B94-4E4A-8C3E-0124C5EA5F6E}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA553F5C-4B94-4E4A-8C3E-0124C5EA5F6E}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA553F5C-4B94-4E4A-8C3E-0124C5EA5F6E}.Release|Any CPU.Build.0 = Release|Any CPU + {3225BD01-42ED-4362-9757-28CBFF6B2D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3225BD01-42ED-4362-9757-28CBFF6B2D70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3225BD01-42ED-4362-9757-28CBFF6B2D70}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3225BD01-42ED-4362-9757-28CBFF6B2D70}.Release|Any CPU.Build.0 = Release|Any CPU + {FE091795-7FBF-4D82-ABD6-51405F210142}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE091795-7FBF-4D82-ABD6-51405F210142}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE091795-7FBF-4D82-ABD6-51405F210142}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE091795-7FBF-4D82-ABD6-51405F210142}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From a17386545c4156b002234a2fc0d0ef97c157e30f Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 19:07:55 +0300 Subject: [PATCH 05/12] Update gettingstarted.rst: Getting Started docs in Introduction --- docs/features/administration.rst | 2 +- docs/features/headerstransformation.rst | 2 + docs/features/qualityofservice.rst | 2 +- docs/features/requestaggregation.rst | 2 +- docs/features/servicediscovery.rst | 2 +- docs/features/tracing.rst | 2 +- docs/introduction/gettingstarted.rst | 151 +++++++++++------------- 7 files changed, 79 insertions(+), 84 deletions(-) diff --git a/docs/features/administration.rst b/docs/features/administration.rst index 61832d1ec..db3d24480 100644 --- a/docs/features/administration.rst +++ b/docs/features/administration.rst @@ -146,4 +146,4 @@ The region is whatever you set against the **Region** field in the `FileCacheOpt """" -.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to DI container. You could call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of :doc:`../features/dependencyinjection` feature. +.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to the DI container. You can call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of the :doc:`../features/dependencyinjection` feature. diff --git a/docs/features/headerstransformation.rst b/docs/features/headerstransformation.rst index c400989c1..c84fa4822 100644 --- a/docs/features/headerstransformation.rst +++ b/docs/features/headerstransformation.rst @@ -45,6 +45,8 @@ If you want to return the `Butterfly APM `_ filtering by |QoS_label| label. .. [#f3] We upgraded `Polly`_ version from v7.x to v8.x! The :ref:`qos-extensibility` feature was requested in issue `1875`_ and delivered by PR `1914`_ as a part of version `23.2`_. diff --git a/docs/features/requestaggregation.rst b/docs/features/requestaggregation.rst index c9a642388..cb03c494e 100644 --- a/docs/features/requestaggregation.rst +++ b/docs/features/requestaggregation.rst @@ -227,4 +227,4 @@ Gotchas """" .. [#f1] This feature was requested as part of `issue 79 `_ and further improvements were made as part of `issue 298 `_. A significant refactoring and revision of the `Multiplexer `_ design was carried out on March 4, 2024 in version `23.1 `_, see PRs `1826 `_ and `1462 `_. -.. [#f2] :ref:`di-the-addocelot-method` adds default ASP.NET services to DI container. You could call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of :doc:`../features/dependencyinjection` feature. +.. [#f2] :ref:`di-the-addocelot-method` adds default ASP.NET services to the DI container. You can call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of the :doc:`../features/dependencyinjection` feature. diff --git a/docs/features/servicediscovery.rst b/docs/features/servicediscovery.rst index 9a3eab06b..eadbe85be 100644 --- a/docs/features/servicediscovery.rst +++ b/docs/features/servicediscovery.rst @@ -541,7 +541,7 @@ But you can leave this ``Type`` option for compatibility between both designs. """" -.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to DI container. You could call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of :doc:`../features/dependencyinjection` feature. +.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to the DI container. You can call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of the :doc:`../features/dependencyinjection` feature. .. [#f2] :ref:`sd-consul-configuration-key` feature was requested in issue `346`_ as a part of version `7.0.0`_. .. [#f3] Customization of :ref:`sd-consul-service-builder` was implemented as a part of bug `954`_ fixing and the feature was delivered in version `23.3`_. diff --git a/docs/features/tracing.rst b/docs/features/tracing.rst index 2ae0fc2e0..fb5827d15 100644 --- a/docs/features/tracing.rst +++ b/docs/features/tracing.rst @@ -88,4 +88,4 @@ Ocelot will now send tracing information to Butterfly when this Route is called. """" -.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to DI container. You could call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of :doc:`../features/dependencyinjection` feature. +.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to the DI container. You can call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of the :doc:`../features/dependencyinjection` feature. diff --git a/docs/introduction/gettingstarted.rst b/docs/introduction/gettingstarted.rst index 2640b4e4b..a10741ca0 100644 --- a/docs/introduction/gettingstarted.rst +++ b/docs/introduction/gettingstarted.rst @@ -1,16 +1,14 @@ Getting Started =============== -Ocelot is designed to work with ASP.NET and is currently on ``net6.0``, ``net7.0`` and ``net8.0`` frameworks. +Ocelot is designed to work with `ASP.NET Core `_ and is currently on `.NET 8 `_ `LTS `_ +and `.NET 9 `_ `STS `_ frameworks. -.NET 8.0 --------- - -Install NuGet package -^^^^^^^^^^^^^^^^^^^^^ +Install +------- Install Ocelot and it's dependencies using `NuGet `_. -You will need to create a `ASP.NET Core minimal API project `_ and bring the package into it. +You will need to create a `ASP.NET Core minimal API project `_ with "ASP.NET Core Empty" template but without ``app.Map*`` methods, and bring the package into it. Then follow the startup below and :doc:`../features/configuration` sections to get up and running. .. code-block:: powershell @@ -20,17 +18,20 @@ Then follow the startup below and :doc:`../features/configuration` sections to g All versions can be found in the `NuGet Gallery | Ocelot `_. Configuration -^^^^^^^^^^^^^ +------------- -The following is a very basic **ocelot.json**. It won't do anything but should get Ocelot starting. +The following is a very basic `ocelot.json`_. +It won't do anything but should get Ocelot starting. .. code-block:: json { - "Routes": [], - "GlobalConfiguration": { - "BaseUrl": "https://api.mybusiness.com" - } + "Routes": [], + "DynamicRoutes": [], + "Aggregates": [], + "GlobalConfiguration": { + "BaseUrl": "https://api.mybusiness.com" + } } If you want some example that actually does something use the following: @@ -38,90 +39,82 @@ If you want some example that actually does something use the following: .. code-block:: json { - "Routes": [ - { - "DownstreamPathTemplate": "/todos/{id}", - "DownstreamScheme": "https", - "DownstreamHostAndPorts": [ - { - "Host": "jsonplaceholder.typicode.com", - "Port": 443 - } - ], - "UpstreamPathTemplate": "/todos/{id}", - "UpstreamHttpMethod": [ "Get" ] - } - ], - "GlobalConfiguration": { - "BaseUrl": "https://localhost:5000" + "Routes": [ + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/ocelot/posts/{id}", + "DownstreamPathTemplate": "/todos/{id}", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { "Host": "jsonplaceholder.typicode.com", "Port": 443 } + ] } + ], + "GlobalConfiguration": { + "BaseUrl": "https://localhost:7777" + } } -The most important thing to note here is **BaseUrl** property. -Ocelot needs to know the URL it is running under in order to do Header find & replace and for certain administration configurations. +The most important thing to note here is ``BaseUrl`` property. +Ocelot needs to know the URL it is running under in order to do Header :ref:`ht-find-and-replace` and for certain :doc:`../features/administration` configurations. When setting this URL it should be the external URL that clients will see Ocelot running on e.g. -If you are running containers Ocelot might run on the URL ``http://123.12.1.1:6543`` but has something like **nginx** in front of it responding on ``https://api.mybusiness.com``. -In this case the Ocelot **BaseUrl** should be ``https://api.mybusiness.com``. +If you are running containers Ocelot might run on the URL ``http://123.12.1.2:6543`` but has something like `nginx `_ in front of it responding on ``https://api.mybusiness.com``. +In this case the Ocelot ``BaseUrl`` should be ``https://api.mybusiness.com``. -If you are using containers and require Ocelot to respond to clients on ``http://123.12.1.1:6543`` then you can do this, +If you are using containers and require Ocelot to respond to clients on ``http://123.12.1.2:6543`` then you can do this, however if you are deploying multiple Ocelot's you will probably want to pass this on the command line in some kind of script. Hopefully whatever scheduler you are using can pass the IP. Program -^^^^^^^ - -Then in your **Program.cs** you will want to have the following. - -The main things to note are +------- -* ``AddOcelot()`` adds Ocelot required and default services [#f1]_ -* ``UseOcelot().Wait()`` sets up all the Ocelot middlewares. +Then in your `Program.cs `_ (with `top-level statements `_) you will want to have the following. .. code-block:: csharp - using System.IO; - using Microsoft.AspNetCore.Hosting; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.Hosting; using Ocelot.DependencyInjection; using Ocelot.Middleware; - namespace OcelotBasic + var builder = WebApplication.CreateBuilder(args); + + // Ocelot Basic setup + builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); // single ocelot.json file in read-only mode + builder.Services + .AddOcelot(builder.Configuration); + + // Add your features + if (builder.Environment.IsDevelopment()) { - public class Program - { - public static void Main(string[] args) - { - new WebHostBuilder() - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json") - .AddEnvironmentVariables(); - }) - .ConfigureServices(s => { - s.AddOcelot(); - }) - .ConfigureLogging((hostingContext, logging) => - { - //add your logging - }) - .UseIISIntegration() - .Configure(app => - { - app.UseOcelot().Wait(); - }) - .Build() - .Run(); - } - } + builder.Logging.AddConsole(); } + // Add middlewares aka app.Use*() + var app = builder.Build(); + await app.UseOcelot(); + app.Run(); + +The main things to note are + +* ``builder.Configuration.AddOcelot()`` adds single `ocelot.json`_ configuration file in read-only mode. +* ``builder.Services.AddOcelot(builder.Configuration)`` adds Ocelot required and default services [#f1]_ +* ``app.UseOcelot()`` sets up all the Ocelot middlewares. Note, we have to await the threading result before calling ``app.Run()`` +* Do not add endpoint mappings (minimal API methods) such as ``app.MapGet()`` because the Ocelot pipeline is not compatible with them! + +Samples +------- + +For beginners, we have prepared basic `samples `_ to help Ocelot newbies clone, compile, and get it running. + +* `Basic `_ sample: It has a single configuration file, `ocelot.json`_. +* `Basic Configuration `_ sample: It has multiple configuration files (``ocelot.*.json``) to be merged into ``ocelot.json`` and written back to disk. + +After running in Visual Studio [#f2]_, you may use ``API.http`` files to send testing requests to the ``localhost`` Ocelot application instance. + """" -.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to DI container. You could call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of :doc:`../features/dependencyinjection` feature. +.. [#f1] :ref:`di-the-addocelot-method` adds default ASP.NET services to the DI container. You can call another extended :ref:`di-addocelotusingbuilder-method` while configuring services to develop your own :ref:`di-custom-builder`. See more instructions in the ":ref:`di-addocelotusingbuilder-method`" section of the :doc:`../features/dependencyinjection` feature. +.. [#f2] All sample projects are organized as the `Ocelot.Samples.sln `_ file for Visual Studio 2022 IDE. + +.. _ocelot.json: https://github.com/ThreeMammals/Ocelot/blob/main/samples/Basic/ocelot.json From 73fc903b98b39d079dc39ac10e3c75caadafd1f3 Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 19:39:52 +0300 Subject: [PATCH 06/12] Update AdministrationApi sample --- .../Ocelot.Samples.AdministrationApi.csproj | 7 ++- samples/Administration/Program.cs | 52 ++++++------------ .../Properties/launchSettings.json | 53 +++++++++++++------ .../appsettings.Development.json | 11 ++++ samples/Administration/appsettings.json | 14 +++-- samples/Administration/ocelot.json | 32 +++++------ samples/Administration/tempkey.jwk | 1 + samples/Web/Properties/launchSettings.json | 2 +- 8 files changed, 93 insertions(+), 79 deletions(-) create mode 100644 samples/Administration/appsettings.Development.json create mode 100644 samples/Administration/tempkey.jwk diff --git a/samples/Administration/Ocelot.Samples.AdministrationApi.csproj b/samples/Administration/Ocelot.Samples.AdministrationApi.csproj index 4632d2545..8860d4a6e 100644 --- a/samples/Administration/Ocelot.Samples.AdministrationApi.csproj +++ b/samples/Administration/Ocelot.Samples.AdministrationApi.csproj @@ -1,8 +1,11 @@  net9.0 - disable - disable + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals diff --git a/samples/Administration/Program.cs b/samples/Administration/Program.cs index 1ae147206..bb0ad382c 100644 --- a/samples/Administration/Program.cs +++ b/samples/Administration/Program.cs @@ -1,43 +1,23 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Ocelot.Administration; +using Ocelot.Administration; using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Samples.Web; -namespace Ocelot.Samples.AdministrationApi; +// var host = OcelotHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); -public class Program +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); // single ocelot.json file in read-only mode +builder.Services + .AddOcelot(builder.Configuration) + .AddAdministration("/administration", "secret"); + +if (builder.Environment.IsDevelopment()) { - public static void Main(string[] args) - { - OcelotHostBuilder.Create(args) - .UseUrls("http://localhost:5000") - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json") - .AddEnvironmentVariables(); - }) - .ConfigureServices(s => - { - s.AddOcelot() - .AddAdministration("/administration", "secret"); - }) - .ConfigureLogging((hostingContext, logging) => - { - logging.AddConsole(); - }) - .UseIISIntegration() - .Configure(app => - { - app.UseOcelot().Wait(); - }) - .Build() - .Run(); - } + builder.Logging.AddConsole(); } + +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/Administration/Properties/launchSettings.json b/samples/Administration/Properties/launchSettings.json index da28e7982..2eda75f8d 100644 --- a/samples/Administration/Properties/launchSettings.json +++ b/samples/Administration/Properties/launchSettings.json @@ -1,27 +1,48 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:9943", - "sslPort": 44396 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, + "http": { + "commandName": "Project", + "launchBrowser": false, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5554" }, - "AdministrationApi": { + "https": { "commandName": "Project", - "launchBrowser": true, - "applicationUrl": "https://localhost:5001;http://localhost:5000", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7776;http://localhost:5554" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": false, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "WSL": { + "commandName": "WSL2", + "launchBrowser": false, + "launchUrl": "https://localhost:7776/ocelot/docs/", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7776;http://localhost:5554" + }, + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62554/", + "sslPort": 44354 } } -} \ No newline at end of file +} diff --git a/samples/Administration/appsettings.Development.json b/samples/Administration/appsettings.Development.json new file mode 100644 index 000000000..07053a355 --- /dev/null +++ b/samples/Administration/appsettings.Development.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" + } + } +} diff --git a/samples/Administration/appsettings.json b/samples/Administration/appsettings.json index 0f1a3d11b..def9159a7 100644 --- a/samples/Administration/appsettings.json +++ b/samples/Administration/appsettings.json @@ -1,10 +1,8 @@ { - "Logging": { - "IncludeScopes": true, - "LogLevel": { - "Default": "Trace", - "System": "Trace", - "Microsoft": "Trace" - } + "Logging": { + "LogLevel": { + "Default": "Warning" } -} \ No newline at end of file + }, + "AllowedHosts": "*" +} diff --git a/samples/Administration/ocelot.json b/samples/Administration/ocelot.json index 02e7c5512..5f8d81e2b 100644 --- a/samples/Administration/ocelot.json +++ b/samples/Administration/ocelot.json @@ -1,18 +1,18 @@ { - "Routes": [ - { - "DownstreamPathTemplate": "/service/stats/collected", - "DownstreamScheme": "http", - "DownstreamHostAndPorts": [ - { - "Host": "localhost", - "Port": 5100 - } - ], - "UpstreamPathTemplate": "/api/stats/collected" - } - ], - "GlobalConfiguration": { - "BaseUrl": "http://localhost:5000" + "Routes": [ + { + "DownstreamPathTemplate": "/service/stats/collected", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5555 + } + ], + "UpstreamPathTemplate": "/api/stats/collected" } - } \ No newline at end of file + ], + "GlobalConfiguration": { + "BaseUrl": "http://localhost:5554" + } +} diff --git a/samples/Administration/tempkey.jwk b/samples/Administration/tempkey.jwk new file mode 100644 index 000000000..e66befbe7 --- /dev/null +++ b/samples/Administration/tempkey.jwk @@ -0,0 +1 @@ +{"AdditionalData":{},"Alg":"RS256","Crv":null,"D":"FmDa4-GmEQ8Djo5oqFBuJ9RXkl7rnbLouiHexPGMC7nQyZsTlxVNIefCuQExufLEpVGP4Q_3ISEcuosBBV2nFd_LtpPnY999rR5LEknqTzA3kqSJori5iCRm1X5OTeLHuPvOuPrLwP7u5JDAAWvSBF2ZNsKr1x09rDjPMbugORw3RaXNq3gqWnDbSRkNSV5SY-4EAgSAZXzofjfgf9lXbemF4s9yU3SC4O9gj03klXnUcCrCDlM0qcxejYgvdGXrLmtXzf8YULEKy4qEV5zJlY97Sff_yTxE9s9hkHPSt7rEAWUzsrH_a4_ybNHXIV0YECP0FuFV7eMCSVESeXhORQ","DP":"CTW_JuwXVhsmpM_KPwJJwAA89zaLZYg4sibHLJa-0SdsP7CUcMgiNFedMny0Jr1DCKTopEuOdsHGhmTVqZor0quwU5RTTcaw2DC_kbQSTa3eAzViOtcrzo-HNR-QoW9Mh_OifVb82tJw1iOCKzX79gmA34kGaYtAJza39vPp7xk","DQ":"dIBChHkIEujaQFt4hglcimKkdGX3wpWIRZL2UzdGnuZEBPy4Oi_g9vLP-p61VCOIasxHwqyi82Z07LajuZvvdFvGhr0OtWT0hAtiLSdFD2CMOZXSAarlbDxomHF0bqc4kAci9G6-zcgR5x5kbL78RYJs55i3dID-hp59dbfhsus","E":"AQAB","K":null,"KeyId":"629DD7109DEAB41B784A898D99354A43","KeyOps":[],"Kid":"629DD7109DEAB41B784A898D99354A43","Kty":"RSA","N":"13S_E_2EEcqxy8xfLSIg4SRrgu7jQL5js4bvXr9QMPX6VkS3wqgeDozni7Y9a3c0A_6KbBSd2IU0ExhQ8nLfc3QBl_X-toJCI20IolrPHPDMGF_WJtNLD64gMFT8vDuh0d_fFa6RYtKtgYwc0H5-S7qPJp6UUbnaOJTBtA_eeydGp97Nay3N-zZ9-NTlVbQeKtEQJw50L3DHbwHWBTAZj3Ry3KRom0Vb-I_bAY6BBVZhE-N2gnFdXBVSGZmAvoSQazMqGZ151iIqrLiZBAYu4ak_IuOkmqIRcufbH7ynLDkcMPGVq8j5CgFczyq83s9uxzC5B9uBxcY0Jm_Oe6sFbQ","Oth":[],"P":"1-CJZnop88aRwlQl-o4rbPRecGPbBFwhLbtEy3ADpzWZX0wwd8_uGRIWKqhYNlUhIsmMYRIywKmvcXmYk_HY48FIFO9qxHxk-qb7dqDHZLsefwd02axfvx11_PUsaAFHWQLJhRRYEAzJe9Hh2ezhPO30YCDGAOJ9epYVB1BJhfM","Q":"_4As_7JAvze4L9Ey6G6RPQfy1VDG9XLCRNpZKgiZgBsqGWGK86f-wZ-mMtLlSZ8Uo97iwLQnyMYQ3o9tnRXhSDyb1V5KFs1CJwMYMEKiSz816WJZ7eXLjAWgfPR31SEJA6wsnKYeqAS55DHjiK1mTLrPWYK6nHvmrGODEHw_Px8","QI":"alZ6B7QrVswWUnyKZo5l42x1W5-2pNg3psntDyjMyW8_xA73gs39lWQ2xVrRscOmvV5YMOqnvQ6QzsP9vQV9M6PNg00PeaaQ9FyceewGnk0jooxnK7zMtDl-mXJafB5WKYoN263WHQqVJ2UEwKIWpOq1TweZY4eSi_Ob6_PMO_Q","Use":null,"X":null,"X5c":[],"X5t":null,"X5tS256":null,"X5u":null,"Y":null,"KeySize":2048,"HasPrivateKey":true,"CryptoProviderFactory":{"CryptoProviderCache":{},"CustomCryptoProvider":null,"CacheSignatureProviders":true,"SignatureProviderObjectPoolCacheSize":32}} \ No newline at end of file diff --git a/samples/Web/Properties/launchSettings.json b/samples/Web/Properties/launchSettings.json index 5178e6632..2f7f054ce 100644 --- a/samples/Web/Properties/launchSettings.json +++ b/samples/Web/Properties/launchSettings.json @@ -9,4 +9,4 @@ "applicationUrl": "https://localhost:60184;http://localhost:60185" } } -} \ No newline at end of file +} From e0b1456cdbab91b4e9c3a03070c8a185de64a725 Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 20:53:30 +0300 Subject: [PATCH 07/12] Update Eureka sample --- .../Ocelot.Samples.Configuration.csproj | 5 +- .../Ocelot.Samples.Eureka.ApiGateway.csproj | 12 ++--- samples/Eureka/ApiGateway/Program.cs | 49 +++++++----------- .../ApiGateway/Properties/launchSettings.json | 48 +++++++++++++----- samples/Eureka/ApiGateway/appsettings.json | 1 - samples/Eureka/ApiGateway/ocelot.json | 24 +++++++-- .../Controllers/CategoryController.cs | 3 +- ...ot.Samples.Eureka.DownstreamService.csproj | 11 ++-- samples/Eureka/DownstreamService/Program.cs | 30 +++++------ .../Properties/launchSettings.json | 50 +++++++++++++------ samples/Eureka/DownstreamService/Startup.cs | 34 ------------- .../appsettings.Development.json | 7 +-- .../Eureka/DownstreamService/appsettings.json | 2 - 13 files changed, 147 insertions(+), 129 deletions(-) delete mode 100644 samples/Eureka/DownstreamService/Startup.cs diff --git a/samples/Configuration/Ocelot.Samples.Configuration.csproj b/samples/Configuration/Ocelot.Samples.Configuration.csproj index 465db5c40..2f5d0bfc8 100644 --- a/samples/Configuration/Ocelot.Samples.Configuration.csproj +++ b/samples/Configuration/Ocelot.Samples.Configuration.csproj @@ -2,8 +2,11 @@ net9.0 - enable enable + enable + 24.0.0 + 24.0.0 + ThreeMammals diff --git a/samples/Eureka/ApiGateway/Ocelot.Samples.Eureka.ApiGateway.csproj b/samples/Eureka/ApiGateway/Ocelot.Samples.Eureka.ApiGateway.csproj index 7ac8ac796..2c272cb97 100644 --- a/samples/Eureka/ApiGateway/Ocelot.Samples.Eureka.ApiGateway.csproj +++ b/samples/Eureka/ApiGateway/Ocelot.Samples.Eureka.ApiGateway.csproj @@ -1,14 +1,12 @@  net9.0 - disable - disable + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals - - - PreserveNewest - - diff --git a/samples/Eureka/ApiGateway/Program.cs b/samples/Eureka/ApiGateway/Program.cs index 0e9608ac7..14a402501 100644 --- a/samples/Eureka/ApiGateway/Program.cs +++ b/samples/Eureka/ApiGateway/Program.cs @@ -1,39 +1,26 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Ocelot.DependencyInjection; +using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Provider.Eureka; using Ocelot.Provider.Polly; using Ocelot.Samples.Web; -namespace Ocelot.Samples.Eureka.ApiGateway; +//_ = OcelotHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); -public class Program +// Ocelot Basic setup +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); +builder.Services + .AddOcelot(builder.Configuration) + .AddEureka() + .AddPolly(); + +if (builder.Environment.IsDevelopment()) { - public static void Main(string[] args) - { - OcelotHostBuilder.Create(args) - .UseUrls("http://localhost:5000") - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json", false, false) - .AddEnvironmentVariables(); - }) - .ConfigureServices(s => - { - s.AddOcelot() - .AddEureka() - .AddPolly(); - }) - .Configure(a => - { - a.UseOcelot().Wait(); - }) - .Build() - .Run(); - } + builder.Logging.AddConsole(); } + +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/Eureka/ApiGateway/Properties/launchSettings.json b/samples/Eureka/ApiGateway/Properties/launchSettings.json index c1b4df874..b2e0b6082 100644 --- a/samples/Eureka/ApiGateway/Properties/launchSettings.json +++ b/samples/Eureka/ApiGateway/Properties/launchSettings.json @@ -1,27 +1,51 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:54060/", - "sslPort": 0 - } - }, "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "Category", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5557" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "category", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7779;http://localhost:5557" + }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, + "launchUrl": "category", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "ApiGateway": { - "commandName": "Project", + "WSL": { + "commandName": "WSL2", "launchBrowser": true, + "launchUrl": "https://localhost:7779/category/", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7779;http://localhost:5557" }, - "applicationUrl": "http://localhost:54061/" + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62557/", + "sslPort": 44357 } } } diff --git a/samples/Eureka/ApiGateway/appsettings.json b/samples/Eureka/ApiGateway/appsettings.json index 4a098bc41..4d08f64b9 100644 --- a/samples/Eureka/ApiGateway/appsettings.json +++ b/samples/Eureka/ApiGateway/appsettings.json @@ -1,6 +1,5 @@ { "Logging": { - "IncludeScopes": true, "LogLevel": { "Default": "Trace", "System": "Information", diff --git a/samples/Eureka/ApiGateway/ocelot.json b/samples/Eureka/ApiGateway/ocelot.json index 747cf23c8..364f189b4 100644 --- a/samples/Eureka/ApiGateway/ocelot.json +++ b/samples/Eureka/ApiGateway/ocelot.json @@ -1,11 +1,29 @@ { "Routes": [ { - "DownstreamPathTemplate": "/api/Category", - "DownstreamScheme": "http", - "UpstreamPathTemplate": "/Category", "ServiceName": "ncore-rat", "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/category", + "DownstreamPathTemplate": "/api/category", + "DownstreamScheme": "http", + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 10000, + "TimeoutValue": 5000 + }, + "FileCacheOptions": { "TtlSeconds": 15 } + }, + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/nodiscovery/category", + "DownstreamPathTemplate": "/api/category", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5558 + } + ], "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 3, "DurationOfBreak": 10000, diff --git a/samples/Eureka/DownstreamService/Controllers/CategoryController.cs b/samples/Eureka/DownstreamService/Controllers/CategoryController.cs index 756cdfa46..15af7a6db 100644 --- a/samples/Eureka/DownstreamService/Controllers/CategoryController.cs +++ b/samples/Eureka/DownstreamService/Controllers/CategoryController.cs @@ -1,12 +1,11 @@ using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; namespace Ocelot.Samples.Eureka.DownstreamService.Controllers; [Route("api/[controller]")] public class CategoryController : Controller { - // GET api/values + // GET api/category [HttpGet] public IEnumerable Get() { diff --git a/samples/Eureka/DownstreamService/Ocelot.Samples.Eureka.DownstreamService.csproj b/samples/Eureka/DownstreamService/Ocelot.Samples.Eureka.DownstreamService.csproj index 2ff83d76e..7682f1ffd 100644 --- a/samples/Eureka/DownstreamService/Ocelot.Samples.Eureka.DownstreamService.csproj +++ b/samples/Eureka/DownstreamService/Ocelot.Samples.Eureka.DownstreamService.csproj @@ -1,14 +1,15 @@  net9.0 - disable - disable + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals - - - + diff --git a/samples/Eureka/DownstreamService/Program.cs b/samples/Eureka/DownstreamService/Program.cs index 2ff1907d9..dd6682e2a 100644 --- a/samples/Eureka/DownstreamService/Program.cs +++ b/samples/Eureka/DownstreamService/Program.cs @@ -1,19 +1,21 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Ocelot.Samples.Web; -using System; +using Steeltoe.Discovery.Client; -namespace Ocelot.Samples.Eureka.DownstreamService; +var builder = WebApplication.CreateBuilder(args); +builder.Services + .AddDiscoveryClient(builder.Configuration) + .AddControllers(); -public class Program +if (builder.Environment.IsDevelopment()) { - public static void Main(string[] args) - { - DownstreamHostBuilder.Create(args) - .UseUrls($"http://{Environment.MachineName}:5001") - .UseStartup() - .Build() - .Run(); - } + builder.Logging.AddConsole(); +} +var app = builder.Build(); +if (app.Environment.IsDevelopment()) +{ + app.UseDeveloperExceptionPage(); } +app.UseHttpsRedirection() + .UseAuthorization(); +app.MapControllers(); +app.Run(); diff --git a/samples/Eureka/DownstreamService/Properties/launchSettings.json b/samples/Eureka/DownstreamService/Properties/launchSettings.json index 0c084db8e..fcdf5e2e6 100644 --- a/samples/Eureka/DownstreamService/Properties/launchSettings.json +++ b/samples/Eureka/DownstreamService/Properties/launchSettings.json @@ -1,29 +1,51 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:53908/", - "sslPort": 0 - } - }, "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/Category", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5558" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/category", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7780;http://localhost:5558" + }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "api/values", + "launchUrl": "api/category", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "DownstreamService": { - "commandName": "Project", + "WSL": { + "commandName": "WSL2", "launchBrowser": true, - "launchUrl": "api/values", + "launchUrl": "https://localhost:7780/api/category", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7780;http://localhost:5558" }, - "applicationUrl": "http://localhost:53909/" + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62558/", + "sslPort": 44358 } } } diff --git a/samples/Eureka/DownstreamService/Startup.cs b/samples/Eureka/DownstreamService/Startup.cs deleted file mode 100644 index fd72ce9a2..000000000 --- a/samples/Eureka/DownstreamService/Startup.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Steeltoe.Discovery.Client; - -namespace Ocelot.Samples.Eureka.DownstreamService; - -public class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddDiscoveryClient(Configuration); - services.AddMvc(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - } -} diff --git a/samples/Eureka/DownstreamService/appsettings.Development.json b/samples/Eureka/DownstreamService/appsettings.Development.json index fa8ce71a9..e298568ac 100644 --- a/samples/Eureka/DownstreamService/appsettings.Development.json +++ b/samples/Eureka/DownstreamService/appsettings.Development.json @@ -1,10 +1,11 @@ { "Logging": { - "IncludeScopes": false, "LogLevel": { "Default": "Debug", - "System": "Information", - "Microsoft": "Information" + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" } } } diff --git a/samples/Eureka/DownstreamService/appsettings.json b/samples/Eureka/DownstreamService/appsettings.json index 4bebaa50a..c6982234f 100644 --- a/samples/Eureka/DownstreamService/appsettings.json +++ b/samples/Eureka/DownstreamService/appsettings.json @@ -1,6 +1,5 @@ { "Logging": { - "IncludeScopes": false, "LogLevel": { "Default": "Warning" } }, "spring": { @@ -21,4 +20,3 @@ "instance": { "port": 5001 } } } - From cf19c03da07aff1831a2e0796c70449c60889d1c Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 21:20:30 +0300 Subject: [PATCH 08/12] Update GraphQL sample --- samples/GraphQL/GraphQlDelegatingHandler.cs | 48 ++++++ samples/GraphQL/Models/Hero.cs | 7 + samples/GraphQL/Models/Query.cs | 20 +++ samples/GraphQL/Ocelot.Samples.GraphQL.csproj | 12 +- samples/GraphQL/Program.cs | 157 ++++-------------- .../GraphQL/Properties/launchSettings.json | 50 ++++-- samples/GraphQL/ocelot.json | 30 ++-- 7 files changed, 162 insertions(+), 162 deletions(-) create mode 100644 samples/GraphQL/GraphQlDelegatingHandler.cs create mode 100644 samples/GraphQL/Models/Hero.cs create mode 100644 samples/GraphQL/Models/Query.cs diff --git a/samples/GraphQL/GraphQlDelegatingHandler.cs b/samples/GraphQL/GraphQlDelegatingHandler.cs new file mode 100644 index 000000000..a9eb8354d --- /dev/null +++ b/samples/GraphQL/GraphQlDelegatingHandler.cs @@ -0,0 +1,48 @@ +using GraphQL; +using GraphQL.NewtonsoftJson; +using System.Net; +using System.Net.Http.Headers; + +namespace Ocelot.Samples.GraphQL; + +public class GraphQLDelegatingHandler : DelegatingHandler +{ + //private readonly ISchema _schema; + private readonly IDocumentExecuter _executer; + private readonly IGraphQLTextSerializer _serializer; + + public GraphQLDelegatingHandler(IDocumentExecuter executer, IGraphQLTextSerializer serializer) + { + _executer = executer; + _serializer = serializer; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + //try get query from body, could check http method :) + var query = await request.Content!.ReadAsStringAsync(cancellationToken); + + //if not body try query string, dont hack like this in real world.. + if (query.Length == 0) + { + var decoded = WebUtility.UrlDecode(request.RequestUri!.Query); + query = decoded.Replace("?query=", string.Empty); + } + + var result = await _executer.ExecuteAsync(_ => + { + _.Query = query; + }); + + // IGraphQLSerializer & IGraphQLTextSerializer: https://github.com/graphql-dotnet/graphql-dotnet/blob/master/docs2/site/docs/getting-started/transport.md#igraphqlserializer--igraphqltextserializer + var responseBody = _serializer.Serialize(result); + var media = new MediaTypeHeaderValue("application/graphql-response+json"); + var response = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(responseBody, media), + }; + + //ocelot will treat this like any other http request... + return response; + } +} diff --git a/samples/GraphQL/Models/Hero.cs b/samples/GraphQL/Models/Hero.cs new file mode 100644 index 000000000..26fa5b45a --- /dev/null +++ b/samples/GraphQL/Models/Hero.cs @@ -0,0 +1,7 @@ +namespace Ocelot.Samples.GraphQL.Models; + +public class Hero +{ + public int Id { get; set; } + public required string Name { get; set; } +} diff --git a/samples/GraphQL/Models/Query.cs b/samples/GraphQL/Models/Query.cs new file mode 100644 index 000000000..a6f973631 --- /dev/null +++ b/samples/GraphQL/Models/Query.cs @@ -0,0 +1,20 @@ +using GraphQL; + +namespace Ocelot.Samples.GraphQL.Models; + +public class Query +{ + private readonly List _heroes = new() + { + new Hero { Id = 1, Name = "R2-D2" }, + new Hero { Id = 2, Name = "Batman" }, + new Hero { Id = 3, Name = "Wonder Woman" }, + new Hero { Id = 4, Name = "Tom Pallister" } + }; + + [GraphQLMetadata("hero")] + public Hero? GetHero(int id) + { + return _heroes.FirstOrDefault(x => x.Id == id); + } +} diff --git a/samples/GraphQL/Ocelot.Samples.GraphQL.csproj b/samples/GraphQL/Ocelot.Samples.GraphQL.csproj index 029bce61b..1b6f0cf37 100644 --- a/samples/GraphQL/Ocelot.Samples.GraphQL.csproj +++ b/samples/GraphQL/Ocelot.Samples.GraphQL.csproj @@ -1,14 +1,12 @@  net9.0 - disable - disable + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals - - - PreserveNewest - - diff --git a/samples/GraphQL/Program.cs b/samples/GraphQL/Program.cs index cbfaa2078..74b44d6a7 100644 --- a/samples/GraphQL/Program.cs +++ b/samples/GraphQL/Program.cs @@ -1,133 +1,42 @@ -using GraphQL; -using GraphQL.Types; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; +using GraphQL.Types; using Ocelot.DependencyInjection; using Ocelot.Middleware; +using Ocelot.Samples.GraphQL; +using Ocelot.Samples.GraphQL.Models; using Ocelot.Samples.Web; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; -using GraphQL.NewtonsoftJson; -namespace Ocelot.Samples.GraphQL; +var schema = Schema.For(@" + type Hero { + id: Int + name: String + } -public class Hero + type Query { + hero(id: Int): Hero + } + ", _ => { - public int Id { get; set; } - public string Name { get; set; } -} - -public class Query + _.Types.Include(); +}); + +//_ = OcelotHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); + +// Ocelot Basic setup +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); +builder.Services + .AddSingleton(schema) + .AddOcelot(builder.Configuration) + .AddDelegatingHandler(); + +builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging")); +if (builder.Environment.IsDevelopment()) { - private readonly List _heroes = new() - { - new Hero { Id = 1, Name = "R2-D2" }, - new Hero { Id = 2, Name = "Batman" }, - new Hero { Id = 3, Name = "Wonder Woman" }, - new Hero { Id = 4, Name = "Tom Pallister" } - }; - - [GraphQLMetadata("hero")] - public Hero GetHero(int id) - { - return _heroes.FirstOrDefault(x => x.Id == id); - } + builder.Logging.AddConsole(); } -public class GraphQlDelegatingHandler : DelegatingHandler -{ - //private readonly ISchema _schema; - private readonly IDocumentExecuter _executer; - private readonly IGraphQLTextSerializer _serializer; - - public GraphQlDelegatingHandler(IDocumentExecuter executer, IGraphQLTextSerializer serializer) - { - _executer = executer; - _serializer = serializer; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - //try get query from body, could check http method :) - var query = await request.Content.ReadAsStringAsync(cancellationToken); - - //if not body try query string, dont hack like this in real world.. - if (query.Length == 0) - { - var decoded = WebUtility.UrlDecode(request.RequestUri.Query); - query = decoded.Replace("?query=", string.Empty); - } - - var result = await _executer.ExecuteAsync(_ => - { - _.Query = query; - }); - - // IGraphQLSerializer & IGraphQLTextSerializer: https://github.com/graphql-dotnet/graphql-dotnet/blob/master/docs2/site/docs/getting-started/transport.md#igraphqlserializer--igraphqltextserializer - var responseBody = _serializer.Serialize(result); - var media = new MediaTypeHeaderValue("application/graphql-response+json"); - var response = new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent(responseBody, media), - }; - - //ocelot will treat this like any other http request... - return response; - } -} - -public class Program -{ - public static void Main(string[] args) - { - var schema = Schema.For(@" - type Hero { - id: Int - name: String - } - - type Query { - hero(id: Int): Hero - } - ", _ => - { - _.Types.Include(); - }); - - OcelotHostBuilder.Create(args) - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json", false, false) - .AddEnvironmentVariables(); - }) - .ConfigureServices(s => - { - s.AddSingleton(schema); - s.AddOcelot() - .AddDelegatingHandler(); - }) - .ConfigureLogging((hostingContext, logging) => - { - logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); - logging.AddConsole(); - }) - .UseIISIntegration() - .Configure(app => - { - app.UseOcelot().Wait(); - }) - .Build() - .Run(); - } -} +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/GraphQL/Properties/launchSettings.json b/samples/GraphQL/Properties/launchSettings.json index ec10c2c0c..43bffabf2 100644 --- a/samples/GraphQL/Properties/launchSettings.json +++ b/samples/GraphQL/Properties/launchSettings.json @@ -1,27 +1,51 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:53639/", - "sslPort": 0 - } - }, "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "graphql", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5559" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "graphql", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7781;http://localhost:5559" + }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, + "launchUrl": "graphql", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "OcelotGraphQL": { - "commandName": "Project", + "WSL": { + "commandName": "WSL2", "launchBrowser": true, + "launchUrl": "https://localhost:7781/graphql", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7781;http://localhost:5559" }, - "applicationUrl": "http://localhost:53640/" + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62559/", + "sslPort": 44359 } } -} \ No newline at end of file +} diff --git a/samples/GraphQL/ocelot.json b/samples/GraphQL/ocelot.json index 3529e0ba8..5bde96156 100644 --- a/samples/GraphQL/ocelot.json +++ b/samples/GraphQL/ocelot.json @@ -1,19 +1,13 @@ { - "Routes": [ - { - "DownstreamPathTemplate": "/", - "DownstreamScheme": "http", - "DownstreamHostAndPorts": [ - { - "Host": "jsonplaceholder.typicode.com", - "Port": 80 - } - ], - "UpstreamPathTemplate": "/graphql", - "DelegatingHandlers": [ - "GraphQlDelegatingHandler" - ] - } - ] - } - \ No newline at end of file + "Routes": [ + { + "UpstreamPathTemplate": "/graphql", + "DownstreamPathTemplate": "/", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { "Host": "jsonplaceholder.typicode.com", "Port": 80 } + ], + "DelegatingHandlers": [ "GraphQLDelegatingHandler" ] + } + ] +} From f478eeb5db01bc53b3c193f089239f0f8b3c02e0 Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 21:53:51 +0300 Subject: [PATCH 09/12] Update Kubernetes sample --- samples/Kubernetes/ApiGateway/Dockerfile | 4 +- ...celot.Samples.Kubernetes.ApiGateway.csproj | 8 +- samples/Kubernetes/ApiGateway/Program.cs | 42 +++++----- .../ApiGateway/Properties/launchSettings.json | 48 ++++++++---- samples/Kubernetes/ApiGateway/Startup.cs | 31 -------- .../ApiGateway/appsettings.Development.json | 6 +- samples/Kubernetes/ApiGateway/ocelot.json | 15 +++- .../Controllers/ValuesController.cs | 1 - .../Controllers/WeatherForecastController.cs | 4 - .../Kubernetes/DownstreamService/Dockerfile | 4 +- .../Models/WeatherForecast.cs | 9 +-- ...amples.Kubernetes.DownstreamService.csproj | 8 +- .../Kubernetes/DownstreamService/Program.cs | 77 +++++++------------ .../Properties/launchSettings.json | 51 ++++++++---- .../appsettings.Development.json | 6 +- 15 files changed, 155 insertions(+), 159 deletions(-) delete mode 100644 samples/Kubernetes/ApiGateway/Startup.cs diff --git a/samples/Kubernetes/ApiGateway/Dockerfile b/samples/Kubernetes/ApiGateway/Dockerfile index 990742e4a..568b81ba5 100644 --- a/samples/Kubernetes/ApiGateway/Dockerfile +++ b/samples/Kubernetes/ApiGateway/Dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src COPY ["ApiGateway/Ocelot.Samples.OcelotKube.ApiGateway.csproj", "ApiGateway/"] RUN dotnet restore "ApiGateway/Ocelot.Samples.OcelotKube.ApiGateway.csproj" diff --git a/samples/Kubernetes/ApiGateway/Ocelot.Samples.Kubernetes.ApiGateway.csproj b/samples/Kubernetes/ApiGateway/Ocelot.Samples.Kubernetes.ApiGateway.csproj index 8cc1b8144..7236bee15 100644 --- a/samples/Kubernetes/ApiGateway/Ocelot.Samples.Kubernetes.ApiGateway.csproj +++ b/samples/Kubernetes/ApiGateway/Ocelot.Samples.Kubernetes.ApiGateway.csproj @@ -1,9 +1,11 @@  net9.0 - disable - disable - InProcess + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals Linux diff --git a/samples/Kubernetes/ApiGateway/Program.cs b/samples/Kubernetes/ApiGateway/Program.cs index 80e6e898f..c6eda7ab2 100644 --- a/samples/Kubernetes/ApiGateway/Program.cs +++ b/samples/Kubernetes/ApiGateway/Program.cs @@ -1,25 +1,27 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; +using Ocelot.Provider.Kubernetes; using Ocelot.Samples.Web; -namespace Ocelot.Samples.Kubernetes.ApiGateway; +//_ = OcelotHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); -public class Program +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); +builder.Services + .AddOcelot(builder.Configuration) + .AddKubernetes(); + +if (builder.Environment.IsDevelopment()) +{ + builder.Logging.AddConsole(); +} + +var app = builder.Build(); +if (app.Environment.IsDevelopment()) { - public static void Main(string[] args) - { - OcelotHostBuilder.Create(args) - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json", false, false) - .AddEnvironmentVariables(); - }) - .UseStartup() - .Build() - .Run(); - } + app.UseDeveloperExceptionPage(); } +await app.UseOcelot(); +app.Run(); diff --git a/samples/Kubernetes/ApiGateway/Properties/launchSettings.json b/samples/Kubernetes/ApiGateway/Properties/launchSettings.json index 5684b7657..fef85746b 100644 --- a/samples/Kubernetes/ApiGateway/Properties/launchSettings.json +++ b/samples/Kubernetes/ApiGateway/Properties/launchSettings.json @@ -1,34 +1,56 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:52363", - "sslPort": 0 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", + "http": { + "commandName": "Project", "launchBrowser": true, "launchUrl": "values", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5560" }, - "ApiGateway": { + "https": { "commandName": "Project", "launchBrowser": true, "launchUrl": "values", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:5000" + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7782;http://localhost:5560" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "WSL": { + "commandName": "WSL2", + "launchBrowser": true, + "launchUrl": "https://localhost:7782/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7782;http://localhost:5560" + }, + "distributionName": "" }, "Docker": { "commandName": "Docker", "launchBrowser": true, "launchUrl": "{Scheme}://localhost:{ServicePort}/values" } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62560/", + "sslPort": 44360 + } } } diff --git a/samples/Kubernetes/ApiGateway/Startup.cs b/samples/Kubernetes/ApiGateway/Startup.cs deleted file mode 100644 index 7388b2f02..000000000 --- a/samples/Kubernetes/ApiGateway/Startup.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Ocelot.DependencyInjection; -using Ocelot.Middleware; -using Ocelot.Provider.Kubernetes; - -namespace Ocelot.Samples.Kubernetes.ApiGateway; - -public class Startup -{ - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddOcelot() - .AddKubernetes(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseOcelot().Wait(); - } -} diff --git a/samples/Kubernetes/ApiGateway/appsettings.Development.json b/samples/Kubernetes/ApiGateway/appsettings.Development.json index e203e9407..07053a355 100644 --- a/samples/Kubernetes/ApiGateway/appsettings.Development.json +++ b/samples/Kubernetes/ApiGateway/appsettings.Development.json @@ -2,8 +2,10 @@ "Logging": { "LogLevel": { "Default": "Debug", - "System": "Information", - "Microsoft": "Information" + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" } } } diff --git a/samples/Kubernetes/ApiGateway/ocelot.json b/samples/Kubernetes/ApiGateway/ocelot.json index f4a5af0b8..b3cfcbae8 100644 --- a/samples/Kubernetes/ApiGateway/ocelot.json +++ b/samples/Kubernetes/ApiGateway/ocelot.json @@ -1,11 +1,20 @@ { "Routes": [ { + "ServiceName": "downstreamservice", + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/values", + "DownstreamPathTemplate": "/api/values", + "DownstreamScheme": "http" + }, + { + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/nodiscovery/values", "DownstreamPathTemplate": "/api/values", "DownstreamScheme": "http", - "UpstreamPathTemplate": "/values", - "ServiceName": "downstreamservice", - "UpstreamHttpMethod": [ "Get" ] + "DownstreamHostAndPorts": [ + { "Host": "localhost", "Port": 5561 } + ] } ], "GlobalConfiguration": { diff --git a/samples/Kubernetes/DownstreamService/Controllers/ValuesController.cs b/samples/Kubernetes/DownstreamService/Controllers/ValuesController.cs index 906c0e5b5..c029eb7a5 100644 --- a/samples/Kubernetes/DownstreamService/Controllers/ValuesController.cs +++ b/samples/Kubernetes/DownstreamService/Controllers/ValuesController.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; namespace Ocelot.Samples.Kubernetes.DownstreamService.Controllers; diff --git a/samples/Kubernetes/DownstreamService/Controllers/WeatherForecastController.cs b/samples/Kubernetes/DownstreamService/Controllers/WeatherForecastController.cs index 8b5242705..8836c7ab0 100644 --- a/samples/Kubernetes/DownstreamService/Controllers/WeatherForecastController.cs +++ b/samples/Kubernetes/DownstreamService/Controllers/WeatherForecastController.cs @@ -1,8 +1,4 @@ using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; namespace Ocelot.Samples.Kubernetes.DownstreamService.Controllers; diff --git a/samples/Kubernetes/DownstreamService/Dockerfile b/samples/Kubernetes/DownstreamService/Dockerfile index 985096fcc..6d672663e 100644 --- a/samples/Kubernetes/DownstreamService/Dockerfile +++ b/samples/Kubernetes/DownstreamService/Dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src COPY ["DownstreamService/Ocelot.Samples.OcelotKube.DownstreamService.csproj", "DownstreamService/"] RUN dotnet restore "DownstreamService/Ocelot.Samples.OcelotKube.DownstreamService.csproj" diff --git a/samples/Kubernetes/DownstreamService/Models/WeatherForecast.cs b/samples/Kubernetes/DownstreamService/Models/WeatherForecast.cs index 83e76c5fa..7f7643b5b 100644 --- a/samples/Kubernetes/DownstreamService/Models/WeatherForecast.cs +++ b/samples/Kubernetes/DownstreamService/Models/WeatherForecast.cs @@ -1,14 +1,9 @@ -using System; - -namespace Ocelot.Samples.Kubernetes.DownstreamService.Models; +namespace Ocelot.Samples.Kubernetes.DownstreamService.Models; public class WeatherForecast { public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string Summary { get; set; } + public string? Summary { get; set; } } diff --git a/samples/Kubernetes/DownstreamService/Ocelot.Samples.Kubernetes.DownstreamService.csproj b/samples/Kubernetes/DownstreamService/Ocelot.Samples.Kubernetes.DownstreamService.csproj index 2773d6759..ec3e7e8a5 100644 --- a/samples/Kubernetes/DownstreamService/Ocelot.Samples.Kubernetes.DownstreamService.csproj +++ b/samples/Kubernetes/DownstreamService/Ocelot.Samples.Kubernetes.DownstreamService.csproj @@ -1,9 +1,11 @@ net9.0 - disable - disable - InProcess + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals Linux diff --git a/samples/Kubernetes/DownstreamService/Program.cs b/samples/Kubernetes/DownstreamService/Program.cs index 9f99c5468..b304a9e2a 100644 --- a/samples/Kubernetes/DownstreamService/Program.cs +++ b/samples/Kubernetes/DownstreamService/Program.cs @@ -1,59 +1,34 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Ocelot.Samples.Web; +using Ocelot.Samples.Web; using System.Text.Json; using System.Text.Json.Serialization; -namespace Ocelot.Samples.Kubernetes.DownstreamService; +_ = DownstreamHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); -public class Program -{ - public static void Main(string[] args) - { - //var builder = DownstreamHostBuilder.Create(args); - var builder = WebApplication.CreateBuilder(args); - - builder.Services - // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle - .AddEndpointsApiExplorer() - .AddSwaggerGen() - - .AddControllers() - .AddJsonOptions(options => - { - options.AllowInputFormatterExceptionMessages = true; - - var jOptions = options.JsonSerializerOptions; - jOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true)); - jOptions.PropertyNameCaseInsensitive = true; - jOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - }); - - AddApplicationServices(builder.Services); +builder.Services + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + .AddEndpointsApiExplorer() + .AddSwaggerGen() - var app = builder.Build(); - - // Configure the HTTP request pipeline. - if (app.Environment.IsDevelopment()) - { - app.UseSwagger(); - app.UseSwaggerUI(); - } - - app.UseHttpsRedirection(); - app.UseAuthorization(); + .AddHttpClient() + .AddControllers() + .AddJsonOptions(options => + { + options.AllowInputFormatterExceptionMessages = true; - app.MapControllers(); - app.Run(); - } + var jOptions = options.JsonSerializerOptions; + jOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true)); + jOptions.PropertyNameCaseInsensitive = true; + jOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + }); - private static void AddApplicationServices(IServiceCollection services) - { - services.AddHttpClient(); // to keep performance of HTTP Client high - //services.AddSingleton - //services.AddScoped - //services.AddTransient - } +var app = builder.Build(); +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); } +app.UseHttpsRedirection(); +app.UseAuthorization(); +app.MapControllers(); +app.Run(); diff --git a/samples/Kubernetes/DownstreamService/Properties/launchSettings.json b/samples/Kubernetes/DownstreamService/Properties/launchSettings.json index 6f9313866..cf5da7198 100644 --- a/samples/Kubernetes/DownstreamService/Properties/launchSettings.json +++ b/samples/Kubernetes/DownstreamService/Properties/launchSettings.json @@ -1,35 +1,56 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:56411", - "sslPort": 0 - } - }, - "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { - "IIS Express": { - "commandName": "IISExpress", + "http": { + "commandName": "Project", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5561" }, - "DownstreamService": { + "https": { "commandName": "Project", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:5000" + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7783;http://localhost:5561" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "WSL": { + "commandName": "WSL2", + "launchBrowser": true, + "launchUrl": "https://localhost:7783/swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7783;http://localhost:5561" + }, + "distributionName": "" }, "Docker": { "commandName": "Docker", "launchBrowser": true, - "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger" + "launchUrl": "{Scheme}://localhost:{ServicePort}/swagger" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62561/", + "sslPort": 44361 } } } diff --git a/samples/Kubernetes/DownstreamService/appsettings.Development.json b/samples/Kubernetes/DownstreamService/appsettings.Development.json index e203e9407..07053a355 100644 --- a/samples/Kubernetes/DownstreamService/appsettings.Development.json +++ b/samples/Kubernetes/DownstreamService/appsettings.Development.json @@ -2,8 +2,10 @@ "Logging": { "LogLevel": { "Default": "Debug", - "System": "Information", - "Microsoft": "Information" + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" } } } From 08cf4d6cb05d39f1f972f6b5cbd3f4933102b75c Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 22:18:34 +0300 Subject: [PATCH 10/12] Update OpenTracing sample --- .../Ocelot.Samples.OpenTracing.csproj | 19 ++--- samples/OpenTracing/Program.cs | 69 +++++++------------ .../Properties/launchSettings.json | 51 ++++++++++++++ .../OpenTracing/appsettings.Development.json | 8 ++- samples/OpenTracing/appsettings.json | 4 +- samples/OpenTracing/ocelot.json | 21 +++--- 6 files changed, 94 insertions(+), 78 deletions(-) create mode 100644 samples/OpenTracing/Properties/launchSettings.json diff --git a/samples/OpenTracing/Ocelot.Samples.OpenTracing.csproj b/samples/OpenTracing/Ocelot.Samples.OpenTracing.csproj index 626779122..cf1cb1efe 100644 --- a/samples/OpenTracing/Ocelot.Samples.OpenTracing.csproj +++ b/samples/OpenTracing/Ocelot.Samples.OpenTracing.csproj @@ -1,9 +1,11 @@  - Exe net9.0 - disable - disable + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals @@ -16,15 +18,4 @@ - - - true - - - true - - - true - - diff --git a/samples/OpenTracing/Program.cs b/samples/OpenTracing/Program.cs index 829c4e33f..cbffd8598 100644 --- a/samples/OpenTracing/Program.cs +++ b/samples/OpenTracing/Program.cs @@ -1,55 +1,34 @@ -using Jaeger; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Samples.Web; using Ocelot.Tracing.OpenTracing; using OpenTracing.Util; -using System.IO; -namespace Ocelot.Samples.OpenTracing; +//_ = OcelotHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); -public static class Program -{ - public static void Main(string[] args) +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); +builder.Services + .AddSingleton(sp => { - OcelotHostBuilder.Create(args) - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", - optional: true, reloadOnChange: false) - .AddJsonFile("ocelot.json", optional: false, reloadOnChange: true) - .AddEnvironmentVariables(); - }) - .ConfigureServices((context, services) => - { - services.AddSingleton(sp => - { - var loggerFactory = sp.GetService(); - var config = new Jaeger.Configuration(context.HostingEnvironment.ApplicationName, loggerFactory); - var tracer = config.GetTracer(); - GlobalTracer.Register(tracer); - return tracer; - }) - .AddOcelot() - .AddOpenTracing(); - }) - .ConfigureLogging(logging => - { - logging.AddConsole(); - }) - .Configure(async app => - { - await app.UseOcelot(); - }) - .Build() - .Run(); - } + var loggerFactory = sp.GetService(); + var config = new Jaeger.Configuration(builder.Environment.ApplicationName, loggerFactory); + var tracer = config.GetTracer(); + GlobalTracer.Register(tracer); + return tracer; + }) + .AddOcelot(builder.Configuration) + .AddOpenTracing(); + +if (builder.Environment.IsDevelopment()) +{ + builder.Logging.AddConsole(); } + +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/OpenTracing/Properties/launchSettings.json b/samples/OpenTracing/Properties/launchSettings.json new file mode 100644 index 000000000..bf08859e3 --- /dev/null +++ b/samples/OpenTracing/Properties/launchSettings.json @@ -0,0 +1,51 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "posts/1", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5562" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "posts/1", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7784;http://localhost:5562" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "posts/1", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "WSL": { + "commandName": "WSL2", + "launchBrowser": true, + "launchUrl": "https://localhost:7784/posts/1", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7784;http://localhost:5562" + }, + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62562/", + "sslPort": 44362 + } + } +} diff --git a/samples/OpenTracing/appsettings.Development.json b/samples/OpenTracing/appsettings.Development.json index 8983e0fc1..07053a355 100644 --- a/samples/OpenTracing/appsettings.Development.json +++ b/samples/OpenTracing/appsettings.Development.json @@ -1,9 +1,11 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" } } } diff --git a/samples/OpenTracing/appsettings.json b/samples/OpenTracing/appsettings.json index d9d9a9bff..def9159a7 100644 --- a/samples/OpenTracing/appsettings.json +++ b/samples/OpenTracing/appsettings.json @@ -1,9 +1,7 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Default": "Warning" } }, "AllowedHosts": "*" diff --git a/samples/OpenTracing/ocelot.json b/samples/OpenTracing/ocelot.json index a5a670321..e96ef610a 100644 --- a/samples/OpenTracing/ocelot.json +++ b/samples/OpenTracing/ocelot.json @@ -1,24 +1,19 @@ { - "ReRoutes": [ + "Routes": [ { - "HttpHandlerOptions": { - "UseTracing": true - }, + "UpstreamHttpMethod": [ "Get" ], + "UpstreamPathTemplate": "/posts/{id}", "DownstreamPathTemplate": "/todos/{id}", "DownstreamScheme": "https", "DownstreamHostAndPorts": [ - { - "Host": "jsonplaceholder.typicode.com", - "Port": 443 - } + { "Host": "jsonplaceholder.typicode.com", "Port": 443 } ], - "UpstreamPathTemplate": "/posts/{id}", - "UpstreamHttpMethod": [ - "Get" - ] + "HttpHandlerOptions": { + "UseTracing": true + } } ], "GlobalConfiguration": { - "BaseUrl": "https://localhost:5000" + "BaseUrl": "https://localhost:7784" } } From 45b5da376994a8098f6f93f79b6d32a9d301dbcd Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Wed, 25 Dec 2024 23:17:47 +0300 Subject: [PATCH 11/12] Update ServiceDiscovery sample --- ...Samples.ServiceDiscovery.ApiGateway.csproj | 7 +- .../ServiceDiscovery/ApiGateway/Program.cs | 84 ++++++++----------- .../ApiGateway/Properties/launchSettings.json | 49 ++++++++--- .../MyServiceDiscoveryProvider.cs | 10 ++- .../MyServiceDiscoveryProviderFactory.cs | 1 - .../ApiGateway/appsettings.Development.json | 11 +++ .../ApiGateway/appsettings.json | 9 +- .../ServiceDiscovery/ApiGateway/ocelot.json | 23 +++-- ....ServiceDiscovery.DownstreamService.csproj | 7 +- .../DownstreamService/Program.cs | 46 ++++++++-- .../Properties/launchSettings.json | 18 +++- .../DownstreamService/Startup.cs | 64 -------------- .../appsettings.Development.json | 9 +- .../DownstreamService/appsettings.json | 5 +- 14 files changed, 177 insertions(+), 166 deletions(-) create mode 100644 samples/ServiceDiscovery/ApiGateway/appsettings.Development.json delete mode 100644 samples/ServiceDiscovery/DownstreamService/Startup.cs diff --git a/samples/ServiceDiscovery/ApiGateway/Ocelot.Samples.ServiceDiscovery.ApiGateway.csproj b/samples/ServiceDiscovery/ApiGateway/Ocelot.Samples.ServiceDiscovery.ApiGateway.csproj index e82285e91..42df3ceea 100644 --- a/samples/ServiceDiscovery/ApiGateway/Ocelot.Samples.ServiceDiscovery.ApiGateway.csproj +++ b/samples/ServiceDiscovery/ApiGateway/Ocelot.Samples.ServiceDiscovery.ApiGateway.csproj @@ -1,8 +1,11 @@ net9.0 - disable - disable + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals diff --git a/samples/ServiceDiscovery/ApiGateway/Program.cs b/samples/ServiceDiscovery/ApiGateway/Program.cs index 143c223b5..6670ef56e 100644 --- a/samples/ServiceDiscovery/ApiGateway/Program.cs +++ b/samples/ServiceDiscovery/ApiGateway/Program.cs @@ -1,61 +1,45 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.DependencyInjection.Extensions; using Ocelot.DependencyInjection; using Ocelot.Middleware; +using Ocelot.Samples.ServiceDiscovery.ApiGateway.ServiceDiscovery; using Ocelot.Samples.Web; using Ocelot.ServiceDiscovery; -namespace Ocelot.Samples.ServiceDiscovery.ApiGateway; +_ = OcelotHostBuilder.Create(args); +var builder = WebApplication.CreateBuilder(args); -using ServiceDiscovery; +builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); -public class Program -{ - public static void Main(string[] args) - { - OcelotHostBuilder.Create(args) - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json", false, false) - .AddEnvironmentVariables(); - }) - .ConfigureServices(s => - { - // Initialize from app configuration or hardcode/choose the best option. - bool easyWay = true; +// Initialize from app configuration or hardcode/choose the best option. +bool easyWay = true; - if (easyWay) - { - // Option #1. Define custom finder delegate to instantiate custom provider - // by default factory which is ServiceDiscoveryProviderFactory - s.AddSingleton((serviceProvider, config, downstreamRoute) - => new MyServiceDiscoveryProvider(serviceProvider, config, downstreamRoute)); - } - else - { - // Option #2. Abstract from default factory (ServiceDiscoveryProviderFactory) and from FinderDelegate, - // and build custom factory by implementation of the IServiceDiscoveryProviderFactory interface. - s.RemoveAll(); - s.AddSingleton(); +if (easyWay) +{ + // Option #1. Define custom finder delegate to instantiate custom provider + // by default factory which is ServiceDiscoveryProviderFactory + builder.Services.AddSingleton((serviceProvider, config, downstreamRoute) + => new MyServiceDiscoveryProvider(serviceProvider, config, downstreamRoute)); +} +else +{ + // Option #2. Abstract from default factory (ServiceDiscoveryProviderFactory) and from FinderDelegate, + // and build custom factory by implementation of the IServiceDiscoveryProviderFactory interface. + builder.Services.RemoveAll() + .AddSingleton(); - // Will not be called, but it is required for internal validators, aka life hack - s.AddSingleton((serviceProvider, config, downstreamRoute) - => null); - } + // Will not be called, but it is required for internal validators, aka life hack + builder.Services.AddSingleton((serviceProvider, config, downstreamRoute) => null); +} +builder.Services + .AddOcelot(builder.Configuration); - s.AddOcelot(); - }) - .Configure(async a => - { - await a.UseOcelot(); - }) - .Build() - .Run(); - } +if (builder.Environment.IsDevelopment()) +{ + builder.Logging.AddConsole(); } + +var app = builder.Build(); +await app.UseOcelot(); +app.Run(); diff --git a/samples/ServiceDiscovery/ApiGateway/Properties/launchSettings.json b/samples/ServiceDiscovery/ApiGateway/Properties/launchSettings.json index 4262362b0..7890335eb 100644 --- a/samples/ServiceDiscovery/ApiGateway/Properties/launchSettings.json +++ b/samples/ServiceDiscovery/ApiGateway/Properties/launchSettings.json @@ -1,28 +1,51 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:54060/", - "sslPort": 0 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", + "http": { + "commandName": "Project", "launchBrowser": true, + "launchUrl": "categories", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5563" }, - "ApiGateway": { + "https": { "commandName": "Project", "launchBrowser": true, "launchUrl": "categories", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:5000/" + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7785;http://localhost:5563" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "categories", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "WSL": { + "commandName": "WSL2", + "launchBrowser": true, + "launchUrl": "https://localhost:7785/categories", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7785;http://localhost:5563" + }, + "distributionName": "" + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62563/", + "sslPort": 44363 } } } diff --git a/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProvider.cs b/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProvider.cs index b874ffedb..67817cd2d 100644 --- a/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProvider.cs +++ b/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProvider.cs @@ -1,9 +1,7 @@ using Ocelot.Configuration; +using Ocelot.Metadata; using Ocelot.ServiceDiscovery.Providers; using Ocelot.Values; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; namespace Ocelot.Samples.ServiceDiscovery.ApiGateway.ServiceDiscovery; @@ -28,12 +26,16 @@ public Task> GetAsync() // Apply configuration checks // ... if (_config.Host) + if (_downstreamRoute.ServiceName.Equals("downstream-service")) { + var instance = _downstreamRoute.GetMetadata("instance"); + var srv = instance.Split(':'); + //For this example we simply do a manual match to a single service var service = new Service( name: "downstream-service", - hostAndPort: new ServiceHostAndPort("localhost", 5001), + hostAndPort: new ServiceHostAndPort(srv[0], int.Parse(srv[1])), id: "downstream-service-1", version: "1.0", tags: new string[] { "downstream", "hardcoded" } diff --git a/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProviderFactory.cs b/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProviderFactory.cs index 1978ebd3d..52dbd512b 100644 --- a/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProviderFactory.cs +++ b/samples/ServiceDiscovery/ApiGateway/ServiceDiscovery/MyServiceDiscoveryProviderFactory.cs @@ -3,7 +3,6 @@ using Ocelot.Responses; using Ocelot.ServiceDiscovery; using Ocelot.ServiceDiscovery.Providers; -using System; namespace Ocelot.Samples.ServiceDiscovery.ApiGateway.ServiceDiscovery; diff --git a/samples/ServiceDiscovery/ApiGateway/appsettings.Development.json b/samples/ServiceDiscovery/ApiGateway/appsettings.Development.json new file mode 100644 index 000000000..07053a355 --- /dev/null +++ b/samples/ServiceDiscovery/ApiGateway/appsettings.Development.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" + } + } +} diff --git a/samples/ServiceDiscovery/ApiGateway/appsettings.json b/samples/ServiceDiscovery/ApiGateway/appsettings.json index 9c1fbf602..def9159a7 100644 --- a/samples/ServiceDiscovery/ApiGateway/appsettings.json +++ b/samples/ServiceDiscovery/ApiGateway/appsettings.json @@ -1,11 +1,8 @@ -{ +{ "Logging": { - "IncludeScopes": true, "LogLevel": { - "Default": "Information", - "System": "Information", - "Microsoft": "Information" + "Default": "Warning" } }, - "Urls": "http://localhost:5000" + "AllowedHosts": "*" } diff --git a/samples/ServiceDiscovery/ApiGateway/ocelot.json b/samples/ServiceDiscovery/ApiGateway/ocelot.json index 7460dcc2a..9b0dc00f6 100644 --- a/samples/ServiceDiscovery/ApiGateway/ocelot.json +++ b/samples/ServiceDiscovery/ApiGateway/ocelot.json @@ -1,19 +1,32 @@ { "Routes": [ { - "DownstreamPathTemplate": "/categories", - "DownstreamScheme": "http", + "ServiceName": "downstream-service", + "UpstreamHttpMethod": [ "Get" ], "UpstreamPathTemplate": "/categories", + "DownstreamPathTemplate": "/categories", + "DownstreamScheme": "https", + "FileCacheOptions": { "TtlSeconds": 15 }, + "Metadata": { + "instance": "localhost:7786" + } + }, + { "ServiceName": "downstream-service", "UpstreamHttpMethod": [ "Get" ], - "FileCacheOptions": { "TtlSeconds": 15 } + "UpstreamPathTemplate": "/health", + "DownstreamPathTemplate": "/health", + "DownstreamScheme": "https", + "Metadata": { + "instance": "localhost:7786" + } } ], "GlobalConfiguration": { "RequestIdKey": "OcRequestId", "AdministrationPath": "/administration", - "ServiceDiscoveryProvider": { - "Type": "MyServiceDiscoveryProvider" + "ServiceDiscoveryProvider": { + "Type": "MyServiceDiscoveryProvider" } } } diff --git a/samples/ServiceDiscovery/DownstreamService/Ocelot.Samples.ServiceDiscovery.DownstreamService.csproj b/samples/ServiceDiscovery/DownstreamService/Ocelot.Samples.ServiceDiscovery.DownstreamService.csproj index b310e7670..4ecfa9a5d 100644 --- a/samples/ServiceDiscovery/DownstreamService/Ocelot.Samples.ServiceDiscovery.DownstreamService.csproj +++ b/samples/ServiceDiscovery/DownstreamService/Ocelot.Samples.ServiceDiscovery.DownstreamService.csproj @@ -2,11 +2,14 @@ net9.0 - disable enable + enable + 24.0.0 + 24.0.0 + ThreeMammals - + diff --git a/samples/ServiceDiscovery/DownstreamService/Program.cs b/samples/ServiceDiscovery/DownstreamService/Program.cs index b2778ce8d..8d87c4ed8 100644 --- a/samples/ServiceDiscovery/DownstreamService/Program.cs +++ b/samples/ServiceDiscovery/DownstreamService/Program.cs @@ -1,16 +1,44 @@ global using Microsoft.AspNetCore.Mvc; -using Ocelot.Samples.Web; +using System.Text.Json; +using System.Text.Json.Serialization; [assembly: ApiController] -namespace Ocelot.Samples.ServiceDiscovery.DownstreamService; +var builder = WebApplication.CreateBuilder(args); -public class Program -{ - public static void Main(string[] args) +builder.Services + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + .AddEndpointsApiExplorer() + .AddSwaggerGen() + + .AddHttpClient() // to keep performance of HTTP Client high + .AddControllers() + .AddJsonOptions(options => { - DownstreamHostBuilder.Create(args) - .UseStartup() - .Build(); //.Run(); - } + options.AllowInputFormatterExceptionMessages = true; + var jOptions = options.JsonSerializerOptions; + jOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true)); + jOptions.PropertyNameCaseInsensitive = true; + jOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + }); + +if (builder.Environment.IsDevelopment()) +{ + builder.Logging.AddConsole(); +} + +var app = builder.Build(); +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); + app.UseDeveloperExceptionPage(); } +else +{ + app.UseHttpsRedirection(); +} + +app.UseRouting(); +app.MapControllers(); +app.Run(); diff --git a/samples/ServiceDiscovery/DownstreamService/Properties/launchSettings.json b/samples/ServiceDiscovery/DownstreamService/Properties/launchSettings.json index a6ccfad22..8088a6c60 100644 --- a/samples/ServiceDiscovery/DownstreamService/Properties/launchSettings.json +++ b/samples/ServiceDiscovery/DownstreamService/Properties/launchSettings.json @@ -8,7 +8,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "dotnetRunMessages": true, - "applicationUrl": "http://localhost:5001" + "applicationUrl": "http://localhost:5564" }, "https": { "commandName": "Project", @@ -18,7 +18,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "dotnetRunMessages": true, - "applicationUrl": "https://localhost:7001;http://localhost:5001" + "applicationUrl": "https://localhost:7786;http://localhost:5564" }, "IIS Express": { "commandName": "IISExpress", @@ -28,6 +28,16 @@ "ASPNETCORE_ENVIRONMENT": "Development" } }, + "WSL": { + "commandName": "WSL2", + "launchBrowser": true, + "launchUrl": "https://localhost:7786/swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7786;http://localhost:5564" + }, + "distributionName": "" + }, "Docker": { "commandName": "Docker", "launchBrowser": true, @@ -41,8 +51,8 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:65100", - "sslPort": 44373 + "applicationUrl": "http://localhost:62564/", + "sslPort": 44364 } } } diff --git a/samples/ServiceDiscovery/DownstreamService/Startup.cs b/samples/ServiceDiscovery/DownstreamService/Startup.cs deleted file mode 100644 index e605c7ba3..000000000 --- a/samples/ServiceDiscovery/DownstreamService/Startup.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Ocelot.Samples.ServiceDiscovery.DownstreamService; - -public class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services - // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle - .AddEndpointsApiExplorer() - .AddSwaggerGen() - - .AddControllers() - .AddJsonOptions(options => - { - options.AllowInputFormatterExceptionMessages = true; - var jOptions = options.JsonSerializerOptions; - jOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, true)); - jOptions.PropertyNameCaseInsensitive = true; - jOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - }); - - AddApplicationServices(services); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseSwagger(); - app.UseSwaggerUI(); - app.UseDeveloperExceptionPage(); - } - else - { - app.UseHttpsRedirection(); - } - - app.UseRouting(); - app.UseEndpoints(configure => - { - configure.MapControllers(); - }); - } - - private static void AddApplicationServices(IServiceCollection services) - { - services.AddHttpClient(); // to keep performance of HTTP Client high - //services.AddSingleton - //services.AddScoped - //services.AddTransient - } -} diff --git a/samples/ServiceDiscovery/DownstreamService/appsettings.Development.json b/samples/ServiceDiscovery/DownstreamService/appsettings.Development.json index b0bacf428..07053a355 100644 --- a/samples/ServiceDiscovery/DownstreamService/appsettings.Development.json +++ b/samples/ServiceDiscovery/DownstreamService/appsettings.Development.json @@ -1,8 +1,11 @@ -{ +{ "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" } } } diff --git a/samples/ServiceDiscovery/DownstreamService/appsettings.json b/samples/ServiceDiscovery/DownstreamService/appsettings.json index 223027717..def9159a7 100644 --- a/samples/ServiceDiscovery/DownstreamService/appsettings.json +++ b/samples/ServiceDiscovery/DownstreamService/appsettings.json @@ -1,8 +1,7 @@ -{ +{ "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Default": "Warning" } }, "AllowedHosts": "*" From 7b72c6243cbd06b866d995946e92bb7b1cab1f77 Mon Sep 17 00:00:00 2001 From: Raman Maksimchuk Date: Thu, 26 Dec 2024 00:30:45 +0300 Subject: [PATCH 12/12] Update ServiceFabric sample --- ...ot.Samples.ServiceFabric.ApiGateway.csproj | 14 ++-- .../ApiGateway/OcelotApplicationApiGateway.cs | 1 - samples/ServiceFabric/ApiGateway/Program.cs | 64 +++++---------- .../ApiGateway/Properties/launchSettings.json | 57 ++++++++++--- .../ApiGateway/ServiceEventListener.cs | 31 +++---- .../ApiGateway/ServiceEventSource.cs | 1 - .../ApiGateway/WebCommunicationListener.cs | 82 ++++++------------- .../ApiGateway/appsettings.Development.json | 11 +++ .../ServiceFabric/ApiGateway/appsettings.json | 10 +-- samples/ServiceFabric/ApiGateway/ocelot.json | 4 +- .../DownstreamService/ApiGateway.cs | 37 +++++---- .../Controllers/ValuesController.cs | 1 - ...les.ServiceFabric.DownstreamService.csproj | 13 ++- .../DownstreamService/Program.cs | 45 ++++------ .../Properties/launchSettings.json | 6 +- .../DownstreamService/ServiceEventSource.cs | 2 - .../DownstreamService/Startup.cs | 32 -------- 17 files changed, 169 insertions(+), 242 deletions(-) create mode 100644 samples/ServiceFabric/ApiGateway/appsettings.Development.json delete mode 100644 samples/ServiceFabric/DownstreamService/Startup.cs diff --git a/samples/ServiceFabric/ApiGateway/Ocelot.Samples.ServiceFabric.ApiGateway.csproj b/samples/ServiceFabric/ApiGateway/Ocelot.Samples.ServiceFabric.ApiGateway.csproj index 5adf624f5..febd19831 100644 --- a/samples/ServiceFabric/ApiGateway/Ocelot.Samples.ServiceFabric.ApiGateway.csproj +++ b/samples/ServiceFabric/ApiGateway/Ocelot.Samples.ServiceFabric.ApiGateway.csproj @@ -1,16 +1,14 @@  Stateless Web Service for Stateful OcelotApplicationApiGateway App - net9.0 - disable - disable Any CPU;x64 + net9.0 + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals - - - PreserveNewest - - diff --git a/samples/ServiceFabric/ApiGateway/OcelotApplicationApiGateway.cs b/samples/ServiceFabric/ApiGateway/OcelotApplicationApiGateway.cs index e8dc10170..5fabce01a 100644 --- a/samples/ServiceFabric/ApiGateway/OcelotApplicationApiGateway.cs +++ b/samples/ServiceFabric/ApiGateway/OcelotApplicationApiGateway.cs @@ -5,7 +5,6 @@ using Microsoft.ServiceFabric.Services.Communication.Runtime; using Microsoft.ServiceFabric.Services.Runtime; -using System.Collections.Generic; using System.Fabric; namespace Ocelot.Samples.ServiceFabric.ApiGateway; diff --git a/samples/ServiceFabric/ApiGateway/Program.cs b/samples/ServiceFabric/ApiGateway/Program.cs index 87679ba23..f05672080 100644 --- a/samples/ServiceFabric/ApiGateway/Program.cs +++ b/samples/ServiceFabric/ApiGateway/Program.cs @@ -1,48 +1,26 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - using Microsoft.ServiceFabric.Services.Runtime; -using System; +using Ocelot.Samples.ServiceFabric.ApiGateway; using System.Diagnostics.Tracing; -using System.Threading; - -namespace Ocelot.Samples.ServiceFabric.ApiGateway; - -/// -/// The service host is the executable that hosts the Service instances. -/// -public class Program +// The service host is the executable that hosts the Service instances. +// Create Service Fabric runtime and register the service type. +try { - public static void Main(string[] args) - { - // Create Service Fabric runtime and register the service type. - try - { - - //Creating a new event listener to redirect the traces to a file - var listener = new ServiceEventListener("OcelotApplicationApiGateway"); - listener.EnableEvents(ServiceEventSource.Current, EventLevel.LogAlways, EventKeywords.All); - - // The ServiceManifest.XML file defines one or more service type names. - // Registering a service maps a service type name to a .NET type. - // When Service Fabric creates an instance of this service type, - // an instance of the class is created in this host process. - ServiceRuntime - .RegisterServiceAsync("OcelotApplicationApiGatewayType", context => new OcelotServiceWebService(context)) - .GetAwaiter() - .GetResult(); - - - // Prevents this host process from terminating so services keep running. - Thread.Sleep(Timeout.Infinite); - } - catch (Exception ex) - { - ServiceEventSource.Current.ServiceHostInitializationFailed(ex); - throw; - } - } + //Creating a new event listener to redirect the traces to a file + var listener = new ServiceEventListener("OcelotApplicationApiGateway"); + listener.EnableEvents(ServiceEventSource.Current, EventLevel.LogAlways, EventKeywords.All); + + // The ServiceManifest.XML file defines one or more service type names. + // Registering a service maps a service type name to a .NET type. + // When Service Fabric creates an instance of this service type, + // an instance of the class is created in this host process. + await ServiceRuntime.RegisterServiceAsync("OcelotApplicationApiGatewayType", context => new OcelotServiceWebService(context)); + + // Prevents this host process from terminating so services keep running. + Thread.Sleep(Timeout.Infinite); +} +catch (Exception ex) +{ + ServiceEventSource.Current.ServiceHostInitializationFailed(ex); + throw; } diff --git a/samples/ServiceFabric/ApiGateway/Properties/launchSettings.json b/samples/ServiceFabric/ApiGateway/Properties/launchSettings.json index e28c33153..ac9664e33 100644 --- a/samples/ServiceFabric/ApiGateway/Properties/launchSettings.json +++ b/samples/ServiceFabric/ApiGateway/Properties/launchSettings.json @@ -1,27 +1,58 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:36034/", - "sslPort": 0 - } - }, "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5565" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7787;http://localhost:5565" + }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, + "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, - "OcelotApplicationApiGateway": { - "commandName": "Project", + "WSL": { + "commandName": "WSL2", "launchBrowser": true, + "launchUrl": "https://localhost:7787/swagger", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "https://localhost:7787;http://localhost:5565" }, - "applicationUrl": "http://localhost:36035/" + "distributionName": "" + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62565/", + "sslPort": 44365 } } -} \ No newline at end of file +} diff --git a/samples/ServiceFabric/ApiGateway/ServiceEventListener.cs b/samples/ServiceFabric/ApiGateway/ServiceEventListener.cs index b49965506..f14705708 100644 --- a/samples/ServiceFabric/ApiGateway/ServiceEventListener.cs +++ b/samples/ServiceFabric/ApiGateway/ServiceEventListener.cs @@ -3,11 +3,8 @@ // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ -using System; using System.Diagnostics.Tracing; using System.Globalization; -using System.IO; -using System.Linq; using System.Text; namespace Ocelot.Samples.ServiceFabric.ApiGateway; @@ -34,18 +31,16 @@ public ServiceEventListener(string appName) /// The event arguments that describe the event. protected override void OnEventWritten(EventWrittenEventArgs eventData) { - using (var writer = new StreamWriter(new FileStream(_filepath + _fileName, FileMode.Append))) - { - // report all event information - writer.Write(" {0} ", Write(eventData.Task.ToString(), - eventData.EventName, + using var writer = new StreamWriter(new FileStream(_filepath + _fileName, FileMode.Append)); + // report all event information + writer.Write(" {0} ", Write( + eventData.Task.ToString(), + eventData.EventName!, eventData.EventId.ToString(), eventData.Level)); - - if (eventData.Message != null) - { - writer.WriteLine(string.Format(CultureInfo.InvariantCulture, eventData.Message, eventData.Payload.ToArray())); - } + if (eventData.Message != null) + { + writer.WriteLine(string.Format(CultureInfo.InvariantCulture, eventData.Message, eventData.Payload!.ToArray())); } } @@ -78,12 +73,10 @@ private static String Write(string taskName, string eventName, string id, EventL private static string ConvertLevelToString(EventLevel level) { - switch (level) + return level switch { - case EventLevel.Informational: - return "Info"; - default: - return level.ToString(); - } + EventLevel.Informational => "Info", + _ => level.ToString(), + }; } } diff --git a/samples/ServiceFabric/ApiGateway/ServiceEventSource.cs b/samples/ServiceFabric/ApiGateway/ServiceEventSource.cs index a3f2d5706..29697b413 100644 --- a/samples/ServiceFabric/ApiGateway/ServiceEventSource.cs +++ b/samples/ServiceFabric/ApiGateway/ServiceEventSource.cs @@ -3,7 +3,6 @@ // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ -using System; using System.Diagnostics.Tracing; namespace Ocelot.Samples.ServiceFabric.ApiGateway; diff --git a/samples/ServiceFabric/ApiGateway/WebCommunicationListener.cs b/samples/ServiceFabric/ApiGateway/WebCommunicationListener.cs index bcb2e1714..e068eddc1 100644 --- a/samples/ServiceFabric/ApiGateway/WebCommunicationListener.cs +++ b/samples/ServiceFabric/ApiGateway/WebCommunicationListener.cs @@ -1,20 +1,9 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.ServiceFabric.Services.Communication.Runtime; +using Microsoft.ServiceFabric.Services.Communication.Runtime; using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Samples.Web; -using System; using System.Fabric; using System.Globalization; -using System.Threading; -using System.Threading.Tasks; namespace Ocelot.Samples.ServiceFabric.ApiGateway; @@ -26,7 +15,7 @@ public class WebCommunicationListener : ICommunicationListener private string _publishAddress; // OWIN server handle. - private IWebHost _webHost; + private WebApplication _webApp; public WebCommunicationListener(string appRoot, ServiceContext serviceInitializationParameters) { @@ -34,7 +23,7 @@ public WebCommunicationListener(string appRoot, ServiceContext serviceInitializa _serviceInitializationParameters = serviceInitializationParameters; } - public Task OpenAsync(CancellationToken cancellationToken) + public async Task OpenAsync(CancellationToken cancellationToken) { ServiceEventSource.Current.Message("Initialize"); @@ -55,68 +44,47 @@ public Task OpenAsync(CancellationToken cancellationToken) try { - _webHost = OcelotHostBuilder.Create() - .UseUrls(_listeningAddress) - .ConfigureAppConfiguration((hostingContext, config) => - { - config - .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) - .AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("ocelot.json", false, false) - .AddEnvironmentVariables(); - }) - .ConfigureLogging((hostingContext, logging) => - { - logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); - logging.AddConsole(); - }) - .ConfigureServices(s => + _ = OcelotHostBuilder.Create(); + var builder = WebApplication.CreateBuilder(); //(args); + builder.WebHost.UseUrls(_listeningAddress); + builder.Configuration + .SetBasePath(builder.Environment.ContentRootPath) + .AddOcelot(); + builder.Services + .AddOcelot(builder.Configuration); + if (builder.Environment.IsDevelopment()) { - s.AddOcelot(); - }) - .Configure(a => - { - a.UseOcelot().Wait(cancellationToken); - }) - .Build(); + builder.Logging.AddConsole(); + } - _webHost.Start(); + _webApp = builder.Build(); + await _webApp.UseOcelot(); + await _webApp.RunAsync(); // .Start(); } catch (Exception ex) { ServiceEventSource.Current.ServiceWebHostBuilderFailed(ex); } - - return Task.FromResult(_publishAddress); + return _publishAddress; } - public Task CloseAsync(CancellationToken cancellationToken) - { - StopAll(); - return Task.FromResult(true); - } - - public void Abort() - { - StopAll(); - } + public Task CloseAsync(CancellationToken cancellationToken) => StopAll(cancellationToken); + public void Abort() => StopAll().GetAwaiter().GetResult(); - /// - /// Stops, cancels, and disposes everything. - /// - private void StopAll() + /// Stops, cancels, and disposes everything. + private Task StopAll(CancellationToken cancellationToken = default) { try { - if (_webHost != null) + if (_webApp != null) { ServiceEventSource.Current.Message("Stopping web server."); - _webHost.Dispose(); + return _webApp.StopAsync(cancellationToken); } } catch (ObjectDisposedException) { } + return Task.CompletedTask; } } diff --git a/samples/ServiceFabric/ApiGateway/appsettings.Development.json b/samples/ServiceFabric/ApiGateway/appsettings.Development.json new file mode 100644 index 000000000..07053a355 --- /dev/null +++ b/samples/ServiceFabric/ApiGateway/appsettings.Development.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.AspNetCore": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Information" + } + } +} diff --git a/samples/ServiceFabric/ApiGateway/appsettings.json b/samples/ServiceFabric/ApiGateway/appsettings.json index 51d924914..def9159a7 100644 --- a/samples/ServiceFabric/ApiGateway/appsettings.json +++ b/samples/ServiceFabric/ApiGateway/appsettings.json @@ -1,10 +1,8 @@ -{ +{ "Logging": { - "IncludeScopes": false, "LogLevel": { - "Default": "Trace", - "System": "Information", - "Microsoft": "Information" + "Default": "Warning" } - } + }, + "AllowedHosts": "*" } diff --git a/samples/ServiceFabric/ApiGateway/ocelot.json b/samples/ServiceFabric/ApiGateway/ocelot.json index 1b174cd62..2718d4863 100644 --- a/samples/ServiceFabric/ApiGateway/ocelot.json +++ b/samples/ServiceFabric/ApiGateway/ocelot.json @@ -3,9 +3,7 @@ { "DownstreamPathTemplate": "/api/values", "UpstreamPathTemplate": "/EquipmentInterfaces", - "UpstreamHttpMethod": [ - "Get" - ], + "UpstreamHttpMethod": [ "Get" ], "DownstreamScheme": "http", "ServiceName": "OcelotServiceApplication/OcelotApplicationService" } diff --git a/samples/ServiceFabric/DownstreamService/ApiGateway.cs b/samples/ServiceFabric/DownstreamService/ApiGateway.cs index da6c76395..5296aaa76 100644 --- a/samples/ServiceFabric/DownstreamService/ApiGateway.cs +++ b/samples/ServiceFabric/DownstreamService/ApiGateway.cs @@ -1,14 +1,8 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.ServiceFabric.Services.Communication.AspNetCore; using Microsoft.ServiceFabric.Services.Communication.Runtime; using Microsoft.ServiceFabric.Services.Runtime; using Ocelot.Samples.Web; -using System; -using System.Collections.Generic; using System.Fabric; -using System.IO; namespace Ocelot.Samples.ServiceFabric.DownstreamService; @@ -33,19 +27,28 @@ protected override IEnumerable CreateServiceInstanceLis { Console.WriteLine($"Starting Kestrel on {url}"); ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}"); - return OcelotHostBuilder.Create() - .UseKestrel() - .ConfigureServices(services => services.AddSingleton(serviceContext)) + + _ = OcelotHostBuilder.Create(); + var builder = WebApplication.CreateBuilder(); //(args); + builder.Services + .AddSingleton(serviceContext) + .AddControllers(); + builder.WebHost + //.UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl) - .UseStartup() - .UseUrls(url) - .ConfigureLogging((hostingContext, logging) => - { - logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); - logging.AddConsole(); - }) - .Build(); + .UseUrls(url); + if (builder.Environment.IsDevelopment()) + { + builder.Logging.AddConsole(); + } + var app = builder.Build(); + app.MapControllers(); + if (app.Environment.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + return app; })) }; } diff --git a/samples/ServiceFabric/DownstreamService/Controllers/ValuesController.cs b/samples/ServiceFabric/DownstreamService/Controllers/ValuesController.cs index 11f39c668..963353f46 100644 --- a/samples/ServiceFabric/DownstreamService/Controllers/ValuesController.cs +++ b/samples/ServiceFabric/DownstreamService/Controllers/ValuesController.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; namespace Ocelot.Samples.ServiceFabric.DownstreamService.Controllers; diff --git a/samples/ServiceFabric/DownstreamService/Ocelot.Samples.ServiceFabric.DownstreamService.csproj b/samples/ServiceFabric/DownstreamService/Ocelot.Samples.ServiceFabric.DownstreamService.csproj index 2a223d8fe..54ff66fb9 100644 --- a/samples/ServiceFabric/DownstreamService/Ocelot.Samples.ServiceFabric.DownstreamService.csproj +++ b/samples/ServiceFabric/DownstreamService/Ocelot.Samples.ServiceFabric.DownstreamService.csproj @@ -2,16 +2,13 @@ Stateless Service Application net9.0 - disable - disable - OcelotApplicationService - OcelotApplicationService - $(PackageTargetFallback) + enable + enable + 24.0.0 + 24.0.0 + ThreeMammals x64 - - - diff --git a/samples/ServiceFabric/DownstreamService/Program.cs b/samples/ServiceFabric/DownstreamService/Program.cs index 268ccf362..13f1c1eac 100644 --- a/samples/ServiceFabric/DownstreamService/Program.cs +++ b/samples/ServiceFabric/DownstreamService/Program.cs @@ -1,35 +1,22 @@ using Microsoft.ServiceFabric.Services.Runtime; -using System; -using System.Threading; +using Ocelot.Samples.ServiceFabric.DownstreamService; -namespace Ocelot.Samples.ServiceFabric.DownstreamService; - -internal static class Program +try { - /// - /// This is the entry point of the service host process. - /// - private static void Main() - { - try - { - // The ServiceManifest.XML file defines one or more service type names. - // Registering a service maps a service type name to a .NET type. - // When Service Fabric creates an instance of this service type, - // an instance of the class is created in this host process. - - ServiceRuntime.RegisterServiceAsync("OcelotApplicationServiceType", - context => new ApiGateway(context)).GetAwaiter().GetResult(); + // The ServiceManifest.XML file defines one or more service type names. + // Registering a service maps a service type name to a .NET type. + // When Service Fabric creates an instance of this service type, + // an instance of the class is created in this host process. + await ServiceRuntime.RegisterServiceAsync("OcelotApplicationServiceType", + (context) => new ApiGateway(context)); - ServiceEventSource.Current.ServiceTypeRegistered(Environment.ProcessId, nameof(ApiGateway)); + ServiceEventSource.Current.ServiceTypeRegistered(Environment.ProcessId, nameof(ApiGateway)); - // Prevents this host process from terminating so services keeps running. - Thread.Sleep(Timeout.Infinite); - } - catch (Exception e) - { - ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString()); - throw; - } - } + // Prevents this host process from terminating so services keeps running. + Thread.Sleep(Timeout.Infinite); +} +catch (Exception e) +{ + ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString()); + throw; } diff --git a/samples/ServiceFabric/DownstreamService/Properties/launchSettings.json b/samples/ServiceFabric/DownstreamService/Properties/launchSettings.json index fb64c02b5..af5711aed 100644 --- a/samples/ServiceFabric/DownstreamService/Properties/launchSettings.json +++ b/samples/ServiceFabric/DownstreamService/Properties/launchSettings.json @@ -1,12 +1,14 @@ { "profiles": { - "OcelotApplicationService": { + "https": { "commandName": "Project", "launchBrowser": true, + "launchUrl": "api/values", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "https://localhost:57625;http://localhost:57626" + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7788;http://localhost:5566" } } } diff --git a/samples/ServiceFabric/DownstreamService/ServiceEventSource.cs b/samples/ServiceFabric/DownstreamService/ServiceEventSource.cs index a3fe87c96..1759d3b97 100644 --- a/samples/ServiceFabric/DownstreamService/ServiceEventSource.cs +++ b/samples/ServiceFabric/DownstreamService/ServiceEventSource.cs @@ -1,7 +1,5 @@ -using System; using System.Diagnostics.Tracing; using System.Fabric; -using System.Threading.Tasks; namespace Ocelot.Samples.ServiceFabric.DownstreamService; diff --git a/samples/ServiceFabric/DownstreamService/Startup.cs b/samples/ServiceFabric/DownstreamService/Startup.cs deleted file mode 100644 index 2e2f7f9c3..000000000 --- a/samples/ServiceFabric/DownstreamService/Startup.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace Ocelot.Samples.ServiceFabric.DownstreamService; - -public class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - } -}