web-dev-qa-db-ja.com

django

Djangoでgzip圧縮したtext/htmlページを提供しようとしていますが、Firefoxからコンテンツのエンコードエラーが発生しています。

ノート:

  • これはベストプラクティスではなく、mod_gzipを使用する可能性が最も高いことを理解しています。これは、何が起こっているのかを理解するための単なる学習課題です。
  • Django gzipミドルウェア-バイナリファイルに問題があることを知っています。

これが私のコードです:

rendered_page =  zlib.compress(template.render(context).encode('utf-8'))

response = HttpResponse(rendered_page)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = len(rendered_page)
return response

ここで何か不足していますか?コンテンツの長さが間違っている可能性はありますか?不足している追加のヘッダーはありますか?

ありがとう。

39
pjbeardsley

zlibは、この目的には低すぎます。 GZipミドルウェア自体がこれを行う方法を次に示します( Django.utils.text.py のcompress_stringを参照):

import cStringIO, gzip
zbuf = cStringIO.StringIO()
zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
zfile.write(template.render(context).encode('utf-8'))
zfile.close()

compressed_content = zbuf.getvalue()
response = HttpResponse(compressed_content)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = str(len(compressed_content))
return response

GZipはzlibを使用しますが、zlib自体がコンテンツエンコードとして「gzip」を表示するブラウザーに対して不適切にエンコードされたコンテンツを生成します。お役に立てば幸いです。

24
Jarret Hardie

DjangoのGZipミドルウェア を使用することもできます。

次のように追加して、settings.pyでミドルウェアを有効にします。

MIDDLEWARE_CLASSES = (
    Django.middleware.gzip.GZipMiddleware,
    ...
)

または、特定の応答を返す前にそれを行います。あなたのviews.pyでは、decは特定のURLのハンドラになります

from Django.middleware.gzip import GZipMiddleware

gzip_middleware = GZipMiddleware()

 def dec(request, *args, **kwargs):
        response = func(request, *args, **kwargs)
        return gzip_middleware.process_response(request, response)
        return dec

注:GZipミドルウェアを使用する前に、サイドチャネル攻撃の影響を受けない確実である必要があります。

警告

セキュリティ研究者は最近、圧縮手法(GZipMiddlewareを含む)がWebサイトで使用されると、サイトがいくつかの可能な攻撃にさらされる可能性があることを明らかにしました。サイトでGZipMiddlewareを使用する前に、これらの攻撃を受けているかどうかを非常に慎重に検討する必要があります。 影響を受けるかどうか疑わしい場合は、GZipMiddlewareの使用を避けてください。詳細については、BREACHペーパー(PDF)を参照してください。とbreachattack.com。

また:

Django 1.10で変更:古いバージョンでは、DjangoのCSRF保護メカニズムは、圧縮が使用された場合のBREACH攻撃に対して脆弱でした。これはもはや当てはまりませんが、独自のセキュリティを侵害しないように注意する必要がありますこの方法で秘密。

90
Andres

すべてのページではなく単一のページをgzip圧縮する場合は、GzipMiddlewareの代わりにgzip_pageデコレータを使用できます。

from Django.views.decorators.gzip import gzip_page

@gzip_page
def viewFunc(request):
  return HttpResponse("hello"*100)

ここで参照: https://docs.djangoproject.com/en/1.4/topics/http/decorators/#module-Django.views.decorators.gzip

26
feifan.overflow

単一のページで必要であり、クラスベースのビューを使用している場合は、これを使用します。

gzip_middleware = GZipMiddleware()

class GZipMixin(object):

    def dispatch(self, request, *args, **kwargs):
        response = super(GZipMixin, self).dispatch(request, *args, **kwargs)
        return gzip_middleware.process_response(request, response)

次に、実際のビューで:

class MyView(GZipMixin, View):
    def get(self, request, *args, **kwargs):
         #return your response
1
Johan

zlibでデータを圧縮する場合は、deflateではなくgzipContent-Encodingを設定する必要があります。

rendered_page =  zlib.compress(template.render(context).encode('utf-8'))

response = HttpResponse(rendered_page)
response['Content-Encoding'] = 'deflate'
response['Content-Length'] = len(rendered_page)
return response

Content-Encoding

(...)

deflate

Deflate圧縮アルゴリズム(RFC 1951で定義)でzlib構造(RFC 1950で定義)を使用します。

0
el.pescado

他の人がこの質問を見つけてnginxを使用しているために、これはSOでうまくいきました:

https://stackoverflow.com/a/41820704/4533488

基本的に、/ etc/nginx/nginx.confファイルでgzipをオンにすると、すべての圧縮処理が行われました。クライアント側では、最新のほとんどのブラウザーが、データを受信すると自動的にデータの抽出(圧縮解除)を処理します。

Nginx.confファイルの設定は次のとおりです。

    http {

        #... other settings ...#

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    }
0
aero