diff --git a/GameMicroServer.sln b/APIGateway.sln similarity index 86% rename from GameMicroServer.sln rename to APIGateway.sln index 01da97b..c10c64a 100644 --- a/GameMicroServer.sln +++ b/APIGateway.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.7.34221.43 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameMicroServer", "GameMicroServer\GameMicroServer.csproj", "{C8787DE3-73A1-4FA9-BC23-865FCF0560AF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "APIGateway", "APIGateway\APIGateway.csproj", "{C8787DE3-73A1-4FA9-BC23-865FCF0560AF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/GameMicroServer/GameMicroServer.csproj b/APIGateway/APIGateway.csproj similarity index 87% rename from GameMicroServer/GameMicroServer.csproj rename to APIGateway/APIGateway.csproj index 1f43d86..f16dbbf 100644 --- a/GameMicroServer/GameMicroServer.csproj +++ b/APIGateway/APIGateway.csproj @@ -9,6 +9,7 @@ + diff --git a/APIGateway/Controllers/GatewayController.cs b/APIGateway/Controllers/GatewayController.cs new file mode 100644 index 0000000..194bcb2 --- /dev/null +++ b/APIGateway/Controllers/GatewayController.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System.Net.Http.Json; + +namespace Gateway +{ + /// + /// Controller responsible for handling requests and responses at the gateway. + /// + [ApiController] + [Route("[controller]")] + public class GatewayController : ControllerBase + { + private readonly HttpClient _httpClient; // Making readonly ensures thread safety + private readonly ILogger _logger; // Making readonly ensures thread safety + + public GatewayController(HttpClient httpClient, ILogger logger) + { + _httpClient = httpClient; + _logger = logger; + } + + /// + /// Handles GET requests to retrieve game information from the microservice. + /// + /// A collection of GameInfo objects. + [HttpGet] + public async Task> Get() + { + try + { + // Make a GET request to the microservice's endpoint + HttpResponseMessage response = await _httpClient.GetAsync("https://localhost:7223/Micro"); // URL might need to change for deployment + + // Check if the request was successful + if (response.IsSuccessStatusCode) + { + // Deserialize the response content to a list of GameInfo objects + var gameInfoList = await response.Content.ReadAsAsync>(); + return gameInfoList; + } + else + { + _logger.LogError($"Failed to retrieve data from microservice. Status code: {response.StatusCode}"); + // Return a placeholder list of GameInfo objects indicating failure + return GenerateFailureResponse(); + } + } + catch (Exception ex) + { + _logger.LogError($"An error occurred while fetching data from microservice: {ex.Message}"); + // Return a placeholder list of GameInfo objects indicating failure + return GenerateFailureResponse(); + } + } + + /// + /// Generates a placeholder list of GameInfo objects indicating failure to retrieve data. + /// + /// A collection of GameInfo objects indicating failure. + private IEnumerable GenerateFailureResponse() + { + // Using IEnumerable allows flexibility in returning a placeholder response. + // It allows the method to return different types of collections (e.g., List, Array) if needed in the future. + // In this case, IEnumerable provides a simple way to return a list of failed responses. + + // Generate a placeholder list of GameInfo objects indicating failure to retrieve data + return new List + { + new GameInfo + { + Title = "Failed to retrieve from Microservice", + Author = "Failed to retrieve from Microservice", + Description = "Failed to retrieve from Microservice", + HowTo = "Failed to retrieve from Microservice", + LeaderBoardStack = new Stack>() // Initializing an empty stack + } + }; + } + } +} diff --git a/GameMicroServer/Dockerfile b/APIGateway/Dockerfile similarity index 100% rename from GameMicroServer/Dockerfile rename to APIGateway/Dockerfile diff --git a/GameMicroServer/GameInfo.cs b/APIGateway/GameInfo.cs similarity index 94% rename from GameMicroServer/GameInfo.cs rename to APIGateway/GameInfo.cs index 8732214..c3110d3 100644 --- a/GameMicroServer/GameInfo.cs +++ b/APIGateway/GameInfo.cs @@ -1,4 +1,4 @@ -namespace Micro +namespace Gateway { public class GameInfo { diff --git a/APIGateway/Logging/TimestampLogger.cs b/APIGateway/Logging/TimestampLogger.cs new file mode 100644 index 0000000..8f9a3fc --- /dev/null +++ b/APIGateway/Logging/TimestampLogger.cs @@ -0,0 +1,41 @@ +namespace APIGateway +{ + using Microsoft.Extensions.Logging; + using System; + + // This class details the beginning steps of the logger with timestamps. It implements ILogger, + // which comes with a few methods to be fulfilled. + + // This was written via ChatGPT 3.5. + public class TimestampLogger : ILogger + { + // This method is called when a new scope is requested for logging. + // Scopes are used to provide additional contextual information for log messages. + // In this implementation, it simply returns null because no specific scope is being managed. + public IDisposable BeginScope(TState state) + { + return null; + } + + // This method is called to check if logging at the specified log level is enabled. + // It can be used to implement filtering based on log levels. + // In this implementation, it always returns true, indicating that logging at any level is enabled. + // You may modify this method to implement filtering based on log levels if needed. + public bool IsEnabled(LogLevel logLevel) + { + return true; // You may implement filtering based on log level + } + + // This method is called to perform the actual logging of a message. + // It formats the log message with a timestamp in the format "yyyy-MM-dd HH:mm:ss", + // combines it with the formatted state and exception provided by the formatter function, + // and writes the resulting message to the console. + // You can replace Console.WriteLine(message) with your preferred logging mechanism. + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + string message = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} - {formatter(state, exception)}"; + + Console.WriteLine(message); // Change this to your preferred logging mechanism + } + } +} diff --git a/APIGateway/Logging/TimestampLoggerExtensions.cs b/APIGateway/Logging/TimestampLoggerExtensions.cs new file mode 100644 index 0000000..48a0a87 --- /dev/null +++ b/APIGateway/Logging/TimestampLoggerExtensions.cs @@ -0,0 +1,27 @@ +namespace APIGateway +{ + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Logging; + using static IServiceCollection; + + // This was written via ChatGPT 3.5. + + public static class TimestampLoggerExtensions + { + // This extension method is used to extend the functionality of the ILoggingBuilder interface. + // It adds the capability to configure the logging system to include a timestamp in log messages. + // The method adds a timestamp logger to the logging builder. + + public static ILoggingBuilder AddTimestampLogger(this ILoggingBuilder builder) + { + // Inside the method, it accesses the IServiceCollection provided by the logging builder (builder.Services). + // It registers the TimestampLoggerProvider as a singleton service for ILoggerProvider. + // This ensures that the TimestampLoggerProvider will be used to create logger instances. + builder.Services.AddSingleton(); + + // Finally, it returns the logging builder instance to support method chaining. + // This allows further configuration to be chained after adding the timestamp logger. + return builder; + } + } +} diff --git a/APIGateway/Logging/TimestampLoggerProvider.cs b/APIGateway/Logging/TimestampLoggerProvider.cs new file mode 100644 index 0000000..84abef5 --- /dev/null +++ b/APIGateway/Logging/TimestampLoggerProvider.cs @@ -0,0 +1,28 @@ +namespace APIGateway +{ + using Microsoft.Extensions.Logging; + using System; + + // This was written via ChatGPT 3.5. + + // This class creates the baseline for the LoggerProvider. It implements ILoggerProvider, + // which simply just needs to create a logger and return it, whilst disposing of any extras. + public class TimestampLoggerProvider : ILoggerProvider + { + // This method is called when a logger is requested for a specific category. + // It creates and returns a new instance of the TimestampLogger class. + // Each logger provider can be associated with one or more logger instances. + // In this case, it always returns a new instance of TimestampLogger for any requested category. + + public ILogger CreateLogger(string categoryName) + { + // Creates and returns a new instance of TimestampLogger. + return new TimestampLogger(); + } + + // This method is called to release any resources used by the logger provider. + // Since this implementation does not hold any resources that need to be released explicitly, + // this method doesn't perform any action. + public void Dispose() { } + } +} diff --git a/GameMicroServer/Program.cs b/APIGateway/Program.cs similarity index 65% rename from GameMicroServer/Program.cs rename to APIGateway/Program.cs index 632a615..8d142e1 100644 --- a/GameMicroServer/Program.cs +++ b/APIGateway/Program.cs @@ -1,3 +1,5 @@ +using APIGateway; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. @@ -7,6 +9,17 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +// Register HttpClient +builder.Services.AddHttpClient(); + +// This creates the services for the Logging files. +builder.Services.AddLogging(builder => +{ + builder.AddConsole(); + builder.AddDebug(); + builder.AddTimestampLogger(); // Add timestamp logger +}); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/GameMicroServer/Properties/launchSettings.json b/APIGateway/Properties/launchSettings.json similarity index 91% rename from GameMicroServer/Properties/launchSettings.json rename to APIGateway/Properties/launchSettings.json index fdaca06..19f5ed8 100644 --- a/GameMicroServer/Properties/launchSettings.json +++ b/APIGateway/Properties/launchSettings.json @@ -1,6 +1,6 @@ { "profiles": { - "GameMicroServer": { + "APIGateway": { "commandName": "Project", "launchBrowser": true, "launchUrl": "swagger", @@ -8,7 +8,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "dotnetRunMessages": true, - "applicationUrl": "https://localhost:7223;http://localhost:5130" + "applicationUrl": "https://localhost:4141" }, "IIS Express": { "commandName": "IISExpress", diff --git a/GameMicroServer/appsettings.Development.json b/APIGateway/appsettings.Development.json similarity index 100% rename from GameMicroServer/appsettings.Development.json rename to APIGateway/appsettings.Development.json diff --git a/GameMicroServer/appsettings.json b/APIGateway/appsettings.json similarity index 100% rename from GameMicroServer/appsettings.json rename to APIGateway/appsettings.json diff --git a/GameMicroServer/Controllers/microController.cs b/GameMicroServer/Controllers/microController.cs deleted file mode 100644 index 931e493..0000000 --- a/GameMicroServer/Controllers/microController.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; - -using Microsoft.Extensions.Caching.Distributed; -using System.Text.Json; - -namespace Micro -{ - [ApiController] - [Route("[controller]")] - public class MicroController : ControllerBase - { - private static readonly List TheInfo = new List - { - new GameInfo { - //Id = 1, - Title = "Snake", - //Content = "~/js/snake.js", - Author = "Fall 2023 Semester", - DateAdded = "", - Description = "Snake is a classic arcade game that challenges the player to control a snake-like creature that grows longer as it eats apples. The player must avoid hitting the walls or the snake's own body, which can end the game.\r\n", - HowTo = "Control with arrow keys.", - //Thumbnail = "/images/snake.jpg" //640x360 resolution - LeaderBoardStack = new Stack>(), - - }, - new GameInfo { - //Id = 2, - Title = "Tetris", - //Content = "~/js/tetris.js", - Author = "Fall 2023 Semester", - DateAdded = "", - Description = "Tetris is a classic arcade puzzle game where the player has to arrange falling blocks, also known as Tetronimos, of different shapes and colors to form complete rows on the bottom of the screen. The game gets faster and harder as the player progresses, and ends when the Tetronimos reach the top of the screen.", - HowTo = "Control with arrow keys: Up arrow to spin, down to speed up fall, space to insta-drop.", - //Thumbnail = "/images/tetris.jpg" - LeaderBoardStack = new Stack>(), - - }, - new GameInfo { - //Id = 3, - Title = "Pong", - //Content = "~/js/pong.js", - Author = "Fall 2023 Semester", - DateAdded = "", - Description = "Pong is a classic arcade game where the player uses a paddle to hit a ball against a computer's paddle. Either party scores when the ball makes it past the opponent's paddle.", - HowTo = "Control with arrow keys.", - //Thumbnail = "/images/pong.jpg" - LeaderBoardStack = new Stack>(), - }, - - }; - - private readonly ILogger _logger; - - public MicroController(ILogger logger) - { - _logger = logger; - } - - [HttpGet] - public IEnumerable Get() - { - return TheInfo; - } - } -} \ No newline at end of file