読者です 読者をやめる 読者になる 読者になる

tumblr

tumblr(タンブラー)は、メディアミックスブログサービス。ブログとミニブログ、そしてソーシャルブックマークを統合したマイクロブログサービスである。アメリカのDavidville.inc(現: Tumblr, Inc.)により2007年3月1日にサービスが開始された。

nginxをリバースプロキシにした時にPOSTがこける

問題

公開してるサーバにpukiwikiをインストールして外からアクセス出来るようにした。
が、新規ページを作成したりそのページ内容を更新したりはできるものの、
更新内容が多すぎるとInternalServerErrorがでる。
pukiwikiphp製なので、「またPHPかよ…クソが…」とか思いながらエラーを見るも、phpからのエラーは一切出力されない…

解決

pukiwikiを入れてるwebサーバの前段にnginxでリバプロかましてたんだけど、このnginxが問題を起こしてた。
nginxのエラーログにはこんなのが出てた。

2012/06/30 23:40:19 [crit] 25289#0: *3164256 open() "/var/tmp/nginx/client//0000009328" failed (2: No such file or directory), client: 192.168.100.1, server: tatshimomura.info, request: "POST /xxx/ HTTP/1.1", host: "tatsh      imomura.info", referrer: "http://tatshimomura.info/xxx/" 

No such file or directoryってのはどういうことだ?
ただwikiのページ内容を更新するためにテキストをPOSTしてるだけなんだけど…

client_body_buffer_size

というディレクティブがnginxにはあって、こいつの設定がよくなかった。

Sets buffer size for reading client request body. In case request body is larger than the buffer, the whole body or only its part is written to a temporary file. By default, buffer size is equal to two memory pages. This is 8K on x86, other 32-bit platforms, and x86-64. It is usually 16K on other 64-bit platforms.

http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size

という感じで、
設定値よりも大きい容量のものがPOSTされると、その内容がtempfileに書き出されるらしい。
(多分書きだしたものをこのリバプロ背後にあるサーバに投げてるんだと思う…)

というわけでこのディレクティブをhttpのところに追加した。

client_body_buffer_size 50k;

これで問題なく更新できるようになった。めでたし。

client_body_temp_path

ではなんでNo such file or directoryというエラーと/var/tmp/nginx/client//0000009328という怪しげなパスがエラーログに出ていたのか。
多分client_body_temp_path pathというディレクティブの設定がうまくいってなかったのではないかと思う。

syntax: client_body_temp_path path [level1 [level2 [level3]]];
default:
client_body_temp_path client_body_temp;
context: http, server, location
Defines a directory for storing temporary files holding client request bodies. Up to three-level subdirectory hierarchy can be used underneath the specified directory. For example, in the following configuration

client_body_temp_path /spool/nginx/client_temp 1 2;
a temporary file might look like this:

/spool/nginx/client_temp/7/45/00000123457

http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_temp_path

という感じでバッファサイズを超えたhttp request bodyは、このディレクティブで指定されるパスに一時ファイルとして保存される。
で、このディレクティブはなんか階層を指定できるみたいなので、その階層指定がうまくいってなかったためにエラーログに出てたようなスラッシュが2つ続きなパスを参照しようとしてしまったんじゃなかろうか。
さっきから「思う」とか「なかろうか」とかって言ってるのは未検証のため。デフォルトの設定はどうなってるかなどの情報が無いためよくわからん…

とりあえずは上の以下のようにしてもclient_body_buffer_sizeを変えずに問題なくPOSTができることが確認できた。ついでに一時ファイルが生成されてるのも確認できた。

client_body_temp_path /var/tmp/nginx;


参考:
http://d.hatena.ne.jp/perezvon/20080421/1208794757