Настройте IIS10 для обслуживания предварительно сжатых файлов

мои проекты angular2 создают предварительно сжатые файлы gzip для моего веб-приложения, но мой IIS обслуживает только обычные файлы ".js" вместо сжатых файлов ".gzip". Мой браузер готов принять gzip.

Как правильно настроить IIS, чтобы разрешить ответы gzip?

Я уже искал в google / SO / SU, но нашел решения только для «предварительно сжатого» контента.


person Alex    schedule 20.02.2018    source источник


Ответы (2)


Более изящное и элегантное решение:

ВНИМАНИЕ: расширение файла .gzip кажется странным, в общем, мы называем файл gziped как .gz, поэтому в этом примере мы используем .gz вместо .gzip, если вы настаиваете на .gzip, просто замените все расширения в следующем файле конфигурации.


Сначала код, это все, что нам нужно для web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <staticContent>
      <remove fileExtension=".js.gz" />
      <remove fileExtension=".css.gz" />
      <remove fileExtension=".png.gz" />
      <remove fileExtension=".jpg.gz" />
      <remove fileExtension=".gif.gz" />
      <remove fileExtension=".svg.gz" />
      <remove fileExtension=".html.gz" />
      <remove fileExtension=".json.gz" />
      <mimeMap fileExtension=".js.gz" mimeType="application/javascript" />
      <mimeMap fileExtension=".css.gz" mimeType="text/css" />
      <mimeMap fileExtension=".png.gz" mimeType="image/png" />
      <mimeMap fileExtension=".jpg.gz" mimeType="image/jpeg" />
      <mimeMap fileExtension=".gif.gz" mimeType="image/gif" />
      <mimeMap fileExtension=".svg.gz" mimeType="image/svg+xml" />
      <mimeMap fileExtension=".html.gz" mimeType="text/html" />
      <mimeMap fileExtension=".json.gz" mimeType="application/json" />
    </staticContent>
  
    <rewrite>
      <outboundRules rewriteBeforeCache="true">
        <rule name="Custom gzip file header">
          <match serverVariable="RESPONSE_CONTENT_ENCODING" pattern=".*" />
          <conditions>
            <add input="{REQUEST_URI}" pattern="\.gz$" />
          </conditions>
          <action type="Rewrite" value="gzip"/>
        </rule>
      </outboundRules>
      
      <rules>
        <rule name="Rewrite gzip file">
          <match url="(.*)"/>
          <conditions>
            <add input="{HTTP_ACCEPT_ENCODING}" pattern="gzip" />
            <add input="{REQUEST_FILENAME}.gz" matchType="IsFile" />
          </conditions>
          <action type="Rewrite" url="{R:1}.gz" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

И вот как это работает:

Для успешной передачи данных в формате gziped нам необходимо:

  • Клиентская сторона принимает данные в формате gziped, Accept-Encoding
  • Ответ с заголовком Content-Encoding
  • Правильный тип MIME, как и исходный файл, НО НЕ application/gzip
  • Gziped файл

Четыре условия должны выполняться одновременно.

Если вы отправите несжатый файл с Content-Encoding: gzip, браузер вернет ошибку;

Если вы отправляете сжатый файл без заголовка Content-Encoding или несоответствующего типа MIME, страница может вернуть текст Zenith Star.

Итак, что мы делаем:

  • Переопределите каждый тип MIME файла gziped
  • Если клиентская сторона принимает файл gziped, перенаправьте файл ответа в версию gziped на стороне сервера напрямую (а не ответ 302/303/307)
  • Перепишите заголовок ответа Content-Encoding, только если клиентская сторона отправит заголовок Accept-Encoding

Это решение работает на моем IIS7, не уверен, будет ли оно работать и на IIS10.

Если вы столкнулись с какой-либо проблемой, дайте мне знать: D

person Losses Don    schedule 17.03.2018
comment
Спасибо за указание на это. К сожалению, мне не удалось заставить это работать в IIS 10 (что, по вашему мнению, может и не быть). Вдобавок я обнаружил, что ответ, который мы искали здесь stackoverflow.com/questions/45199213/ не работает во всех браузерах. FireFox (например) не загружает файлы .js с ошибкой SyntaxError: недопустимый символ. Однако мне не удалось подтвердить или опровергнуть, есть ли в вашем решении такая же проблема. - person mikeo; 30.03.2018
comment
@mikeo хмммммм, я только что попробовал эту конфигурацию на своих Windows 10, с IIS 10 он работает хорошо ... - person Losses Don; 31.03.2018
comment
И он обслуживает предварительно сжатые файлы? Не сжатые динамически? Вот куда я не мог добраться. Он обслуживал сжатые файлы, но они были динамически сжатыми ... показывая, что размер файла несколько больше, чем у моих предварительно сжатых. Если так, я попробую еще раз и дам вам знать. - person mikeo; 31.03.2018
comment
@mikeo попробуйте сначала отключить динамический gzip, если после этого он сработает, мы можем найти другое решение. - person Losses Don; 01.04.2018
comment
да, я делал и то, и другое (в разное время устранение неполадок), когда я удаляю динамический, он просто обслуживает полный файл, который намного больше, чем предварительно сжатый или динамически сжатый. Что странно, так это то, что другая настройка ответа (похожая, но менее надежная, чем ваша) работает (во всем, кроме Firefox) в IIS10. Итак, я не уверен, почему это тоже не сработает. - person mikeo; 02.04.2018
comment
Это было очень полезно. Чтобы воспользоваться преимуществами, мне пришлось установить модуль динамического сжатия. Спасибо, что поделились своими знаниями и идеями! - person omostan; 04.04.2020

После долгих поисков я нашел обходной путь с URL-Rewrite.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <remove name="X-Powered-By" />
            </customHeaders>
        </httpProtocol>
        <rewrite>
            <rules>
                <clear />
                <rule name="Https redirect" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTP_HOST}" pattern="^domain.com$" />
                        <add input="{HTTPS}" pattern="^OFF$" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
                </rule>
                <rule name="LetsEncrypt">
                    <match url=".well-known/acme-challenge/*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="None" />
                </rule>
                <rule name="Angular Routes" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/" />
                </rule>
                <rule name="br_rewrite" enabled="true" stopProcessing="true">
                    <match url="(.*).(js$|svg|css)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTP_ACCEPT_ENCODING}" pattern="br" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" />
                    </conditions>
                    <action type="Rewrite" url="{R:1}.{R:2}.br" logRewrittenUrl="true" />
                </rule>
                <rule name="gzip_rewrite" enabled="true" stopProcessing="true">
                    <match url="(.*).(js$|svg|css)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTP_ACCEPT_ENCODING}" pattern="gzip" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" />
                    </conditions>
                    <action type="Rewrite" url="{R:1}.{R:2}.gz" logRewrittenUrl="true" />
                </rule>
            </rules>
            <outboundRules rewriteBeforeCache="true">
                <rule name="Remove Server header" enabled="true">
                    <match serverVariable="RESPONSE_Server" pattern=".+" />
                    <action type="Rewrite" value="" />
                </rule>
                <rule name="Rewrite content-encoding header gzip" preCondition="IsGZ" enabled="true" stopProcessing="false">
                    <match serverVariable="RESPONSE_CONTENT_ENCODING" pattern=".*" />
                    <action type="Rewrite" value="gzip" />
                </rule>
                <rule name="Rewrite content-encoding header br" preCondition="IsBR" enabled="true" stopProcessing="false">
                    <match serverVariable="RESPONSE_CONTENT_ENCODING" pattern=".*" />
                    <action type="Rewrite" value="br" />
                </rule>
                <rule name="css content type" preCondition="IsCSS" enabled="true" stopProcessing="false">
                    <match serverVariable="RESPONSE_CONTENT_TYPE" pattern="(.*)" />
                    <action type="Rewrite" value="text/css" />
                </rule>
                <rule name="js content type" preCondition="IsJS" enabled="true" stopProcessing="false">
                    <match serverVariable="RESPONSE_CONTENT_TYPE" pattern="(.*)" />
                    <action type="Rewrite" value="application/javascript" />
                </rule>
                <rule name="svg content type" preCondition="IsSVG" enabled="true" stopProcessing="false">
                    <match serverVariable="RESPONSE_CONTENT_TYPE" pattern="(.*)" />
                    <action type="Rewrite" value="image/svg+xml" />
                </rule>
                <preConditions>
                    <preCondition name="IsGZ">
                        <add input="{URL}" pattern="\.gz$" />
                    </preCondition>
                    <preCondition name="IsBR">
                        <add input="{URL}" pattern="\.br$" />
                    </preCondition>
                    <preCondition name="IsCSS">
                        <add input="{URL}" pattern="css" />
                    </preCondition>
                    <preCondition name="IsJS">
                        <add input="{URL}" pattern="js" />
                    </preCondition>
                    <preCondition name="IsSVG">
                        <add input="{URL}" pattern="svg" />
                    </preCondition>
                </preConditions>
            </outboundRules>
        </rewrite>
        <urlCompression doStaticCompression="true" doDynamicCompression="false" />
        <httpCompression sendCacheHeaders="false" />
        <staticContent>
            <mimeMap fileExtension=".br" mimeType="application/brotli" />
            <clientCache cacheControlMode="UseMaxAge" />
        </staticContent>
    </system.webServer>
</configuration>

Он успешно обрабатывает запросы BR и GZIP для предварительно созданных файлов angular (JS, CSS, SVG).

Надеюсь, это поможет кому-то другому. Если вы знаете лучшее решение, дайте мне знать.

person Alex    schedule 26.02.2018
comment
Используя этот обходной путь, я мог видеть, что Chrome теперь использует brotli файлы. Но когда я удаляю правила для brotli и сохраняю gzip, сжатие не работает в IIS 10. @Alex - person Uthpala Pathirana; 07.08.2019
comment
Я не эксперт по IIS, поэтому мое решение - попытка ошибиться (скорее всего, очень подвержена ошибкам). Вы пробовали решение от @Losses Don? Он предложил более чистое решение, которое может обойтись без проблем, если вам понадобится только gzip. - person Alex; 07.08.2019
comment
Я сделал. Используя это, казалось, что он обслуживает gz файлы (я понял по размеру), но возникают синтаксические ошибки из-за отсутствия заголовка content-encoding: gzip, где браузер не может декодировать. - person Uthpala Pathirana; 08.08.2019
comment
Я решил, что для получения предварительно сжатых файлов необходимо включить SSL, даже если сервер настроен, как указано выше. - person Uthpala Pathirana; 15.08.2019