クロスドメインなAjaxリクエスト時に取得できないレスポンスヘッダーについて

mediba制作部 メディアクリエイティブグループ所属、フロントエンジニアの土方です。 Webページの制作および成果物の監修を担当しております。

jQueryでAjaxリクエストした際のレスポンスヘッダーについて、getAllResponseHeaders()で取得しようとした時、同一ドメインでは取得でき、クロスドメインの場合には取得できないヘッダーがあります。 今回、この件について紹介させていただきます。

ヘッダーの相違

仮にhttp://www.example.jp/index.htmlからAjaxリクエストするものとします。(※jQuery1.8以降の場合のコードです。)

同一ドメインの場合

リクエスト

$.ajax({
    type: 'HEAD',
    url: '',
    cache: false,
}).done(function(data, status, xhr) {
        console.log(xhr.getAllResponseHeaders());
}).fail(function(data, status, xhr){
        console.log('error!');
});

結果

Date: Tue, 27 Oct 2015 05:53:29 GMT
Last-Modified: Mon, 17 Jun 2013 10:28:48 GMT
Server: Apache/2.2.29
ETag: "2744725-39-4df570fdaf800"
Content-Type: text/html
Connection: Keep-Alive
Accept-Ranges: bytes
Keep-Alive: timeout=5, max=19
Content-Length: 57

クロスドメインの場合

リクエスト

$.ajax({
    type: 'HEAD',
    url: 'http://api.example.jp/',
    cache: false,
}).done(function(data, status, xhr) {
        console.log(xhr.getAllResponseHeaders());
}).fail(function(data, status, xhr){
        console.log('error!');
});

結果

Last-Modified: Mon, 26 Oct 2015 04:04:22 GMT
Content-Type: text/html
Cache-Control: max-age=86400
Expires: Wed, 28 Oct 2015 05:44:37 GMT
  • DATE
  • Server
  • ETag
  • Connection
  • Accept-Ranges
  • Keep-Alive
  • Content-Length

クロスドメインの場合には、上記ヘッダーを取得できていないことがわかります。

環境

下記環境について、取得できるヘッダーが制限されることを確認しました。

  • Xperia Z2 (Android4.4.2 標準ブラウザ)
  • Xperia Z3 (Android5.0.2 標準ブラウザ)
  • Infobar C01 (Android2.3.5 標準ブラウザ)
  • Android版Chrome 46.0.2490.76
  • iPhone6 (iOS8.1.3 Safari)
  • iPhone版Chrome 46.0.2490.73
  • Mac版GoogleChrome 46.0.2490.71
  • Mac版Safari 8.0.8(10600.8.9)
  • Mac版Firefox 41.0.2

記事投稿時点(2015年11月6日)において、事実上全ての環境と考えて差し支えないでしょう。

Ajaxリクエストし、レスポンスヘッダーを取得する場合にはクロスドメインであるかどうかを意識する必要があります。

備考

Javascriptでレスポンスヘッダーを取得する場合とは?

例えばこんな理由が考えられます。

  • 閲覧日時によって表示やアニメーションなどの効果を切り替える
  • 掲示板などで投稿からの経過時間を計算する

などの用途で、Javascriptで時刻を取り扱いたいことがあります。 Javascriptはクライアント側で動作するので

new Date();

とするとクライアントに設定されている時刻を取得するため、 クライアントの時刻が狂っている場合には狂った時刻を取得してしまいます。

サーバー時刻であればクライアントの時刻設定に依らないため、これを取得することで正確に近い時刻を使用することができるわけです。

NTPサーバーが提供しているjson(Ex.NICTのjson)から時刻を取得できれば話が早いのですが、一般に公開されているNTPサーバーは負荷に耐えられる保証はありませんし、なにより商業利用はできません。

また予算や工期の都合で、自前でNTPサーバーを用意することが困難な場合があります。

NTPサーバーが使えないのであれば、レスポンスヘッダーからDATEヘッダーを取得すればサーバー時刻を使用できるということになります。

このような場合、クロスドメインなサーバーへAjaxリクエストしてもgetAllResponseHeaders()でDATEヘッダーの値を取得することは出来ません。

同一ドメインなサーバーへアクセスして取得する必要があります。

ソースコードについて

(※)古いVer.では下記。

$.ajax({
    type: 'HEAD',
    url: '',
    cache: false,
    success: function (data, status, xhr) {
        console.log(xhr.getAllResponseHeaders());
    },
    error: function(data, status, xhr){
        console.log('error!');
    },
});