Необычная ошибка: в скрипте PHP, обслуживающем видеофайлы, у меня есть несколько условий тестирования (аутентификация токена, убедитесь, что файл существует и т. д.) перед отправкой заголовка «video/mp4» и вывод MP4-файл.Отдельный PHP-выход; заявление предотвращает видео HTML5 в Safari
Если какой-либо из тестов завершился с ошибкой, $fail
присваивается неверное значение.
В конце испытаний есть это if
заявление:
if ($fail) {
exit;
}
Этот код работает, как ожидается, в Chrome, но не в Safari. Однако (и поверьте мне, я проверил это в каждом направлении), если я просто закомментируйте exit;
, как:
if ($fail) {
//exit;
}
... код отлично работает в Safari - видео сразу же начинает загрузку.
Я уверен, что блок if
никогда не вводится, иначе скрипт прекратит выполнение, и я бы не видел заголовок video/mp4
(не говоря уже о том, что он не будет работать в Chrome). Кроме того, независимо от того, что делает PHP за кулисами, он должен быть полностью прозрачным для браузера. Я подумал, что, может быть, возникла проблема с выходом, но я бы получил предупреждение, если бы я вывел что-либо перед заголовками.
Я наблюдаю это поведение последовательно в течение нескольких дней - я проверил его, вероятно, 25 раз в недоумении.
Уверен, что-то мне не хватает?
UPDATE
Для выяснения вопроса, я изменил код немного:
$fail = true;
if ($fail) {
die('Fail');
}
Теперь мы гарантированно поразить die()
заявление, и выход "провал". Вот заголовки, как видно Safari: (. "Сбой" выводится, как и ожидалось, тоже)
Connection:Keep-Alive
Content-Type:text/html
Date:Thu, 24 Jun 2010 23:31:28 GMT
Keep-Alive:timeout=10, max=29
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
Transfer-Encoding:Identity
X-Powered-By:PHP/5.2.13
Теперь, когда я закомментировать $fail = true;
заголовки изменится:
Connection:Keep-Alive
Content-Length:47406944
Content-Type:video/mp4
Date:Thu, 24 Jun 2010 23:32:58 GMT
Keep-Alive:timeout=10, max=30
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
X-Powered-By:PHP/5.2.13
Но видео все равно не будет воспроизводиться! (Логотип QuickTime с вопросительным знаком над ним.)
Я думаю, что это достаточно доказательство, что $fail
остается ложным и что die()
не выполняется.
Теперь получите это: если я снова закомментировать die()
(функционально эквивалентный exit
), так что мой окончательный код:
//$fail = true;
if ($fail) {
//die('Fail');
}
... видео воспроизводится в Safari!
UPDATE 2
Если изменить код:
$fail = false;
if ($fail) {
die('Fail');
}
... абсолютно гарантировать, что $fail
является false
, он играет в Safari!
Такое поведение не имеет смысла для меня, б/с, если $fail
был быть установлен из-за одного из моих условий проверки, то он никогда не будет выводить video/mp4
заголовок, так как, когда я явно установить $fail
к true
- и вместо этого будет выведите страницу text/html
со словом «Сбой» - правильно?
UPDATE 3
Вот все соответствующего кода, просто чтобы быть совершенно ясно:
// verify
$fail = false;
$token = false;
$file_name = [rest assured that $file_name is correct];
if (!$file_name) {
$fail = true;
} else {
$file_name = '../video/'.$file_name;
}
if (!isset($_REQUEST['ts'])) {
$fail = true;
}
if (isset($_POST['token']) || isset($_GET['token'])) {
$token = isset($_POST['token']) ? $_POST['token'] : $_GET['token'];
} else if (isset($_COOKIE['token'])) {
$token = $_COOKIE['token'];
}
if ($token != md5(SALT_HASH.$_REQUEST['ts'])) {
$fail = true;
}
if (((int)($_REQUEST['ts']) + 60 * 10) < mktime()) {
$fail = true;
}
if (!is_file($file_name)) {
$fail = true;
}
if ($fail) {
die('Fail');
}
// output
$file_size = (string)(filesize($file_name));
header('Content-Type: video/mp4');
header('Content-Length: '.$file_size);
readfile_chunked($file_name);
exit;
надеюсь, последний UPDATE/СУЩНОСТЬ
Этот вопрос, вероятно, уже слишком но я подумал, что в последний раз попробую подвести итог тому, как это странно. Есть 3 различных ответов:
1) Если я $fail = true;
проводных перед тем if ($fail) die('Fail');
, просто так, у меня есть базовый уровень для отказа, я получаю text/html
заголовок, и слово «нормально» выводится, как и ожидалось.
2) Если я оставляю код, как он выше, я получаю заголовок video/mp4
, но сломанное видео в Safari (оно будет воспроизводиться в Chrome).
3) Наконец (и это основано на новом тестировании, которое я сделал сегодня), если я прокомментирую $fail = true;
в условной проверке токена, я получаю заголовок video/mp4
, и видео воспроизводится в Safari. Теперь я понял, что должен что-то не в порядке с проверкой маркера - но когда я затрудняюсь в другом тесте, чтобы повторить значение $ fail после теста, он по-прежнему остается ложным! Условие не вводится (я также просто положил прямой die('!');
вместо $fail = true;
- и я все еще получаю заголовок video/mp4
).
Я просто не могу поверить, что комментарий кода, который никогда не будет выполнен, может вызвать отчетный отклик - и, кроме того, он будет играть в Chrome, но не в Safari; все, что происходит на стороне сервера с PHP, должно быть полностью прозрачным для браузера.
Сумасшедший.
AHA!
Я добавил несколько записей в мой скрипт, и выясняется, что при обслуживании видео HTML5 браузер делает двумя запросами.
Вот два (успешные) запросы от Chrome:
Fri Jun 25 17:41:22 2010 Browser: [Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4] Fail: [0] Token: [83e50b519c0ed4662b6b7fabb8f6671e] Timestamp: [1277509282]
Fri Jun 25 17:41:22 2010 Verification passed
Fri Jun 25 17:41:22 2010 Browser: [Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4] Fail: [0] Token: [83e50b519c0ed4662b6b7fabb8f6671e] Timestamp: [1277509282]
Fri Jun 25 17:41:22 2010 Verification passed
И вот два из Safari (первый успешный, второй сбой):
Fri Jun 25 17:41:32 2010 Browser: [Apple Mac OS X v10.6.4 CoreMedia v1.0.0.10F569] Fail: [0] Token: [6374fba3d9eac7d94de9741db76953c6] Timestamp: [1277509291]
Fri Jun 25 17:41:32 2010 Verification passed
Fri Jun 25 17:41:33 2010 Browser: [QuickTime/7.6.6 (qtver=7.6.6;cpu=IA32;os=Mac 10.6.4)] Fail: [1] Token: [] Timestamp: [1277509291]
Я должен выйти прямо сейчас, но я почти уверен, что это поведение является корнем ошибки. По какой-то причине второй запрос Safari не может найти токен.
Используйте [Wireshark] (http://www.wireshark.org/) или еще один инструмент, чтобы узнать, что действительно происходит по сети. –
Укажите, что вы делаете: не используйте $ _REQUEST --- используйте $ _GET и $ _POST и $ _COOKIE – alexanderpas
Есть ли веская причина не использовать $ _REQUEST? В любом случае, ни один из фактических условий проверки не имеет значения, когда я изменяю значение $ fail перед окончательным «if ($ fail) {}». – JKS