Skip to content

Commit

Permalink
tag helper do not add cdn or pathBase if url is absolute (#324)
Browse files Browse the repository at this point in the history
[release]
  • Loading branch information
grahamwebscale authored Aug 8, 2024
1 parent 01d6e4d commit cc073d0
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/WebOptimizer.Core/Taghelpers/LinkTagHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
}
else
{
href = AddCdn(AddPathBase(href));
if (!Uri.TryCreate(href, UriKind.Absolute, out Uri _))
{
href = AddCdn(AddPathBase(href));
}
output.Attributes.SetAttribute("href", href);
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/WebOptimizer.Core/Taghelpers/ScriptTagHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
}
else
{
src = AddCdn(AddPathBase(src));
if (!Uri.TryCreate(src, UriKind.Absolute, out Uri _))
{
src = AddCdn(AddPathBase(src));
}
output.Attributes.SetAttribute("src", src);
}

Expand Down
107 changes: 107 additions & 0 deletions test/WebOptimizer.Core.Test/TagHelpers/LinkTagHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,5 +240,112 @@ public void CdnUrl_RouteIsAsset_TagHelperBundlingDisabled_Success(string cdnUrl,
Assert.Contains($"href=\"{options.CdnUrl}{pathBase}{cacheValue}\"", linkTags[0]);
Assert.Contains($"href=\"{options.CdnUrl}{pathBase}{cacheValue2}\"", linkTags[1]);
}

[Theory2]
[InlineData("//google.com/test.css")]
[InlineData("http://google.com/test.css")]
[InlineData("https://google.com/test.css")]
public void AbsoluteUrl_RouteIsNotAsset_DoesNotAddCdnOrPath(string absoluteUrl)
{
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(fi => fi.Exists).Returns(true);
var fileProvider = new Mock<IFileProvider>();
fileProvider.Setup(fp => fp.GetFileInfo(It.IsAny<string>())).Returns(fileInfo.Object);
var env = new Mock<IWebHostEnvironment>();
env.Setup(e => e.WebRootFileProvider).Returns(fileProvider.Object);

var options = new WebOptimizerOptions
{
CdnUrl = "https://mycdn.com"
};
var optionsFactory = new Mock<IOptionsFactory<WebOptimizerOptions>>();
optionsFactory.Setup(x => x.Create(It.IsAny<string>())).Returns(options);
var optionsMonitor = new Mock<OptionsMonitor<WebOptimizerOptions>>(optionsFactory.Object, new List<IOptionsChangeTokenSource<WebOptimizerOptions>>(), new Mock<IOptionsMonitorCache<WebOptimizerOptions>>().Object);
optionsMonitor.Setup(x => x.Get(It.IsAny<string>())).Returns(options);
var linkTagHelper = new LinkTagHelper(env.Object, new Mock<IMemoryCache>().Object,
new Mock<IAssetPipeline>().Object, optionsMonitor.Object);
var context = new Mock<HttpContext>().SetupAllProperties();
StringValues ae = "gzip, deflate";

context.SetupSequence(c => c.Request.Headers.TryGetValue("Accept-Encoding", out ae))
.Returns(false)
.Returns(true);
context.Setup(c => c.RequestServices.GetService(typeof(IWebHostEnvironment)))
.Returns(env.Object);
var pathBase = "/myApp";
context.SetupGet(c => c.Request.PathBase).Returns(pathBase);

var viewContext = new ViewContext
{
HttpContext = context.Object
};
linkTagHelper.ViewContext = viewContext;
linkTagHelper.CurrentViewContext = viewContext;

var tagHelperContext = new Mock<TagHelperContext>(
"link",
new TagHelperAttributeList(),
new Dictionary<object, object>(),
"unique");
var attributes = new TagHelperAttributeList { new TagHelperAttribute("href", absoluteUrl) };

var tagHelperOutput = new TagHelperOutput("link", attributes, (useCachedResult, encoder) => Task.Factory.StartNew<TagHelperContent>(
() => new DefaultTagHelperContent()));
linkTagHelper.Process(tagHelperContext.Object, tagHelperOutput);
var hrefValue = tagHelperOutput.Attributes.First(x => x.Name == "href").Value;
Assert.Equal(absoluteUrl, hrefValue);
}

[Fact2]
public void RelativeUrl_RouteIsNotAsset_DoesAddCdnAndPath()
{
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(fi => fi.Exists).Returns(true);
var fileProvider = new Mock<IFileProvider>();
fileProvider.Setup(fp => fp.GetFileInfo(It.IsAny<string>())).Returns(fileInfo.Object);
var env = new Mock<IWebHostEnvironment>();
env.Setup(e => e.WebRootFileProvider).Returns(fileProvider.Object);

var options = new WebOptimizerOptions
{
CdnUrl = "https://mycdn.com"
};
var optionsFactory = new Mock<IOptionsFactory<WebOptimizerOptions>>();
optionsFactory.Setup(x => x.Create(It.IsAny<string>())).Returns(options);
var optionsMonitor = new Mock<OptionsMonitor<WebOptimizerOptions>>(optionsFactory.Object, new List<IOptionsChangeTokenSource<WebOptimizerOptions>>(), new Mock<IOptionsMonitorCache<WebOptimizerOptions>>().Object);
optionsMonitor.Setup(x => x.Get(It.IsAny<string>())).Returns(options);
var linkTagHelper = new LinkTagHelper(env.Object, new Mock<IMemoryCache>().Object, new Mock<IAssetPipeline>().Object, optionsMonitor.Object);
var context = new Mock<HttpContext>().SetupAllProperties();
StringValues ae = "gzip, deflate";

context.SetupSequence(c => c.Request.Headers.TryGetValue("Accept-Encoding", out ae))
.Returns(false)
.Returns(true);
context.Setup(c => c.RequestServices.GetService(typeof(IWebHostEnvironment)))
.Returns(env.Object);
var pathBase = "/myApp";
context.SetupGet(c => c.Request.PathBase).Returns(pathBase);

var viewContext = new ViewContext
{
HttpContext = context.Object
};
linkTagHelper.ViewContext = viewContext;
linkTagHelper.CurrentViewContext = viewContext;

var tagHelperContext = new Mock<TagHelperContext>(
"link",
new TagHelperAttributeList(),
new Dictionary<object, object>(),
"unique");
var relativeUrl = "/test.css";
var attributes = new TagHelperAttributeList { new TagHelperAttribute("href", relativeUrl) };

var tagHelperOutput = new TagHelperOutput("link", attributes, (useCachedResult, encoder) => Task.Factory.StartNew<TagHelperContent>(
() => new DefaultTagHelperContent()));
linkTagHelper.Process(tagHelperContext.Object, tagHelperOutput);
var hrefValue = tagHelperOutput.Attributes.First(x => x.Name == "href").Value;
Assert.Equal($"{options.CdnUrl}{pathBase}{relativeUrl}", hrefValue);
}
}
}
106 changes: 106 additions & 0 deletions test/WebOptimizer.Core.Test/TagHelpers/ScriptTagHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,111 @@ public void CdnUrl_RouteIsAsset_TagHelperBundlingDisabled_Success(string cdnUrl,
Assert.Contains($"src=\"{options.CdnUrl}{pathBase}{cacheValue}\"", scriptTags[0]);
Assert.Contains($"src=\"{options.CdnUrl}{pathBase}{cacheValue2}\"", scriptTags[1]);
}

[Theory2]
[InlineData("//google.com/test.js")]
[InlineData("http://google.com/test.js")]
[InlineData("https://google.com/test.js")]
public void AbsoluteUrl_RouteIsNotAsset_DoesNotAddCdnOrPath(string absoluteUrl)
{
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(fi => fi.Exists).Returns(true);
var fileProvider = new Mock<IFileProvider>();
fileProvider.Setup(fp => fp.GetFileInfo(It.IsAny<string>())).Returns(fileInfo.Object);
var env = new Mock<IWebHostEnvironment>();
env.Setup(e => e.WebRootFileProvider).Returns(fileProvider.Object);

var options = new WebOptimizerOptions
{
CdnUrl = "https://mycdn.com"
};
var optionsFactory = new Mock<IOptionsFactory<WebOptimizerOptions>>();
optionsFactory.Setup(x => x.Create(It.IsAny<string>())).Returns(options);
var optionsMonitor = new Mock<OptionsMonitor<WebOptimizerOptions>>(optionsFactory.Object, new List<IOptionsChangeTokenSource<WebOptimizerOptions>>(), new Mock<IOptionsMonitorCache<WebOptimizerOptions>>().Object);
optionsMonitor.Setup(x => x.Get(It.IsAny<string>())).Returns(options);
var scriptTagHelper = new ScriptTagHelper(env.Object, new Mock<IMemoryCache>().Object, new Mock<IAssetPipeline>().Object, optionsMonitor.Object);
var context = new Mock<HttpContext>().SetupAllProperties();
StringValues ae = "gzip, deflate";

context.SetupSequence(c => c.Request.Headers.TryGetValue("Accept-Encoding", out ae))
.Returns(false)
.Returns(true);
context.Setup(c => c.RequestServices.GetService(typeof(IWebHostEnvironment)))
.Returns(env.Object);
var pathBase = "/myApp";
context.SetupGet(c => c.Request.PathBase).Returns(pathBase);

var viewContext = new ViewContext
{
HttpContext = context.Object
};
scriptTagHelper.ViewContext = viewContext;
scriptTagHelper.CurrentViewContext = viewContext;

var tagHelperContext = new Mock<TagHelperContext>(
"script",
new TagHelperAttributeList(),
new Dictionary<object, object>(),
"unique");
var attributes = new TagHelperAttributeList { new TagHelperAttribute("src", absoluteUrl) };

var tagHelperOutput = new TagHelperOutput("scripts", attributes, (useCachedResult, encoder) => Task.Factory.StartNew<TagHelperContent>(
() => new DefaultTagHelperContent()));
scriptTagHelper.Process(tagHelperContext.Object, tagHelperOutput);
var srcValue = tagHelperOutput.Attributes.First(x => x.Name == "src").Value;
Assert.Equal(absoluteUrl, srcValue);
}

[Fact2]
public void RelativeUrl_RouteIsNotAsset_DoesAddCdnAndPath()
{
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(fi => fi.Exists).Returns(true);
var fileProvider = new Mock<IFileProvider>();
fileProvider.Setup(fp => fp.GetFileInfo(It.IsAny<string>())).Returns(fileInfo.Object);
var env = new Mock<IWebHostEnvironment>();
env.Setup(e => e.WebRootFileProvider).Returns(fileProvider.Object);

var options = new WebOptimizerOptions
{
CdnUrl = "https://mycdn.com"
};
var optionsFactory = new Mock<IOptionsFactory<WebOptimizerOptions>>();
optionsFactory.Setup(x => x.Create(It.IsAny<string>())).Returns(options);
var optionsMonitor = new Mock<OptionsMonitor<WebOptimizerOptions>>(optionsFactory.Object, new List<IOptionsChangeTokenSource<WebOptimizerOptions>>(), new Mock<IOptionsMonitorCache<WebOptimizerOptions>>().Object);
optionsMonitor.Setup(x => x.Get(It.IsAny<string>())).Returns(options);
var scriptTagHelper = new ScriptTagHelper(env.Object, new Mock<IMemoryCache>().Object, new Mock<IAssetPipeline>().Object, optionsMonitor.Object);
var context = new Mock<HttpContext>().SetupAllProperties();
StringValues ae = "gzip, deflate";

context.SetupSequence(c => c.Request.Headers.TryGetValue("Accept-Encoding", out ae))
.Returns(false)
.Returns(true);
context.Setup(c => c.RequestServices.GetService(typeof(IWebHostEnvironment)))
.Returns(env.Object);
var pathBase = "/myApp";
context.SetupGet(c => c.Request.PathBase).Returns(pathBase);

var viewContext = new ViewContext
{
HttpContext = context.Object
};
scriptTagHelper.ViewContext = viewContext;
scriptTagHelper.CurrentViewContext = viewContext;

var tagHelperContext = new Mock<TagHelperContext>(
"script",
new TagHelperAttributeList(),
new Dictionary<object, object>(),
"unique");
var relativeUrl = "/test.js";
var attributes = new TagHelperAttributeList { new TagHelperAttribute("src", relativeUrl) };

var tagHelperOutput = new TagHelperOutput("scripts", attributes, (useCachedResult, encoder) => Task.Factory.StartNew<TagHelperContent>(
() => new DefaultTagHelperContent()));
scriptTagHelper.Process(tagHelperContext.Object, tagHelperOutput);
var srcValue = tagHelperOutput.Attributes.First(x => x.Name == "src").Value;
Assert.Equal($"{options.CdnUrl}{pathBase}{relativeUrl}", srcValue);
}
}
}

0 comments on commit cc073d0

Please sign in to comment.