FessのAI検索モードで、検索結果のソースリンクがコンテンツプロキシ(/go/ URL)を利用していない問題がありました。通常の検索では、検索結果のリンクは /go/ URLを経由することで、クリックトラッキングやアクセス制御のログ記録が行われますが、AI検索モードではこの仕組みが使われていませんでした。今回、通常の検索と同様に /go/ URLを生成するように修正しました。
問題
通常の検索結果では、各結果のリンクが /go/?doc.id=...&rt=...&qt=... のような形式で、コンテンツプロキシを経由します。これにより、以下のことが可能になります。
- クリックトラッキング(どの検索結果がクリックされたか)
- アクセス制御のログ記録
- URLのリダイレクト管理
しかし、AI検索モードのソースカードでは、生のURLがそのまま使われていたため、これらの機能が働いていませんでした。
変更内容
ChatClient.java
主な変更は ChatClient.java に集中しています。
ChatSearchResultラッパークラスを導入し、検索結果のドキュメントと一緒にqueryIdとrequestedTimeを保持できるようにしましたbuildGoUrl()メソッドを追加し、URLエンコードされた/go/リンクを構築しますaddSourcesToMessage()メソッドで、ソース情報の付与を一箇所に集約しましたresolveContextPath()で、SSE処理の前にHTTPコンテキストパスを取得します(SSE処理中はリクエストコンテキストが利用できなくなる可能性があるため)
ThreadLocalを使って searchDocuments メソッドからメタデータを伝播させることで、protectedなAPIのシグネチャを変更せずに済んでいます。
ChatMessage.java
ChatSource クラスに urlLink と goUrl フィールドを追加し、ドキュメントマップから url_link を読み取れるようにしました。
chat.js
ソースカードのリンクを goUrl → urlLink → url の優先順位で解決するように変更しました。goUrl が利用できない場合でも後方互換性を保っています。
テスト
ChatClientTest.java に以下のユニットテストが追加されています。
buildGoUrlの基本的な動作- コンテキストパスがある場合の動作
- docIdやqueryIdがnullの場合の動作
- 特殊文字のURLエンコード
ChatSourceのフィールドアクセサ