DevDevデブ!!

プログラミングのこととか書きます。多分。。。

echoのcontent-type上書きに注意(訂正:上書きしてませんでした)

(訂正) 上書きしてませんでした (2018-08-25)

コメントをいただき、修正しました

HTMLBlobやBlobなどのレスポンスを書き込むContext構造体の関数は、content-typeの上書きはしません

HTMLBlobやBlobなどのレスポンスを書き込む関数(以降、便宜的にレスポンス関数と呼称する)は内部でContext構造体の関数、writeContentTypeを呼び出して、content-typeを設定するのですが、writeContentTypeのコードは以下のようになっています。

https://github.com/labstack/echo/blob/56091a418657bf36f44fcb061f2e307ed39fc29a/context.go#L209

func (c *context) writeContentType(value string) {
    header := c.Response().Header()
    if header.Get(HeaderContentType) == "" {
        header.Set(HeaderContentType, value)
    }
}

はい。ヘッダーに既にContent-Typeが設定済みなら何もせずに関数を抜けるという処理になっております。上書きはしません。

間違ってRequestのヘッダーに設定してしまっていたのと、処理を最後まで追っていなかったために、完全に誤解しておりました。

失礼しました。

以下、元の文章↓

またgoのechoの話です。

javascirptを実行して欲しかったんや。。。

scriptタグを吐き出すechoのエンドポイントを書いてたんだけど、ブラウザからアクセスしてもjavascriptとして実行されず、プレーンテキストとしてブラウザ上に表示されます。

まあ原因は簡単で、content-typeがtext/plainだったから。

c.String(http.statusOk, script)

ほんじゃあcontent-typeを適切なものに変更しましょうって話になりますね。

なので以下のようにしてみたわけです。

c.Request().Header.Set(echo.HeaderContentType, echo.MIMEApplicationJavaScript)
c.String(http.statusOk, script)

再トライしてもtext/plainのまま(;´Д`)

echoの書き込みメソッドはContent-Typeを上書きする

はい。してました。(普通に考えりゃそりゃそうだって話なんだけど)

func (c *context) String(code int, s string) (err error) {
    return c.Blob(code, MIMETextPlainCharsetUTF8, []byte(s))
}

上記はechoのcontext構造体のStringメソッド

c.Blogの真ん中の引数がContent-Typeなわけです。

JSONメソッドとかHTMLメソッドも中でc.Blobを叩いてて、適切なContent-Typeを設定している。

なので、最初から出力内容に適切なメソッドを使うか、Blobを直接叩いて自分で適切なContent-Typeを指定してあげる必要があると。

今回出力しようとしていたjavascriptはscriptタグを含んだものだったので、HTMLメソッドで出力するとちゃんと動いてくれた。