Cómo realizar solicitudes HTTP en PHP y no esperar la respuesta
¿Existe alguna forma en PHP de realizar llamadas HTTP y no esperar una respuesta? No me importa la respuesta, solo quiero hacer algo como file_get_contents()
, pero no esperar a que finalice la solicitud antes de ejecutar el resto de mi código. Esto sería muy útil para activar "eventos" de algún tipo en mi aplicación o desencadenar procesos largos.
¿Algunas ideas?
La respuesta que había aceptado previamente no funcionó. Todavía esperaba respuestas. Sin embargo, esto funciona, tomado de ¿Cómo realizo una solicitud GET asincrónica en PHP?
function post_without_wait($url, $params)
{
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
}
Si controlas el objetivo al que deseas llamar de forma asincrónica (por ejemplo, tu propio "longtask.php"), puedes cerrar la conexión desde ese extremo y ambos scripts se ejecutarán en paralelo. Funciona así:
- Quick.php abre longtask.php a través de cURL (aquí no hay magia)
- longtask.php cierra la conexión y continúa (¡magia!)
- cURL vuelve a quick.php cuando se cierra la conexión
- Ambas tareas continúan en paralelo
He probado esto y funciona bien. Pero quick.php no sabrá nada sobre el rendimiento de longtask.php, a menos que cree algún medio de comunicación entre los procesos.
Pruebe este código en longtask.php, antes de hacer cualquier otra cosa. Cerrará la conexión, pero seguirá ejecutándose (y suprimirá cualquier resultado):
while(ob_get_level()) ob_end_clean();
header('Connection: close');
ignore_user_abort();
ob_start();
echo('Connection Closed');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
El código se copia de las notas aportadas por el usuario del manual de PHP y se ha mejorado algo.
Puedes hacer trucos usando exec() para invocar algo que pueda realizar solicitudes HTTP, como wget
, pero debes dirigir toda la salida del programa a algún lugar, como un archivo o /dev/null; de lo contrario, el proceso PHP esperará esa salida. .
Si desea separar completamente el proceso del hilo de Apache, intente algo como (no estoy seguro de esto, pero espero que entienda la idea):
exec('bash -c "wget -O (url goes here) > /dev/null 2>&1 &"');
No es un buen negocio y probablemente querrá algo como un trabajo cron que invoque un script de latido que sondee una cola de eventos de base de datos real para realizar eventos asincrónicos reales.