Skip to content

Commit

Permalink
initial public commit
Browse files Browse the repository at this point in the history
  • Loading branch information
saucecontrol committed Feb 6, 2018
0 parents commit 3fa7d25
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root = true

[*]
indent_style = tab
indent_size = 4
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.vs
obj
x64
configuration

*.suo
*.obj
*.aps
*.pch
*.ncb
*.sdf
*.user
*.cachefile
21 changes: 21 additions & 0 deletions license
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License

Copyright (c) 2018 Clinton Ingram

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
97 changes: 97 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
Brotli IIS Compression Scheme Plugin
====================================

Brotli is a new-ish open-sourced compression algorithm specifically designed for HTTP content encoding. The algorithm and reference encoder/decoder libraries were [created by Google](https://github.com/google/brotli) and offered for free.

Brotli offers significantly [better compression than gzip](https://samsaffron.com/archive/2016/06/15/the-current-state-of-brotli-compression) with very little additional compression cost and almost no additional decompression cost.

This IIS Compression Scheme plugin is free and open source, in keeping with the philosophy of Brotli itself.

This plugin is a very thin wrapper around Google's Brotli encoding library. There is no license management code, no automagic configuration, no unnecessary procecessing. This plugin contains only what is absolutely necessary to cleanly integrate Google's Brotli encoder with IIS's built-in Static and Dynamic Compression Modules.

Of course, that means you have to configure it yourself. But a proper HTTP compression design requires that you know what you're doing anyway, so this should not be a problem. If you're new to this, you may find the following links useful for learning about IIS compression and the configuration thereof.

[Configuring HTTP Compression in IIS 7](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771003(v%3dws.10))
[IIS 7 Compression. Good? Bad? How much?](https://weblogs.asp.net/owscott/iis-7-compression-good-bad-how-much)
[Changes to compression in IIS7](http://www.ksingla.net/2006/06/changes_to_compression_in_iis7/)
[Built-in GZip/Deflate Compression on IIS 7.x](https://weblog.west-wind.com/posts/2011/May/05/Builtin-GZipDeflate-Compression-on-IIS-7x)

Very little has changed since IIS 7 was released, but here's one more article highlighting some improvements to dynamic compression in IIS 10
[IIS Dynamic Compression and new Dynamic Compression features in IIS 10](https://blogs.msdn.microsoft.com/friis/2017/09/05/iis-dynamic-compression-and-new-dynamic-compression-features-in-iis-10/)

Features
--------

* Works with the built-in IIS Static and Dynamic Compression Modules.
* Uses the latest version of Google's Brotli encoder (v1.02).

Requirements
------------

IIS 7.5 or later (Windows 7/Windows Server 2008 R2), x64 only. You must have admin permissions to modify the root applicationHost.config file.

Installation
------------

The Brotli IIS Compression Scheme Plugin is packaged as a single DLL file with no external dependencies. The simplest way to install it is to copy it to your `inetsrv` folder, alongside the built-in `gzip.dll`.

Binaries for x64 Windows are available on the [releases page](https://github.com/saucecontrol/BrotliIIS/releases).

The Compression Scheme must be registered in the `applicationHost.config` file. You can do this manually or with AppCmd.exe or IIS Manager. Final configuration will look something like this:

```
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="br" dll="%Windir%\system32\inetsrv\brotli.dll" dynamicCompressionLevel="5" staticCompressionLevel="11" />
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" dynamicCompressionLevel="4" staticCompressionLevel="9" />
<staticTypes>
<add mimeType="text/*" enabled="true" />
...
</staticTypes>
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
...
</dynamicTypes>
</httpCompression>
```

Note: The name `br` shown above is important. This name must match the `Accept-Encoding` header value sent by the client and will be returned to the client in the `Content-Encoding` header. `br` is the official designator for Brotli.

Browser Support
---------------

As of the end of 2017, Brotli is supported in [all modern browsers](https://caniuse.com/#feat=brotli).

There are however, some gotchas related to the way the browser support is implemented.

### HTTPS is Required

Current browsers will only request and accept Brotli encoding over HTTPS. Due to some poorly-behaved intermediate software/devices (proxies, caches, etc) in the wild, the [Chrome team decided](https://bugs.chromium.org/p/chromium/issues/detail?id=452335#c87) to only advertise Brotli support over HTTPS to make sure these poorly-behaved intermediate software and devices couldn't interfere with Brotli-encoded responses. Other vendors followed suit.

If you aren't using HTTPS, you can't use Brotli. Thankfully, with [Let's Encrypt](https://github.com/Lone-Coder/letsencrypt-win-simple), HTTPS is now free and easy to set up. Just do it.

### Brotli is Low-Priority

Current browsers advertise Brotli support with a lower priority than gzip or deflate. Typical `Accept-Encoding` headers will be `Accept-Encoding: gzip, deflate, br`. This is probably also for reasons related to existing poorly-behaved Internet software.

However, because the IIS Compression Modules are well-behaved and respect the client's requested encoding priority, they will not choose Brotli if `gzip` or `deflate` compression is also configured on your server. It is desirable to keep `gzip` enabled to support non-Brotli clients, so if you want to force Brotli, you will need to modify the requests as they enter your IIS pipeline. The [IIS URL Rewrite Module](https://www.iis.net/downloads/microsoft/url-rewrite) makes this easy.

You'll need to enable rewrite of the `Accept-Encoding` header and then configure a rule to prioritize `br` for clients that support it. Here is a sample configuration:

```
<rewrite>
<allowedServerVariables>
<add name="HTTP_ACCEPT_ENCODING" />
</allowedServerVariables>
<rule name="Prioritize Brotli">
<match url=".*" />
<conditions>
<add input="{HTTP_ACCEPT_ENCODING}" pattern="\bbr\b" />
</conditions>
<serverVariables>
<set name="HTTP_ACCEPT_ENCODING" value="br" />
</serverVariables>
</rule>
</rewrite>
```

This rule simply looks for the string `br` (surrounded by word boundaries) in the `Accept-Encoding` header and re-writes it to be just `br`, removing the choice of others. With only one choice of valid `Response-Encoding`, the IIS Compression Modules will be forced to select Brotli. This allows you to leave `gzip` and/or `deflate` enabled for clients that do no advertise `br` support.
112 changes: 112 additions & 0 deletions src/BrotliIIS.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{281A02A7-1B14-4207-8A5C-45B829AD8611}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>BrotliIIS</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<ProjectName>BrotliIIS</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>brotli</TargetName>
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>true</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>brotli</TargetName>
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>true</RunCodeAnalysis>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;BRIIS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\brotli\out\install\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<EnablePREfast>true</EnablePREfast>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\brotli\out\install\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;BRIIS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\brotli\out\install\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnablePREfast>true</EnablePREfast>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\brotli\out\install\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="brotli.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
33 changes: 33 additions & 0 deletions src/BrotliIIS.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="brotli.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
Binary file added src/brotli.cpp
Binary file not shown.
Binary file added src/dllmain.cpp
Binary file not shown.
Binary file added src/stdafx.cpp
Binary file not shown.
Binary file added src/stdafx.h
Binary file not shown.

0 comments on commit 3fa7d25

Please sign in to comment.