2
votes

s3.getObject (). promise () ne renvoie jamais rien

Si vous utilisez ce code dans un Lambda qui est conforme à tout ce que j'ai lu sur stackoverflow et sur la documentation du kit AWS SDK.

Cependant, il ne renvoie rien ni ne génère d'erreur. Le code est simplement bloqué sur s3.getObject (params) .promise () afin que la fonction lambda s'exécute avec un délai d'expiration, même après plus de 30 secondes. Le fichier que j'essaie de récupérer est en fait de 25 Ko.

Une idée de pourquoi cela se produit?

var AWS = require('aws-sdk');
var s3 = new AWS.S3({httpOptions: {timeout: 3000}});    

async function getObject(bucket, objectKey) {
        try {
            const params = {
                Bucket: bucket,
                Key: objectKey
            }
            console.log("Trying to fetch " + objectKey + " from bucket " + bucket)
            const data = await s3.getObject(params).promise()
            console.log("Done loading image from S3")
            return data.Body.toString('utf-8')
        } catch (e) {
            console.log("error loading from S3")
            throw new Error(`Could not retrieve file from S3: ${e.message}`)
        }
    }

Lors du test de la fonction, je reçois le délai d'expiration suivant.

START RequestId: 97782eac-019b-4d46-9e1e-3dc36ad87124 Version: $ LATEST 2019-03-19T07: 51: 30.225Z 97782eac-019b-4d46-9e1e-3dc36ad87124 Essayer de récupérer public-images / low / ZARGES_41137_PROD_TECH_ST_LI.jpg à partir du bucket zarges-pimdata-test 2019-03-19T07: 51: 54.979Z 97782eac-019b-4d46-9e1e-3dc36ad87124 Erreur de chargement à partir de S3 2019-03-19T07: 51: 54.981Z 97782eac-019b-4d46-9e1e-3dc36ad87124 {"errorMessage": "Impossible de récupérer le fichier de S3: la connexion a expiré après 3000 ms", "errorType": "Erreur", "stackTrace" : ["getObject (/var/task/index.js:430:15)","","process._tickDomainCallback (interne / process / next_tick.js: 228: 7)"]} END RequestId: 97782eac-019b-4d46-9e1e-3dc36ad87124 RAPPORT RequestId: 97782eac-019b-4d46-9e1e-3dc36ad87124 Durée: 24876.90 ms Durée facturée: 24900 ms Taille de la mémoire: 512 Mo Mémoire maximale utilisée: 120 Mo

L'image que je récupère est en fait accessible au public: https: // s3. eu-central-1.amazonaws.com/zarges-pimdata-test/public-images/low/ZARGES_41137_PROD_TECH_ST_LI.jpg


1 commentaires

J'ai mis à jour le code ci-dessus. J'ai fait une erreur de copier / coller en rendant le code plus lisible pour stackoverflow. Le code ci-dessus se comporte exactement comme décrit.


5 Réponses :


2
votes

Ce problème est certainement lié à la connexion.

Vérifiez vos paramètres VPC car ils bloquent probablement la connexion Lambda à Internet (les services gérés par AWS comme S3 ne sont accessibles que via Internet).


5 commentaires

En fait, le code était comme vous l'avez suggéré. J'ai fait une erreur de copier / coller en rendant le code plus lisible pour stackoverflow. Ma faute - désolé. Cependant, le code suggéré par vous ne renvoie rien non plus. Je l'ai corrigé dans la description ci-dessus.


Le code est correct. Le problème est probablement ailleurs. Peut-être en relation. Votre Lambda est-il à l'intérieur d'un VPN? Obtenez-vous ce comportement uniquement pour S3? Pouvez-vous faire un simple appel HTTP?


Pas de VPN, mais un groupe de sécurité VPC et VPC. Mais s'il s'agissait d'une connexion ou d'une autorisation, ne devrait-il pas générer une erreur ou quelque chose?


Cela dépend de la connexion, disons le délai d'expiration de la connexion du client pendant 5 minutes, votre lambda meurt en 3 minutes, puis vous n'obtenez aucune erreur ou réponse.


Vous avez raison. Je n'avais pas cela en tête. J'ai changé mon code pour utiliser un timeout de 3000ms. Comme décrit ici Je n'ai toujours pas reçu de délai d'expiration à cause des tentatives. J'avais besoin d'étendre le délai d'expiration lamda à environ une minute pour recevoir le délai d'expiration S3 réel.



9
votes

Si vous ne voulez pas l'extraire dans une variable avant d'accéder au corps comme @tuulka l'a suggéré, mettez-le simplement entre parenthèses.

const data = (await (s3.getObject(params).promise())).Body.toString('utf-8')


0 commentaires

1
votes

Le délai d'expiration par défaut du kit AWS SDK est de 1 20000 ms. Si le délai d'expiration de votre lambda est plus court, vous ne recevrez jamais l'erreur réelle.

Prolongez votre délai d'expiration AWS

var AWS = require('aws-sdk');
var s3 = new AWS.S3({httpOptions: {timeout: 3000}});

ou prolongez le délai d'expiration de votre lambda.


0 commentaires

1
votes

Si votre fonction Lambda est associée à un VPC, elle perd l'accès à Internet nécessaire pour accéder à S3. Cependant, au lieu de suivre l'avertissement Lambda indiquant «Associer un NAT», etc., vous pouvez créer un point de terminaison S3 dans les paramètres VPC> Endpoints, et votre fonction Lambda fonctionnera comme prévu, sans avoir à configurer manuellement l'accès Internet pour votre VPC.

https://aws.amazon. com / blogs / aws / nouveau-vpc-endpoint-pour-amazon-s3 /


0 commentaires

0
votes

Si vous utilisez localstack, assurez-vous que SSL est faux et que s3ForcePathStyle est vrai.

C'était mon problème

AWS.S3({endpoint: '0.0.0.0:4572', sslEnabled: false, s3ForcePathStyle:true})

Plus de détails ici


0 commentaires