Wie vergleichen sich Express und Hapi?


132

Wie vergleichen sich Express und Hapi aus Sicht des Designs und der Entwicklung von Webanwendungen? Grundlegende Beispiele scheinen ähnlich zu sein, ich bin jedoch daran interessiert, mehr über die wichtigsten Unterschiede in der gesamten Anwendungsstruktur zu erfahren.

Soweit ich erfahren habe, verwendet Hapi beispielsweise einen anderen Routing-Mechanismus, der die Registrierungsreihenfolge nicht berücksichtigt, schnellere Suchvorgänge durchfü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 (anstelle von Express) für die Entwicklung der neuen Website npmjs.com. In diesem Artikel heißt es: "Das Plugin-System von Hapi bedeutet, dass wir verschiedene Facetten und Dienste der Anwendung auf eine Weise isolieren können, die Microservices in der Zukunft. Express hingegen erfordert etwas mehr Konfiguration, um die gleiche Funktionalität zu erhalten ", was bedeutet das genau?

Antworten:


230

Dies ist eine große Frage und erfordert eine lange Antwort, um vollständig zu sein. Daher werde ich nur eine Teilmenge der wichtigsten Unterschiede ansprechen. Entschuldigung, dass es immer noch eine lange Antwort ist.

Wie sind sie ähnlich?

Sie haben absolut Recht, wenn Sie sagen:

Für grundlegende Beispiele scheinen sie ähnlich zu sein

Beide Frameworks lösen das gleiche Grundproblem: Bereitstellung einer praktischen API zum Erstellen von HTTP-Servern im Knoten. Das heißt, bequemer als die Verwendung des nativen httpModuls der unteren Ebene allein. Das httpModul 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 Web-Frameworks auf hoher Ebene gibt: Routing, Handler, Plugins, Authentifizierungsmodule. Sie hatten vielleicht nicht immer die gleichen Namen, aber sie sind ungefähr 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
  • Antworten Sie auf 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 bahnbrechend, oder? Warum also eins über das andere wählen?

Wie unterscheiden sie sich?

Die einfache Antwort lautet: Hapi ist viel mehr und es macht viel mehr Out-of-the-Box. Das ist möglicherweise nicht klar, wenn Sie sich nur das einfache Beispiel von oben ansehen. In der Tat ist dies beabsichtigt. Die einfachen Fälle werden einfach gehalten. Untersuchen wir also einige der großen Unterschiede:

Philosophie

Express soll sehr minimal sein. Indem Sie eine kleine API mit nur einem dünnen Staub darauf bereitstellen http, sind Sie in Bezug auf das Hinzufügen zusätzlicher Funktionen immer noch sehr allein. Wenn Sie den Text einer eingehenden Anforderung lesen möchten (eine häufig verwendete Aufgabe), müssen Sie ein separates Modul installieren . Wenn Sie erwarten, dass verschiedene Inhaltstypen an diese Route gesendet werden, müssen Sie auch den Content-typeHeader überprüfen , um zu überprüfen , um welche es sich handelt, und ihn entsprechend analysieren (z. B. Formulardaten vs JSON vs mehrteilig), häufig unter Verwendung separater Module .

Hapi verfügt über umfangreiche Funktionen, die häufig durch 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 eine einfache 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 für beide Projekte vergleichen, um festzustellen, dass Hapi einen größeren Funktionsumfang bietet.

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

Erweiterbarkeit und Modularität

Hapi und Express gehen auf ganz andere Weise auf Erweiterbarkeit ein. 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 Anforderungslebenszyklus und bietet Erweiterungspunkte , die mit Middleware-Funktionen vergleichbar sind, jedoch mehrere definierte Punkte im Anforderungslebenszyklus aufweisen.

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 Block arbeiten zu lassen. Aus diesem Grund haben sie das Plugin-System in Hapi erstellt.

Ein Plugin ist wie eine Unteranwendung. Sie können in einer Hapi-App alles tun, Routen, Erweiterungspunkte usw. hinzufügen. In einem Plugin können Sie sicher sein, dass Sie keinen anderen Teil der Anwendung beschädigen, da die Reihenfolge von 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 sofort einsatzbereit sind, müssen Sie nach draußen schauen, wenn Sie Ihrem Projekt etwas hinzufügen möchten. In den meisten Fällen, wenn Sie mit Hapi arbeiten, ist die Funktion, die Sie benötigen, entweder integriert oder es gibt ein Modul, das vom Kernteam erstellt wurde.

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

Sicherheit

hapi wurde vom Walmart-Team für den Black Friday-Verkehr entwickelt, sodass Sicherheit und Stabilität immer ein Hauptanliegen waren. Aus diesem Grund führt das Framework viele zusätzliche Aufgaben aus, z. B. die Begrenzung der Größe eingehender Nutzdaten, um zu verhindern, dass Ihr Prozessspeicher erschöpft wird. Es gibt auch Optionen für Dinge wie die maximale Verzögerung der Ereignisschleife, den maximalen verwendeten RSS-Speicher und die maximale Größe des v8-Heaps, 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 Ihre größten Bedenken anspricht. Tauchen Sie ein in die beiden Gemeinden (IRC, Gitter, Github) und finden Sie heraus, welche Sie bevorzugen. Nimm nicht einfach mein Wort. Und viel Spaß beim Hacken!


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


7
Matt, danke für den umfangreichen Beitrag. Die Abschnitte "Erweiterbarkeit und Modularität" und "Sicherheit" waren für mich die hilfreichsten Abschnitte. Ich denke, es ist erwähnenswert, dass das neue Routing-System in Express 4 eine verbesserte Modularität für Unteranwendungen bietet.
Ali Shakiba

1
Tolle Antwort Matt. Wir sind auch s / w Hapi und Express verwirrt. Ein Nachteil, den wir bei Hapi sehen, ist, dass es keine so umfassende Community-Unterstützung wie Express hat und ein großes Problem sein könnte, wenn wir irgendwo stecken bleiben. Benötigen Sie Ihre Meinung dazu.
Aman Gupta

1
Express ist generisch, während Hapi etwas unternehmerischer ist.
Windmaomao

1
@ MattHarrison tolle Antwort, im Moment lese ich dein Buch über Hapi, es ist einfach toll. Ich bin dabei, einen neuen Marktplatz für Bücher mit Hapi im Backend und vue.js im Frontend zu entwickeln. Nachdem ich mich an Hapi gewöhnt habe, möchte ich aktiv am Hapi-Projekt teilnehmen.
Humoyun Ahmad

1
@ Humoyun Großartig! Beachten Sie jedoch, dass es seit <= v16.0.0 eine neue Hauptversion von Hapi mit einigen erheblichen Änderungen gibt. Ich produziere derzeit eine Screencast-Serie, in der Leute v17 lernen können: youtube.com/playlist?list=PLi303AVTbxaxqjaSWPg94nccYIfqNoCHz
Matt Harrison

54

Meine Organisation geht mit Hapi. Deshalb gefällt es uns.

Hapi ist:

  • Unterstützt von einem großen Korps. Dies bedeutet, dass die Community-Unterstützung stark sein wird und in zukünftigen Versionen für Sie da ist. Es ist leicht, leidenschaftliche Hapi-Leute zu finden, und es gibt gute Tutorials (wenn auch nicht so zahlreich und weitläufig wie ExpressJs Tutorials). Ab diesem Post-Datum verwenden npm und Walmart Hapi.
  • Es kann die Arbeit verteilter Teams erleichtern, die an verschiedenen Teilen der Backend-Services arbeiten, ohne umfassende Kenntnisse über den Rest der API-Oberfläche zu haben (die Plugin-Architektur von Hapi ist der Inbegriff dieser Qualität).
  • Lassen Sie das Framework das tun, was ein Framework tun soll: Dinge konfigurieren. Danach sollte das Framework unsichtbar sein und es Entwicklern ermöglichen, ihre wahre kreative Energie auf den Aufbau von Geschäftslogik zu konzentrieren. Nachdem ich Hapi ein Jahr lang verwendet habe, 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 hat sich Hapi zum bevorzugten Rahmen für viele große und kleine Projekte entwickelt. Was Hapi einzigartig macht, ist seine Fähigkeit, 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. Die Architektur und Philosophie von hapi bewältigt die zunehmende Komplexität, ohne dass der Code ständig überarbeitet werden muss. [read more]

Der Einstieg in Hapi ist nicht so einfach wie bei ExpressJs, da Hapi nicht die gleiche "Sternenkraft" hat ... aber sobald Sie sich wohl fühlen, erhalten Sie eine Menge Kilometer. Ich habe ungefähr 2 Monate als neuer Hacker gebraucht, der einige Jahre lang verantwortungslos ExpressJs verwendet hat. Wenn Sie ein erfahrener Backend-Entwickler sind, wissen Sie, wie man die Dokumente liest, und Sie werden dies wahrscheinlich nicht einmal bemerken.

Bereiche, in denen sich die Hapi-Dokumentation verbessern kann:

  1. So authentifizieren Sie Benutzer und erstellen Sitzungen
  2. Bearbeitung von Cross-Origin-Requests (CORS)
  3. Hochladen von Dateien (mehrteilig, aufgeteilt)

Ich denke, die Authentifizierung wäre der schwierigste Teil davon, da Sie sich entscheiden müssen, welche Authentifizierungsstrategie verwendet werden soll (Basisauthentifizierung, Cookies, JWT-Token, OAuth). Obwohl es technisch gesehen nicht das Problem von Hapi ist, dass die Sitzungs- / Authentifizierungslandschaft so fragmentiert ist ... aber ich wünschte, sie hätten dafür etwas Handarbeit geleistet. Dies würde das Entwicklerglück erheblich steigern.

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


2

Kurze Fakten über Hapi oder warum Hapi JS?

Hapi ist konfigurationsorientiert. Es verfügt über eine in das Framework integrierte Authentifizierung und Autorisierung. Es wurde in einer kampferprobten Atmosphäre veröffentlicht und hat sich wirklich bewährt. Alle Module verfügen über eine 100% ige Testabdeckung. Es registriert den höchsten Abstraktionsgrad außerhalb des Kern-HTTP. Leicht zu erfassen über die Plugin-Architektur

In Bezug auf die Leistung ist Hapi die bessere Wahl. Hapi verwendet einen anderen Routing-Mechanismus, der schnellere Suchvorgänge durchführen und die Registrierungsreihenfolge berücksichtigen kann. 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 Zukunft in vielerlei Hinsicht helfen würden.

Verwendung

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

Einige Gründe, warum Entwickler sich beim Erstellen von Unternehmensanwendungen nicht für Express entscheiden, sind:

Routen sind in Express schwieriger zu erstellen

Middleware stört die meiste Zeit. Jedes Mal, wenn Sie die Routen definieren, müssen Sie so viele Codes schreiben.

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

Ein weiterer großer Vorteil von Hapi ist, dass es bei einer Fehlkonfiguration detaillierte Fehlermeldungen liefert. Mit Hapi können Sie auch standardmäßig die Größe Ihres Datei-Uploads konfigurieren. Wenn die maximale Upload-Größe begrenzt ist, können Sie dem Benutzer eine Fehlermeldung senden, die besagt, dass die Dateigröße zu groß ist. Dies würde Ihren Server vor einem Absturz schützen, da beim Hochladen von Dateien nicht mehr versucht wird, eine ganze Datei zu puffern.

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

  2. Hapi.js ist sehr stilvoll und organisiert den Code sehr gut. Wenn Sie sehen, wie es Routing macht und die Kernlogik in Controllern steckt, werden Sie es trotzig lieben.

  3. Hapi.js bietet offiziell mehrere Plugins exklusiv für hapi.js an, von tokenbasierter Authentifizierung über Sitzungsverwaltung bis hin zu vielen weiteren Plug-ins. Dies bedeutet nicht, dass das traditionelle npm nicht verwendet werden kann. Alle werden von hapi.js unterstützt

  4. Wenn Sie in hapi.js codieren, ist ein Code sehr wartbar.


"Wenn Sie sehen, wie es Routing macht und die Kernlogik in Steuerungen steckt ...". Ich sehe kein Beispiel in der Dokumentation, das die Verwendung von Controllern zeigt. Alle Routing-Beispiele verwenden die Handler-Eigenschaft, die eine Funktion ist. Ich vergleiche diesen Weg mit dem, was Laravel (PHP-Framework) und AdonisJs (Node.js-Framework) für das Routing tun, bei dem wir Controller für das Routing verwenden können. Ich habe wahrscheinlich Teile des HAPI-Dokuments übersehen, die die Verwendung von Controllern für das Routing zeigen. Wenn diese Funktion vorhanden ist, ist sie gut für mich, da ich es gewohnt bin, Controller für das Routing in Laravel zu verwenden.
Lex Soft

1

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

  1. Einfacher zu testen. Beispielsweise:

    • 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 die aktuelle uri, port etc. an.
    • server.settingsZugriff auf die Konfiguration, z. B. server.settings.cacheAbrufen des aktuellen Cache-Anbieters
    • Im Zweifelsfall sehen Sie sich die /testOrdner für einen Teil der App oder die unterstützten Plugins an, um Vorschläge zum Verspotten / Testen / Stub usw. zu erhalten.
    • Meiner Meinung nach können Sie mit dem Architekturmodell von Hapi vertrauen, aber überprüfen, z. B. ob meine Plugins registriert sind . Wie kann ich eine Modulabhängigkeit deklarieren ?
  2. Es funktioniert sofort , z. B. Datei-Uploads , Rückgabe von Streams von Endpunkten usw.

  3. Wichtige Plugins werden zusammen mit der Kernbibliothek verwaltet. zB Vorlagenanalyse , Caching usw. Der zusätzliche Vorteil besteht darin, dass die gleichen Codierungsstandards für alle wesentlichen Dinge 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ühzeitig ausgelöst werden und nicht unerwartete Verhaltensweisen, die ein Debugging erfordern.


-1

Nur ein weiterer Punkt, den man hinzufügen sollte: Hapi unterstützt ab Version 16 "http2" -Aufrufe (wenn ich mich nicht irre). Express muss das 'http2'-Modul jedoch noch direkt bis Express 4 unterstützen. Obwohl die Funktion in der Alpha-Version von Express 5 veröffentlicht wurde.


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

Willkommen bei StackOverflow. Könnten Sie näher auf Ihre Antwort eingehen und wie sie sich auf die von OP gestellte Frage bezieht?
Szymon Maszke

-3
    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();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.