Skip to content

Commit f978f07

Browse files
committed
added sitemap
1 parent a9f672a commit f978f07

4 files changed

Lines changed: 89 additions & 1 deletion

File tree

Endpoints/RobotsEndpoint.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace downpatch.Endpoints
2+
{
3+
public static class RobotsEndpoints
4+
{
5+
public static IEndpointRouteBuilder MapRobots(this IEndpointRouteBuilder app)
6+
{
7+
app.MapGet("/robots.txt", (HttpContext ctx) =>
8+
{
9+
var baseUrl = $"{ctx.Request.Scheme}://{ctx.Request.Host}".TrimEnd('/');
10+
var txt =
11+
$@"User-agent: *
12+
Allow: /
13+
14+
Sitemap: {baseUrl}/sitemap.xml
15+
";
16+
return Results.Text(txt, "text/plain");
17+
});
18+
19+
return app;
20+
}
21+
}
22+
23+
}

Endpoints/SitemapEndpoint.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using downpatch.Data;
2+
using downpatch.Services;
3+
using Microsoft.Extensions.Options;
4+
using System.Text;
5+
using System.Xml.Linq;
6+
7+
namespace downpatch.Endpoints
8+
{
9+
public static class SitemapEndpoints
10+
{
11+
public static IEndpointRouteBuilder MapSitemap(this IEndpointRouteBuilder app)
12+
{
13+
app.MapGet("/sitemap.xml", (
14+
HttpContext ctx,
15+
MarkdownStore store,
16+
IOptions<MarkdownOptions> opt) =>
17+
{
18+
var max = Math.Clamp(opt.Value.MaxSitemapUrls, 1, 50_000);
19+
20+
var baseUrl = $"{ctx.Request.Scheme}://{ctx.Request.Host}".TrimEnd('/');
21+
22+
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
23+
var urlset = new XElement(ns + "urlset");
24+
25+
int count = 0;
26+
foreach (var (slug, last) in store.EnumerateAll().OrderBy(x => x.slug))
27+
{
28+
if (count++ >= max) break;
29+
30+
var loc = string.IsNullOrWhiteSpace(slug) ? $"{baseUrl}/" : $"{baseUrl}/guide/{slug}";
31+
//trim "index" from the end of URLs
32+
if (loc.EndsWith("/index", StringComparison.OrdinalIgnoreCase))
33+
{
34+
loc = loc.Substring(0, loc.Length - 6);
35+
}
36+
37+
urlset.Add(new XElement(ns + "url",
38+
new XElement(ns + "loc", loc),
39+
new XElement(ns + "lastmod", last.ToString("yyyy-MM-dd"))
40+
));
41+
}
42+
43+
//Double check no duplicates (shouldn't be any, but just in case)
44+
var distinctUrls = urlset.Elements(ns + "url")
45+
.GroupBy(x => x.Element(ns + "loc")?.Value)
46+
.Select(g => g.First())
47+
.ToList();
48+
49+
urlset.RemoveAll();
50+
urlset.Add(distinctUrls);
51+
52+
53+
54+
var doc = new XDocument(urlset);
55+
return Results.Text(doc.ToString(SaveOptions.DisableFormatting), "application/xml", Encoding.UTF8);
56+
});
57+
58+
return app;
59+
}
60+
}
61+
62+
}

Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using downpatch.Components;
22
using downpatch.Data;
3+
using downpatch.Endpoints;
34
using downpatch.Services;
45
using Markdig.Renderers;
56
using Microsoft.AspNetCore.HttpOverrides;
@@ -56,6 +57,8 @@ public static void Main(string[] args)
5657

5758
app.UseAntiforgery();
5859
app.UseStaticFiles();
60+
app.MapRobots();
61+
app.MapSitemap();
5962

6063
app.MapStaticAssets();
6164
app.MapRazorComponents<App>();

downpatch.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk.Web">
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
44
<TargetFramework>net10.0</TargetFramework>

0 commit comments

Comments
 (0)