El m贸dulo de solicitud de Node.js

    En estos d铆as, nuestras aplicaciones web tienden a tener muchas integraciones con otros servicios, ya sea interactuando con un servicio REST como Twitter o descargando im谩genes de Flickr. El uso de Node / JavaScript es uno de los lenguajes m谩s populares para manejar aplicaciones como esta. De cualquier manera, realizar谩 muchas solicitudes HTTP, lo que significa que necesitar谩 un m贸dulo s贸lido para que la escritura del c贸digo sea mucho m谩s llevadera.

    los solicitud module es, con mucho, el paquete Node m谩s popular (no est谩ndar) para realizar solicitudes HTTP. En realidad, es solo una envoltura de los componentes integrados de Node http m贸dulo, para que pueda lograr la misma funcionalidad por su cuenta con http, pero request simplemente lo hace mucho m谩s f谩cil.

    Realizaci贸n de solicitudes HTTP

    Si bien hay bastantes opciones disponibles en request (muchos de los cuales cubriremos a lo largo de este art铆culo), tambi茅n puede ser bastante simple de usar. El ejemplo de “hola mundo” para esta biblioteca es tan f谩cil como pasar una URL y una devoluci贸n de llamada:

    const request = require('request');
    
    request('http://Pharos.sh.com', function(err, res, body) {
        console.log(body);
    });
    

    El c贸digo anterior env铆a una solicitud HTTP GET a Pharos.sh.com y luego imprime el HTML devuelto en la pantalla. Este tipo de solicitud funciona para cualquier punto final HTTP, ya sea que devuelva HTML, JSON, una imagen o casi cualquier otra cosa.

    El primer argumento para request puede ser una cadena de URL o un objeto de opciones. Estas son algunas de las opciones m谩s comunes que encontrar谩 en sus aplicaciones:

    • url: La URL de destino de la solicitud HTTP
    • method: El m茅todo HTTP que se utilizar谩 (GET, POST, DELETE, etc.)
    • headers: Un objeto de encabezados HTTP (clave-valor) que se establecer谩 en la solicitud
    • form: Un objeto que contiene datos de formulario de valor-clave
    const request = require('request');
    
    const options = {
        url: 'https://www.reddit.com/r/funny.json',
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            'Accept-Charset': 'utf-8',
            'User-Agent': 'my-reddit-client'
        }
    };
    
    request(options, function(err, res, body) {
        let json = JSON.parse(body);
        console.log(json);
    });
    

    Utilizando la options objeto, esta solicitud utiliza el m茅todo GET para recuperar datos JSON directamente de Reddit, que se devuelve como una cadena en el body campo. Desde aqu铆, puede usar JSON.parse y utilizar los datos como un objeto JavaScript normal.

    Este mismo formato de solicitud se puede utilizar para cualquier tipo de m茅todo HTTP, ya sea DELETE, PUT, POST u OPTIONS. Aunque, no todos los m茅todos se utilizan exactamente igual. Algunos, como el m茅todo POST, pueden incluir datos dentro de la solicitud. Hay algunas formas en que se pueden enviar estos datos, algunas de las cuales son:

    • body: UN Buffer, Stringo Stream objeto (puede ser un objeto si json la opci贸n est谩 configurada en true)
    • form: Un objeto de datos de pares clave-valor (veremos esto m谩s adelante)
    • multipart: Una matriz de objetos que pueden contener sus propios encabezados y atributos de cuerpo

    Cada uno satisface una necesidad diferente (y hay incluso m谩s formas de enviar datos, que se pueden encontrar en esta secci贸n del archivo README de la solicitud). los request Sin embargo, el m贸dulo contiene algunos m茅todos convenientes que hacen que sea un poco m谩s f谩cil trabajar con ellos, as铆 que aseg煤rese de leer los documentos completos para evitar que su c贸digo sea m谩s dif铆cil de lo que debe ser.

    Hablando de m茅todos auxiliares, una forma mucho m谩s sucinta de llamar a los diferentes m茅todos HTTP es utilizar los respectivos m茅todos auxiliares proporcionados. 脡stos son algunos de los m谩s utilizados:

    • request.get(options, callback)
    • request.post(options, callback)
    • request.head(options, callback)
    • request.delete(options, callback)

    Si bien esto no le ahorrar谩 un mont贸n de l铆neas de c贸digo, al menos har谩 que su c贸digo sea un poco m谩s f谩cil de entender al permitirle ver el m茅todo que se llama y no tener que analizar todas las opciones para encontrar eso.

    Formularios

    Ya sea que est茅 interactuando con una API REST o creando un bot para rastrear y enviar datos en sitios web, en alg煤n momento deber谩 enviar datos para un formulario. Como siempre con request, esto se puede hacer de diferentes formas, dependiendo de sus necesidades.

    Para formularios regulares (codificados en URL, con un M脥MICA tipo de application/x-www-form-urlencoded), es mejor que uses el .post() m茅todo de conveniencia con el objeto de formulario:

    let options = {
        url: 'http://http://mockbin.com/request',
        form: {
            email: '[email聽protected]',
            password: 'myPassword'
        }
    };
    
    request.post(options, callback);
    

    Esto cargar谩 datos como lo har铆a un formulario HTML, con la 煤nica limitaci贸n de que no puede cargar archivos de esta manera. Para hacer eso, necesita usar el formData en su lugar, que utiliza la formulario-datos biblioteca debajo.

    Utilizando formData en su lugar, ahora podemos pasar datos de archivo al servidor a trav茅s de Buffers, Streams, o incluso datos que no son de archivo (como antes) con pares clave-valor simples.

    let formData = {
        // Pass single file with a key
        profile_pic: fs.createReadStream(__dirname + '/me.jpg'),
    
        // Pass multiple files in an array
        attachments: [
            fs.readFileSync(__dirname + '/cover-letter.docx'),  // Buffer
            fs.createReadStream(__dirname + '/resume.docx'),    // Stream
        ],
    
        // Pass extra meta-data with your files
        detailed_file: {
            value: fs.createReadStream(__dirname + '/my-special-file.txt'),
            options: {
                filename: 'data.json',
                contentType: 'application/json'
            }
        },
    
        // Simple key-value pairs
        username: 'ScottWRobinson'
    };
    
    request.post('http://http://mockbin.com/request', {formData: formData}, callback);
    

    Esto enviar谩 sus archivos con un tipo MIME de multipart/form-data, que es una carga de formulario de varias partes.

    Si bien esto ser谩 m谩s que suficiente para la mayor铆a de los casos de uso de los usuarios, hay ocasiones en las que necesita un control a煤n m谩s detallado, como CLRF (nuevas l铆neas) pre / post, fragmentaci贸n o especificar sus propias partes m煤ltiples. Para obtener m谩s informaci贸n sobre estas opciones adicionales, consulte esta secci贸n del request L脡AME.

    Corrientes

    Una de las caracter铆sticas m谩s infrautilizadas en muchos lenguajes de programaci贸n, en mi opini贸n, son las transmisiones. Su utilidad se extiende m谩s all谩 de las solicitudes de red, pero esto sirve como un ejemplo perfecto de por qu茅 deber铆a usarlas. Para obtener una breve descripci贸n sobre c贸mo y por qu茅 deber铆a usarlos, consulte la secci贸n “Flujos” del art铆culo Servidores HTTP de node para el servicio de archivos est谩ticos.

    En resumen, el uso de transmisiones para grandes cantidades de datos (como archivos) puede ayudar a reducir la huella de memoria de su aplicaci贸n y el tiempo de respuesta. Para hacer esto m谩s f谩cil de usar, cada uno de los request los m茅todos pueden pipe su salida a otra corriente.

    En este ejemplo, descargamos el logotipo de Node.js mediante una solicitud GET y lo transmitimos a un archivo local:

    let fileStream = fs.createWriteStream('node.png');
    request('https://nodejs.org/static/images/logos/nodejs-new-white-pantone.png').pipe(fileStream);
    

    Tan pronto como la solicitud HTTP comience a devolver partes de la imagen descargada, “canalizar谩” esos datos directamente al archivo “node.png”.

    Descargar un archivo de esta manera tambi茅n tiene otros beneficios. Las transmisiones son excelentes para aplicar transformaciones en los datos a medida que se descargan. Por ejemplo, digamos que est谩 descargando una gran cantidad de datos confidenciales con request que debe cifrarse de inmediato. Para hacer esto, puede aplicar una transformaci贸n de cifrado canalizando la salida de request a crypto.createCipher:

    let url="http://example.com/super-sensitive-data.json";
    let pwd = new Buffer('myPassword');
    
    let aesTransform = crypto.createCipher('aes-256-cbc', pwd);
    let fileStream = fs.createWriteStream('encrypted.json');
    
    request(url)
        .pipe(aesTransform)     // Encrypts with aes256
        .pipe(fileStream)       // Write encrypted data to a file
        .on('finish', function() {
            console.log('Done downloading, encrypting, and saving!');
        });
    

    Es f谩cil pasar por alto las transmisiones, y muchas personas lo hacen cuando escriben c贸digo, pero pueden ayudar bastante a tu rendimiento, especialmente con una biblioteca como request.

    Misc. Configuraciones

    Las solicitudes HTTP implican mucho m谩s que simplemente especificar una URL y descargar los datos. Para aplicaciones m谩s grandes, y especialmente aquellas que deben admitir una gama m谩s amplia de entornos, es posible que sus solicitudes deban manejar bastantes par谩metros de configuraci贸n, como proxies o certificados de confianza SSL especiales.

    Un miscel谩neo importante. caracter铆stica a se帽alar es la request.defaults() , que le permite especificar par谩metros predeterminados para que no tenga que proporcionarlos para cada solicitud que realice.

    let req = request.defaults({
        headers: {
            'x-access-token': '123abc',
            'User-Agent': 'my-reddit-client'
        }
    });
    
    req('http://your-api.com', function(err, res, body) {
        console.log(body);
    });
    

    Ahora, en el ejemplo anterior, todas las solicitudes realizadas con req siempre tendr谩 los encabezados x-access-token y User-Agent conjunto. Esto es ideal para configurar encabezados como estos, servidores proxy o configuraciones TLS / SSL.

    A lo largo del resto de esta secci贸n, veremos algunas caracter铆sticas m谩s comunes que encontrar谩:

    Proxies

    Ya sea que su computadora est茅 detr谩s de un proxy corporativo o desee redirigir su tr谩fico a otro pa铆s, en alg煤n momento es posible que deba especificar una direcci贸n de proxy. La forma m谩s sencilla de lograrlo es utilizar el proxy opci贸n, que toma una direcci贸n en la que el tr谩fico se transfiere a trav茅s de:

    let options = {
        url: 'https://www.google.com',
        proxy: 'http://myproxy.com'
    };
    
    request(options, callback);
    

    los options object es una forma de especificar un proxy, pero request tambi茅n utiliza las siguientes variables de entorno para configurar una conexi贸n proxy:

    • HTTP_PROXY / http_proxy
    • HTTPS_PROXY / https_proxy
    • NO_PROXY / no_proxy

    Esto le brinda un poco m谩s de control, como configurar qu茅 sitios no deben ser proxiados a trav茅s del NO_PROXY variable.

    TLS / SSL

    A veces, una API necesita tener algo de seguridad adicional y, por lo tanto, requiere un certificado de cliente. En realidad, esto es bastante com煤n con las API corporativas privadas, por lo que vale la pena saber c贸mo hacerlo.

    Otro escenario posible es que desee que sus solicitudes HTTP conf铆en expl铆citamente en ciertos autoridades de certificaci贸n, que podr铆a incluir certificados autofirmados por usted o su empresa.

    Al igual que con todas las otras configuraciones que hemos visto hasta ahora, estas se establecen en el options objeto:

    const fs = require('fs');
    const request = require('request');
    
    let myCertFile = fs.readFileSync(__dirname + '/ssl/client.crt')
    let myKeyFile = fs.readFileSync(__dirname + '/ssl/client.key')
    let myCaFile = fs.readFileSync(__dirname + '/ssl/ca.cert.pem')
     
    var options = {
        url: 'https://mockbin.com/request',
        cert: myCertFile,
        key: myKeyFile,
        passphrase: 'myPassword',
        ca: myCaFile
    };
     
    request.get(options);
    
    Autenticaci贸n b谩sica

    Sitios que utilizan autenticaci贸n de acceso b谩sico todav铆a se puede acceder utilizando el auth opci贸n:

    const request = require('request');
     
    var options = {
        url: 'https://mockbin.com/request',
        auth: {
            username: 'ScottWRobinson',
            password: 'myPassword'
        }
    };
     
    request.get(options);
    

    Esta opci贸n establece uno de los encabezados HTTP como "authorization": "Basic c2NvdHQ6cGFzc3dvcmQh". La cadena ‘B谩sica’ en el encabezado ‘autorizaci贸n’ declara que se trata de una solicitud de autenticaci贸n b谩sica y la cadena alfanum茅rica que sigue es una codificaci贸n RFC2045-MIME (una variante de Base64) de nuestro nombre de usuario y contrase帽a.

    Redireccionamientos

    Descubr铆 que en algunas aplicaciones, como el raspado web, hay bastantes casos en los que es necesario seguir las redirecciones para que su solicitud sea exitosa. Como probablemente adivin贸, hay una opci贸n para especificar si se deben seguir las redirecciones de forma predeterminada, pero request va incluso un paso m谩s all谩 y le permitir谩 proporcionar una funci贸n que se puede utilizar para determinar condicionalmente si se debe seguir la redirecci贸n.

    Algunas de las opciones de redireccionamiento son:

    • followRedirect: Si true, luego siga todas las redirecciones HTTP 3xx. O env铆e un function(res) {} que se utiliza para determinar si se debe seguir o no el redireccionamiento
    • followAllRedirects: Siga todos los redireccionamientos HTTP 3xx que no sean GET
    • maxRedirects: El n煤mero m谩ximo de veces que se deben seguir los redireccionamientos encadenados (el valor predeterminado es 10)

    Conclusi贸n

    Sin duda request es un m贸dulo poderoso y probablemente uno que usar谩 con frecuencia. Dadas todas las caracter铆sticas que proporciona, puede actuar como un excelente punto de partida para cualquier cosa, desde un rastreador web hasta una biblioteca cliente para su API.

    Hay bastantes opciones y configuraciones m谩s que se pueden utilizar con request de lo que hemos mostrado aqu铆, as铆 que aseg煤rese de revisar el documentaci贸n para m谩s detalles. Tenga en cuenta que no todo en el m贸dulo est谩 documentado, por lo que es posible que deba hacer m谩s b煤squedas / experimentos para encontrar la respuesta.

    Has usado request en alguno de tus proyectos? 驴Si es as铆, c贸mo?

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *