Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable static content compression in IIS with with i18n localization module causes ERR_CONTENT_DECODING_FAILED #163

Closed
bubaker opened this issue Dec 3, 2014 · 11 comments

Comments

@bubaker
Copy link

bubaker commented Dec 3, 2014

As per the title - If I have enabled static content compression on the site in iis and I have the i18n module running browsers will fail to load .js files, normally on the first refresh. It is intermittent, often everything works first time in but at a later point normally on a page refresh the js files will fail to load. If I stop use the i18n module everything will start working. If I switch off enable static content compression everything will start working. If I switch them both on bang it breaks. I think that it is intermittently serving up the JS files uncompressed and the browsers choke when they try to decompress.

Windows 7 64. IIS. MVC4 application. .Net 4.5

@bubaker
Copy link
Author

bubaker commented Dec 3, 2014

Oh and it's running the default app pool in integrated mode

@turquoiseowl
Copy link
Owner

Presumably, then, in the HTTP response that fails with ERR_CONTENT_DECODING_FAILED, the Content-Encoding header says gzip, but the content isn't gzipped. Can you confirm that? Is the response body plain text?

Just pulling out a bit, do you want these .js files to be localized? Presumably not because static content compression will thwart that by definition.

If you don't want them to be localized, you can instruct i18n to ignore them (i18n.LocalizedApplication.Current.ContentTypesToLocalize).

@turquoiseowl
Copy link
Owner

Any insights into what caching the browser is doing of those .js files may help to diagnose this also.

@bubaker
Copy link
Author

bubaker commented Dec 3, 2014

Thanks for the quick response.

Yes, I would like the JS files localized (for text in alerts etc) so if static content compression means that's not possible then I have my answer: I can't switch static compression on.

@turquoiseowl
Copy link
Owner

If the IIS static compression feature allows you configure the types of content to target for compression, then you need to get it to exclude .js files by the sounds of it.

If not, then it looks like you do need to disable it.

(Not sure why you get that error, though, and not simply an un-localized .js file content.)

@turquoiseowl
Copy link
Owner

Additional information about IIS compression and i18n:

With static compression enabled on IIS 7+ for a mime type that i18n is localizing (ref i18n.LocalizedApplication.Current.ContentTypesToLocalize), any request which does NOT involve cached content from a previously compressed request will work ok. However, where the request involes the cache employed by the static compression feature then it appears to fail.

The nature of the failure is an error indicating an error decoding the content. While the response headers all appear correct, the body is missing/empty (hence the decode error!).

By integrating with the compression API, there may be scope to get this working.

For now, dynamic compression seems to work fine and is compatible with i18n localized content. E.g., in web.config:

<system.webServer>
    <urlCompression doStaticCompression="false" doDynamicCompression="true" />
    <httpCompression>
        <dynamicTypes>
            <clear />
            <add enabled="true" mimeType="text/*"/>
            <add enabled="true" mimeType="message/*"/>
            <add enabled="true" mimeType="application/javascript"/>
            <add enabled="true" mimeType="application/x-javascript"/>
            <add enabled="true" mimeType="application/atom+xml"/>
            <add enabled="true" mimeType="application/xaml+xml"/>
            <add enabled="true" mimeType="application/json"/>
            <add enabled="false" mimeType="*/*"/>
        </dynamicTypes>
    </httpCompression>
</system.webServer>

Azure IIS 8.0 / .NET 4.5 / ASP.NET MVC 4

@gitsno
Copy link
Contributor

gitsno commented Mar 20, 2015

I've just started using this library but I think I may have a solution for this. From what I can tell it seems that the problem only ever happens with the ScriptResource.axd and WebResource.axd requests. Is anyone else seeing this happen for other requests?

In my case I was only seeing it for those requests, and it seems this is a known issue documented here
https://connect.microsoft.com/VisualStudio/feedback/details/594413/multiple-select-does-not-return-correct-form-data-during-callback
There is a workaround given there, which involves creating a Response Filter, but given that this library already does that I simply put a test into OnReleaseRequestState in LocalizingModule.cs to ensure that the filter is not touched for the two axds and it seems to be working now.

So I changed the OnReleaseRequestState code to

    private void OnReleaseRequestState(object sender, EventArgs e)
    {
        HttpApplication application = sender as HttpApplication;

        if (application != null)
        {
            if (!application.Request.Url.ToString().Contains("ScriptResource.axd") && !application.Request.Url.ToString().Contains("WebResource.axd"))
            {
                //
                HttpContextBase context = HttpContext.Current.GetHttpContextBase();
                DebugHelpers.WriteLine("LocalizingModule::OnReleaseRequestState -- sender: {0}, e:{1}, ContentType: {2},\n+++>Url: {3}\n+++>RawUrl:{4}", sender, e, context.Response.ContentType, context.Request.Url, context.Request.RawUrl);

                // If the content type of the entity is eligible for processing AND the URL is not to be excluded,
                // wire up our filter to do the processing. The entity data will be run through the filter a
                // bit later on in the pipeline.
                if ((LocalizedApplication.Current.ContentTypesToLocalize != null
                        && LocalizedApplication.Current.ContentTypesToLocalize.Match(context.Response.ContentType).Success) // Include certain content types from being processed
                    &&
                    (LocalizedApplication.Current.UrlsToExcludeFromProcessing != null
                        && LocalizedApplication.Current.UrlsToExcludeFromProcessing.Match(context.Request.RawUrl).Success) == false) // Exclude certain URLs from being processed
                {
                    DebugHelpers.WriteLine("LocalizingModule::OnReleaseRequestState -- Installing filter");
                    context.Response.Filter = new ResponseFilter(
                        context,
                        context.Response.Filter,
                        UrlLocalizer.UrlLocalizationScheme == UrlLocalizationScheme.Void ? null : m_rootServices.EarlyUrlLocalizerForApp,
                        m_rootServices.NuggetLocalizerForApp);
                }
                else
                {
                    DebugHelpers.WriteLine("LocalizingModule::OnReleaseRequestState -- No content-type match ({0}). Bypassing filter.", context.Response.ContentType);
                }
            }
        }
    }

Before I submit a pull request I wanted to see if anyone else has comments on whether or not you've seen the ERR_CONTENT_DECODING_FAILED error for other requests?

@turquoiseowl
Copy link
Owner

Yes, I've experienced ERR_CONTENT_DECODING_FAILED (in turn resulting from an empty response body) using ASP.NET MVC 4. I don't think that relates to the .axd resources you mention. Further details in my message above.

@gitsno
Copy link
Contributor

gitsno commented Mar 23, 2015

I figured there probably were other cases, it seems like the filters are a little fragile. My case doesn't need a change to the library anyway, all I'm going to do is use i18n.LocalizedApplication.Current.UrlsToExcludeFromProcessing to exclude the two axds from being localized.

When I get a chance I'l spend some more time looking into the filters to see if that can be made more robust, but for now no changes necessary! Thanks

@gitsno
Copy link
Contributor

gitsno commented Apr 7, 2015

This issue is now resolved in a commit in #193
Note that the fix prevents corruption of content that is compressed before it reaches the i18n module, it does not localize within the compressed content, so if you need to have nuggets in static files localized you should turn off static file compression, but having static file compression turned on will no longer result in corrupt responses.

@ajbeaven
Copy link
Contributor

Yay, just discovered this issue after spending a long time investigating the ERR_CONTENT_DECODING_FAILED error - it is very strange behaviour.

Note, despite the commit in #193 I'm still finding the response comes back empty when static compression is enabled on a .js file with nuggets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants