LoginSignup
4
2

More than 5 years have passed since last update.

iOS10.3.1/Safariにおいてdocument.writeでスクリプトを呼び出した際にエンコードがページ文字コードと異なると2重でHTTPアクセスが発生する

Last updated at Posted at 2017-05-11

概要

少なくとも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は下記の物を用意した。

shift_jis_log.js
console.log('テスト shift_jis');
utf-8_log.js
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
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>
ネットワーク

1_network.png

コンソール

1_console.png

2. ページ文字指定:指定なし スクリプトcharset:shift_jis

2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)

HTML
2.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>
ネットワーク

2_network.png

コンソール

2_console.png

3. ページ文字指定:utf-8 スクリプトcharset:指定なし (utf-8_log.jsを使用)

1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)

HTML
3.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>
ネットワーク

3_network.png

コンソール

3_console.png

4. ページ文字指定:utf-8 スクリプトcharset:指定なし (shift_jis_log.jsを使用)

1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、shift_jisなファイルをUTF-8扱いで読み込んでいるだけ。
(正常)

HTML
4.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>
ネットワーク

4_network.png

コンソール

4_console.png

5. ページ文字指定:utf-8 スクリプトcharset:utf-8

1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)

HTML
5.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>
ネットワーク

5_network.png

コンソール

5_console.png

6. ページ文字指定:utf-8 スクリプトcharset:shift_jis

2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)

HTML
6.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>
ネットワーク

6_network.png

コンソール

6_console.png

7. ページ文字指定:shift_jis スクリプトcharset:指定なし (utf-8_log.jsを使用)

1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、UTF-8なファイルをshift_jis扱いで読み込んでいるだけ。
(正常)

HTML
7.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>
ネットワーク

7_network.png

コンソール

7_console.png

8. ページ文字指定:shift_jis スクリプトcharset:指定なし (shift_jis_log.jsを使用)

1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)

HTML
8.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>
ネットワーク

8_network.png

コンソール

8_console.png

9. ページ文字指定:shift_jis スクリプトcharset:utf-8

2回のHTTP呼び出しが行われている。
JSの実行は1回。
(異常)

HTML
9.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>
ネットワーク

9_network.png

コンソール

9_console.png

10. ページ文字指定:shift_jis スクリプトcharset:shift_jis

1回のHTTP呼び出しが行われている。
JSの実行は1回。
(正常)

HTML
10.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>
ネットワーク

10_network.png

コンソール

10_console.png

11. ページ文字指定:指定なし スクリプトcharset:指定なし (utf-8_log.jsを使用)

1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、UTF-8なファイルを別のエンコード(何のエンコード?)扱いで読み込んでいるだけ。
(正常)

HTML
11.html
<html>
<head>
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/utf-8_log.js"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク

11_network.png

コンソール

11_console.png

12. ページ文字指定:指定なし スクリプトcharset:指定なし (shift_jis_log.jsを使用)

1回のHTTP呼び出しが行われている。
JSの実行は1回。
コンソール出力結果が化けているが、UTF-8なファイルを別のエンコード(何のエンコード?)扱いで読み込んでいるだけ。
(正常)

HTML
12.html
<html>
<head>
</head>
<body>
<script>
document.write('<script type="text/javascript" src="//example.com/shift_jis_log.js"></scr'+'ipt>');
</script>
</body>
</html>
ネットワーク

12_network.png

コンソール

12_console.png

結果

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
こことかに報告すればいいのでしょうか…どなたか知っていたら教えてください。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2