Saya memulai dengan AWS Lambda dan saya mencoba meminta layanan eksternal dari fungsi penangan saya. Menurut jawaban ini , permintaan HTTP seharusnya berfungsi dengan baik, dan saya belum menemukan dokumentasi yang mengatakan sebaliknya. (Faktanya, orang telah memposting kode yang menggunakan Twilio API untuk mengirim SMS .)
Kode penangan saya adalah:
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);
}
dan saya melihat 4 baris berikut di log CloudWatch saya:
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
Saya mengharapkan baris lain di sana:
2015-02-11 07:38:06 UTC eb19c89d-b1c0-11e4-bceb-d310b88d37e2 Got response: 302
tapi itu hilang. Jika saya menggunakan bagian penting tanpa pembungkus penangan di node di mesin lokal saya, kode berfungsi seperti yang diharapkan.
Yang inputfile.txt
saya gunakan untuk invoke-async
panggilan adalah ini:
{
"url":"http://www.google.com"
}
Sepertinya bagian dari kode penangan yang melakukan permintaan dilewati seluruhnya. Saya mulai dengan permintaan lib dan kembali menggunakan plainhttp
untuk membuat contoh minimal. Saya juga mencoba meminta URL dari layanan yang saya kontrol untuk memeriksa log dan tidak ada permintaan yang masuk.
Saya benar-benar bingung. Apakah ada alasan Node dan / atau AWS Lambda tidak akan menjalankan permintaan HTTP?
Jawaban:
Tentu saja, saya salah memahami masalahnya. Seperti yang dikatakan oleh AWS sendiri :
Saya menelepon
context.done
jauh sebelum panggilan balik untuk permintaan tersebut diaktifkan, menyebabkan penghentian fungsi saya sebelumnya.Kode kerjanya adalah ini:
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); }
Pembaruan: mulai 2017 AWS tidak lagi menggunakan Nodejs 0.10 lama dan hanya run-time 4.3 yang lebih baru yang sekarang tersedia (fungsi lama harus diperbarui). Runtime ini memperkenalkan beberapa perubahan pada fungsi handler. Penangan baru sekarang memiliki 3 parameter.
function(event, context, callback)
Meskipun Anda masih akan menemukan
succeed
,done
danfail
pada parameter konteks, AWS menyarankan untuk menggunakancallback
fungsi sebagai gantinya ataunull
dikembalikan secara default.callback(new Error('failure')) // to return error callback(null, 'success msg') // to return ok
Dokumentasi lengkap dapat ditemukan di http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
sumber
context.done()
Panggilan perlu pindah ke callback (untuk sukses dan kasus error).Contoh Kerja Sederhana dari permintaan Http menggunakan node.
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(); }); }
sumber
node-fetch
request
dll tidak tersedia di Lambda secara default.Ya, jawaban awendt sempurna. Saya hanya akan menunjukkan kode kerja saya ... Saya memiliki konteks. Berhasil ('Blah'); baris tepat setelah reqPost.end (); garis. Memindahkannya ke tempat saya tunjukkan di bawah menyelesaikan segalanya.
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(); };
sumber
Saya menghadapi masalah ini pada versi Node 10.X. di bawah ini adalah kode kerja saya.
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(); };
sumber
Saya memiliki masalah yang sama dan kemudian saya menyadari bahwa pemrograman di NodeJS sebenarnya berbeda dari Python atau Java karena berbasis JavaScript. Saya akan mencoba menggunakan konsep sederhana karena mungkin ada beberapa orang baru yang tertarik atau mungkin datang ke pertanyaan ini.
Mari kita lihat kode berikut:
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) }
Setiap kali Anda melakukan panggilan ke metode dalam paket http (1), itu dibuat sebagai acara dan acara ini membuatnya menjadi acara terpisah. Fungsi 'get' (2) sebenarnya adalah titik awal dari acara terpisah ini.
Sekarang, fungsi di (3) akan dijalankan dalam acara terpisah, dan kode Anda akan melanjutkan jalur eksekusi dan akan langsung melompat ke (4) dan menyelesaikannya, karena tidak ada lagi yang harus dilakukan.
Tetapi peristiwa yang dilakukan pada (2) masih berjalan di suatu tempat dan akan membutuhkan waktu yang menyenangkan untuk menyelesaikannya. Cukup aneh, bukan?. Ya, tidak. Ini adalah cara kerja NodeJS dan sangat penting bagi Anda untuk memahami konsep ini. Ini adalah tempat di mana Janji JavaScript datang untuk membantu.
Anda dapat membaca lebih lanjut tentang Janji JavaScript di sini . Singkatnya, Anda memerlukan JavaScript Promise untuk menjaga eksekusi kode sebaris dan tidak akan menelurkan utas baru / ekstra.
Sebagian besar paket NodeJS yang umum memiliki versi Promised dari API mereka, tetapi ada pendekatan lain seperti BlueBirdJS yang mengatasi masalah serupa.
Kode yang telah Anda tulis di atas dapat ditulis ulang secara longgar sebagai berikut.
'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); };
Harap diperhatikan bahwa kode di atas tidak akan berfungsi secara langsung jika Anda akan mengimpornya di AWS Lambda. Untuk Lambda, Anda juga perlu mengemas modul dengan basis kode.
sumber
context.done()
panggilan kefinally
metode dirantai .Saya telah menemukan banyak postingan di web tentang berbagai cara untuk melakukan permintaan, tetapi tidak ada yang benar-benar menunjukkan cara memproses respons secara sinkron di AWS Lambda.
Berikut adalah fungsi lambda Node 6.10.3 yang menggunakan permintaan https, mengumpulkan dan mengembalikan seluruh respons, dan meneruskan kontrol ke fungsi yang tidak terdaftar
processBody
dengan hasilnya. Saya yakin http dan https dapat dipertukarkan dalam kode ini.Saya menggunakan modul utilitas async , yang lebih mudah dipahami oleh pemula. Anda harus memasukkannya ke AWS Stack untuk menggunakannya (saya merekomendasikan kerangka kerja tanpa server ).
Perhatikan bahwa data kembali dalam potongan, yang dikumpulkan dalam variabel global, dan terakhir callback dipanggil saat data telah
end
diubah.'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); }); } };
sumber
Tambahkan kode di atas di gateway API di bagian GET-Integration Request> bagian pemetaan.
sumber
Ya, sebenarnya ada banyak alasan mengapa Anda dapat mengakses suka AWS Lambda dan HTTP Endpoint.
Arsitektur AWS Lambda
Ini adalah layanan mikro. Berjalan di dalam EC2 dengan AMI Amazon Linux (Versi 3.14.26–24.46.amzn1.x86_64) dan berjalan dengan Node.js. Memori dapat berukuran 128mb dan 1gb. Saat sumber data memicu peristiwa, detailnya diteruskan ke fungsi Lambda sebagai parameternya.
Apa yang terjadi?
AWS Lambda dijalankan di dalam wadah, dan kodenya langsung diunggah ke wadah ini dengan paket atau modul. Misalnya, kami TIDAK PERNAH dapat melakukan SSH untuk mesin linux yang menjalankan fungsi lambda Anda. Satu-satunya hal yang dapat kami pantau adalah log, dengan CloudWatchLogs dan pengecualian yang berasal dari runtime.
AWS menangani peluncuran dan menghentikan kontainer untuk kami, dan cukup menjalankan kodenya. Jadi, meskipun Anda menggunakan require ('http'), ini tidak akan berfungsi, karena tempat kode ini dijalankan, tidak dibuat untuk ini.
sumber