Ищем HTTPHandler для изменения страниц на лету, чтобы они указывали на CDN - PullRequest
7 голосов
/ 19 мая 2011

Я пытаюсь создать (или, возможно, уже существует) HTTPHandler, который будет фильтровать сгенерированный HTML ASP.NET для использования сети доставки контента (CDN).Например, я хочу переписать ссылки, такие как это:

/ Portals / _default / default.css

в

http://cdn.example.com/Portals/_default/default.css

Я очень счастлив, используя RegEx, чтобы соответствовать начальным строкам.Такими шаблонами регулярных выражений могут быть:

href=['"](/Portals/.+\.css)

или

src=['"](/Portals/.+\.(css|gif|jpg|jpeg))

Это сайт dotnetnuke, и я не могу контролировать весь сгенерированный HTML, поэтому я хочусделать это с HTTPHandler.Таким образом, изменения могут быть сделаны после генерации страницы.

1 Ответ

13 голосов
/ 19 мая 2011

Вы можете написать фильтр ответов , который можно зарегистрировать в пользовательском модуле HTTP и который будет изменять сгенерированный HTML-код всех страниц, на которых выполняется указанное вами регулярное выражение.

Например:

public class CdnFilter : MemoryStream
{
    private readonly Stream _outputStream;
    public CdnFilter(Stream outputStream)
    {
        _outputStream = outputStream;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        var contentInBuffer = Encoding.UTF8.GetString(buffer);

        contentInBuffer = Regex.Replace(
            contentInBuffer, 
            @"href=(['""])(/Portals/.+\.css)",
            m => string.Format("href={0}http://cdn.example.com{1}", m.Groups[1].Value, m.Groups[2].Value)
        );

        contentInBuffer = Regex.Replace(
            contentInBuffer,
            @"src=(['""])(/Portals/.+\.(css|gif|jpg|jpeg))",
            m => string.Format("href={0}http://cdn.example.com{1}", m.Groups[1].Value, m.Groups[2].Value)
        );

        _outputStream.Write(Encoding.UTF8.GetBytes(contentInBuffer), offset, Encoding.UTF8.GetByteCount(contentInBuffer));
    }
}

, а затем написать модуль:

public class CdnModule : IHttpModule
{
    void IHttpModule.Dispose()
    {
    }

    void IHttpModule.Init(HttpApplication context)
    {
        context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
    }

    void context_ReleaseRequestState(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Filter = new CdnFilter(HttpContext.Current.Response.Filter);
    }
}

и зарегистрируйтесь в web.config:

<httpModules>
  <add name="CdnModule" type="MyApp.CdnModule, MyApp"/>
</httpModules>
...