Skip to content

Commit 18083c5

Browse files
committed
Consume original-resource
1 parent 7914646 commit 18083c5

File tree

1 file changed

+50
-29
lines changed

1 file changed

+50
-29
lines changed

src/StaticAssets/src/Development/StaticAssetDevelopmentRuntimeHandler.cs

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics;
45
using System.Globalization;
56
using System.IO.Compression;
67
using System.IO.Pipelines;
@@ -22,51 +23,34 @@
2223
namespace Microsoft.AspNetCore.Builder;
2324

2425
// Handles changes during development to support common scenarios where for example, a developer changes a file in the wwwroot folder.
25-
internal sealed partial class StaticAssetDevelopmentRuntimeHandler(List<StaticAssetDescriptor> descriptors)
26+
internal sealed partial class StaticAssetDevelopmentRuntimeHandler
2627
{
27-
private readonly Dictionary<(string Route, string ETag), StaticAssetDescriptor> _descriptorsMap;
28+
internal const string ReloadStaticAssetsAtRuntimeKey = "ReloadStaticAssetsAtRuntime";
2829

29-
public StaticAssetDevelopmentRuntimeHandler(List<StaticAssetDescriptor> descriptors)
30-
{
31-
_descriptorsMap = new();
32-
for (var i = 0; i < descriptors.Count; i++)
33-
{
34-
var descriptor = descriptors[i];
35-
var etag = GetDescriptorETagResponseHeader(descriptor);
36-
if (!_descriptorsMap.TryGetValue((descriptor.Route, etag), out var existing))
37-
{
38-
_descriptorsMap[(descriptor.Route, etag)] = descriptor;
39-
}
40-
}
41-
}
30+
private readonly Dictionary<(string Route, string ETag), StaticAssetDescriptor> _descriptorsMap = [];
4231

43-
private static string? GetDescriptorETagResponseHeader(StaticAssetDescriptor descriptor)
32+
public StaticAssetDevelopmentRuntimeHandler(List<StaticAssetDescriptor> descriptors)
4433
{
45-
for (var i = 0; i < descriptor.ResponseHeaders.Count; i++)
46-
{
47-
var header = descriptor.ResponseHeaders[i];
48-
if (string.Equals(header.Name, HeaderNames.ETag, StringComparison.OrdinalIgnoreCase))
49-
{
50-
return header.Value;
51-
}
52-
}
53-
54-
return null;
34+
CreateDescriptorMap(descriptors);
5535
}
5636

57-
internal const string ReloadStaticAssetsAtRuntimeKey = "ReloadStaticAssetsAtRuntime";
58-
5937
public void AttachRuntimePatching(EndpointBuilder builder)
6038
{
6139
var original = builder.RequestDelegate!;
6240
var asset = builder.Metadata.OfType<StaticAssetDescriptor>().Single();
6341
if (asset.HasContentEncoding())
6442
{
6543
var originalETag = GetDescriptorOriginalResourceProperty(asset);
66-
if (originalETag is not null && _descriptorsMap.TryGetValue((descriptors.Route, originalETag), out var originalAsset))
44+
StaticAssetDescriptor? originalAsset = null;
45+
if (originalETag is not null && _descriptorsMap.TryGetValue((asset.Route, originalETag), out originalAsset))
6746
{
6847
asset = originalAsset;
6948
}
49+
else
50+
{
51+
Debug.Assert(originalETag != null, $"The static asset descriptor {asset.Route} - {asset.AssetPath} does not have an original-resource property.");
52+
Debug.Assert(originalAsset != null, $"The static asset descriptor {asset.Route} - {asset.AssetPath} has an original-resource property that does not match any known static asset descriptor.");
53+
}
7054
}
7155

7256
builder.RequestDelegate = async context =>
@@ -102,6 +86,43 @@ public void AttachRuntimePatching(EndpointBuilder builder)
10286
return null;
10387
}
10488

89+
private static string? GetDescriptorETagResponseHeader(StaticAssetDescriptor descriptor)
90+
{
91+
for (var i = 0; i < descriptor.ResponseHeaders.Count; i++)
92+
{
93+
var header = descriptor.ResponseHeaders[i];
94+
if (string.Equals(header.Name, HeaderNames.ETag, StringComparison.OrdinalIgnoreCase))
95+
{
96+
return header.Value;
97+
}
98+
}
99+
100+
return null;
101+
}
102+
103+
private void CreateDescriptorMap(List<StaticAssetDescriptor> descriptors)
104+
{
105+
for (var i = 0; i < descriptors.Count; i++)
106+
{
107+
var descriptor = descriptors[i];
108+
if (descriptor.HasContentEncoding())
109+
{
110+
continue;
111+
}
112+
var etag = GetDescriptorETagResponseHeader(descriptor);
113+
if (etag != null && !_descriptorsMap.ContainsKey((descriptor.Route, etag)))
114+
{
115+
_descriptorsMap[(descriptor.Route, etag)] = descriptor;
116+
}
117+
else
118+
{
119+
Debug.Assert(etag != null, $"The static asset descriptor {descriptor.Route} - {descriptor.AssetPath} does not have an ETag response header.");
120+
Debug.Assert(_descriptorsMap.ContainsKey((descriptor.Route, etag)),
121+
$"The static asset descriptor {descriptor.Route} - {descriptor.AssetPath} has an ETag response header that is already registered in the map. This should not happen, as the ETag should be unique for each static asset.");
122+
}
123+
}
124+
}
125+
105126
internal static string GetETag(IFileInfo fileInfo)
106127
{
107128
using var stream = fileInfo.CreateReadStream();

0 commit comments

Comments
 (0)