Skip to content

Instantly share code, notes, and snippets.

@uupaa
Last active January 20, 2022 05:49
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uupaa/ad00a1912b5770b0023d to your computer and use it in GitHub Desktop.
Save uupaa/ad00a1912b5770b0023d to your computer and use it in GitHub Desktop.
Unknown 2 byte range request occurred in Chrome for Android and nginx proxy.

現象

Chrome for Android で HLS 再生をしようと playlist.m3u8 をリクエストすると、 Range: bytes=0-1 を含む意図しないリクエストが発生し、2byte のデータ(改行コード)が返る。 その結果 video.js が「サポートしていないファイルだ」として再生を諦めてしまう。

Name Status Type Initiator Size Time ...
playlist.m3u8 200 media unknown 0 ...

調査

  • XMLHttpRequest の setRequestHeader で Range: bytes=0-1 を発行している箇所を探ったがそのようなコードはない
  • ブレークポイントを設定してコードを丹念に追ったが、いつの間にかエラーになる
  • Google.search("nginx proxy range request streaming") で探す
    • 以下の情報がヒットした

    • httpdがRangeリクエスト(bytes)に対応していないとiphoneから動画再生ができない 2012-01-08

      • Accept-Range: bytes をサポートしていないサーバが 200 を返すと iPhone で動画や音声を再生できないらしい

      iphoneのリクエストヘッダを見ていると、動画再生時にまず"Range: bytes=0-1" を送って、Rangeリクエストに対応しているかチェックしている様子。そのときに"206 Partial Content" が返ってこない場合、Rangeリクエストに対応していないと判断して、動画の再生を諦めるっぽ。

    • nginxリバースProxyにてRANGEリクエスト対応 2014-04-06

      • iPhone(Chrome for Androidも?) ではストリーミング再生に先立ち、Range: bytes=0-1 の 2byte を要求し、206 が返ってこない場合は再生を諦めるらしい
      • nginx のリバースプロキシにおいてキャッシュしつつ 206 を返す方法は2つあるとのこと
        • 1つは proxy_cache_key $http_range を追加する

        • 2つ目は nginx にパッチを当てるらしい(nginx 1.2.0 で有効との事)

          // ngx_http_upstream.c
            #if (NGX_HTTP_CACHE)
          -     if (r->cached) {
          +     if (r->cached || r->upstream->>cacheable) {
                    r->allow_ranges = 1;
                    return NGX_OK;
                }
            #endif
      • さらに探すと nginx 1.7.7 以降で使える proxy_force_ranges という directive がある との事

      Syntax: proxy_force_ranges on | off; Default: proxy_force_ranges off; Context: http, server, location This directive appeared in version 1.7.7.

      Enables byte-range support for both cached and uncached responses from the proxied server regardless of the “Accept-Ranges” field in these responses. via

試行

        location /api/ {
            proxy_http_version 1.1;
            proxy_pass http://xx.xx.xx.xx/api/;

            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
            add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
            add_header Access-Control-Allow-Credentials true;

            proxy_force_ranges on; # https://gist.github.com/uupaa/ad00a1912b5770b0023d
        }

結果

上手く行った!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment