2015-05-16 18 views
6

Sto tentando di caricare un'immagine su S3 ma quando chiamo s3.putObject (params, callback), la mia callback non viene mai chiamata e non vengono registrati errori.S3.putObject - la richiamata non viene mai chiamata

Ecco il codice rilevante:

var params = { 
    Key: key, 
    Body: imageData, 
    ContentLength: imageData.byteCount, 
    ContentType: contentType, 
}; 
this.s3.putObject(params, function(err, data) { 
    console.log('here'); 
    if (err) { 
    callback(err); 
    return; 
    } 
    callback(null, key); 
}); 

Dove params è { Key: 'e2f99bf3a321282cc7dfaef69fe8ca62.jpg', Body: {imageData parsed from request using node-multiparty}, ContentLength: 27802, ContentType: 'image/jpeg', }

Ho verificato che this.s3 sia valido e typeof this.s3.putObject è la funzione come previsto.

+0

È possibile ottenere alcune informazioni installando e richiedendo il modulo 'nock' da npm che stamperà esattamente quale URL viene richiesto. Se il programma si blocca in attesa della richiamata, forse un firewall sta ignorando il tentativo di connessione TCP. Hai lasciato il programma bloccato per diversi minuti per vedere se alla fine si verifica il timeout e viene richiamata la richiamata? –

+0

Il programma termina l'esecuzione prima che l'evento asincrono possa restituire un valore? Guarda un argomento simile con AWS Lambda: https://stackoverflow.com/questions/28449363/why-is-this-http-request-not-working-on-aws-lambda –

risposta

3

Se si utilizza questo codice per una funzione lambda è necessario aggiungere context.done() all'interno funzione di callback del putObject in questo modo:

 s3.putObject(params, function(err, data) { 
      if (err) console.log(err, err.stack); // an error occurred 
      else  console.log(data);   // successful response 
      context.done(); 
     }); 

Questo costringe l'esecuzione di aspettare fino a quando il callback viene riempita prima esce. Affinché questo funzioni, è necessario rimuovere qualsiasi context.succeed o context.done dal gestore principale se ne hai uno lì.

+0

Che cos'è il "contesto" in questo ... um ... contesto? Non è dichiarato da nessuna parte nel codice o nella domanda originale. –

+0

Ah, buon punto @boutell. Ho assunto che questa domanda si riferiva all'uso di AWS Lambda, anche se non lo dice esplicitamente. Modificherò la mia risposta per riflettere questo. Il contesto è un oggetto specifico Lambda. Se si utilizza Lambda, è necessaria una chiamata a un metodo di finitura del contesto (completato, riuscito, non riuscito) all'interno della funzione di callback per consentirne il completamento. Se questo non è il codice Lambda, il programma in uso termina prima del completamento della richiamata. – Charles

+0

Grazie per il chiarimento! Potresti voler scrivere "AWS Lambda" semplicemente perché le funzioni lambda hanno un significato più generale. –

0

Ho ottenuto esattamente lo stesso comportamento con tutti i diritti IAM e ho perso un po 'di tempo prima che riuscissi a farlo funzionare.

Se la funzione lambda viene eseguita all'interno di un VPC, è necessario creare un endpoint per S3 come descritto in this article from AWS blog.

Se si desidera visualizzare più in dettaglio dove si blocca, è possibile utilizzare il seguente codice. Invece di dare una richiamata, mantieni il riferimento sulla richiesta e osserva fondamentalmente i suoi eventi (vedi la documentazione di S3.putObject e AWS.Request).

var obj = s3.putObject(params); 
obj.on('validate',    (...args)=>{args.unshift('validate');    console.log(...args);}) 
    .on('build',    (...args)=>{args.unshift('build');    console.log(...args);}) 
    .on('sign',     (...args)=>{args.unshift('sign');     console.log(...args);}) 
    .on('send',     (...args)=>{args.unshift('send');     console.log(...args);}) 
    .on('retry',    (...args)=>{args.unshift('retry');    console.log(...args);}) 
    .on('extractError',   (...args)=>{args.unshift('extractError');   console.log(...args);}) 
    .on('extractData',   (...args)=>{args.unshift('extractData');   console.log(...args);}) 
    .on('success',    (...args)=>{args.unshift('success');    console.log(...args);}) 
    .on('error',    (...args)=>{args.unshift('error');    console.log(...args);}) 
    .on('complete',    (...args)=>{args.unshift('complete');    console.log(...args);}) 
    .on('httpHeaders',   (...args)=>{args.unshift('httpHeaders');   console.log(...args);}) 
    .on('httpData',    (...args)=>{args.unshift('httpData');    console.log(...args);}) 
    .on('httpUploadProgress', (...args)=>{args.unshift('httpUploadProgress'); console.log(...args);}) 
    .on('httpDownloadProgress', (...args)=>{args.unshift('httpDownloadProgress'); console.log(...args);}) 
    .on('httpError',   (...args)=>{args.unshift('httpError');   console.log(...args);}) 
    .on('httpDone',    (...args)=>{args.unshift('httpDone');    console.log(...args);}) 
    .send(); 

Facendo così ho avuto modo di vedere la richiesta HTTP sottostante stava cercando di raggiungere gli URL pubblici del secchio, che non è possibile da un VPC se non si ha l'endpoint :).

Ecco anche un altro post sull'accesso di risorse AWS da un VPC anche da AWS blog.

Problemi correlati