Skip to content

Commit

Permalink
feat: allow extensionless HTML content access
Browse files Browse the repository at this point in the history
  • Loading branch information
filzrev committed Nov 28, 2024
1 parent 68d6a95 commit 58072f4
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/Docfx.App/RunServe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Docfx.Common;
using Docfx.Plugins;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

#nullable enable

namespace Docfx;

/// <summary>
Expand Down Expand Up @@ -44,6 +48,7 @@ public static void Exec(string folder, string host, int? port, bool openBrowser,
Console.WriteLine($"Serving \"{folder}\" on {url}");
Console.WriteLine("Press Ctrl+C to shut down");
using var app = builder.Build();
app.UseExtensionlessHtmlUrl();
app.UseServe(folder);

if (openBrowser || !string.IsNullOrEmpty(openFile))
Expand Down Expand Up @@ -161,4 +166,41 @@ private static void LaunchBrowser(string url)
Logger.LogError($"Could not launch the browser process. with error - {ex.Message}");
}
}

/// <summary>
/// Enable HTML content access with extensionless URL.
/// This extension method must be called before `UseFileServer` or `UseStaticFiles`.
/// </summary>
private static IApplicationBuilder UseExtensionlessHtmlUrl(this WebApplication app)
{
// Configure middleware that rewrite extensionless url to physical HTML file path.
return app.Use(async (context, next) =>
{
if (IsGetOrHeadMethod(context.Request.Method)
&& TryResolveHtmlFilePath(context.Request.Path, out var htmlFilePath))
{
context.Request.Path = htmlFilePath;
}

await next();
});

static bool IsGetOrHeadMethod(string method) => HttpMethods.IsGet(method) || HttpMethods.IsHead(method);

// Try to resolve HTML file path.
bool TryResolveHtmlFilePath(PathString pathString, [NotNullWhen(true)] out string? htmlPath)
{
var path = pathString.Value;
if (!string.IsNullOrEmpty(path) && !Path.HasExtension(path) && !path.EndsWith('/'))
{
htmlPath = $"{path}.html";
var fileInfo = app.Environment.WebRootFileProvider.GetFileInfo(htmlPath);
if (fileInfo != null)
return true;
}

htmlPath = null;
return false;
}
}
}

0 comments on commit 58072f4

Please sign in to comment.