Bagaimana Express dan hapi dibandingkan satu sama lain?


133

Dari desain aplikasi web dan sudut pandang pengembangan, bagaimana Express dan Hapi dibandingkan satu sama lain? Untuk contoh dasar mereka tampak serupa, namun saya tertarik untuk mempelajari lebih lanjut tentang perbedaan utama dalam struktur aplikasi secara keseluruhan.

Sebagai contoh, sejauh yang saya pelajari, Hapi menggunakan mekanisme perutean yang berbeda yang tidak memperhitungkan pesanan registrasi, dapat melakukan pencarian lebih cepat, tetapi terbatas dibandingkan dengan Express. Apakah ada perbedaan penting lainnya?

Ada juga sebuah artikel tentang memilih Hapi (over Express) untuk mengembangkan situs web npmjs.com baru, artikel ini menyatakan bahwa "Sistem plugin Hapi berarti bahwa kita dapat mengisolasi berbagai aspek dan layanan aplikasi dengan cara yang memungkinkan untuk layanan mikro di Express, di sisi lain, memerlukan konfigurasi yang sedikit lebih banyak untuk mendapatkan fungsi yang sama ", apa artinya sebenarnya?

Jawaban:


231

Ini adalah pertanyaan besar dan membutuhkan jawaban panjang untuk lengkap, jadi saya hanya akan membahas subset dari perbedaan yang paling penting. Mohon maaf bahwa itu masih merupakan jawaban yang panjang.

Bagaimana mereka serupa?

Anda benar ketika mengatakan:

Sebagai contoh dasar, mereka tampak serupa

Kedua kerangka kerja memecahkan masalah dasar yang sama: Menyediakan API yang nyaman untuk membangun server HTTP di node. Dengan kata lain, lebih nyaman daripada menggunakan httpmodul asli level bawah saja. The httpmodul dapat melakukan segala yang kami inginkan tapi itu membosankan untuk menulis aplikasi dengan.

Untuk mencapai hal ini, mereka berdua menggunakan konsep yang telah ada dalam kerangka kerja web tingkat tinggi untuk waktu yang lama: perutean, penangan, plugin, modul otentikasi. Mereka mungkin tidak selalu memiliki nama yang sama tetapi mereka kira-kira setara.

Sebagian besar contoh dasar terlihat seperti ini:

  • Buat rute
  • Jalankan fungsi ketika rute diminta, menyiapkan respons
  • Tanggapi permintaan itu

Mengekspresikan:

app.get('/', function (req, res) {

    getSomeValue(function (obj) {

        res.json({an: 'object'});
    });
});

hapi:

server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        getSomeValue(function (obj) {

            reply(obj);
        });
    }
});

Perbedaannya bukan di sini, bukan? Jadi mengapa memilih satu dari yang lain?

Bagaimana mereka berbeda?

Jawaban sederhananya adalah hapi jauh lebih banyak dan memang lebih banyak di luar kotak. Itu mungkin tidak jelas ketika Anda hanya melihat contoh sederhana dari atas. Sebenarnya, ini disengaja. Kasing sederhana dibuat sederhana. Jadi mari kita periksa beberapa perbedaan besar:

Filsafat

Express dimaksudkan sangat minim. Dengan memberi Anda API kecil dengan hanya sedikit debu di atasnya http, Anda masih sangat mandiri dalam hal menambahkan fungsionalitas tambahan. Jika Anda ingin membaca isi permintaan yang masuk (tugas yang cukup umum), Anda perlu menginstal modul terpisah . Jika Anda mengharapkan berbagai tipe konten untuk dikirim ke rute itu, Anda juga perlu memeriksa Content-typetajuk untuk memeriksa yang mana dan menguraikannya sesuai (misalnya, formulir-data vs JSON vs multi-bagian), sering menggunakan modul terpisah .

hapi memiliki serangkaian fitur yang kaya, sering diekspos melalui opsi konfigurasi, daripada membutuhkan kode untuk ditulis. Misalnya, jika kami ingin memastikan bahwa badan permintaan (payload) sepenuhnya terbaca ke dalam memori dan diuraikan dengan tepat (secara otomatis berdasarkan pada tipe konten) sebelum pawang dijalankan, itu hanya opsi sederhana :

server.route({
    config: {
        payload: {
            output: 'data',
            parse: true
        }
    },
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        reply(request.payload);
    }
});

fitur

Anda hanya perlu membandingkan dokumentasi API pada kedua proyek untuk melihat bahwa hapi menawarkan serangkaian fitur yang lebih besar.

hapi mencakup beberapa fitur berikut yang tidak dimiliki Express (sejauh yang saya tahu):

Ekstensibilitas & modularitas

hapi dan Express melakukan ekstensibilitas dengan cara yang sangat berbeda. Dengan Express, Anda memiliki fungsi middleware . Fungsi-fungsi Middleware adalah semacam filter yang Anda susun dan semua permintaan menjalankannya sebelum mengenai handler Anda.

hapi memiliki siklus hidup permintaan dan menawarkan titik ekstensi , yang sebanding dengan fungsi middleware tetapi ada beberapa titik yang ditentukan dalam siklus hidup permintaan.

Salah satu alasan Walmart membuat hapi dan berhenti menggunakan Express adalah frustrasi dengan betapa sulitnya memecah aplikasi Express menjadi bagian-bagian yang terpisah, dan meminta anggota tim yang berbeda untuk bekerja dengan aman di chunk mereka. Untuk alasan ini mereka menciptakan sistem plugin di hapi.

Plugin seperti sub-aplikasi, Anda dapat melakukan semua yang Anda bisa dalam aplikasi hapi, menambahkan rute, ekstensi poin dll. Dalam sebuah plugin Anda dapat yakin bahwa Anda tidak melanggar bagian lain dari aplikasi, karena urutan pendaftaran untuk rute tidak masalah dan Anda tidak dapat membuat rute yang bertentangan. Anda kemudian dapat menggabungkan plugin ini ke server dan menyebarkannya.

Ekosistem

Karena Express memberi Anda begitu sedikit di luar kotak, Anda perlu melihat ke luar ketika Anda perlu menambahkan sesuatu ke proyek Anda. Sering kali ketika bekerja dengan hapi, fitur yang Anda butuhkan adalah built-in atau ada modul yang dibuat oleh tim inti.

Minimal terdengar hebat. Tetapi jika Anda membangun aplikasi produksi yang serius, kemungkinan Anda akan membutuhkan semua ini pada akhirnya.

Keamanan

hapi dirancang oleh tim di Walmart untuk menjalankan lalu lintas Black Friday sehingga keamanan dan stabilitas selalu menjadi perhatian utama. Untuk alasan ini kerangka kerja melakukan banyak hal ekstra seperti membatasi ukuran muatan masuk untuk mencegah melelahkan memori proses Anda. Ia juga memiliki opsi untuk hal-hal seperti penundaan loop acara maks, memori RSS maksimum yang digunakan dan ukuran maksimum tumpukan v8, di luar itu server Anda akan merespons dengan batas waktu 503 alih-alih hanya mogok.

Ringkasan

Evaluasilah mereka berdua sendiri. Pikirkan tentang kebutuhan Anda dan manakah di antara keduanya yang menangani masalah terbesar Anda. Berenanglah di dua komunitas (IRC, Gitter, Github), lihat yang Anda inginkan. Jangan hanya menerima kata-kata saya. Dan selamat melakukan peretasan!


PENOLAKAN: Saya bias sebagai penulis buku tentang hapi dan di atas sebagian besar adalah pendapat pribadi saya.


7
Matt, terima kasih untuk posting yang luas, bagian "ekstensibilitas & modularitas" dan "keamanan" adalah bagian yang paling membantu bagi saya. Saya kira perlu disebutkan bahwa sistem perutean baru di Express 4 memberikan peningkatan modularitas untuk sub-aplikasi.
Ali Shakiba

1
Jawaban yang bagus Matt. Kami juga bingung dengan Hapi dan Express, satu kekurangan yang kami lihat dengan Hapi adalah bahwa ia tidak memiliki dukungan komunitas seluas Express dan bisa menjadi masalah besar jika kami terjebak di suatu tempat. Perlu pendapat Anda tentang hal yang sama.
Aman Gupta

1
Ekspres adalah generik, sementara hapi sedikit lebih kuat.
windmaomao

1
@MattHarrison jawaban yang bagus, saat ini saya sedang membaca buku Anda tentang Hapi, itu bagus sekali. Saya akan mengembangkan pasar baru untuk buku yang menggunakan Hapi di backend dan vue.js di frontend, setelah terbiasa dengan Hapi, saya ingin berpartisipasi aktif dalam proyek Hapi.
Humoyun Ahmad

1
@Humoyun Hebat! Perlu diketahui juga bahwa ada versi utama hapi baru dengan beberapa perubahan besar sejak <= v16.0.0. Saat ini saya sedang memproduksi seri screencast yang dirancang untuk dipelajari orang-orang v17: youtube.com/playlist?list=PLi303AVTbxaxqjaSWPg94nccYIfqNoCHz
Matt Harrison

54

Organisasi saya pergi dengan Hapi. Inilah sebabnya kami menyukainya.

Hapi adalah:

  • Didukung oleh korps besar. Ini berarti dukungan komunitas akan kuat, dan ada untuk Anda sepanjang rilis mendatang. Sangat mudah untuk menemukan orang-orang Hapi yang penuh gairah, dan ada tutorial bagus di luar sana (meskipun tidak banyak dan luas seperti tutorial ExpressJs). Pada tanggal posting ini npm dan Walmart menggunakan Hapi.
  • Ini dapat memfasilitasi pekerjaan tim terdistribusi yang bekerja pada berbagai bagian layanan backend tanpa harus memiliki pengetahuan komprehensif tentang sisa permukaan API (arsitektur plugin Hapi adalah lambang kualitas ini).
  • Biarkan kerangka melakukan apa yang seharusnya kerangka: mengkonfigurasi hal-hal. Setelah itu, kerangka kerja harus tidak terlihat dan memungkinkan para pengembang untuk memusatkan energi kreatif mereka yang sebenarnya untuk membangun logika bisnis. Setelah menggunakan Hapi selama setahun, saya pasti merasa Hapi menyelesaikan ini. Saya merasa senang!

Jika Anda ingin mendengar langsung dari Eran Hammer (lead Hapi)

Selama empat tahun terakhir hapi tumbuh menjadi kerangka pilihan untuk banyak proyek, besar atau kecil. Apa yang membuat hapi unik adalah kemampuannya untuk meningkatkan ke penyebaran besar dan tim besar. Seiring pertumbuhan proyek, kompleksitasnya juga - kompleksitas teknik dan kompleksitas proses. Arsitektur dan filosofi hapi menangani peningkatan kompleksitas tanpa harus terus-menerus memperbaiki kode [baca selengkapnya]

Memulai dengan Hapi tidak akan semudah ExpressJs karena Hapi tidak memiliki "kekuatan bintang" yang sama ... tetapi begitu Anda merasa nyaman, Anda akan mendapatkan BANYAK jarak tempuh. Butuh waktu sekitar 2 bulan sebagai peretas baru yang secara tidak bertanggung jawab menggunakan ExpressJ selama beberapa tahun. Jika Anda seorang pengembang backend berpengalaman Anda akan tahu cara membaca dokumen, dan Anda mungkin tidak akan menyadarinya.

Area yang dapat diperbaiki oleh dokumentasi Hapi:

  1. cara mengautentikasi pengguna dan membuat sesi
  2. menangani Cross-Origin-Requests (CORS)
  3. mengunggah file (multipart, potong)

Saya pikir otentikasi akan menjadi bagian yang paling menantang karena Anda harus memutuskan strategi auth apa yang digunakan (Otentikasi Dasar, Cookie, JWT Tokens, OAuth). Meskipun secara teknis bukan masalah Hapi bahwa lanskap sesi / otentikasi begitu terfragmentasi ... tapi saya berharap mereka menyediakan beberapa pegangan untuk ini. Itu akan sangat meningkatkan kebahagiaan pengembang.

Dua yang tersisa sebenarnya tidak terlalu sulit, dokumen hanya bisa ditulis sedikit lebih baik.


3

Fakta Singkat tentang Hapi Atau Mengapa Hapi JS?

Hapi adalah konfigurasi-sentris. Ini memiliki otentikasi dan otorisasi yang dibangun ke dalam kerangka kerja. Dilepaskan dalam suasana yang telah teruji perang dan telah benar-benar membuktikan nilainya. Semua modul memiliki cakupan uji 100%. Ia mencatat abstraksi tingkat tertinggi jauh dari inti HTTP. Mudah dikompilasi. melalui arsitektur plugin

Hapi adalah pilihan kinerja yang lebih baik karena Hapi menggunakan mekanisme routing yang berbeda, yang dapat melakukan pencarian lebih cepat, dan mempertimbangkan urutan pendaftaran. Namun demikian, itu sangat terbatas jika dibandingkan dengan Express. Dan berkat sistem plugin Hapi, dimungkinkan untuk mengisolasi berbagai aspek dan layanan yang akan membantu aplikasi dalam banyak cara di masa depan.

Pemakaian

Hapi adalah kerangka kerja yang paling disukai jika dibandingkan dengan Express. Hapi digunakan terutama untuk aplikasi perusahaan skala besar.

Beberapa alasan mengapa pengembang tidak memilih Express saat membuat aplikasi perusahaan adalah:

Rute lebih sulit dibuat di Express

Middleware menghalangi sebagian besar waktu; setiap kali Anda menentukan rute, Anda harus menulis sebanyak mungkin kode.

Hapi akan menjadi pilihan terbaik bagi pengembang yang ingin membangun API RESTful. Hapi memiliki arsitektur layanan-mikro dan juga dimungkinkan untuk mentransfer kontrol dari satu handler ke handler lain berdasarkan parameter tertentu. Dengan plugin Hapi, Anda dapat menikmati tingkat abstraksi yang lebih besar di sekitar HTTP karena Anda dapat membagi logika bisnis menjadi beberapa bagian yang mudah dikelola.

Keuntungan besar lainnya dengan Hapi adalah menyediakan pesan kesalahan terperinci saat Anda salah konfigurasi. Hapi juga memungkinkan Anda mengkonfigurasi ukuran unggahan file Anda secara default. Jika ukuran unggahan maksimum terbatas, Anda dapat mengirim pesan kesalahan kepada pengguna yang menyampaikan bahwa ukuran file terlalu besar. Ini akan melindungi server Anda dari crash karena file unggahan tidak akan lagi mencoba untuk buffer seluruh file.

  1. Apa pun yang dapat Anda capai menggunakan express juga dapat dengan mudah dicapai menggunakan hapi.js.

  2. Hapi.js sangat bergaya dan mengatur kode dengan sangat baik. Jika Anda melihat bagaimana ia melakukan perutean dan menempatkan logika inti dalam pengontrol, Anda pasti akan menyukainya.

  3. Hapi.js secara resmi menyediakan beberapa plugin khusus untuk hapi.js mulai dari autent berbasis token hingga manajemen sesi dan banyak lagi, yang merupakan iklan. Itu tidak berarti npm tradisional tidak dapat digunakan, semuanya didukung oleh hapi.js

  4. Jika Anda kode di hapi.js, kode akan sangat mudah dikelola.


"Jika Anda melihat bagaimana cara melakukan routing dan menempatkan logika inti dalam pengontrol ...". Saya tidak melihat contoh apa pun dalam dokumentasi yang menunjukkan penggunaan pengontrol. Semua contoh perutean menggunakan properti handler yang merupakan fungsi. Saya membandingkan cara ini dengan apa yang dilakukan Laravel (kerangka PHP) dan AdonisJs (kerangka Node.js) untuk perutean di mana kita dapat menggunakan pengontrol untuk perutean. Saya mungkin melewatkan bagian-bagian dokumen HAPI yang menunjukkan penggunaan pengontrol untuk perutean. Jadi, jika fitur ini ada, akan baik bagi saya, karena saya terbiasa menggunakan pengontrol untuk perutean di Laravel.
Lex Soft

1

Saya sudah mulai menggunakan Hapi baru-baru ini dan saya cukup senang dengannya. Alasan saya adalah

  1. Lebih mudah untuk diuji. Sebagai contoh:

    • server.inject memungkinkan Anda untuk menjalankan aplikasi dan mendapatkan respons tanpa menjalankan dan mendengarkan.
    • server.info memberikan uri saat ini, port dll.
    • server.settingsmengakses konfigurasi mis. server.settings.cachedapatkan penyedia cache saat ini
    • ketika ragu melihat /testfolder untuk bagian mana pun dari aplikasi atau plugin yang didukung untuk melihat saran tentang cara mengejek / menguji / rintisan dll.
    • pengertian saya adalah bahwa model arsitektur hapi memungkinkan Anda untuk percaya tetapi memverifikasi misalnya Apakah plugin saya terdaftar ? Bagaimana saya bisa mendeklarasikan ketergantungan modul ?
  2. Ini berfungsi di luar kotak mis . Unggahan file , kembalikan aliran dari titik akhir dll.

  3. Plugin penting dipertahankan bersama dengan perpustakaan inti. misal penguraian template , caching dll. Manfaat tambahannya adalah standar pengkodean yang sama diterapkan pada hal-hal penting.

  4. Kesalahan dan penanganan kesalahan waras. Hapi memvalidasi opsi konfigurasi dan menyimpan tabel rute internal untuk mencegah duplikat rute. Ini cukup berguna saat belajar karena kesalahan dilempar lebih awal daripada perilaku tak terduga yang memerlukan debugging.


-1

Hanya hal lain untuk ditambahkan, Hapi telah mulai mendukung panggilan 'http2' dari versi 16 dan seterusnya (jika saya tidak salah). Namun, express belum mendukung modul 'http2' secara langsung hingga express 4. Meskipun mereka telah merilis fitur dalam versi alpha express 5.


-2
'use strict';
const Hapi = require('hapi');
const Basic = require('hapi-auth-basic');
const server = new Hapi.Server();
server.connection({
    port: 2090,
    host: 'localhost'
});


var vorpal = require('vorpal')();
const chalk = vorpal.chalk;
var fs = require("fs");

var utenti = [{
        name: 'a',
        pass: 'b'
    },
    {
        name: 'c',
        pass: 'd'
    }
];

const users = {
    john: {
        username: 'john',
        password: 'secret',
        name: 'John Doe',
        id: '2133d32a'
    },
    paul: {
        username: 'paul',
        password: 'password',
        name: 'Paul Newman',
        id: '2133d32b'
    }
};

var messaggi = [{
        destinazione: 'a',
        sorgente: 'c',
        messsaggio: 'ciao'
    },
    {
        destinazione: 'a',
        sorgente: 'c',
        messsaggio: 'addio'
    },
    {
        destinazione: 'c',
        sorgente: 'a',
        messsaggio: 'arrivederci'
    }
];

var login = '';
var loggato = false;

vorpal
    .command('login <name> <pass>')
    .description('Effettua il login al sistema')
    .action(function (args, callback) {
        loggato = false;
        utenti.forEach(element => {
            if ((element.name == args.name) && (element.pass == args.pass)) {
                loggato = true;
                login = args.name;
                console.log("Accesso effettuato");
            }
        });
        if (!loggato)
            console.log("Login e Password errati");
        callback();
    });

vorpal
    .command('leggi')
    .description('Leggi i messaggi ricevuti')
    .action(function (args, callback) {
        if (loggato) {
            var estratti = messaggi.filter(function (element) {
                return element.destinazione == login;
            });

            estratti.forEach(element => {
                console.log("mittente : " + element.sorgente);
                console.log(chalk.red(element.messsaggio));
            });
        } else {
            console.log("Devi prima loggarti");
        }
        callback();
    });

vorpal
    .command('invia <dest> "<messaggio>"')
    .description('Invia un messaggio ad un altro utente')
    .action(function (args, callback) {
        if (loggato) {
            var trovato = utenti.find(function (element) {
                return element.name == args.dest;
            });
            if (trovato != undefined) {
                messaggi.push({
                    destinazione: args.dest,
                    sorgente: login,
                    messsaggio: args.messaggio
                });
                console.log(messaggi);
            }
        } else {
            console.log("Devi prima loggarti");
        }
        callback();
    });

vorpal
    .command('crea <login> <pass>')
    .description('Crea un nuovo utente')
    .action(function (args, callback) {
        var trovato = utenti.find(function (element) {
            return element.name == args.login;
        });
        if (trovato == undefined) {
            utenti.push({
                name: args.login,
                pass: args.pass
            });
            console.log(utenti);
        }
        callback();
    });

vorpal
    .command('file leggi utenti')
    .description('Legge il file utenti')
    .action(function (args, callback) {
        var contents = fs.readFileSync("utenti.json");
        utenti = JSON.parse(contents);
        callback();
    });

vorpal
    .command('file scrivi utenti')
    .description('Scrive il file utenti')
    .action(function (args, callback) {
        var jsontostring = JSON.stringify(utenti);
        fs.writeFile('utenti.json', jsontostring, function (err) {
            if (err) {
                return console.error(err);
            }
        });
        callback();
    });

vorpal
    .command('file leggi messaggi')
    .description('Legge il file messaggi')
    .action(function (args, callback) {
        var contents = fs.readFileSync("messaggi.json");
        messaggi = JSON.parse(contents);
        callback();
    });

vorpal
    .command('file scrivi messaggi')
    .description('Scrive il file messaggi')
    .action(function (args, callback) {
        var jsontostring = JSON.stringify(messaggi);
        fs.writeFile('messaggi.json', jsontostring, function (err) {
            if (err) {
                return console.error(err);
            }
        });
        callback();
    });

// leggi file , scrivi file

vorpal
    .delimiter(chalk.yellow('messaggi$'))
    .show();




const validate = function (request, username, password, callback) {
    loggato = false;


    utenti.forEach(element => {
        if ((element.name == username) && (element.pass == password)) {
            loggato = true;
            console.log("Accesso effettuato");
            return callback(null, true, {
                name: username
            })
        }
    });
    if (!loggato)
        return callback(null, false);
};

server.register(Basic, function (err) {
    if (err) {
        throw err;
    }
});

server.auth.strategy('simple', 'basic', {
    validateFunc: validate
});



server.route({
    method: 'GET',
    path: '/',
    config: {
        auth: 'simple',
        handler: function (request, reply) {
            reply('hello, ' + request.auth.credentials.name);
        }
    }
});

//route scrivere
server.route({
    method: 'POST',
    path: '/invia',
    config: {
        auth: 'simple',
        handler: function (request, reply) {
            //console.log("Received POST from " + request.payload.name + "; id=" + (request.payload.id || 'anon'));
            var payload = encodeURIComponent(request.payload)
            console.log(request.payload);
            console.log(request.payload.dest);
            console.log(request.payload.messaggio);
            messaggi.push({
                destinazione: request.payload.dest,
                sorgente: request.auth.credentials.name,
                messsaggio: request.payload.messaggio
            });
            var jsontostring = JSON.stringify(messaggi);
            fs.writeFile('messaggi.json', jsontostring, function (err) {
                if (err) {
                    return console.error(err);
                }
            });
            console.log(messaggi);
            reply(messaggi[messaggi.length - 1]);

        }
    }
});


//route leggere (json)
server.route({
    method: 'GET',
    path: '/messaggi',
    config: {
        auth: 'simple',
        handler: function (request, reply) {
            messaggi = fs.readFileSync("messaggi.json");
            var estratti = messaggi.filter(function (element) {
                return element.destinazione == request.auth.credentials.name;
            });
            var s = [];

            console.log(request.auth.credentials.name);
            console.log(estratti.length);
            estratti.forEach(element => {

                s.push(element);

                //fare l'array con stringify
                //s+="mittente : "+element.sorgente+": "+element.messsaggio+"\n";

            });
            var a = JSON.stringify(s);
            console.log(a);
            console.log(s);
            reply(a);
        }
    }
});



server.start(function () {
    console.log('Hapi is listening to ' + server.info.uri);
});

function EseguiSql(connection, sql, reply) {
    var rows = [];
    request = new Request(sql, function (err, rowCount) {
        if (err) {
            console.log(err);
        } else {
            console.log(rowCount + ' rows');
            console.log("Invio Reply")
            reply(rows);
        }
    });

    request.on('row', function (columns) {
        var row = {};
        columns.forEach(function (column) {
            row[column.metadata.colName] = column.value;
        });
        rows.push(row);
    });

    connection.execSql(request);
}

server.route({
    method: 'POST',
    path: '/query',
    handler: function (request, reply) {
        // Qui dovrebbe cercare i dati nel body e rispondere con la query eseguita
        var connection = new Connection(config);

        // Attempt to connect and execute queries if connection goes through
        connection.on('connect', function (err) {
            if (err) {
                console.log(err);
            } else {

                console.log('Connected');
                console.log(request.payload.sql);
                EseguiSql(connection, request.payload.sql, reply);
            }
        });

    }
});

server.connection({
    host: process.env.HOST || 'localhost',
    port: process.env.PORT || 8080
});

var config = {
    userName: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    server: process.env.DB_SERVER,
    options: {
        database: process.env.DB_NAME,
        encrypt: true
    }
}

Selamat datang di StackOverflow. Bisakah Anda menguraikan lebih lanjut tentang respons Anda dan bagaimana kaitannya dengan pertanyaan yang diposting oleh OP?
Szymon Maszke
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.