Varnishのvcl_errorで日本語のエラーページを返す

VCLで日本語を使えない

Varnish の VCL では vcl_error でエラーメージをカスタマイズすることができる。

オフィシャルパッケージのサンプルだと、次のようになっている。

sub vcl_error {
  set obj.http.Content-Type = "text/html; charset=utf-8";
  set obj.http.Retry-After = "5";
  synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title>"} + obj.status + " " + obj.response + {"</title>
  </head>
  <body>
    <h1>Error "} + obj.status + " " + obj.response + {"</h1>
    <p>"} + obj.response + {"</p>
    <h3>Guru Meditation:</h3>
    <p>XID: "} + req.xid + {"</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>
"};
  return (deliver);
}

上の vcl_error に対して実際にエラーを発生させたのが以下。

$ curl -X GET -i -D - http://localhost:8080/index.html
HTTP/1.1 405 Not allowed.
Server: Varnish
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 415
Accept-Ranges: bytes
Date: Thu, 14 Jan 2014 14:07:34 GMT
X-Varnish: 1778367689
Age: 0
Via: 1.1 varnish
Connection: close


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title>405 Not allowed.</title>
  </head>
  <body>
    <h1>Error 405 Not allowed.</h1>
    <p>Not allowed.</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 1778367689</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

この vcl_error を少し書き換えて

  ...
  <body>
    あいうえお
    <h1>...

というように日本語を追加して同じように GET メソッドでリクエストすると、日本語の箇所が化けてしまう。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <title>405 Not allowed.</title>
  </head>
  <body>
    ?77777743?77777601?77777602?77777743?77777601?77777604?77777743?77777601?77777606?77777743?77777601?77777610?77777743?77777601?77777612
    <h1>Error 405 Not allowed.</h1>
    <p>Not allowed.</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 1650517089</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

化けてしまう原因の深追いは別の機会に譲って、取り急ぎ、エラーページの言語を日本語にしたい。

日本語をVCLの外に追い出す

姑息に文字化けを解消するには日本語を VCL の外にだしてやれば良い。

Varnish 3 からはデフォルトで利用可能な VMOD std にファイルを読み込む関数 fileread が追加された。
これを利用してファイルから読み込んだ文字列をエラーページのHTMLに利用すれば良い。

https://www.varnish-cache.org/docs/trunk/reference/vmod_std.html

HTML をベタ書きしていた vcl_error を std.fileread で外部ファイル化したのが以下

import std;
sub vcl_error {
  set obj.http.Content-Type = "text/html; charset=utf-8";
  set obj.http.Retry-After = "5";
  synthetic std.fileread("/path/to/file.html");
  return (deliver);
}

テキストだけだと寂しいので画像もはさみたい場合は、画像を base64 でエンコード($ base64 filename)してインラインで埋め込んじゃえば OK

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" />

注意

注意点としては、VCL ファイルを読み込んだ時にstd.fileread はパスごとにキャッシュする。
エラーファイルを更新するには、パスを変更して再読み込みさせるか、Varnish を再起動させる必要がある。
ファイルの書き換えだけや、パスを変えないまま VCL ファイルを再読み込みしても、エラーメッセージは更新されない。

VCL ファイルの再読み込み方法

vcl.load コマンドに対して VCL の名前とファイルパスを指定して設定ファイルをコンパイル。
vcl.use コマンドに対して有効にする VCL 名を指定する。

varnish> vcl.load reload01 /etc/varnish/default.vcl
200
VCL compiled.
varnish> vcl.use reload01
200

VCl ファイルに割り当てる名前 reload01 はユニークな名前に適宜変更すること。

Tagged with: , ,
Posted in middleware

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
%d bloggers like this: