概要
少なくともiOS10.3.1/Safariにおいて
下記のようにページのエンコーディングとdocument.writeで設置されるスクリプトのcharset属性が異なる場合、設置されるスクリプトが2重でHTTPアクセスが発生する。
※iOS9.0では発生しなかった
<html>
<head>
<meta charset="shift_jis" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/piyopiyo.js" charset="utf-8" ></scr'+'ipt>');
</script>
</body>
</html>
どのようなパターンでこの事象が起こるのか簡単にテストを行う
検証パターンとJSファイルの用意
下記のパターンそれぞれの組み合わせを想定しテストを行ってみる。
- meta charset
- 指定なし
- utf-8
- shift_jis
- scriptタグ属性charset
- 指定なし
- utf-8
- shift_jis
JSは下記の物を用意した。
console.log('テスト shift_jis');
console.log('テスト utf-8');
どちらのJSを呼んだかわかりやすくなるようにエンコーディング名を末尾に記載しているのと、実際の文字エンコーディングもそれぞれのファイル名通りのものとなっている。
なお、レスポンスヘッダのContent-Typeでは呼び出し元HTML/JS共にcharsetを明示的に指定していない状態。
検証はiPhoneSE/iOS10.3.1/Safariな端末をMacOSに繋げた後
MacOS上SafariのWEBインスペクタのコンソールを確認という形で行う
最終的な検証パターンは下記のような感じ
No | ページcharset | スクリプトcharset |
---|---|---|
1 | 指定なし | utf-8 |
2 | 指定なし | shift_jis |
3 | utf-8 | 指定なし (utf-8_log.jsを使用) |
4 | utf-8 | 指定なし (shift_jis_log.jsを使用) |
5 | utf-8 | utf-8 |
6 | utf-8 | shift_jis |
7 | shift_jis | 指定なし (utf-8_log.jsを使用) |
8 | shift_jis | 指定なし (shift_jis_log.jsを使用) |
9 | shift_jis | utf-8 |
10 | shift_jis | shift_jis |
11 | 指定なし | 指定なし (utf-8_log.jsを使用) |
12 | 指定なし | 指定なし (shift_jis_log.jsを使用) |
それぞれのJSはHTMLとは別サーバに置いて、httpアクセスで取得するものとする。
※example.comの部分は実際には自前で用意した別サーバのURLが入ります。
検証が縦に長くなってしまったので、結果だけ確認したい方は一番下までスクロールしてください。
検証する
1. ページ文字指定:指定なし スクリプトcharset:utf-8
2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)
HTML
<html>
<head>
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js" charset="utf-8" ></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
2. ページ文字指定:指定なし スクリプトcharset:shift_jis
2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)
HTML
<html>
<head>
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js" charset="shift_jis" ></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
3. ページ文字指定:utf-8 スクリプトcharset:指定なし (utf-8_log.jsを使用)
1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)
HTML
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js" ></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
4. ページ文字指定:utf-8 スクリプトcharset:指定なし (shift_jis_log.jsを使用)
1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、shift_jisなファイルをUTF-8扱いで読み込んでいるだけ。
(正常)
HTML
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js" ></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
5. ページ文字指定:utf-8 スクリプトcharset:utf-8
1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)
HTML
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js" charset="utf-8"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
6. ページ文字指定:utf-8 スクリプトcharset:shift_jis
2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)
HTML
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js" charset="shift_jis"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
7. ページ文字指定:shift_jis スクリプトcharset:指定なし (utf-8_log.jsを使用)
1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、UTF-8なファイルをshift_jis扱いで読み込んでいるだけ。
(正常)
HTML
<html>
<head>
<meta charset="shift_jis" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
8. ページ文字指定:shift_jis スクリプトcharset:指定なし (shift_jis_log.jsを使用)
1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)
HTML
<html>
<head>
<meta charset="shift_jis" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
9. ページ文字指定:shift_jis スクリプトcharset:utf-8
2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)
HTML
<html>
<head>
<meta charset="shift_jis" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js" charset="utf-8"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
10. ページ文字指定:shift_jis スクリプトcharset:shift_jis
1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)
HTML
<html>
<head>
<meta charset="shift_jis" />
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js" charset="shift_jis"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
11. ページ文字指定:指定なし スクリプトcharset:指定なし (utf-8_log.jsを使用)
1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、UTF-8なファイルを別のエンコード(何のエンコード?)扱いで読み込んでいるだけ。
(正常)
HTML
<html>
<head>
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
12. ページ文字指定:指定なし スクリプトcharset:指定なし (shift_jis_log.jsを使用)
1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、UTF-8なファイルを別のエンコード(何のエンコード?)扱いで読み込んでいるだけ。
(正常)
HTML
<html>
<head>
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク
コンソール
結果
No | ページcharset | スクリプトcharset | HTTPが2重で呼ばれているか |
---|---|---|---|
1 | 指定なし | utf-8 | ◯ |
2 | 指定なし | shift_jis | ◯ |
3 | utf-8 | 指定なし (utf-8_log.jsを使用) | |
4 | utf-8 | 指定なし (shift_jis_log.jsを使用) | |
5 | utf-8 | utf-8 | |
6 | utf-8 | shift_jis | ◯ |
7 | shift_jis | 指定なし (utf-8_log.jsを使用) | |
8 | shift_jis | 指定なし (shift_jis_log.jsを使用) | |
9 | shift_jis | utf-8 | ◯ |
10 | shift_jis | shift_jis | |
11 | 指定なし | 指定なし (utf-8_log.jsを使用) | |
12 | 指定なし | 指定なし (shift_jis_log.jsを使用) |
- ページエンコーディングと明示的に違うエンコーディングであることを示すと今回の事象が起こるらしい。
- レスポンスヘッダのContent-Typeのcharsetで同じことが起こるのかは未検証。
- 今回は未指定
終わりに
おそらくiOSないしSafariのバグだと思っているのですが
https://www.apple.com/jp/feedback/iphone.html
こことかに報告すればいいのでしょうか…どなたか知っていたら教えてください。