TigerZF
🌐Español

38.2. Zend_Http_Client - Uso avanzado

38.2.1. Redirecciones HTTP

Por defecto, Zend_Http_Client gestiona automáticamente las redirecciones HTTP, y seguirá hasta 5 redirecciones. Esto se puede cambiar configurando el parámetro de configuración 'maxredirects'.

Según el RFC de HTTP/1.1, las respuestas HTTP 301 y 302 deberían ser tratadas por el cliente reenviando la misma petición a la ubicación especificada, usando el mismo método de petición. Sin embargo, la mayoría de los clientes no implementan esto y siempre usan una petición GET al redirigir. Por defecto, Zend_Http_Client hace lo mismo - cuando redirige en una respuesta 301 o 302, todos los parámetros GET y POST se reinician, y se envía una petición GET a la nueva ubicación. Este comportamiento se puede cambiar configurando el parámetro de configuración 'strictredirects' al booleano TRUE:

Ejemplo 38.6. Forzar redirecciones estrictas RFC 2616 en respuestas 301 y 302

// Strict Redirections
$client->setConfig(array('strictredirects' => true));

// Non-strict Redirections
$client->setConfig(array('strictredirects' => false));


Siempre puede obtener el número de redirecciones realizadas después de enviar una petición usando el método getRedirectionsCount().

38.2.2. Añadir cookies y usar la persistencia de cookies

Zend_Http_Client proporciona una interfaz sencilla para añadir cookies a su petición, de modo que no se requiere ninguna modificación directa de la cabecera. Esto se hace usando el método setCookie(). Este método se puede usar de varias maneras:

Ejemplo 38.7. Configurar cookies usando setCookie()

// Easy and simple: by providing a cookie name and cookie value
$client->setCookie('flavor', 'chocolate chips');

// By directly providing a raw cookie string (name=value)
// Note that the value must be already URL encoded
$client->setCookie('flavor=chocolate%20chips');

// By providing a Zend_Http_Cookie object
$cookie = Zend_Http_Cookie::fromString('flavor=chocolate%20chips');
$client->setCookie($cookie);


Para más información sobre los objetos Zend_Http_Cookie, vea esta sección.

Zend_Http_Client también proporciona los medios para la persistencia de cookies - es decir, hacer que el cliente almacene internamente todas las cookies enviadas y recibidas, y las reenvíe automáticamente en peticiones subsiguientes. Esto es útil, por ejemplo, cuando necesita iniciar sesión en un sitio remoto primero y recibir una cookie de autenticación o de sesión antes de enviar más peticiones.

Ejemplo 38.8. Habilitar la persistencia de cookies

// To turn cookie stickiness on, set a Cookie Jar
$client->setCookieJar();

// First request: log in and start a session
$client->setUri('http://example.com/login.php');
$client->setParameterPost('user', 'h4x0r');
$client->setParameterPost('password', '1337');
$client->request('POST');

// The Cookie Jar automatically stores the cookies set
// in the response, like a session ID cookie.

// Now we can send our next request - the stored cookies
// will be automatically sent.
$client->setUri('http://example.com/read_member_news.php');
$client->request('GET');


Para más información sobre la clase Zend_Http_CookieJar, vea esta sección.

38.2.3. Configurar cabeceras de petición personalizadas

Configurar cabeceras personalizadas se puede hacer usando el método setHeaders(). Este método es bastante versátil y se puede usar de varias maneras, como muestra el siguiente ejemplo:

Ejemplo 38.9. Configurar una única cabecera de petición personalizada

// Setting a single header, overwriting any previous value
$client->setHeaders('Host', 'www.example.com');

// Another way of doing the exact same thing
$client->setHeaders('Host: www.example.com');

// Setting several values for the same header
// (useful mostly for Cookie headers):
$client->setHeaders('Cookie', array(
    'PHPSESSID=1234567890abcdef1234567890abcdef',
    'language=he'
));


setHeader() también se puede usar fácilmente para configurar varias cabeceras en una sola llamada, proporcionando un array de cabeceras como único parámetro:

Ejemplo 38.10. Configurar múltiples cabeceras de petición personalizadas

// Setting multiple headers, overwriting any previous value
$client->setHeaders(array(
    'Host' => 'www.example.com',
    'Accept-encoding' => 'gzip,deflate',
    'X-Powered-By' => 'Zend Framework'));

// The array can also contain full array strings:
$client->setHeaders(array(
    'Host: www.example.com',
    'Accept-encoding: gzip,deflate',
    'X-Powered-By: Zend Framework'));


38.2.4. Subida de archivos

Puede subir archivos a través de HTTP usando el método setFileUpload. Este método toma un nombre de archivo como primer parámetro, un nombre de formulario como segundo parámetro, y datos como tercer parámetro opcional. Si el tercer parámetro de datos es NULL, el primer parámetro de nombre de archivo se considera un archivo real en disco, y Zend_Http_Client intentará leer este archivo y subirlo. Si el parámetro de datos no es NULL, el primer parámetro de nombre de archivo se enviará como el nombre del archivo, pero no es necesario que exista un archivo real en el disco. El segundo parámetro de nombre de formulario siempre es obligatorio, y equivale al atributo "name" de una etiqueta >input<, si el archivo fuera a subirse a través de un formulario HTML. Un cuarto parámetro opcional proporciona el content-type del archivo. Si no se especifica, y Zend_Http_Client lee el archivo del disco, se usará la función mime_content_type para adivinar el tipo de contenido del archivo, si está disponible. En cualquier caso, el tipo MIME por defecto será application/octet-stream.

Ejemplo 38.11. Usar setFileUpload para subir archivos

// Uploading arbitrary data as a file
$text = 'this is some plain text';
$client->setFileUpload('some_text.txt', 'upload', $text, 'text/plain');

// Uploading an existing file
$client->setFileUpload('/tmp/Backup.tar.gz', 'bufile');

// Send the files
$client->request('POST');


En el primer ejemplo, la variable $text se sube y estará disponible como $_FILES['upload'] en el lado del servidor. En el segundo ejemplo, el archivo existente /tmp/Backup.tar.gz se sube al servidor y estará disponible como $_FILES['bufile']. El tipo de contenido se adivinará automáticamente si es posible - y si no, el tipo de contenido se establecerá en 'application/octet-stream'.

[Note] Subida de archivos

Al subir archivos, el content-type de la petición HTTP se establece automáticamente en multipart/form-data. Tenga en cuenta que debe enviar una petición POST o PUT para subir archivos. La mayoría de los servidores ignorarán el cuerpo de la petición en otros métodos de petición.

38.2.5. Enviar datos POST en bruto

Puede usar un Zend_Http_Client para enviar datos POST en bruto usando el método setRawData(). Este método toma dos parámetros: el primero es el dato a enviar en el cuerpo de la petición. El segundo parámetro opcional es el content-type del dato. Aunque este parámetro es opcional, normalmente debería configurarlo antes de enviar la petición - ya sea usando setRawData(), o con otro método: setEncType().

Ejemplo 38.12. Enviar datos POST en bruto

$xml = '<book>' .
       '  <title>Islands in the Stream</title>' .
       '  <author>Ernest Hemingway</author>' .
       '  <year>1970</year>' .
       '</book>';

$client->setRawData($xml, 'text/xml')->request('POST');

// Another way to do the same thing:
$client->setRawData($xml)->setEncType('text/xml')->request('POST');


Los datos deberían estar disponibles en el lado del servidor a través de la variable $HTTP_RAW_POST_DATA de PHP o a través del flujo php://input.

[Note] Uso de datos POST en bruto

Configurar datos POST en bruto para una petición anulará cualquier parámetro POST o subida de archivos. No debería intentar usar ambos en la misma petición. Tenga en cuenta que la mayoría de los servidores ignorarán el cuerpo de la petición a menos que envíe una petición POST.

38.2.6. Autenticación HTTP

Actualmente, Zend_Http_Client solo soporta la autenticación básica HTTP. Esta característica se utiliza mediante el método setAuth(), o especificando un nombre de usuario y una contraseña en la URI. El método setAuth() toma 3 parámetros: el nombre de usuario, la contraseña y un parámetro opcional de tipo de autenticación. Como se mencionó, actualmente solo se soporta la autenticación básica (el soporte para la autenticación digest está planeado).

Ejemplo 38.13. Configurar el usuario y la contraseña de autenticación HTTP

// Using basic authentication
$client->setAuth('shahar', 'myPassword!', Zend_Http_Client::AUTH_BASIC);

// Since basic auth is default, you can just do this:
$client->setAuth('shahar', 'myPassword!');

// You can also specify username and password in the URI
$client->setUri('http://christer:secret@example.com');


38.2.7. Enviar múltiples peticiones con el mismo cliente

Zend_Http_Client también fue diseñado específicamente para gestionar varias peticiones consecutivas con el mismo objeto. Esto es útil en casos en los que un script requiere obtener datos de varios lugares, o cuando acceder a un recurso HTTP específico requiere iniciar sesión y obtener una cookie de sesión, por ejemplo.

Al realizar varias peticiones al mismo host, se recomienda encarecidamente habilitar el indicador de configuración 'keepalive'. De esta manera, si el servidor soporta conexiones keep-alive, la conexión al servidor solo se cerrará una vez que todas las peticiones se hayan completado y el objeto Client se destruya. Esto evita la sobrecarga de abrir y cerrar conexiones TCP con el servidor.

Cuando realiza varias peticiones con el mismo cliente, pero quiere asegurarse de que todos los parámetros específicos de la petición se limpian, debería usar el método resetParameters(). Esto asegura que los parámetros GET y POST, el cuerpo de la petición y las cabeceras específicas de la petición se reinician y no se reutilizan en la siguiente petición.

[Note] Reiniciar parámetros

Tenga en cuenta que las cabeceras que no son específicas de la petición no se reinician por defecto cuando se usa el método resetParameters(). Solo se reinician las cabeceras 'Content-length' y 'Content-type'. Esto le permite configurar de una vez cabeceras como 'Accept-language' y 'Accept-encoding'

Para limpiar todas las cabeceras y otros datos excepto la URI y el método, use resetParameters(true).

Otra característica diseñada específicamente para peticiones consecutivas es el objeto Cookie Jar. Los Cookie Jar le permiten guardar automáticamente las cookies establecidas por el servidor en la primera petición, y enviarlas en peticiones consecutivas de forma transparente. Esto permite, por ejemplo, pasar por una petición de autenticación antes de enviar la petición real de obtención de datos.

Si su aplicación requiere una petición de autenticación por usuario, y las peticiones consecutivas pueden realizarse en más de un script en su aplicación, podría ser una buena idea almacenar el objeto Cookie Jar en la sesión del usuario. De esta manera, solo necesitará autenticar al usuario una vez por sesión.

Ejemplo 38.14. Realizar peticiones consecutivas con un cliente

// First, instantiate the client
$client = new Zend_Http_Client('http://www.example.com/fetchdata.php', array(
    'keepalive' => true
));

// Do we have the cookies stored in our session?
if (isset($_SESSION['cookiejar']) &&
    $_SESSION['cookiejar'] instanceof Zend_Http_CookieJar) {

    $client->setCookieJar($_SESSION['cookiejar']);
} else {
    // If we don't, authenticate and store cookies
    $client->setCookieJar();
    $client->setUri('http://www.example.com/login.php');
    $client->setParameterPost(array(
        'user' => 'shahar',
        'pass' => 'somesecret'
    ));
    $client->request(Zend_Http_Client::POST);

    // Now, clear parameters and set the URI to the original one
    // (note that the cookies that were set by the server are now
    // stored in the jar)
    $client->resetParameters();
    $client->setUri('http://www.example.com/fetchdata.php');
}

$response = $client->request(Zend_Http_Client::GET);

// Store cookies in session, for next page
$_SESSION['cookiejar'] = $client->getCookieJar();

38.2.8. Transmisión de datos

Por defecto, Zend_Http_Client acepta y devuelve datos como cadenas de PHP. Sin embargo, en muchos casos hay archivos grandes que enviar o recibir, por lo que mantenerlos en memoria puede ser innecesario o demasiado costoso. Para estos casos, Zend_Http_Client soporta leer datos de archivos (y en general, flujos de PHP) y escribir datos en archivos (flujos).

Para usar un flujo para pasar datos a Zend_Http_Client, use el método setRawData() con el argumento de datos siendo un recurso de flujo (por ejemplo, el resultado de fopen()).

Ejemplo 38.15. Enviar un archivo a un servidor HTTP con transmisión

$fp = fopen("mybigfile.zip", "r");
$client->setRawData($fp, 'application/zip')->request('PUT');


Actualmente solo las peticiones PUT soportan el envío de flujos al servidor HTTP.

Para recibir datos del servidor como flujo, use setStream(). El argumento opcional especifica el nombre de archivo donde se almacenarán los datos. Si el argumento es simplemente TRUE (por defecto), se usará un archivo temporal que se eliminará una vez que el objeto de respuesta se destruya. Configurar el argumento en FALSE deshabilita la funcionalidad de transmisión.

Al usar la transmisión, el método request() devolverá un objeto de la clase Zend_Http_Client_Response_Stream, que tiene dos métodos útiles: getStreamName() devolverá el nombre del archivo donde se almacena la respuesta, y getStream() devolverá el flujo desde el cual se puede leer la respuesta.

Puede escribir la respuesta en un archivo predefinido, o usar un archivo temporal para almacenarla y enviarla o escribirla en otro archivo usando funciones de flujo habituales.

Ejemplo 38.16. Recibir un archivo de un servidor HTTP con transmisión

$client->setStream(); // will use temp file
$response = $client->request('GET');
// copy file
copy($response->getStreamName(), "my/downloads/file");
// use stream
$fp = fopen("my/downloads/file2", "w");
stream_copy_to_stream($response->getStream(), $fp);
// Also can write to known file
$client->setStream("my/downloads/myfile")->request('GET');