FessのWebクロールでHTTPヘッダーの文字コードを反映する

Shift_JISやEUC-JPのページをFessでクロールしたとき、ブラウザーでは読めるのに検索結果のタイトルや本文が文字化けすることがあります。HTTPヘッダーだけで文字コードを指定しているページを正しく扱うため、fess-crawlerのHTTPクライアントとHTML解析処理を修正しました。

HTTPヘッダーのcharsetを使う

従来は文字コードをContent-Encodingから読み取っていました。このヘッダーはgzipなどの圧縮方式を表すもので、文字コードの指定ではありません。修正後はContent-Typeのcharsetを読み取り、HTML側に文字コード指定がない場合も解析処理へ引き継ぎます。HttpClient 4と5の両方が対象です。

Content-Type: text/html; charset=Shift_JIS

例えば実際の本文がShift_JISで、HTMLにmeta charsetがなく、上記のヘッダーだけがあるページが対象になります。EUC-JPも同じ考え方です。新しい有効化設定は追加されていません。

初期値と優先順位

HTML内のmeta charsetがある場合は、その指定が従来どおり優先されます。meta指定がなければクライアントが報告した文字コードを使います。HTTP応答のcharsetが未指定、未対応、または不正な名前の場合の初期値はUTF-8です。文字コードを自動推定する機能ではないので、何も宣言していないShift_JISのページは引き続き文字化けします。

HtmlTransformerのdefaultEncodingは、クライアントからも文字コードが報告されていない場合だけ使われます。HTTPクライアントは未指定時もUTF-8を報告するため、defaultEncodingだけでHTTPページの未指定文字コードを上書きできるとは考えないでください。

クロール先で確認すること

文字化けがあれば、まず応答ヘッダーとHTMLのmeta charset、実際のファイルの文字コードを照合します。ヘッダーもmetaもないページには正しい指定を追加し、本文を再取得してインデックスを更新します。誤ったcharsetを送るサーバーも、ヘッダーが尊重されるようになるため修正が必要です。

ファイル、FTP、SMB、S3、GCS経由のHTMLにも、meta指定がない場合はクライアントの設定charsetが引き継がれます。これらの初期値もUTF-8です。この変更はHTML標準に合わせてヘッダーをmetaより優先する変更ではなく、既存の優先順位を維持しています。

関連PR

Fessの文書レポートとインデックス統計でファイルを整理する

ファイルサーバーをクロールし続けると、重複した資料や長く更新されていない文書がたまってきます。Fessの管理画面に文書レポート、fess-kopfに文書インデックスの統計画面が追加され、整理対象を調べやすくなりました。

重複と休眠文書を調べる

Fessの「システム情報」>「文書レポート」で、重複と休眠文書のタブを切り替えます。smb://server/share/などのURL接頭辞で対象を絞り、CSVで取り出せます。管理ロールはadmin-docreport、閲覧専用はadmin-docreport-viewです。

fess_config.propertiesの初期値は次のとおりです。

docreport.duplicate.group.size=100
docreport.duplicate.docs.size=10
docreport.duplicate.export.page.size=10000
docreport.dormant.days=365

画面は最大100の重複グループ、各グループ10文書を表示します。重複判定には本文のMinHash署名content_minhash_bitsを使うので、完全一致だけでなく近い内容も含み得ます。ファイルのバイナリーが同一であることを保証する判定ではありません。トークンのない本文は誤った巨大グループになるため除外します。

通常のマッピングでは既存の署名を使い、署名のためだけの再インデックスは不要です。cloudやawsのマッピングでは署名を計算しないため、重複レポートを利用できません。大きなインデックスでは画面の集計が見落とす組み合わせもあり、全体確認にはページングで取得するCSVを使います。

休眠文書は初期値で365日以上更新されていない文書です。最終更新日時のない文書は含めません。「検索結果から一度も開かれていない」条件はクリック数が正でない文書を対象にします。画面のページングには結果ウィンドウの上限があるため、それを超える確認はCSVで行います。

インデックスの全体像を見る

fess-kopfのdocuments画面では、ファイル種別、MIMEタイプ、ホスト、ラベル、所有者、最終更新者の上位20件と、その他・値なしの件数を表示します。サイズ分布、更新年、インデックス登録年、最大サイズの10文書も確認できます。

fess.searchエイリアスがある環境で文書タブを表示します。インデックスのメニューから過去の世代を指定することもできます。画面を開くときと更新時に取得し、クラスターポーリングごとの集計は行いません。

数字の読み方と制限

createdは元ファイルの作成日ではなくFessへ登録した時刻です。ファイルの年齢を見るときはlast_modifiedを使います。年の集計は閲覧側のタイムゾーンに従い、サイズはバイナリー単位です。

古いインデックスのフィールド型によっては集計できない項目があります。利用可能な.keywordが全ての対象インデックスにある場合は代用し、それ以外は集計不能と表示します。fess-kopf側にはCSV出力と定期レポート機能はありません。

両画面とも調査のための読み取り機能です。重複や休眠というだけで不要と判断せず、原本や保管義務、実際の利用状況を確認してからファイル整理へつなげてください。

利用できるバージョン

Fess 15.9.0に含まれる予定の機能になります。現時点では、まだ、リリースしていないので、今後のテストで変更される可能性もあります。

関連PR

FessのStaticテーマでWebKitのプレビューが空になる場合の設定

FessのStaticテーマで、WebKit系ブラウザではPDFのプレビューやキャッシュ表示が空になる問題がありました。この対策として、テーマ画面が送るContent-Security-Policyのframe-ancestorsを設定できるようにしました。

プレビューが表示されない原因

テーマは取得したファイルやキャッシュをBlobにし、blob: URLのiframeで表示します。WebKitでは、この文書へ親ページのCSPが引き継がれ、frame-ancestors 'none'によって自分のページ内のフレームも拒否されます。ChromiumやFirefoxでは同じ表示が拒否されないため、ブラウザによって差が出ていました。

コンソールにframe-ancestorsに関するBlobの読み込み拒否が出る場合、今回の設定で対応できます。

設定方法

今回の変更を含むFessでは、fess_config.propertiesに以下を指定します。

theme.index.frame.ancestors=

空の値にすると、テーマのHTMLレスポンスからframe-ancestorsディレクティブを省略します。JVMオプションでは次の形です。

-Dfess.config.theme.index.frame.ancestors=

既存の起動オプションへ追加し、変更を反映して再起動します。docker-filesearchにはこの空値の指定を組み込む変更も追加しました。対応前のFessビルドではキーを指定してもプレビュー対策としては機能しません。

デフォルトとフレーム埋め込み制限

デフォルトは従来と同じ'none'です。アップグレードしただけではWebKit向けの挙動は変わりません。

空値でも、同じレスポンスのX-Frame-Options: DENYは維持します。PRのブラウザ検証では、同一オリジン・別オリジンからのページ埋め込みをともに拒否しつつ、Blobのプレビューを表示できることを確認しています。

'self'を指定した場合は意味が異なります。CSPを優先するブラウザでは同一オリジンからの埋め込みを許可するため、プレビュー対策として空値と同じ扱いにはしないでください。

検証範囲

変更の確認はPlaywrightのChromium、Firefox、WebKitで行われています。実機Safariでの検証は含まれません。また、ヘッドレスWebKitではPDFの画面描画そのものを比較できず、PDF文書がフレームに読み込まれることと拒否の解消までを確認しています。

キャッシュ中のbase要素について出る別のCSP警告は、今回の変更の対象外です。表示できない原因がこの設定に該当するか、コンソールのメッセージを確認して適用してください。

関連PR