cocuh's note

type(あうとぷっと) -> 駄文

Pyramid.eventsでhookして任意処理を実行

Pyramidで作ったアプリケーションのヘッダにCSPを追加したかったり、
すべてのページにヘッダを追加したかったのでメモです。

ついでにrender前にhookができたりするようです。

Pyramid.eventsを使う

pyramidのeventsを使ってresponse生成前とrender前にhookを仕掛けて処理します。

response生成前のhookでは、すべてのヘッダにCSPを追加してます。

render前のhookでは、ページにusernameを表示させるために、sessionからusernameをrenderに渡す辞書に追加してます。

NewResponseはclassですが、BeforeRendererはdictとバラバラです。
それぞれの挙動はソースコードを読みながら試しながらしたほうがいいです。

from pyramid.events import (
    NewResponse,
    BeforeRender,
    subscriber,
    )


# add CSP headers
csp_header = [
    ("default-src", [
        "'self'",
    ]),
    ("script-src", [
        "'self'",
        "https://ajax.googleapis.com",# for jquery
    ]),
    ("img-src", ["*"]),
    ]

def csp_header_encoder(header):
    res = []
    for key,valuelist in header:
        value = " ".join(valuelist)
        res.append(" ".join([key, value]))
    return "; ".join(res)

@subscriber(NewResponse)
def add_csp_header(event):
    header = csp_header_encoder(csp_header)
    event.response.headers["Content-Security-Policy"] = header
    event.response.headers["X-Content-Security-Policy"] = header
    event.response.headers["X-WebKit-CSP"] = header


# add username
@subscriber(BeforeRender)
def use_template(event):
    if "username" in event["request"].session:
        username = event["request"].session["username"]
        event.rendering_val["username"] = username