Files
Essentials/src/PepperDash.Essentials/HttpLogoServer.cs
2025-07-22 15:53:01 +00:00

133 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials
{
/// <summary>
/// HTTP server for serving logo images and files
/// </summary>
public class HttpLogoServer
{
/// <summary>
/// The HTTP server instance
/// </summary>
readonly HttpServer _server;
/// <summary>
/// The directory containing files to serve
/// </summary>
readonly string _fileDirectory;
/// <summary>
/// Dictionary mapping file extensions to content types
/// </summary>
public static Dictionary<string, string> ExtensionContentTypes;
/// <summary>
/// Initializes a new instance of the HttpLogoServer class
/// </summary>
/// <param name="port">Port number for the HTTP server</param>
/// <param name="directory">Directory containing files to serve</param>
public HttpLogoServer(int port, string directory)
{
ExtensionContentTypes = new Dictionary<string, string>
{
//{ ".css", "text/css" },
//{ ".htm", "text/html" },
//{ ".html", "text/html" },
{ ".jpg", "image/jpeg" },
{ ".jpeg", "image/jpeg" },
//{ ".js", "application/javascript" },
//{ ".json", "application/json" },
//{ ".map", "application/x-navimap" },
{ ".pdf", "application/pdf" },
{ ".png", "image/png" },
//{ ".txt", "text/plain" },
};
_server = new HttpServer {Port = port};
_fileDirectory = directory;
_server.OnHttpRequest += Server_OnHttpRequest;
_server.Open();
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
}
/// <summary>
/// Handles incoming HTTP requests and serves files from the configured directory
/// </summary>
/// <param name="sender">The HTTP server instance</param>
/// <param name="args">HTTP request arguments</param>
void Server_OnHttpRequest(object sender, OnHttpRequestArgs args)
{
var path = args.Request.Path;
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "HTTP Request with path: '{requestPath:l}'", args.Request.Path);
try
{
if (File.Exists(_fileDirectory + path))
{
var filePath = path.Replace('/', '\\');
var localPath = string.Format(@"{0}{1}", _fileDirectory, filePath);
Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server attempting to find file: '{localPath:l}'", localPath);
if (File.Exists(localPath))
{
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension);
args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server Cannot find file '{localPath:l}'", localPath);
args.Response.ContentString = string.Format("Not found: '{0}'", filePath);
args.Response.Code = 404;
}
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server: '{file:l}' does not exist", _fileDirectory + path);
args.Response.ContentString = string.Format("Not found: '{0}'", _fileDirectory + path);
args.Response.Code = 404;
}
}
catch (Exception ex)
{
Debug.LogMessage(LogEventLevel.Error, "Exception getting file: {exception}", ex.Message, ex.StackTrace);
Debug.LogMessage(LogEventLevel.Verbose, "Stack Trace: {stackTrace}", ex.StackTrace);
args.Response.Code = 400;
args.Response.ContentString = string.Format("invalid request");
}
}
/// <summary>
/// Handles program status events and closes the server when the program is stopping
/// </summary>
/// <param name="programEventType">The program status event type</param>
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{
if (programEventType == eProgramStatusEventType.Stopping)
_server.Close();
}
/// <summary>
/// Gets the content type for a file based on its extension
/// </summary>
/// <param name="extension">The file extension</param>
/// <returns>The corresponding content type string</returns>
/// <summary>
/// GetContentType method
/// </summary>
public static string GetContentType(string extension)
{
var type = ExtensionContentTypes.ContainsKey(extension) ? ExtensionContentTypes[extension] : "text/plain";
return type;
}
}
}