Porque é que este pedido HTTP não está a funcionar na AWS Lambda?

Estou a começar com a AWS Lambda e estou a tentar pedir um serviço externo à minha função de contacto. De acordo com esta resposta, Os pedidos HTTP devem funcionar muito bem, e não encontrei nenhuma documentação que diga o contrário. (Na verdade, as pessoas postaram o código que usa o Twilio API para enviar o SMS .)

o meu código de contacto é:

var http = require('http');

exports.handler = function(event, context) {
  console.log('start request to ' + event.url)
  http.get(event.url, function(res) {
    console.log("Got response: " + res.statusCode);
  }).on('error', function(e) {
    console.log("Got error: " + e.message);
  });

  console.log('end request to ' + event.url)
  context.done(null);
}
E vejo as seguintes 4 linhas nos meus registos de CloudWatch:
2015-02-11 07:38:06 UTC START RequestId: eb19c89d-b1c0-11e4-bceb-d310b88d37e2
2015-02-11 07:38:06 UTC eb19c89d-b1c0-11e4-bceb-d310b88d37e2 start request to http://www.google.com
2015-02-11 07:38:06 UTC eb19c89d-b1c0-11e4-bceb-d310b88d37e2 end request to http://www.google.com
2015-02-11 07:38:06 UTC END RequestId: eb19c89d-b1c0-11e4-bceb-d310b88d37e2
Eu esperaria outro. fila ali dentro:
2015-02-11 07:38:06 UTC eb19c89d-b1c0-11e4-bceb-d310b88d37e2 Got response: 302
Mas isso desapareceu. Se estou a usar a parte essencial sem o invólucro do controlador no nó da minha máquina local, o código funciona como esperado.

o inputfile.txt que estou a usar é para a chamada invoke-async é esta:

{
   "url":"http://www.google.com"
}
Parece que a parte do código que faz o pedido é ignorada por completo. Comecei com o pedido lib e voltei a usar o plain http para criar um exemplo mínimo. Eu também tentei solicitar um URL de um serviço que eu controlo para verificar os registos e não há pedidos a chegar.

Estou completamente perplexo. existe alguma razão para o Node e / ou o AWS Lambda não executar o pedido HTTP?

Author: Community, 2015-02-11

8 answers

É claro que me enganei no problema. como a própria AWS o disse.:
([11]} Para aqueles que encontram nodejs pela primeira vez em Lambda, um comum erro é esquecer que os callbacks executam assíncronamente e chamando context.done() no manipulador original quando realmente querias esperar para outro callback (como um S3.Operação de colocação) para completar, forçando a função de terminar com seu trabalho incompleto.

Eu estava chamando context.done Caminho antes de qualquer chamada para o pedido ser disparada, causando a interrupção da minha função antes do tempo.

O código de trabalho é este:

var http = require('http');

exports.handler = function(event, context) {
  console.log('start request to ' + event.url)
  http.get(event.url, function(res) {
    console.log("Got response: " + res.statusCode);
    context.succeed();
  }).on('error', function(e) {
    console.log("Got error: " + e.message);
    context.done(null, 'FAILURE');
  });

  console.log('end request to ' + event.url);
}

Update: starting 2017 AWS has depreciated the old Nodejs 0.10 and only the newer 4.3 run-time is now available (old functions should be updated). Este tempo de execução introduziu algumas alterações na função de handler. O novo manipulador tem agora 3 parâmetros.

function(event, context, callback)

Embora ainda encontres o succeed, done e fail na parâmetro de contexto, AWS sugere usar a função callback em vez disso ou null é devolvido por padrão.

callback(new Error('failure')) // to return error
callback(null, 'success msg') // to return ok

A documentação Completa pode ser encontrada em http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html

 81
Author: awendt, 2017-01-31 20:30:08

Exemplo simples de trabalho do pedido Http usando o nó.

const http = require('https')
exports.handler = async (event) => {
    return httprequest().then((data) => {
        const response = {
            statusCode: 200,
            body: JSON.stringify(data),
        };
    return response;
    });
};
function httprequest() {
     return new Promise((resolve, reject) => {
        const options = {
            host: 'jsonplaceholder.typicode.com',
            path: '/todos',
            port: 443,
            method: 'GET'
        };
        const req = http.request(options, (res) => {
          if (res.statusCode < 200 || res.statusCode >= 300) {
                return reject(new Error('statusCode=' + res.statusCode));
            }
            var body = [];
            res.on('data', function(chunk) {
                body.push(chunk);
            });
            res.on('end', function() {
                try {
                    body = JSON.parse(Buffer.concat(body).toString());
                } catch(e) {
                    reject(e);
                }
                resolve(body);
            });
        });
        req.on('error', (e) => {
          reject(e.message);
        });
        // send the request
       req.end();
    });
}
 24
Author: smsivaprakaash, 2019-06-12 15:48:46
Sim, a resposta acordada é perfeita. Vou mostrar o meu código de trabalho... Eu tinha o contexto.succeed ('Blah'); line right after the reqPost.end (); line. Mudá-lo para onde eu mostrar abaixo resolveu tudo.
console.log('GW1');

var https = require('https');

exports.handler = function(event, context) {

    var body='';
    var jsonObject = JSON.stringify(event);

    // the post options
    var optionspost = {
        host: 'the_host',
        path: '/the_path',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    };

    var reqPost = https.request(optionspost, function(res) {
        console.log("statusCode: ", res.statusCode);
        res.on('data', function (chunk) {
            body += chunk;
        });
        context.succeed('Blah');
    });

    reqPost.write(jsonObject);
    reqPost.end();
};
 11
Author: imTachu, 2016-05-17 00:25:20

Enfrentei este problema no nó 10.X version. abaixo está o meu código de trabalho.

const https = require('https');

exports.handler = (event,context,callback) => {
    let body='';
    let jsonObject = JSON.stringify(event);

    // the post options
    var optionspost = {
      host: 'example.com', 
      path: '/api/mypath',
      method: 'POST',
      headers: {
      'Content-Type': 'application/json',
      'Authorization': 'blah blah',
    }
    };

    let reqPost =  https.request(optionspost, function(res) {
        console.log("statusCode: ", res.statusCode);
        res.on('data', function (chunk) {
            body += chunk;
        });
        res.on('end', function () {
           console.log("Result", body.toString());
           context.succeed("Sucess")
        });
        res.on('error', function () {
          console.log("Result Error", body.toString());
          context.done(null, 'FAILURE');
        });
    });
    reqPost.write(jsonObject);
    reqPost.end();
};
 5
Author: Ameya Salagre, 2019-11-08 07:15:30

Eu tive o mesmo problema e então eu percebi que a programação em NodeJS é realmente diferente de Python ou Java como seu baseado em JavaScript. Vou tentar usar conceitos simples como pode haver algumas pessoas novas que estariam interessadas ou podem vir a esta questão.

Vamos ver o seguinte código:
var http = require('http'); // (1)
exports.handler = function(event, context) {
  console.log('start request to ' + event.url)
  http.get(event.url,  // (2)
  function(res) {  //(3)
    console.log("Got response: " + res.statusCode);
    context.succeed();
  }).on('error', function(e) {
    console.log("Got error: " + e.message);
    context.done(null, 'FAILURE');
  });

  console.log('end request to ' + event.url); //(4)
}

Sempre que você faz uma chamada para um método em http package (1) , ele é criado como evento e este evento recebe-o evento separado. A função' get '(2) é realmente o ponto de partida deste evento separado.

Agora, a função at (3) estará executando em um evento separado, e seu código vai continuar executando caminho e vai diretamente Saltar para (4) e terminá-lo, porque não há mais nada a fazer.

[[3]} mas o evento disparado em (2) ainda está em execução em algum lugar e vai levar seu próprio tempo doce para terminar. Muito bizarro, certo ?. Não, Não é. É assim que o NodeJS funciona e é muito importante que envolvas a tua cabeça nisto. conceito. Este é o lugar onde JavaScript promete vir para ajudar.

Você pode ler mais sobre as promessas de JavaScript aqui. Em poucas palavras, você precisa de uma promessa JavaScript para manter a execução de código inline e não vai desovar novos / threads extra.

A maioria dos pacotes NodeJS comuns têm uma versão prometida de sua API disponível, mas existem outras abordagens como BlueBirdJS que abordam o problema similar.

O código que você tinha escrito acima pode ser vagamente reescrito como segue.

'use strict';
console.log('Loading function');
var rp = require('request-promise');
exports.handler = (event, context, callback) => {    

    var options = {
    uri: 'https://httpbin.org/ip',
    method: 'POST',
    body: {

    },
    json: true 
};


    rp(options).then(function (parsedBody) {
            console.log(parsedBody);
        })
        .catch(function (err) {
            // POST failed... 
            console.log(err);
        });

    context.done(null);
};

por favor, note que o código acima não vai funcionar diretamente se você vai importá-lo na AWS Lambda. Para Lambda, você vai precisar empacotar os módulos com a base de código também.

 3
Author: mmansoor, 2016-05-03 14:02:36

Eu encontrei muitos posts em toda a web sobre as várias maneiras de fazer o pedido, mas nenhum que realmente mostram como processar a resposta sincronicamente na AWS Lambda.

Aqui está uma função lambda Node 6.10.3 que usa um pedido https, recolhe e devolve o corpo inteiro da resposta, e passa o controle para uma função não listada processBody com os resultados. Acredito que http e https são permutáveis neste código.

Estou a usar o módulo de utilidadesasync , que é é mais fácil de entender para novatos. Você vai precisar empurrar isso para a sua pilha AWS para usá-lo (eu recomendo o framework ([11]}sem servidor ).

Note que os dados voltam em pedaços, que são recolhidos em uma variável global, e finalmente o callback é chamado quando os dados têm end ed.

'use strict';

const async = require('async');
const https = require('https');

module.exports.handler = function (event, context, callback) {

    let body = "";
    let countChunks = 0;

    async.waterfall([
        requestDataFromFeed,
        // processBody,
    ], (err, result) => {
        if (err) {
            console.log(err);
            callback(err);
        }
        else {
            const message = "Success";
            console.log(result.body);
            callback(null, message);
        }
    });

    function requestDataFromFeed(callback) {
        const url = 'https://put-your-feed-here.com';
        console.log(`Sending GET request to ${url}`);
        https.get(url, (response) => {
            console.log('statusCode:', response.statusCode);
            response.on('data', (chunk) => {
                countChunks++;
                body += chunk;
            });
            response.on('end', () => {
                const result = {
                    countChunks: countChunks,
                    body: body
                };
                callback(null, result);
            });
        }).on('error', (err) => {
            console.log(err);
            callback(err);
        });
    }
};
 3
Author: Zodman, 2018-03-21 04:44:51

enter image description here

Adicionar o código acima na 'gateway' da API sob pedido de integração> secção de mapeamento.

 0
Author: Sher Singh, 2020-10-19 11:25:27
Sim, há muitas razões para aceder à AWS Lambda e ao endpoint HTTP.

A arquitectura da AWS Lambda

É um micro-serviço. Rodando dentro do EC2 com Amazon Linux AMI (versão 3.14.26-24.46.amzn1.x86_64) e corre com o nó.js. A memória pode ser beetwen 128mb e 1gb. Quando a fonte de dados despoleta o evento, os detalhes são passados a uma função Lambda como parâmetros. O que aconteceu? A "AWS Lambda run" está dentro de um recipiente, e a o código é enviado diretamente para este container com pacotes ou módulos. Por exemplo, nós nunca podemos fazer SSH para a máquina linux executando sua função lambda. As únicas coisas que podemos monitorar são os registros, com CloudWatchLogs e a exceção que veio do tempo de execução. A AWS trata do lançamento e elimina os contentores por nós, e apenas executa o código. Então, mesmo que você use require ('http'), não vai funcionar, porque o lugar onde este código é executado, não foi feito para isso.
 -15
Author: jonathanbaraldi, 2015-02-18 03:42:37