Client Hintをwebサーバで取得してみる


Client Hintって何?

httpリクエストヘッダに載ってくるUserAgentの情報が、Chromeのとあるバージョンからマイナーバージョンが0.0.0に固定されるというアップデートが2021年前期に発生するとのこと。詳細はこちらを参照

端的にいうと下記のようになる。
【現行】User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
【改修後】Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/85.0.0.0 Safari/537.36

メジャーバージョンは引き続き更新されていく予定で、一見些細な改修のように感じるがその傍らClinet Hintというものが既に実装されている。

新規に下記のようなリクエストヘッダー情報が追加されるのだ。

上記を利用することでマイナーバージョンもしっかりと取得することができる。
またこの実装背景として、真偽は定かではないが、意味不明な文字列であるUserAgentを今後無くして、ClientHintに絞ろうという意向を感じている。

現状UserAgentを利用して判定し、クライアントサイドに返すコンテンツをコントロールしているものがあまりにも多いのですぐには起こらないだろうが、UserAgentではなく、Client Hintを利用していくのが今後推奨されていくのではないか。

そのためにもClient Hintをしっかり取得する方法を学んでおいて損はないだろう。

Client Hint取得方法

例えばphpでは、$_SERVERなどを利用してhttpの一部ヘッダ情報を取得可能だが現時点(2020年12月現在)では不可能である。php等のアプリケーション側でも取得する方法は存在するが本記事ではwebサーバレイヤーのみ(apacheとnginx)で、それぞれapacheのaccess_logとnginxのaccess_logにClient Hintを含める方法を記載していく。

ApacheのlogにClientHintを含める

具体的には/var/log/httpd/acc_XXXXXXXXXX.logにClientHintを含める方法だ。
特にカスタムのconfファイルを追加していない場合、2か所修正が必要となる。
【修正1】下記のheader set 追加

/etc/httpd/conf/httpd.conf
Header set Accept-CH "UA-Full-Version, UA-Arch, UA-Model, UA-Platform, UA-Platform-Version, UA-Mobile"

【修正2】Logformatに\"%{sec-ch-ua}i\"追加

/etc/httpd/conf/httpd.conf

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{sec-ch-ua}i\"" combined

が必要である。
\"%{sec-ch-ua}i\"の部分は適宜必要なヘッダー要素の名前をhttpリクエストヘッダを参照すると良い。

解説

修正1ではまず、apacheがクライアントに対して、以降のhttpリクエストヘッダにClientHintを含めるように指定をしている内容である。(デフォルトではClientHintは取得できない)
修正2では生成されるapachelogはhttpd.conf内でフォーマットを持っており、そのフォーマットを修正してログにも出力されるようにしている。
もしカスタムのログフォーマットを持っている場合、そのパス/var/log/XXXX(カスタムのフォーマット名)/acc_XXXXXXXXXX.logに置かれているものが編集が必要なのでそれに応じたLogformatをいじらなければいけない。

NginxのlogにClientHintを含める

nginx_confを下記のように修正する必要がある。

/etc/nginx/conf.d/nginx.conf
http{
    log_format formatA #ここに'"$http_sec_ch_ua"'を追加
    access_log /var/log/nginx/access_log formatA
}

解説

こちらも同様にlogのformatにClientHintを追加してやる必要がある。
ClientHintの形式は$http_と開発者ツールで見れる属性(「-」を「_」に変える必要あり)の結合文字列によって取得可能になる。($https_sec_ch_ua_full_versionなど)

まとめ

ClientHintを取得可能にするメリットは下記の3つ
★UserAgent文字列が凍結されてもマイナーバージョンまで取得可能
★UserAgentを利用するよりはるかに判定がしやすくなる
★UserAgentが今後無くなる可能性があり、クライアント情報を得る次世代方式

デメリットは
★ログにカラムが追加されるため、以降のフロー(集計処理など)がおかしくなる可能性
★多少ログデータが重くなる
などがある。

少なくともクライアント情報をUserAgentから取得している処理がある場合は今後の各種ブラウザのClientHintの実装状況にしっかりアンテナを張っておくべきだろう。