在页面呈现后,将 nofollow 属性添加到每个具有外部 link 的 <a> 标签
Add nofollow attribute to each <a> tag with external link after the page was rendered
客户要求我们的 sitecore 解决方案中所有指向外部页面的链接都应具有 nofollow 属性。我应该使用哪个管道来访问响应 html(在将链接与标记一起发送到浏览器之前更改链接)?或者有没有更好的解决方案来完成这个?
JavaScript 在这里没有太大帮助,因为我不确定是否所有搜索引擎都能够 运行 JavaScript.
RenderField 处理器也不可用,因为我们的代码中有很多自定义标签
您可以使用 Sitecore.Pipelines.HttpRequest
并在 ExecuteRequest 之后打补丁。
此时您已经完全呈现 html,包括来自 HTML 缓存的所有缓存组件。
编辑添加示例:
#region Using
using System;
using System.IO;
using Sitecore.Pipelines.HttpRequest;
#endregion
namespace MySpace.Sitecore.Pipelines
{
public class MyProcessor : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
if (!global::Sitecore.Context.PageMode.IsPageEditor)
{
if (!args.Context.Request.RawUrl.Contains(".") || (args.Context.Request.RawUrl.ToLower().Contains(".aspx") && !args.Context.Request.RawUrl.ToLower().StartsWith("/sitecore")))
{
args.Context.Response.Filter = new MyInterestFilter(args.Context.Response.Filter);
}
}
}
#region Stream filter
public class MyInterestFilter : Stream
{
public MyInterestFilter(Stream sink)
{
_sink = sink;
}
private Stream _sink;
#region Properites
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override void Flush()
{
_sink.Flush();
}
public override long Length
{
get { return 0; }
}
private long _position;
public override long Position
{
get { return _position; }
set { _position = value; }
}
#endregion
#region Methods
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _sink.Seek(offset, origin);
}
public override void SetLength(long value)
{
_sink.SetLength(value);
}
public override void Close()
{
_sink.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string html = System.Text.Encoding.Default.GetString(buffer);
html = MyReplace(html);
byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
_sink.Write(outdata, 0, outdata.GetLength(0));
}
public static string MyReplace(string html)
{
html = html.Replace("TESTSTRING", "REPLACEDTESTSTRING");
return html;
}
#endregion
}
#endregion
}
}
并在 App_Config 包含目录中设置补丁文件,如下所示:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<httpRequestBegin>
<processor type="MySpace.Sitecore.Pipelines.MyProcessor, MySpace.Sitecore" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel']"/>
</httpRequestBegin>
</pipelines>
</sitecore>
</configuration>
客户要求我们的 sitecore 解决方案中所有指向外部页面的链接都应具有 nofollow 属性。我应该使用哪个管道来访问响应 html(在将链接与标记一起发送到浏览器之前更改链接)?或者有没有更好的解决方案来完成这个?
JavaScript 在这里没有太大帮助,因为我不确定是否所有搜索引擎都能够 运行 JavaScript.
RenderField 处理器也不可用,因为我们的代码中有很多自定义标签
您可以使用 Sitecore.Pipelines.HttpRequest 并在 ExecuteRequest 之后打补丁。
此时您已经完全呈现 html,包括来自 HTML 缓存的所有缓存组件。
编辑添加示例:
#region Using
using System;
using System.IO;
using Sitecore.Pipelines.HttpRequest;
#endregion
namespace MySpace.Sitecore.Pipelines
{
public class MyProcessor : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
if (!global::Sitecore.Context.PageMode.IsPageEditor)
{
if (!args.Context.Request.RawUrl.Contains(".") || (args.Context.Request.RawUrl.ToLower().Contains(".aspx") && !args.Context.Request.RawUrl.ToLower().StartsWith("/sitecore")))
{
args.Context.Response.Filter = new MyInterestFilter(args.Context.Response.Filter);
}
}
}
#region Stream filter
public class MyInterestFilter : Stream
{
public MyInterestFilter(Stream sink)
{
_sink = sink;
}
private Stream _sink;
#region Properites
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override void Flush()
{
_sink.Flush();
}
public override long Length
{
get { return 0; }
}
private long _position;
public override long Position
{
get { return _position; }
set { _position = value; }
}
#endregion
#region Methods
public override int Read(byte[] buffer, int offset, int count)
{
return _sink.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _sink.Seek(offset, origin);
}
public override void SetLength(long value)
{
_sink.SetLength(value);
}
public override void Close()
{
_sink.Close();
}
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string html = System.Text.Encoding.Default.GetString(buffer);
html = MyReplace(html);
byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
_sink.Write(outdata, 0, outdata.GetLength(0));
}
public static string MyReplace(string html)
{
html = html.Replace("TESTSTRING", "REPLACEDTESTSTRING");
return html;
}
#endregion
}
#endregion
}
}
并在 App_Config 包含目录中设置补丁文件,如下所示:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<httpRequestBegin>
<processor type="MySpace.Sitecore.Pipelines.MyProcessor, MySpace.Sitecore" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel']"/>
</httpRequestBegin>
</pipelines>
</sitecore>
</configuration>