using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;
using NetCoreServer;
namespace HttpServer
{
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(NetCoreServer.HttpServer server) : base(server) {}
protected override void OnReceivedRequest(HttpRequest request)
{
// Show HTTP request content
Console.WriteLine(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));
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 : NetCoreServer.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}");
}
}
class Program
{
static void Main(string[] args)
{
// HTTP server port
int port = 8080;
if (args.Length > 0)
port = int.Parse(args[0]);
// HTTP server content path
string www = "../../../../../www/api";
if (args.Length > 1)
www = args[1];
Console.WriteLine($"HTTP server port: {port}");
Console.WriteLine($"HTTP server static content path: {www}");
Console.WriteLine($"HTTP server website: http://localhost:{port}/api/index.html");
Console.WriteLine();
// Create a new HTTP server
var server = new HttpCacheServer(IPAddress.Any, port);
server.AddStaticContent(www, "/api");
// Start the server
Console.Write("Server starting...");
server.Start();
Console.WriteLine("Done!");
Console.WriteLine("Press Enter to stop the server or '!' to restart the server...");
// Perform text input
for (;;)
{
string line = Console.ReadLine();
if (string.IsNullOrEmpty(line))
break;
// Restart the server
if (line == "!")
{
Console.Write("Server restarting...");
server.Restart();
Console.WriteLine("Done!");
}
}
// Stop the server
Console.Write("Server stopping...");
server.Stop();
Console.WriteLine("Done!");
}
}
}