japankun / bbs.jpnkn.com

BBS.JPNKN.COMのリポジトリ
https://bbs.jpnkn.com/
6 stars 0 forks source link

nicocastで受信が中断されましたとなる #10

Closed japankun closed 4 years ago

japankun commented 5 years ago

nicocast 1.23で確認

japankun commented 5 years ago

ログでは200返している。

[01/Jul/2019:14:00:09 +0000] "GET /**/dat/1558181204.dat HTTP/1.1" 200 15776 "-" "Monazilla/1.00 nicocast/1.23"

japankun commented 5 years ago

GET /**/dat/1561983167.dat HTTP/1.0 Host: bbs.jpnkn.com Range: bytes=9215- User-Agent: Monazilla/1.00 nicocast/1.23 Connection: Close

HTTP/1.1 200 OK Server: nginx/1.14.1 Date: Tue, 02 Jul 2019 09:07:41 GMT Content-Type: text/plain; charset=Shift_JIS Connection: close X-Powered-By: PHP/7.3.2 Pragma: no-cache Vary: Accept-Encoding

japankun commented 5 years ago

問題点

打開策

解説

HTTP/1.1の仕様ではContent-LengthとTransfer-Encodingの両方をレスポンスヘッダー含めてはならない という仕様を逆手に取った解決方法なのであまり良くないと思われる。

If a Content-Length header field (Section 14.13) is present, its decimal value in OCTETs represents both the entity-length and the transfer-length. The Content-Length header field must not be sent if these two lengths are different (i.e., if a Transfer-Encoding header field is present). If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter must be ignored. https://tools.ietf.org/html/rfc2616#section-4.4

japankun commented 5 years ago

再発のため状態をオープンに変更した。 HTTP/1.0でリクエストが来ているにも関わらず、HTTP/1.1で返していることも確認済み。 nginxの設定に穴がありそう。

japankun commented 5 years ago

Rangeなし

GET /thread/dat/1561992624.dat HTTP/1.0 Host: bbs.jpnkn.com User-Agent: Monazilla/1.00 nicocast/1.23 Connection: Close

HTTP/1.1 200 OK Server: nginx/1.17.3 Date: Mon, 04 Nov 2019 14:18:19 GMT Content-Type: text/plain; charset=Shift_JIS Content-Length: 14077 Connection: close X-Powered-By: PHP/7.3.11 Pragma: no-cache Vary: Accept-Encoding

Rangeあり

GET /thread/dat/1561992624.dat HTTP/1.0 Host: bbs.jpnkn.com Range: bytes=14076- User-Agent: Monazilla/1.00 nicocast/1.23 Connection: Close

HTTP/1.1 200 OK Server: nginx/1.17.3 Date: Mon, 04 Nov 2019 14:23:14 GMT Content-Type: text/plain; charset=Shift_JIS Content-Length: 14077 Connection: close X-Powered-By: PHP/7.3.11 Pragma: no-cache Vary: Accept-Encoding

japankun commented 5 years ago

これで動いてるけど大丈夫かな。 nicocast/1.23 動きます。

$total = strlen($dat);

if (isset($_SERVER["HTTP_RANGE"])) {

    $pragma = str_replace("bytes=", "", $_SERVER["HTTP_RANGE"]);
    $range = explode("-", $pragma);

    if ($range[0] > $total) {

        header('HTTP/1.1 205 Reset Content');
        return;

    } else {

        $dat = substr($dat, $range[0]);
        $part = strlen($dat);

        header("Content-Length: ${part}");
        header("Content-Range: bytes ".($total - $part)."-${part}/${total}");

        return $dat;

    }

}
japankun commented 5 years ago

nginxがHTTP/1.1で返すことについては

HTTP/1.0のリクエストが来た場合 HTTP/1.0で返すかHTTP/1.1で返すかはサーバー側が決めていいが HTTP/1.1で追加されたものを取り除いてもHTTP/1.0として解釈できるものでなければならない

https://serverfault.com/questions/442960/nginx-ignoring-clients-http-1-0-request-and-respond-by-http-1-1

さらにHTTP/1.0ではTransfer-Encoding:chunkedを解釈できないので HTTP/1.1として返答する場合であってもTransfer-Encoding:chunkedを使用してはならない

japankun commented 5 years ago

Rangeの解釈を厳格にしたほうがいいのと、一部を返してる場合に206を返したほうがいいのかな。

japankun commented 4 years ago

Jane系で壊れることがあるみたいなので後でチェックする。

japankun commented 4 years ago

クライアントの要求の答えるならこうか ちなみにrange-endだけの指定「-100」とかの指定はできないらしい。

if (isset($_SERVER["HTTP_RANGE"])) {

    $pragma = str_replace("bytes=", "", $_SERVER["HTTP_RANGE"]);
    $range = explode("-", $pragma);

    if ($range[0] > $total) {

        header('HTTP/1.1 205 Reset Content');
        return;

    } else if ($range[0] && $range[1] == "") {

        // <range-start>-

        $dat = substr($dat, $range[0]);
        $part = strlen($dat);

        header('HTTP/1.1 206 Partial Content');
        header("Content-Length: ${part}");
        header("Content-Range: bytes ".$range[0]."-".$total."/${total}");

    } else {

        // <range-start>-<range-end>

        $dat = substr($dat, $range[0], ($range[1] - $range[0]));
        $part = strlen($dat);

        header('HTTP/1.1 206 Partial Content');
        header("Content-Length: ${part}");
        header("Content-Range: bytes ".$range[0]."-".$range[1]."/${total}");

    }

}
japankun commented 4 years ago

$range[]の中身は0の場合もあるわけだからこうしないとダメか。

if (isset($_SERVER["HTTP_RANGE"])) {

    $pragma = str_replace("bytes=", "", $_SERVER["HTTP_RANGE"]);
    $range = explode("-", $pragma);

    if ($range[0] > $total) {

        header('HTTP/1.1 205 Reset Content');
        return;

    } else if ($range[0] != "" && $range[1] == "") {

        // <range-start>-

        $dat = substr($dat, $range[0]);
        $part = strlen($dat);

        header('HTTP/1.1 206 Partial Content');
        header("Content-Length: ${part}");
        header("Content-Range: bytes ".$range[0]."-".$total."/${total}");

    } else {

        // <range-start>-<range-end>

        $dat = substr($dat, $range[0], ($range[1] - $range[0]));
        $part = strlen($dat);

        header('HTTP/1.1 206 Partial Content');
        header("Content-Length: ${part}");
        header("Content-Range: bytes ".$range[0]."-".$range[1]."/${total}");

    }

}
japankun commented 4 years ago

JaneStyle/4.0.0.5で壊れないことを確認。

japankun commented 4 years ago

特に問題なさそうなので一旦クローズ