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();
}
}
}