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

Improved support for compressed content #93

Closed
eyJhb opened this issue Jan 9, 2023 · 5 comments
Closed

Improved support for compressed content #93

eyJhb opened this issue Jan 9, 2023 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@eyJhb
Copy link

eyJhb commented Jan 9, 2023

For my use case I am serving a lot of compressed static files, however, this does not seem like a case that has been thought into microdot.
For getting this to work, I am currently doing the following:

        res = send_file(localPathGzip)
        res.headers["Content-Encoding"] = "gzip"

        # set correct content-type
        ext = path.rsplit(".", 1)[-1]
        contentType = res.default_content_type
        if ext in res.types_map:
            contentType = res.types_map[ext]
        res.headers["Content-Type"] = contentType

        return res

I am unsure of the best way to implement this, but maybe send_file could accept contentType and contentEncoding, as well as moving the mime type detection into a separate function which accepts the filename/path as input (with optional set of default mime)?

@miguelgrinberg miguelgrinberg added the enhancement New feature or request label Jan 9, 2023
@miguelgrinberg miguelgrinberg self-assigned this Jan 9, 2023
@miguelgrinberg
Copy link
Owner

Would it help if send_file() looked for .gz extension and added the content encoding header on its own? It could also look for the original extension before the .gz to also guess the content type.

@eyJhb
Copy link
Author

eyJhb commented Jan 9, 2023

That could be a possibility, however, there would also be cases where the server would not want to add the Content-Encoding header, ie. if it was a file that the client should download.

So I don't think the function can do it automatically, at least, without there being some kind of switch.

Also, thanks for the fast reply! Highly appreciated!

@miguelgrinberg
Copy link
Owner

Yes, that's a good point. What you could do on your own to simplify your solution is to move all your compressed static files to a compressed or gzip folder and then have them there with their original uncompressed name. Then your code can be reduced to 3 lines:

        res = send_file(localPathGzip)
        res.headers["Content-Encoding"] = "gzip"
        return res

I'll think about all the options and see what is the argument or set of arguments that make more sense to add. The other use case I would like to support is to optionally perform the compression of the file on the fly, which is probably not something you'd do on a microcontroller, but with Python would work okay.

@eyJhb
Copy link
Author

eyJhb commented Jan 10, 2023

That would be possible yes, but would be somewhat hacky, however! You've made me realize something!
The URL requested is still the normal file extension, ie. path would be index.html, file.js, etc. so actually the only thing that is needed, is a content_encoding argument (would also be nice with ability to overwrite content_type), combined with a get_mime_type(filename), then the code could look like.

        send_file(localPathGzip, content_encoding="gzip", content_type=get_mime_type(url_path))

This could also enable what you want to do with encoding on-the-fly (at least if send_file will accept a stream maybe).

Does this look like something that could work for you? Also, keep in mind I might be a little biased with how the implementation (ie. adding content_encoding and content_type to the function definition) because of tinyweb (see here https://github.com/belyalov/tinyweb/blob/master/tinyweb/server.py#L256 )

@gogglespisano
Copy link

This is how I added support for GZip

        actual_filename = filename
        content_encoding = None
        ext = filename.split('.')[-1]
        if ext == 'gz':
            content_encoding = 'gzip'
            filename = filename[:-3]

        if content_type is None:
            ext = filename.split('.')[-1]
            if ext in Response.types_map:
                content_type = Response.types_map[ext]
            else:
                content_type = 'program/octet-stream'

        headers = {'Content-Type': content_type}
        if content_encoding is not None:
            headers['Content-Encoding'] = content_encoding

        f = open(actual_filename, 'rb')
        return cls(body=f, status_code=status_code, headers=headers)

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

No branches or pull requests

3 participants