Разорвать HTTP-запрос прямо с сервера - PullRequest
1 голос
/ 07 марта 2012

У меня есть два файла client.php и server.php.Файл клиента отправляет HTTP-запрос на файл сервера.Файл сервера может быть очень медленным для обработки запроса, поэтому я просто хочу, чтобы он ответил клиенту: «ОК, запрос верен, результат будет отправлен по электронной почте».

Но я не знаю, чтобызаставить сервер закрыть HTTP-запрос с подходящими заголовками и продолжить его работу.Если я укажу время ожидания в 1 секунду, я не смогу узнать, будет ли запрос принят сервером.

Так возможно ли это в PHP?Знаете ли вы, как?

client.php:

<?php

$resource = curl_init();
curl_setopt($resource, CURLOPT_URL, 'http://localhost/server.php');
curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
curl_setopt($resource, CURLOPT_TIMEOUT, 30);
curl_exec($resource);

server.php

<?php

header('200 OK');
echo 'OK the request is correct, the result will be sent by email';

// How to write the method below?
send_result_to_client();

// Simulates a slow process
sleep(60);

Хорошо Я нашел решение.В функции send_result_to_client должно отображаться:

function send_result_to_client()
{
    $myString = '...';
    $size = strlen($myString);
    header("Content-Length: $size"); 
    header('Connection: close');
    flush();
}

Ответы [ 2 ]

1 голос
/ 07 марта 2012

Я знаю, что это не совсем то, что вы спрашиваете (не уверен, что это возможно), но у меня была бы очередь, которая обрабатывается другим потоком. Запрос поступает на сервер, он добавляет детали в очередь (может быть в БД) и отвечает клиенту. После этого у вас может быть cron, который запускает и обрабатывает очередь позже.

0 голосов
/ 05 июля 2012

Извините, но отправка Connection:close и flush() - это , а не решение - не переносится между серверами или браузерами.Может показаться, что - решение, потому что оно работает, когда вы запускаете простой тест.Если вы попробуете это с

 send_result_to_client();
 sleep(60);  // simulate a job...
 mail(...);  // ...ENDING with a mail message

, а затем ничего не сделаете, или, что еще хуже, сделайте то, что сделает любой пользователь - закройте окно, как только он увидит сообщение «Вы получите уведомление по электронной почте» - выВы обнаружите, что на большинстве платформ электронное письмо никогда не отправляется, и работа никогда не выполняется.

curl может прерваться, если были получены Connection:close и Content-Length байты, но из RFC2616 ,

HTTP/1.1 defines the "close" connection option for **the sender** to signal that the connection will be closed after completion of the response.

Но сервер не закрывает соединение, не совсем.Для этого потребуется die() или exit(), прежде чем задание будет обработано.

Таким образом, ваш сценарий продолжает выполняться только до тех пор, пока браузер фактически не закроет соединение - в этот момент ( обычно )обработка прерывается.Возможно, на некоторых платформах это не так, но не рассчитывайте на это.

Вы можете попытаться улучшить ситуацию с помощью другого хака:

  set_time_limit(VERY_LONG_TIME);
  ignore_user_abort();

, но это действительнохак.

По-настоящему портативных решений не существует.Обычно, как предполагает Манаток, задание ставится в очередь где-то еще, а очередь обрабатывается асинхронно другим потоком.Возможно, это лучшее решение.

Другие возможности включают другой и, возможно, более простой способ сделать то же самое, используя atd и at command (или эквивалент в Windows), чтобы поставить задачу в очередь.Вы можете создать «управление заданиями» с помощью shell_exec, отправив новый PHP-скрипт для выполнения atd:

shell_exec("echo 'php -q /path/to/script.php \"param1\" \"param2\" | at now");

(или более эффективно, запустив "at now" с popenи записать команду для выполнения в stdin).

См., например:

https://github.com/treffynnon/PHP-at-Job-Queue-Wrapper

Вы также можете попытаться создать параллельное задание через popen или shell_exec, но вам нужно отсоединить его от процесса сервера, или вы обнаружите, что система перегружена копиями исполняемого файла задания (или CMD.EXE, если вы делаете это в Windows).

См .:

Exec асинхронной оболочки в PHP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...