it-swarm.com.de

Wie sind Express und Hapi miteinander vergleichbar?

Wie vergleichen sich Express und Hapi im Hinblick auf Design und Entwicklung von Webanwendungen? Für grundlegende Beispiele scheinen sie ähnlich zu sein. Ich bin jedoch daran interessiert, mehr über die wichtigsten Unterschiede in der allgemeinen Anwendungsstruktur zu erfahren.

Soweit ich es gelernt habe, verwendet Hapi beispielsweise einen anderen Routing-Mechanismus, der die Registrierungsreihenfolge nicht berücksichtigt, schnellere Suchvorgänge ausführen kann, jedoch im Vergleich zu Express eingeschränkt ist. Gibt es noch andere wichtige Unterschiede?

Es gibt auch einen Artikel über die Wahl von Hapi (über Express) für die Entwicklung der neuen npmjs.com-Website. In diesem Artikel heißt es: "Das Plugin-System von Hapi bedeutet, dass wir verschiedene Facetten und Dienste der Anwendung so isolieren können, wie dies möglich wäre für Microservices in der Zukunft. Express dagegen erfordert etwas mehr Konfiguration, um die gleiche Funktionalität zu erhalten ", was bedeutet das genau?

118
Ali Shakiba

Dies ist eine große Frage und erfordert eine lange Antwort, um vollständig zu sein. Ich werde daher nur auf eine Teilmenge der wichtigsten Unterschiede eingehen. Entschuldigung, dass es noch eine lange Antwort ist.

Wie ähnlich sind sie?

Sie haben vollkommen recht, wenn Sie sagen:

Für grundlegende Beispiele scheinen sie ähnlich

Beide Frameworks lösen das gleiche Grundproblem: Bereitstellung einer praktischen API zum Erstellen von HTTP-Servern in Node. Dies ist praktischer als die Verwendung des nativen Moduls http auf niedrigerer Ebene. Das http -Modul kann alles, was wir wollen, aber es ist mühsam, Anwendungen mit zu schreiben.

Um dies zu erreichen, verwenden beide Konzepte, die es schon lange in hochrangigen Webframeworks gibt: Routing, Handler, Plugins und Authentifizierungsmodule. Sie hatten vielleicht nicht immer die gleichen Namen, aber sie sind in etwa gleichwertig.

Die meisten grundlegenden Beispiele sehen ungefähr so ​​aus:

  • Erstellen Sie eine Route
  • Führen Sie eine Funktion aus, wenn die Route angefordert wird, und bereiten Sie die Antwort vor
  • Beantworten Sie die Anfrage

Ausdrücken:

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);
        });
    }
});

Der Unterschied ist hier nicht gerade wegweisend, oder? Warum also eins über das andere wählen?

Wie unterscheiden sie sich?

Die einfache Antwort lautet: Hapi ist viel mehr und es ist viel mehr out-of-the-box. Das ist vielleicht nicht klar, wenn Sie sich nur das einfache Beispiel von oben ansehen. In der Tat ist dies beabsichtigt. Die einfachen Fälle sind einfach gehalten. Schauen wir uns also einige der großen Unterschiede an:

Philosophie

Express soll sehr minimal sein. Indem Sie eine kleine API mit nur wenig Staub auf http setzen, sind Sie immer noch auf sich allein gestellt, um zusätzliche Funktionen hinzuzufügen. Wenn Sie den Hauptteil einer eingehenden Anforderung lesen möchten (eine recht häufige Aufgabe), müssen Sie ein separates Modul installieren. Wenn Sie erwarten, dass verschiedene Inhaltstypen an diese Route gesendet werden, müssen Sie auch das Kontrollkästchen Content-type -Header, um zu überprüfen, welche es ist, und sie entsprechend zu analysieren (z. B. Formulardaten gegenüber JSON gegenüber mehrteiligen), wobei häufig separate Module verwendet werden.

hapi verfügt über umfangreiche Funktionen, die häufig über Konfigurationsoptionen verfügbar gemacht werden, anstatt dass Code geschrieben werden muss. Wenn wir beispielsweise sicherstellen möchten, dass ein Anforderungshauptteil (Nutzdaten) vollständig in den Speicher eingelesen und entsprechend analysiert wird (automatisch basierend auf dem Inhaltstyp), bevor der Handler ausgeführt wird, ist dies nur ein einfaches Option :

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

        reply(request.payload);
    }
});

Eigenschaften

Sie müssen nur die API-Dokumentation beider Projekte vergleichen, um festzustellen, dass Hapi einen größeren Funktionsumfang bietet.

hapi enthält einige der folgenden Funktionen, die in Express nicht integriert sind (soweit ich weiß):

Erweiterbarkeit & Modularität

bei Hapi und Express geht es um Erweiterbarkeit auf ganz andere Weise. Mit Express haben Sie Middleware Funktionen. Middleware-Funktionen ähneln Filtern, die Sie stapeln und die alle Anforderungen durchlaufen, bevor Sie Ihren Handler erreichen.

hapi hat den Request Lifecycle und bietet Extension Points , die mit Middleware-Funktionen vergleichbar sind, jedoch mehrere definierte Punkte im Request Lifecycle haben.

Einer der Gründe, warum Walmart Hapi baute und Express nicht mehr verwendete, war die Frustration darüber, wie schwierig es war, eine Express-App in separate Teile aufzuteilen und verschiedene Teammitglieder sicher an ihrem Chunk arbeiten zu lassen. Aus diesem Grund haben sie das Plugin-System in hapi erstellt.

Ein Plugin ist wie eine Unteranwendung. Sie können alles tun, was Sie in einer Hapi-App können, Routen, Erweiterungspunkte usw. hinzufügen. In einem Plugin können Sie sicher sein, dass Sie keinen anderen Teil der Anwendung aufgrund der Reihenfolge von brechen Registrierungen für Routen spielen keine Rolle und Sie können keine widersprüchlichen Routen erstellen. Sie können diese Plugins dann zu einem Server kombinieren und bereitstellen.

Ökosystem

Da Sie mit Express so wenig von der Stange haben, müssen Sie nach draußen schauen, wenn Sie Ihrem Projekt etwas hinzufügen möchten. Wenn Sie mit hapi arbeiten, benötigen Sie häufig eine integrierte Funktion oder ein vom Kernteam erstelltes Modul.

Minimal klingt großartig. Aber wenn Sie eine ernstzunehmende Produktions-App erstellen, werden Sie wahrscheinlich all diese Dinge irgendwann brauchen.

Sicherheit

hapi wurde vom Walmart-Team für die Ausführung des Black Friday-Verkehrs entwickelt, sodass Sicherheit und Stabilität seit jeher ein zentrales Anliegen sind. Aus diesem Grund führt das Framework eine Reihe weiterer Aufgaben aus, z. B. die Begrenzung der Größe eingehender Nutzdaten, um die Erschöpfung des Prozessspeichers zu verhindern. Es gibt auch Optionen für die maximale Verzögerung von Ereignisschleifen, den maximal verwendeten RSS-Speicher und die maximale Größe des v8-Heapspeichers, ab der Ihr Server mit einem Timeout von 503 reagiert und nicht nur abstürzt.

Zusammenfassung

Bewerten Sie beide selbst. Denken Sie über Ihre Bedürfnisse nach und welche der beiden Adressen Ihre größten Bedenken aufwirft. Tauchen Sie ein in die beiden Communities (IRC, Gitter, Github), welche Sie bevorzugen. Nimm nicht einfach mein Wort. Und viel Spaß beim Hacken!


HAFTUNGSAUSSCHLUSS: Ich bin voreingenommen als Autor eines Buch über Hapi und das oben Gesagte ist größtenteils meine persönliche Meinung.

216
Matt Harrison

Meine Organisation geht mit Hapi. Deshalb mögen wir es.

Hapi ist:

  • Unterstützt von einem großen Korps. Dies bedeutet, dass die Community-Unterstützung stark ist und auch in zukünftigen Versionen zur Verfügung steht. Es ist leicht, leidenschaftliche Hapi-Leute zu finden, und es gibt gute Tutorials (wenn auch nicht so zahlreich und umfangreich wie ExpressJs-Tutorials). Ab diesem Postdatum verwenden npm und Walmart Hapi.
  • Es kann die Arbeit verteilter Teams erleichtern, die an verschiedenen Teilen der Backend-Services arbeiten, ohne umfassende Kenntnisse der übrigen API-Oberfläche zu besitzen (die Plugin-Architektur von Hapi ist der Inbegriff dieser Qualität).
  • Lassen Sie das Framework das tun, was ein Framework tun soll: Konfigurieren Sie die Dinge. Danach sollte das Framework unsichtbar sein und es Entwicklern ermöglichen, ihre eigentliche kreative Energie darauf zu konzentrieren, Geschäftslogik zu entwickeln. Nachdem ich Hapi ein Jahr lang verwendet hatte, habe ich definitiv das Gefühl, dass Hapi dies erreicht. Ich bin glücklich!

Wenn Sie direkt von Eran Hammer (Hapis Leitung) hören möchten

In den letzten vier Jahren entwickelte sich hapi für viele große und kleine Projekte zum bevorzugten Rahmen. Was Hapi einzigartig macht, ist die Möglichkeit, sich auf große Bereitstellungen und große Teams zu skalieren. Wenn ein Projekt wächst, wächst auch seine Komplexität - technische Komplexität und Prozesskomplexität. hapis Architektur und Philosophie bewältigen die erhöhte Komplexität, ohne dass der Code ständig umgestaltet werden muss. [weiterlesen]

Der Einstieg in Hapi wird nicht so einfach wie mit ExpressJs sein, da Hapi nicht die gleiche "Sternenkraft" hat ... aber wenn Sie sich wohl fühlen, werden Sie VIELE Kilometer sammeln. Es dauerte ungefähr 2 Monate als neuer Hacker, der einige Jahre lang unverantwortlich ExpressJs benutzte. Wenn Sie ein erfahrener Backend-Entwickler sind, wissen Sie, wie Sie die Dokumente lesen, und Sie werden dies wahrscheinlich nicht bemerken.

Bereiche, in denen die Hapi-Dokumentation verbessert werden kann:

  1. wie Sie Benutzer authentifizieren und Sitzungen erstellen
  2. bearbeitung von Cross-Origin-Requests (CORS)
  3. dateien hochladen (mehrteilig, chunked)

Ich denke, die Authentifizierung wäre der schwierigste Teil davon, weil Sie entscheiden müssen, welche Art von Authentifizierungsstrategie verwendet werden soll (Standardauthentifizierung, Cookies, JWT-Token, OAuth). Obwohl es technisch gesehen nicht das Problem von Hapi ist, dass die Session/Authentication-Landschaft so fragmentiert ist ... aber ich wünsche mir, dass sie dafür etwas Handhaltendes bereitstellten. Dies würde die Entwicklerzufriedenheit erheblich erhöhen.

Die verbleibenden zwei sind eigentlich nicht so schwierig, die Dokumente könnten einfach etwas besser geschrieben werden.

48
williamle8300

Kurzinformationen zu Hapi oder warum Hapi JS? 

Hapi ist konfigurationszentrisch Es verfügt über Authentifizierung und Autorisierung, die in das Framework integriert sind Es wurde in einer von der Schlacht erprobten Atmosphäre veröffentlicht und hat sich wirklich bewährt Alle Module haben eine 100% ige TestabdeckungIt registriert die höchste Abstraktionsebene abseits des Kerns HTTP Einfach über die Plugin-Architektur kompatibel

Hapi ist eine bessere Wahl hinsichtlich der Leistung Hapi verwendet einen anderen Routing-Mechanismus, der schnellere Suchvorgänge ausführen kann und die Registrierungsreihenfolge berücksichtigt . Trotzdem ist es im Vergleich zu Express recht begrenzt. Und dank des Hapi-Plugin-Systems ist es möglich die verschiedenen Facetten und Dienste zu isolieren, die der Anwendung in der Zukunft in vielerlei Hinsicht helfen würden.

Verwendungszweck

Im Vergleich zu Express ist Hapi das am meisten bevorzugte Gerüst. Hapi wird hauptsächlich für große Unternehmensanwendungen verwendet.

Es gibt einige Gründe, warum Entwickler sich beim Erstellen von Unternehmensanwendungen nicht für Express entscheiden:

Routen lassen sich in Express schwieriger zusammenstellen

Middleware steht meistens im Weg; Jedes Mal, wenn Sie die Routen definieren, müssen Sie so viele Codes wie möglich schreiben.

Hapi ist die beste Wahl für Entwickler, die RESTful-API erstellen möchten. Hapi verfügt über eine Mikrodienstarchitektur und es ist auch möglich, die Steuerung anhand bestimmter Parameter von einem Handler auf einen anderen zu übertragen. Mit dem Hapi-Plugin können Sie eine höhere Abstraktionsebene in Bezug auf HTTP genießen, da Sie die Geschäftslogik in einfach zu verwaltende Teile aufteilen können.

Ein weiterer großer Vorteil von Hapi ist, dass bei falscher Konfiguration detaillierte Fehlermeldungen angezeigt werden. Mit Hapi können Sie auch die Größe Ihrer Dateiupload standardmäßig konfigurieren. Wenn die maximale Uploadgröße begrenzt ist, können Sie eine Fehlermeldung an den Benutzer senden, dass die Dateigröße zu groß ist. Dies würde Ihren Server vor dem Absturz schützen, da die Dateiuploads nicht mehr versuchen, eine ganze Datei zu puffern.

  1. Was auch immer Sie mit Express erreichen können, lässt sich mit hapi.js problemlos erreichen.

  2. Hapi.js ist sehr stilvoll und organisiert den Code sehr gut. Wenn Sie sehen, wie Routing ausgeführt wird, und die Kernlogik in Controller Setzt, werden Sie es auf jeden Fall lieben.

  3. Hapi.js bietet offiziell mehrere Plugins exklusiv für hapi.js an, von Token-basierter Authentifizierung bis hin zur Sitzungsverwaltung und vieles mehr..... Dies ist eine Anzeige. Das bedeutet nicht, dass das traditionelle npm nicht verwendet werden kann, alle werden von hapi.js unterstützt 

  4. Wenn Sie in hapi.js codieren, wäre ein Code sehr wartbar.

1
user9961607

Ich habe kürzlich angefangen, Hapi zu verwenden und bin ziemlich zufrieden damit. Meine Gründe sind

  1. Einfacher zu testen. Zum Beispiel:

    • server.inject ermöglicht es Ihnen, die App auszuführen und eine Antwort zu erhalten, ohne dass sie ausgeführt und abgehört wird.
    • server.info gibt den aktuellen URI, Port usw. an.
    • server.settings greift auf die Konfiguration zu, z. server.settings.cache ruft den aktuellen Cache-Anbieter ab
    • im Zweifelsfall sehen Sie in den /test-Ordnern nach, welche Teile der App oder der unterstützten Plugins enthalten sind, um Vorschläge zum Verspotten/Testen/Stoppen usw. zu erhalten.
    • mein Gefühl ist, dass das Architekturmodell von Hapi es Ihnen ermöglicht, zu vertrauen, aber zu verifizieren, z. Sind meine Plugins registriert ? Wie kann ich eine Modulabhängigkeit deklarieren ?
  2. Es funktioniert sofort, z. Dateiuploads , Rückgabe von Streams von Endpunkten usw.

  3. Wichtige Plugins werden zusammen mit der Kernbibliothek verwaltet. z. B. Template Parsing , Caching usw. Der zusätzliche Vorteil ist, dass für alle wesentlichen Dinge die gleichen Codierungsstandards angewendet werden.

  4. Vernünftige Fehler und Fehlerbehandlung. Hapi überprüft die Konfigurationsoptionen und führt eine interne Routentabelle, um doppelte Routen zu vermeiden. Dies ist beim Lernen sehr nützlich, da Fehler früher ausgegeben werden als unerwartete Verhaltensweisen, die ein Debuggen erfordern.

0
Peter
'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
    }
}

Noch ein weiterer Punkt, der hinzugefügt werden muss: Hapi unterstützt ab Version 16 "http2" -Aufrufe (wenn ich mich nicht irre). Express unterstützt das Modul 'http2' jedoch noch bis Express 4. Das Feature wurde jedoch in der Alpha-Version von Express 5 veröffentlicht.

0
UchihaItachi
    const Hapi = require('hapi');
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
const server = new Hapi.Server();
var vorpal = require('vorpal')();

server.connection({
    Host: process.env.Host || 'localhost',
    port: process.env.PORT || 3000
});
server.start(function (err) {
    if (err) {
        throw err;
    }
    console.log("server running at : " + server.info.uri);
});

var config =
{
    userName: 'sa',
    password: 'password.123',
    server: 'localhost',

    options:
    {
        database: '',
        port: 1433
    }
}

server.route(
    {
        method: 'GET',
        path: '/{categoria}',
        handler: function (request, reply) {
            var connection = new Connection(config);
            connection.on('connect', function (err) {
                if (err) {
                    console.log(err);
                }
                else {
                    console.log('Connected');
                    EseguiSqlGet(connection, request.params.categoria, reply);
                }
            });
        }
    }
);
function EseguiSqlGet(connection, cat, reply) {
    var rows = [];
    var sql = 'SELECT * FROM Prodotti INNER JOIN Categorie
 on Categorie.IdCategoria = Prodotti.IdCategoria
 WHERE Categorie.IdCategoria = ' + cat ;
    request_sql = new Request(sql, function(err, rowCount) {
        if (err) {
            console.log(err);
        } else {
            console.log(rowCount + ' rows');
            console.log("Invio Reply")
            reply(rows);
        }
    });

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

    connection.execSql(request_sql);
}
// POST
server.route(
    {
        method: 'POST',
        path: '/inserisci',
        handler: function (request, reply) {
            var connection = new Connection(config);
            connection.on('connect', function (err) {
                if (err) {
                    console.log(err);
                }
                else {
                    console.log('Connected');
                    EseguiSqlPost(connection,reply, 
request.payload.idcat, request.payload.nome, request.payload.prezzo );
                }
            });
        }
    }
);
function EseguiSqlPost(connection,reply, cat,nome,prezzo) {

    var sql = "INSERT INTO Prodotti
 VALUES("+ cat +",'"+nome+"',"+prezzo+")";
    request_sql = new Request(sql, function(err, rowCount) {
        if (err) {
            console.log(err);
        } else {
            console.log(rowCount + ' rows');
            console.log("Invio Reply")
            reply('riga aggiunta');
        }
    });

    /*request_sql.on('row', function(columns) {
        var row = {};
        columns.forEach(function (column) {
            row[column.metadata.colName] = column.value;
        });
        rows.Push(row);
    });
*/
    connection.execSql(request_sql);
}






//VORPAL COMMAND PROMT
var categoria = [
    {

        'idcategoria':'1',
        'nome':'ciao',

    }
]


vorpal
    .command('inserisci <categoria> <nome>')
    .action(function(args, callback)
    {
        categoria.Push(   
{'idcategoria':args.categoria,'nome':args.nome}     );
        console.log(JSON.stringify(categoria));
        callback();
    });

vorpal
.delimiter("delimeter")
.show();