Skip to content

add original content length header #39

Open
@Alex-ley

Description

@Alex-ley

Feature request:

  • can we add the original content length into an 'Original-Content-Length' header in the after_request func (behind an optional flag in the init method if you don't want it to be a default behaviour), something like the below?

If you would be open to it, I can also do a PR for it? But I didn't want to assume it would be accepted and do the PR without a discussion first.

    def after_request(self, response):
        app = self.app or current_app

        vary = response.headers.get('Vary')
        if not vary:
            response.headers['Vary'] = 'Accept-Encoding'
        elif 'accept-encoding' not in vary.lower():
            response.headers['Vary'] = '{}, Accept-Encoding'.format(vary)

        accept_encoding = request.headers.get('Accept-Encoding', '')
        chosen_algorithm = self._choose_compress_algorithm(accept_encoding)

        if (chosen_algorithm is None or
            response.mimetype not in app.config["COMPRESS_MIMETYPES"] or
            response.status_code < 200 or
            response.status_code >= 300 or
            (response.is_streamed and app.config["COMPRESS_STREAMS"] is False)or
            "Content-Encoding" in response.headers or
            (response.content_length is not None and
             response.content_length < app.config["COMPRESS_MIN_SIZE"])):
            return response

        response.direct_passthrough = False
        
        # add original content length for clients that want to update a download progress bar with
        # the progress event of the `XMLHttpRequest` instance
        # https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event
        # https://github.com/axios/axios/issues/1591#issuecomment-431400903
        # https://stackoverflow.com/a/42345816/9792594 (non-ideal approximation)
        response.headers["Original-Content-Length"] = response.content_length

        if self.cache is not None:
            key = self.cache_key(request)
            compressed_content = self.cache.get(key)
            if compressed_content is None:
                compressed_content = self.compress(app, response, chosen_algorithm)
            self.cache.set(key, compressed_content)
        else:
            compressed_content = self.compress(app, response, chosen_algorithm)

        response.set_data(compressed_content)

        response.headers['Content-Encoding'] = chosen_algorithm
        response.headers['Content-Length'] = response.content_length # compressed length

        # "123456789"   => "123456789:gzip"   - A strong ETag validator
        # W/"123456789" => W/"123456789:gzip" - A weak ETag validator
        etag = response.headers.get('ETag')
        if etag:
            response.headers['ETag'] = '{0}:{1}"'.format(etag[:-1], chosen_algorithm)

        return response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions