Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 11283] ファイルの概要

このコミットは、Go言語の標準ライブラリ html/template パッケージのドキュメント (src/pkg/html/template/doc.go) におけるAPI使用例の修正を目的としています。具体的には、html/template パッケージのAPI変更に伴い、テンプレートの初期化方法 (template.Set{} から template.New へ) とテンプレートの実行方法 (Execute から ExecuteTemplate へ) の記述を更新し、さらにエスケープされた出力の表現をより厳密なHTMLエンティティ (') に修正しています。

コミット

html/template: fix docs after API changes

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5528109

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/369454d7b2f3b03ee5bdfde1eae6092bace14951

元コミット内容

commit 369454d7b2f3b03ee5bdfde1eae6092bace14951
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date:   Thu Jan 19 21:49:28 2012 -0200

    html/template: fix docs after API changes
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/5528109
---
 src/pkg/html/template/doc.go | 14 +++++++-------\n 1 file changed, 7 insertions(+), 7 deletions(-)\n

変更の背景

このコミットは、html/template パッケージのAPIが変更されたことに伴い、その公式ドキュメントに記載されているコード例が古くなったために行われました。Go言語の標準ライブラリは、開発の初期段階においてAPIの改善や洗練のために変更が行われることがあります。この場合、テンプレートの作成と実行に関するAPIが変更され、それに合わせてドキュメントのサンプルコードを最新の状態に保つ必要が生じました。特に、セキュリティを考慮したHTMLエスケープの挙動も改善されたため、その出力例も更新されています。

前提知識の解説

Go言語の text/templatehtml/template パッケージ

Go言語には、テキストベースのテンプレートを扱うための text/template パッケージと、HTMLコンテンツを安全に生成するための html/template パッケージがあります。

  • text/template: 任意のテキスト形式の出力を生成するための汎用的なテンプレートエンジンです。例えば、設定ファイル、コード生成、プレーンテキストのレポートなどに使用できます。このパッケージは、出力されるコンテンツがHTMLとして解釈されることを前提としていないため、セキュリティ上のエスケープ処理は行いません。
  • html/template: text/template を基盤としつつ、HTMLコンテンツを生成する際にクロスサイトスクリプティング (XSS) などの脆弱性を防ぐための自動エスケープ機能を提供するパッケージです。テンプレート内でユーザー入力などの動的なデータを表示する際、html/template は自動的に適切なエスケープ処理(例: <&lt; に変換)を行い、悪意のあるスクリプトの埋め込みを防ぎます。

テンプレートの初期化と実行

Goのテンプレートパッケージでは、通常以下の手順でテンプレートを扱います。

  1. テンプレートの作成: テンプレート文字列を解析し、*template.Template 型のインスタンスを作成します。
  2. データの結合: 作成したテンプレートにデータを渡し、テンプレートを「実行」して最終的な出力を生成します。

自動エスケープ (Autoescaping)

html/template の最も重要な機能の一つが自動エスケープです。これは、テンプレート内で表示されるデータが、そのコンテキスト(例: HTML要素のテキスト、属性値、URLなど)に応じて自動的に適切なエスケープ処理が施される仕組みです。これにより、開発者が手動でエスケープ処理を記述する手間を省き、同時にXSS攻撃のリスクを大幅に低減します。例えば、<script>alert('XSS')</script> のような文字列がHTMLコンテンツに挿入される場合、html/template はこれを &lt;script&gt;alert(&#39;XSS&#39;)&lt;/script&gt; のようにエスケープし、ブラウザがスクリプトとして実行するのを防ぎます。

技術的詳細

このコミットにおける技術的な変更点は、主に html/template パッケージのAPI利用方法と、エスケープされた出力の表現に関するものです。

  1. テンプレートの初期化方法の変更:

    • 変更前: (&template.Set{}).Parse(...)
    • 変更後: template.New("foo").Parse(...) これは、テンプレートセットを初期化する際の推奨される方法が変更されたことを示しています。以前は template.Set{} のような構造体リテラルを直接使用していましたが、新しいAPIでは template.New("name") 関数を使用して、名前付きの新しいテンプレートセットを作成するようになりました。template.New は、テンプレートセットに一意の名前を割り当てることで、複数のテンプレートセットを管理しやすくする目的があります。この変更は、APIの設計思想の成熟と、より明確なテンプレート管理の促進を反映していると考えられます。
  2. テンプレートの実行方法の変更:

    • 変更前: t.Execute(out, "T", ...)
    • 変更後: t.ExecuteTemplate(out, "T", ...) Execute メソッドは、通常、テンプレートセット内のルートテンプレート(名前が空文字列のテンプレート)を実行するために使用されます。一方、ExecuteTemplate メソッドは、テンプレートセット内の特定の名前を持つテンプレートを実行するために使用されます。この変更は、ドキュメントの例が {{define "T"}} のように名前付きテンプレート T を定義しているため、そのテンプレートを明示的に実行する ExecuteTemplate の方が適切であるというAPIの意図を反映しています。これにより、コードの意図がより明確になります。
  3. エスケープされた出力の表現の変更:

    • 変更前: Hello, &lt;script&gt;alert('you have been pwned')&lt;/script&gt;!
    • 変更後: Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;! この変更は、シングルクォート ' のエスケープ方法が &#39; というHTMLエンティティに統一されたことを示しています。HTMLでは、シングルクォートは属性値などで特別な意味を持つため、安全のためにエスケープされるべき文字です。&#39; はシングルクォートの数値文字参照であり、より厳密で普遍的なエスケープ表現です。この変更は、html/template が提供する自動エスケープ機能の堅牢性とセキュリティが向上したことを示唆しています。

コアとなるコードの変更箇所

変更は src/pkg/html/template/doc.go ファイルに集中しており、主にGoのテンプレートAPIの使用例が更新されています。

--- a/src/pkg/html/template/doc.go
+++ b/src/pkg/html/template/doc.go
@@ -31,8 +31,8 @@ Example

   import "text/template"
   ...
-  t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
-  err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")
+  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+  err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")

 produces

@@ -42,12 +42,12 @@ but with contextual autoescaping,

   import "html/template"
   ...
-  t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
-  err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")
+  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+  err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")

 produces safe, escaped HTML output

-  Hello, &lt;script&gt;alert('you have been pwned')&lt;/script&gt;!
+  Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!


 Contexts
@@ -57,8 +57,8 @@ functions to each simple action pipeline, so given the excerpt

   <a href="/search?q={{.}}\">{{.}}</a>

-At parse time each {{.}} is overwritten to add escaping functions as necessary,
-in this case,
+At parse time each {{.}} is overwritten to add escaping functions as necessary.
+In this case it becomes

   <a href=\"/search?q={{. | urlquery}}\">{{. | html}}</a>

コアとなるコードの解説

上記の差分は、html/template パッケージのドキュメント内の3つの主要なセクション(text/template の例、html/template の例、コンテキストの例)におけるコードスニペットと出力例を更新しています。

  1. text/template の例の修正:

    • t, err := (&template.Set{}).Parse(...)t, err := template.New("foo").Parse(...) に変更されました。これは、text/template でも template.New を使用してテンプレートセットを初期化する新しい推奨パターンを反映しています。
    • err = t.Execute(out, "T", ...)err = t.ExecuteTemplate(out, "T", ...) に変更されました。これは、名前付きテンプレート T を実行するために ExecuteTemplate を使用する、より正確な方法を示しています。
  2. html/template の例の修正:

    • text/template の例と同様に、テンプレートの初期化と実行方法が template.NewExecuteTemplate を使用するように更新されました。
    • 最も重要な変更は、出力例の Hello, &lt;script&gt;alert('you have been pwned')&lt;/script&gt;!Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;! に変更された点です。これは、html/template がシングルクォート '&#39; というHTMLエンティティにエスケープするようになったことを示しており、より堅牢なセキュリティ対策が講じられていることを強調しています。
  3. コンテキストの例の修正:

    • At parse time each {{.}} is overwritten to add escaping functions as necessary, in this case, という説明文が At parse time each {{.}} is overwritten to add escaping functions as necessary. In this case it becomes に変更されました。これは、文法的な修正であり、より自然な英語表現になっています。このセクションは、html/template がどのようにコンテキストに基づいて自動的にエスケープ関数(例: urlquery, html)を挿入するかを説明しています。

これらの変更は、html/template パッケージのAPIがより洗練され、セキュリティが強化されたことをドキュメントを通じてユーザーに伝えるための重要な更新です。

関連リンク

参考にした情報源リンク