using System; using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using NetCoreServer; using Xunit; namespace tests { class CommonCache { public static CommonCache GetInstance() { if (_instance == null) _instance = new CommonCache(); return _instance; } public string GetAllCache() { var result = new StringBuilder(); result.Append("[\n"); foreach (var item in _cache) { result.Append(" {\n"); result.AppendFormat($" \"key\": \"{item.Key}\",\n"); result.AppendFormat($" \"value\": \"{item.Value}\",\n"); result.Append(" },\n"); } result.Append("]\n"); return result.ToString(); } public bool GetCacheValue(string key, out string value) { return _cache.TryGetValue(key, out value); } public void PutCacheValue(string key, string value) { _cache[key] = value; } public bool DeleteCacheValue(string key, out string value) { return _cache.TryRemove(key, out value); } private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); private static CommonCache _instance; } class HttpCacheSession : HttpSession { public HttpCacheSession(HttpServer server) : base(server) {} protected override void OnReceivedRequest(HttpRequest request) { // Process HTTP request methods if (request.Method == "HEAD") SendResponseAsync(Response.MakeHeadResponse()); else if (request.Method == "GET") { string key = request.Url; // Decode the key value key = Uri.UnescapeDataString(key); key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase); key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase); if (string.IsNullOrEmpty(key)) { // Response with all cache values SendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(), "application/json; charset=UTF-8")); } // Get the cache value by the given key else if (CommonCache.GetInstance().GetCacheValue(key, out var value)) { // Response with the cache value SendResponseAsync(Response.MakeGetResponse(value)); } else SendResponseAsync(Response.MakeErrorResponse(404, "Required cache value was not found for the key: " + key)); } else if ((request.Method == "POST") || (request.Method == "PUT")) { string key = request.Url; string value = request.Body; // Decode the key value key = Uri.UnescapeDataString(key); key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase); key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase); // Put the cache value CommonCache.GetInstance().PutCacheValue(key, value); // Response with the cache value SendResponseAsync(Response.MakeOkResponse()); } else if (request.Method == "DELETE") { string key = request.Url; // Decode the key value key = Uri.UnescapeDataString(key); key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase); key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase); // Delete the cache value if (CommonCache.GetInstance().DeleteCacheValue(key, out var value)) { // Response with the cache value SendResponseAsync(Response.MakeGetResponse(value)); } else SendResponseAsync(Response.MakeErrorResponse(404, "Deleted cache value was not found for the key: " + key)); } else if (request.Method == "OPTIONS") SendResponseAsync(Response.MakeOptionsResponse()); else if (request.Method == "TRACE") SendResponseAsync(Response.MakeTraceResponse(request.Cache)); else SendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: " + request.Method)); } protected override void OnReceivedRequestError(HttpRequest request, string error) { Console.WriteLine($"Request error: {error}"); } protected override void OnError(SocketError error) { Console.WriteLine($"HTTP session caught an error: {error}"); } } class HttpCacheServer : HttpServer { public HttpCacheServer(IPAddress address, int port) : base(address, port) {} protected override TcpSession CreateSession() { return new HttpCacheSession(this); } protected override void OnError(SocketError error) { Console.WriteLine($"HTTP session caught an error: {error}"); } } public class HttpTests { [Fact(DisplayName = "HTTP server test")] public void HttpServerTest() { string address = "127.0.0.1"; int port = 8080; // Create and start HTTP server var server = new HttpCacheServer(IPAddress.Any, port); Assert.True(server.Start()); while (!server.IsStarted) Thread.Yield(); // Create a new HTTP client var client = new HttpClientEx(address, port); // Test CRUD operations var response = client.SendGetRequest("/test").Result; Assert.True(response.Status == 404); response = client.SendPostRequest("/test", "old_value").Result; Assert.True(response.Status == 200); response = client.SendGetRequest("/test").Result; Assert.True(response.Status == 200); Assert.True(response.Body == "old_value"); response = client.SendPutRequest("/test", "new_value").Result; Assert.True(response.Status == 200); response = client.SendGetRequest("/test").Result; Assert.True(response.Status == 200); Assert.True(response.Body == "new_value"); response = client.SendDeleteRequest("/test").Result; Assert.True(response.Status == 200); response = client.SendGetRequest("/test").Result; Assert.True(response.Status == 404); // Stop the HTTP server Assert.True(server.Stop()); while (server.IsStarted) Thread.Yield(); } } }