特定のフォルダ下に含まれるファイルをWebサーバー上で公開するためにNode.jsのexpressを使っていたのですが、日本語のファイルを使い始めた途端ハマりました。現象としては、日本語のファイルを同ディレクトリに複数含んでいる場合、ファイルのリンクが一部見れなくなっている時がある。というものでした。
サーバー側のソースコードはこんな感じです。expressが4.xなのでserve-indexなどのミドルウェアは自分で入れる必要があります。問題は後述しますが、express 3.xであっても問題は発生します。
server.js
var express = require('express'), serveIndex = require('serve-index'), app = express(); app.use(express.static(__dirname + '/public')); app.use(serveIndex(__dirname + '/public')); app.listen(3000);
package.json
{ "name": "test", "version": "0.0.0", "description": "", "main": "index.js", "dependencies": { "express": "~4.6.1", "serve-index": "~1.1.4", "serve-static": "~1.3.2", "connect": "~3.0.2" }, "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
実際にChromeからサーバーにアクセスすると日本語のファイルが1つ見えなくなっていました。このページをJavascriptコンソール上で見てもHTMLファイルがある程度補完されて見えるので注意が必要です。コンソール越しでなく、HTMLのソースを見ると、下記のようになっていて途中でHTMLが途切れていることがわかります。
実際にexpressでファイル公開を行うと良い感じのデザインでHTMLが生成されています。これをやっているのがserve-indexっぽいのですが、node_modules/serve-index/index.jsのexports.html内で動的に生成したhtmlの文字列長をContent-Lengthにそのまま渡しています。日本語やURLエンコードされた文字が含まれると、この値は眉唾な気がしてコメントアウトしてみました。
// res.setHeader('Content-Length', str.length);
そしてサーバーを再起動します。ブラウザ側でChrome Web Store - Live HTTP Headersを通してみるとContent-lengthは受信していませんが、すべてのファイルが正しく表示されています。HTMLも壊れていません。
イマイチ問題がはっきりしていませんが、日本語の文字列長の扱いが怪しい、ということで今回は乗り切ることにします。。