Skip to content

actix-files: Range request for static HTML file results in Content Encoding Error #3191

@puzzlepaint

Description

@puzzlepaint

Expected Behavior

Serving static HTML files via actix-files should allow viewing these files in a web browser.

Current Behavior

Serving static HTML files via actix-files works partially, but under some circumstances, trying to view a file results in a "Content Encoding Error" (tested with Firefox).

Possible Solution

I investigated the error using Firefox' developer tools and it turned out that it occurs if the browser sends a range request for the HTML file. Not being a web developer, I am not aware of why the browser sometimes sends a range request when normally browsing to a file; they seemed to be conditional range requests related to the ETag, which seems like a caching mechanism.

The responses to the range requests contained an HTTP header "Content-Encoding: identity". Looking at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding, "identity" does not appear on this page. Thus, it seems to me that "identity" is not a valid value for the Content-Encoding header, which likely causes the "Content Encoding Error" display.

I had a look at the actix-files code and found that this snippet is responsible for adding that header to replies to range requests:

if req.headers().contains_key(&header::ACCEPT_ENCODING) {

// When a Content-Encoding header is present in a 206 partial content response
// for video content, it prevents browser video players from starting playback
// before loading the whole video and also prevents seeking.
//
// See: https://github.com/actix/actix-web/issues/2815
//
// The assumption of this fix is that the video player knows to not send an
// Accept-Encoding header for this request and that downstream middleware will
// not attempt compression for requests without it.
//
// TODO: Solve question around what to do if self.encoding is set and partial
// range is requested. Reject request? Ignoring self.encoding seems wrong, too.
// In practice, it should not come up.
if req.headers().contains_key(&header::ACCEPT_ENCODING) {
    // don't allow compression middleware to modify partial content
    res.insert_header((
        header::CONTENT_ENCODING,
        HeaderValue::from_static("identity"),
    ));
}

Testing with a patched version of actix-files, commenting out this snippet seemed to solve the issue. However, according to the comment in the code, it seems that this will break cases where compression middleware is used.

I am not familiar with how actix-web works internally, but given the above, it seems to me that a proper solution might be to either:

  • Communicate the requirement not to compress partial content to the middleware differently, or
  • Remove the "Content-Encoding: identity" header before the response is sent.

Steps to Reproduce (for bugs)

Serve static HTML files via actix-files and view them in a browser, having the browser use range requests. It is not clear to me under which conditions browsers use range requests for HTML files.

Context

Serving some static HTML files via actix-files.

Your Environment

  • Rust Version (I.e, output of rustc -V): rustc 1.73.0 (cc66ad468 2023-10-03)
  • Actix Web Version: 4.4.0
  • Actix Files Version: 0.6.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions