using System; using System.Net; using System.IO; namespace NetCoreServer { /// <summary> /// HTTP server is used to create HTTP Web server and communicate with clients using HTTP protocol. It allows to receive GET, POST, PUT, DELETE requests and send HTTP responses. /// </summary> /// <remarks>Thread-safe.</remarks> public class HttpServer : TcpServer { /// <summary> /// Initialize HTTP server with a given IP address and port number /// </summary> /// <param name="address">IP address</param> /// <param name="port">Port number</param> public HttpServer(IPAddress address, int port) : base(address, port) { Cache = new FileCache(); } /// <summary> /// Initialize HTTP server with a given IP address and port number /// </summary> /// <param name="address">IP address</param> /// <param name="port">Port number</param> public HttpServer(string address, int port) : base(address, port) { Cache = new FileCache(); } /// <summary> /// Initialize HTTP server with a given DNS endpoint /// </summary> /// <param name="endpoint">DNS endpoint</param> public HttpServer(DnsEndPoint endpoint) : base(endpoint) { Cache = new FileCache(); } /// <summary> /// Initialize HTTP server with a given IP endpoint /// </summary> /// <param name="endpoint">IP endpoint</param> public HttpServer(IPEndPoint endpoint) : base(endpoint) { Cache = new FileCache(); } /// <summary> /// Get the static content cache /// </summary> public FileCache Cache { get; } /// <summary> /// Add static content cache /// </summary> /// <param name="path">Static content path</param> /// <param name="prefix">Cache prefix (default is "/")</param> /// <param name="filter">Cache filter (default is "*.*")</param> /// <param name="timeout">Refresh cache timeout (default is 1 hour)</param> public void AddStaticContent(string path, string prefix = "/", string filter = "*.*", TimeSpan? timeout = null) { timeout ??= TimeSpan.FromHours(1); bool Handler(FileCache cache, string key, byte[] value, TimeSpan timespan) { var response = new HttpResponse(); response.SetBegin(200); response.SetContentType(Path.GetExtension(key)); response.SetHeader("Cache-Control", $"max-age={timespan.Seconds}"); response.SetBody(value); return cache.Add(key, response.Cache.Data, timespan); } Cache.InsertPath(path, prefix, filter, timeout.Value, Handler); } /// <summary> /// Remove static content cache /// </summary> /// <param name="path">Static content path</param> public void RemoveStaticContent(string path) { Cache.RemovePath(path); } /// <summary> /// Clear static content cache /// </summary> public void ClearStaticContent() { Cache.Clear(); } protected override TcpSession CreateSession() { return new HttpSession(this); } #region IDisposable implementation // Disposed flag. private bool _disposed; protected override void Dispose(bool disposingManagedResources) { if (!_disposed) { if (disposingManagedResources) { // Dispose managed resources here... Cache.Dispose(); } // Dispose unmanaged resources here... // Set large fields to null here... // Mark as disposed. _disposed = true; } // Call Dispose in the base class. base.Dispose(disposingManagedResources); } // The derived class does not have a Finalize method // or a Dispose method without parameters because it inherits // them from the base class. #endregion } }