はじめてのwebアプリ② unicode/utf8で文字数を数える
バグを直す
文字数カウントのwebアプリは、以下のバグがあるので直す。
- 文字数ではなくバイト数を算出している
- HTMLのエスケープをしていない
このため、
<font color="red">𩸽</font>
上記文字列を入力すると、スクリーンショットの通り、fontタグが適用されて文字が赤字表記になり、なおかつ本当は26文字と数えて欲しいにもかかわらず29文字と数えてしまう。
文字数ではなくバイト数を算出している
これは前に学んだunicode/utf8のRuneCountInStringで数を調べるよう改める。
[before]
text := r.FormValue("text") count := len(text)
[after]
// import "unicode/utf8" text := r.FormValue("text") count := utf8.RuneCountInString(text)
HTMLのエスケープをかける
次に、HTMLのエスケープをかけるため、html/templateのHTMLEscapeStringを使うことにした。
[before]
content := fmt.Sprintf(`...HTML本文`, text, count, css)
[after]
// import htmlTemplate "html/template" content := fmt.Sprintf(`...HTML本文`, htmlTemplate.HTMLEscapeString(text), count, css)
text/templateモジュールでHTMLを出力するよう変更
html/templateをよく見たら、HTMLEscapeStringを使わなくても、テンプレート機能を利用すれば出力の式({{.名前}})で自動エスケープしてくれるようだ。
なので、以下の通り改めた。
// import htmlTemplate "html/template" // import "log" wc, _ := htmlTemplate.New("wc").Parse(` <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>文字数カウント結果</title> <style type="text/css"> .err { border: solid 1px red; } </style> </head> <body> <h1>文字数カウント結果</h1> 入力文字: {{.text}}<br> 文字数は: {{.count}}<br> でした。<br><br> 文字を入力してください。 <form action="/count" method="GET"> <input type="text" name="text" size="32" class="{{.css}}"> <input type="submit"> </form> </body> </html>`) type Context map[string]interface{} data := Context{"text": text, "count": count, "css": css} if err := wc.Execute(w, data); err != nil { log.Panic(err) }
これでHTMLのタグはエスケープされ、文字数も正しく26を数えてくれるようになった。