The jonki

呼ばれて飛び出てじょじょじょじょーんき

expressで特定のディレクトリ下の日本語ファイルをサーバー上で公開する

特定のフォルダ下に含まれるファイルを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が途切れていることがわかります。
f:id:jonki:20140716005751p:plain

実際に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も壊れていません。


イマイチ問題がはっきりしていませんが、日本語の文字列長の扱いが怪しい、ということで今回は乗り切ることにします。。