You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
7.3 KiB
180 lines
7.3 KiB
using System; |
|
using System.IO; |
|
using System.Net.Http; |
|
using System.Text; |
|
using System.Threading.Tasks; |
|
using Microsoft.AspNetCore.Builder; |
|
using Microsoft.AspNetCore.Http; |
|
|
|
namespace ReZero.SuperAPI |
|
{ |
|
public class SuperAPIStaticFileMiddleware |
|
{ |
|
private readonly RequestDelegate _next; |
|
|
|
// Constants for ReZero paths and file locations |
|
internal static string ReZeroDirName = "rezero"; |
|
internal static string RezeroPathPrefix = $"/{ReZeroDirName}/"; |
|
internal static string RezeroRootPath = $"/{ReZeroDirName}"; |
|
internal static string DefaultIndexPath = "index.html"; |
|
internal static string WwwRootPath = "wwwroot"; |
|
internal static string DefaultUiFolderName = "default_ui"; |
|
internal static string UiFolderPath { get; set; } = $"{ReZeroDirName}/{DefaultUiFolderName}"; |
|
|
|
public SuperAPIStaticFileMiddleware(RequestDelegate next) |
|
{ |
|
_next = next ?? throw new ArgumentNullException(nameof(next)); |
|
} |
|
|
|
/// <summary> |
|
/// Invokes the middleware to handle the request. |
|
/// </summary> |
|
/// <param name="context">The HttpContext for the request.</param> |
|
public async Task InvokeAsync(HttpContext context) |
|
{ |
|
// Get the lowercase path of the request |
|
var path = (context.Request.Path.Value ?? string.Empty).ToLower(); |
|
|
|
// Check if the request is for the root URL of ReZero |
|
if (IsRezeroRootUrl(path)) |
|
{ |
|
// Redirect to the default index.html if it is the root URL |
|
context.Response.Redirect($"{RezeroPathPrefix}{DefaultIndexPath}"); |
|
return; |
|
} |
|
// Check if the request is for a ReZero static file |
|
else if (IsRezeroFileUrl(path)) |
|
{ |
|
|
|
var filePathByCurrentDirectory = GetFilePathByCurrentDirectory(path); |
|
var filePathByBaseDirectory = GetFilePathByBaseDirectory(path); |
|
|
|
if (FileExistsAndIsNotHtml(filePathByCurrentDirectory)) |
|
{ |
|
await CopyToFile(context, filePathByCurrentDirectory); |
|
return; |
|
} |
|
else if (FileExistsHtml(filePathByCurrentDirectory)) |
|
{ |
|
await CopyToHtml(context, filePathByCurrentDirectory); |
|
return; |
|
} |
|
else if (FileExistsAndIsNotHtml(filePathByBaseDirectory)) |
|
{ |
|
await CopyToFile(context, filePathByBaseDirectory); |
|
return; |
|
} |
|
else if (FileExistsHtml(filePathByBaseDirectory)) |
|
{ |
|
await CopyToHtml(context, filePathByBaseDirectory); |
|
return; |
|
} |
|
else |
|
{ |
|
// If the file does not exist, return a 404 Not Found status |
|
context.Response.StatusCode = 404; |
|
return; |
|
} |
|
} |
|
|
|
// If the request doesn't match ReZero paths, call the next middleware |
|
await _next(context); |
|
} |
|
|
|
/// <summary> |
|
/// Checks if the requested file exists and is not an HTML file. |
|
/// </summary> |
|
/// <param name="filePath">The path of the file to check.</param> |
|
/// <returns>True if the file exists and is not an HTML file, false otherwise.</returns> |
|
private static bool FileExistsAndIsNotHtml(string filePath) |
|
{ |
|
return File.Exists(filePath) && !filePath.Contains(".html"); |
|
} |
|
|
|
/// <summary> |
|
/// Checks if the requested file exists and is an HTML file. |
|
/// </summary> |
|
/// <param name="filePath">The path of the file to check.</param> |
|
/// <returns>True if the file exists and is an HTML file, false otherwise.</returns> |
|
private static bool FileExistsHtml(string filePath) |
|
{ |
|
return File.Exists(filePath) && filePath.Contains(".html"); |
|
} |
|
|
|
/// <summary> |
|
/// Copies the content of the requested file to the response stream. |
|
/// </summary> |
|
/// <param name="context">The HttpContext for the request.</param> |
|
/// <param name="filePath">The path of the file to copy.</param> |
|
private static async Task CopyToFile(HttpContext context, string filePath) |
|
{ |
|
// Read the file content and send it to the client |
|
using (var fileStream = File.OpenRead(filePath)) |
|
{ |
|
await fileStream.CopyToAsync(context.Response.Body); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Copies the content of the requested HTML file to the response stream. |
|
/// </summary> |
|
/// <param name="context">The HttpContext for the request.</param> |
|
/// <param name="filePath">The path of the HTML file to copy.</param> |
|
private static async Task CopyToHtml(HttpContext context, string filePath) |
|
{ |
|
// Read the file content |
|
string fileContent; |
|
using (var reader = new StreamReader(filePath)) |
|
{ |
|
fileContent = await reader.ReadToEndAsync(); |
|
} |
|
// Check if the file is a master page |
|
IUiManager defaultUiManager = UIFactory.uiManager; |
|
if (defaultUiManager.IsMasterPage(fileContent)) |
|
{ |
|
// If the file is a master page, get the HTML and send it to the client |
|
fileContent = await defaultUiManager.GetHtmlAsync(fileContent, filePath, context); |
|
} |
|
else |
|
{ |
|
fileContent = await defaultUiManager.GetCustomPageHtmlAsync(fileContent, filePath, context); |
|
} |
|
// Send the file content to the client |
|
await context.Response.WriteAsync(fileContent); |
|
} |
|
|
|
/// <summary> |
|
/// Checks if the requested URL is for a ReZero static file. |
|
/// </summary> |
|
/// <param name="path">The path of the requested URL.</param> |
|
/// <returns>True if the requested URL is for a ReZero static file, false otherwise.</returns> |
|
private static bool IsRezeroFileUrl(string path) |
|
{ |
|
return path.StartsWith(RezeroPathPrefix) && path.Contains("."); |
|
} |
|
|
|
/// <summary> |
|
/// Checks if the requested URL is the root URL of ReZero. |
|
/// </summary> |
|
/// <param name="path">The path of the requested URL.</param> |
|
/// <returns>True if the requested URL is the root URL of ReZero, false otherwise.</returns> |
|
private static bool IsRezeroRootUrl(string path) |
|
{ |
|
return path.TrimEnd('/') == RezeroRootPath; |
|
} |
|
|
|
|
|
internal static string GetFilePathByCurrentDirectory(string path) |
|
{ |
|
var relativePath = path.Replace(RezeroPathPrefix, string.Empty); |
|
var fullPath = Path.Combine(Directory.GetCurrentDirectory(), WwwRootPath, UiFolderPath, relativePath); |
|
return Path.GetFullPath(fullPath); |
|
} |
|
internal static string GetFilePathByBaseDirectory(string path) |
|
{ |
|
var relativePath = path.Replace(RezeroPathPrefix, string.Empty); |
|
var fullPath = Path.Combine(AppContext.BaseDirectory, WwwRootPath, UiFolderPath, relativePath); |
|
return Path.GetFullPath(fullPath); |
|
} |
|
} |
|
} |