Un guide du calcul scientifique avec des outils Open Source
Science Des Données Et Bases De Données
Il est inutile de mentionner la popularité croissante de Node.js pour le développement d’applications. eBay exécute un service d'API Node de production depuis 2011. PayPal reconstruit activement son front-end dans Node. Le site mobile de Walmart est devenu la plus grande application Node, en termes de trafic. Le week-end de Thanksgiving en 2014, Les serveurs Walmart ont traité 1,5 milliard de requêtes , Dont 70% ont été livrés via mobile et alimentés par Node.js. Du côté du développement, le gestionnaire de packages Node ( au dessus du niveau de la mer ) continue de croître rapidement, dépassant récemment les 150 000 modules hébergés.
Tandis que Ruby a des rails et Python a Django, le cadre de développement d'applications dominant pour Node n'a pas encore été établi. Mais, il y a un concurrent puissant qui gagne du terrain: LoopBack , un framework d'API open source construit par San Mateo, Californie, société StrongLoop . StrongLoop est un contributeur important à la dernière Version du nœud , sans parler des mainteneurs de longue date de Express , l'un des frameworks Node les plus populaires existants.
Examinons de plus près LoopBack et ses capacités en mettant tout en pratique et en créant un exemple d’application.
LoopBack est un framework pour création d'API et les connecter avec des sources de données backend. Construit sur Express, il peut prendre une définition de modèle de données et générer facilement une API REST de bout en bout entièrement fonctionnelle qui peut être appelée par n'importe quel client.
LoopBack est livré avec un client intégré, Explorateur d'API . Nous allons l'utiliser car cela permet de voir plus facilement les résultats de notre travail et afin que notre exemple puisse se concentrer sur la création de l'API elle-même.
Vous aurez bien sûr besoin de Node installé sur votre machine pour suivre. Tu piges Ici . npm est livré avec, vous pouvez donc installer facilement les packages nécessaires. Commençons.
Notre application gérera les personnes qui souhaiteraient donner des cadeaux ou des choses dont elles n’ont tout simplement plus besoin à une personne qui pourrait en avoir besoin. Ainsi, les utilisateurs seront des donateurs et des récepteurs. Un donateur peut créer un nouveau cadeau et voir la liste des cadeaux. Un destinataire peut voir la liste des cadeaux de tous les utilisateurs et peut réclamer ceux qui ne sont pas réclamés. Bien sûr, nous pourrions créer des donateurs et des destinataires en tant que rôles distincts sur la même entité (utilisateur), mais essayons de les séparer afin de voir comment créer des relations dans LoopBack. Le nom de cette application révolutionnaire sera Donne à quelqu'un .
Installez les outils de ligne de commande StrongLoop via npm:
$ npm install -g strongloop
Exécutez ensuite le générateur d'applications de LoopBack:
$ slc loopback _-----_ | | .--------------------------. |--(o)--| | Let's create a LoopBack | `---------´ | application! | ( _´U`_ ) '--------------------------' /___A___ | ~ | __'.___.'__ ´ ` |° ´ Y ` ? What's the name of your application? Givesomebody
Ajoutons un modèle. Notre premier modèle s'appellera Gift. LoopBack demandera la source de données et la classe de base. Comme nous n'avons pas encore configuré la source de données, nous pouvons mettre db (memory)
. La classe de base est une classe de modèle générée automatiquement, et nous voulons utiliser PersistedModel
dans ce cas, car il contient déjà toutes les méthodes CRUD habituelles pour nous. Ensuite, LoopBack demande s'il doit exposer le modèle via REST (oui) et le nom du service REST. Appuyez sur Entrée ici pour utiliser la valeur par défaut, qui est simplement le pluriel du nom du modèle (dans notre cas, gifts
).
$ slc loopback:model ? Enter the model name: Gift ? Select the data-source to attach Gift to: (Use arrow keys) ❯ db (memory) ? Select model's base class: (Use arrow keys) Model ❯ PersistedModel ? Expose Gift via the REST API? (Y/n) Yes ? Custom plural form (used to build REST URL):
Enfin, nous donnons les noms des propriétés, leurs types de données et les indicateurs requis / non requis. Le cadeau aura name
et description
Propriétés:
Let's add some Gift properties now. Enter an empty property name when done. ? Property name: name invoke loopback:property ? Property type: (Use arrow keys) ❯ string ? Required? (y/N)Yes
Entrez un nom de propriété vide pour indiquer que vous avez terminé de définir les propriétés.
Le générateur de modèle créera deux fichiers qui définissent le modèle dans l’application common/models
: gift.json
et gift.js
. Le fichier JSON spécifie toutes les métadonnées sur l'entité: propriétés, relations, validations, rôles et noms de méthode. Le fichier JavaScript est utilisé pour définir un comportement supplémentaire et pour spécifier les hooks distants à appeler avant ou après certaines opérations (par exemple, créer, mettre à jour ou supprimer).
Les deux autres entités modèles seront nos modèles de donneur et de receveur. Nous pouvons les créer en utilisant le même processus, sauf que cette fois, mettons User
comme classe de base. Cela nous donnera des propriétés comme username
, password
, email
hors de la boîte. Nous pouvons ajouter simplement le nom et le pays, par exemple, pour avoir une entité complète. Pour le destinataire, nous souhaitons également ajouter l'adresse de livraison.
Jetons un coup d'œil à la structure du projet généré:
Les trois répertoires principaux sont: - /server
- Contient des scripts d'application de nœud et des fichiers de configuration. - /client
- Contient .js, .html, .css et tous les autres fichiers statiques. - /common
- Ce dossier est commun au serveur et au client. Les fichiers de modèle vont ici.
Voici une ventilation détaillée du contenu de chaque répertoire, tirée du Documentation LoopBack :
Fichier ou répertoire | La description | Comment accéder en code |
---|---|---|
Répertoire des applications de niveau supérieur | ||
package.json | Spécification standard du package npm. Voir package.json | N / A |
/ répertoire du serveur - Fichiers d'application de nœud | ||
server.js | Fichier principal du programme d'application. | N / A |
config.json | Paramètres de l'application. Voir config.json . | app.get('setting-name') |
datasources.json | Fichier de configuration de la source de données. Voir datasources.json .Pour un exemple, voir Créer une nouvelle source de données . | app.datasources['datasource-name'] |
model-config.json | Fichier de configuration du modèle. Voir model-config.json .Pour plus d'informations, consultez Connexion de modèles à des sources de données . | N / A |
middleware.json | Fichier de définition du middleware. Pour plus d'informations, consultez Définition du middleware . | N / A |
/boot annuaire | Ajoutez des scripts pour effectuer l'initialisation et la configuration. Voir scripts de démarrage . | Les scripts sont automatiquement exécutés par ordre alphabétique. |
/ répertoire client - fichiers d'application client | ||
README.md | Les générateurs LoopBack créent un fichier README vide au format markdown. | N / A |
Autre | Ajoutez vos fichiers HTML, CSS, JavaScript client. | |
/ répertoire commun - fichiers d'application partagés | ||
/models annuaire | Fichiers de modèles personnalisés:
| Nœud: myModel = app.models.myModelName |
Dans notre exemple, nous avons quelques relations importantes à modéliser. Un donateur peut faire don de nombreux cadeaux, ce qui donne à la relation Le donateur a de nombreux cadeaux . Un receveur peut également recevoir de nombreux cadeaux, nous avons donc également la relation Le destinataire a de nombreux cadeaux . D'un autre côté, Le cadeau appartient au donateur , et peut aussi appartiennent au receveur si le séquestre choisit de l'accepter. Mettons cela dans la langue de LoopBack.
Lequel des éléments suivants est un élément important à garder à l'esprit lorsque vous créez votre design mobile ?
$ slc loopback:relation ? Select the model to create the relationship from: Donor ? Relation type: has many ? Choose a model to create a relationship with: Gift ? Enter the property name for the relation: gifts ? Optionally enter a custom foreign key: ? Require a through model? No
Notez qu'il n'y a pas de modèle traversant; nous tenons simplement la référence au Don.
Si nous répétons la procédure ci-dessus pour Receiver, et ajoutons deux appartient à relations avec Gift, nous réaliserons notre conception de modèle sur un côté arrière. LoopBack met automatiquement à jour les fichiers JSON pour les modèles afin d'exprimer exactement ce que nous venons de faire à travers ces boîtes de dialogue simples:
// common/models/donor.json ... 'relations': { 'gifts': { 'type': 'hasMany', 'model': 'Gift', 'foreignKey': '' } }, ...
Voyons maintenant comment attacher une véritable source de données pour stocker toutes nos données d'application. Aux fins de cet exemple, nous utiliserons MongoDB , mais LoopBack a des modules pour se connecter à Oracle, MySQL, PostgreSQL, Redis et SQL Server.
Tout d'abord, installez le connecteur:
$ npm install --save loopback-connector-mongodb
Ensuite, ajoutez une source de données à votre projet:
$ slc loopback:datasource ? Enter the data-source name: givesomebody ? Select the connector for givesomebody: MongoDB (supported by StrongLoop)
L'étape suivante consiste à configurer votre source de données dans server/datasources.json
. Utilisez cette configuration pour un serveur MongoDB local:
... 'givesomebody': { 'name': 'givesomebody', 'connector': 'mongodb', 'host': 'localhost', 'port': 27017, 'database': 'givesomebody', 'username': '', 'password': '' } ...
Enfin, ouvrez server/model-config.json
et changez le datasource
pour toutes les entités que nous voulons conserver dans la base de données vers 'givesomebody'
.
{ ... 'User': { 'dataSource': 'givesomebody' }, 'AccessToken': { 'dataSource': 'givesomebody', 'public': false }, 'ACL': { 'dataSource': 'givesomebody', 'public': false }, 'RoleMapping': { 'dataSource': 'givesomebody', 'public': false }, 'Role': { 'dataSource': 'givesomebody', 'public': false }, 'Gift': { 'dataSource': 'givesomebody', 'public': true }, 'Donor': { 'dataSource': 'givesomebody', 'public': true }, 'Receiver': { 'dataSource': 'givesomebody', 'public': true } }
Il est temps de voir ce que nous avons construit jusqu'à présent! Nous utiliserons le formidable outil intégré, Explorateur d'API , qui peut être utilisé comme client pour le service que nous venons de créer. Essayons de tester API REST appels.
Dans une fenêtre séparée, démarrez MongoDB avec:
$ mongod
Exécutez l'application avec:
$ node .
Dans votre navigateur, accédez à http://localhost:3000/explorer/
. Vous pouvez voir vos entités avec la liste des opérations disponibles. Essayez d'ajouter un donateur avec un POST /Donors
appel.
Explorateur d'API est très intuitif; sélectionnez l'une des méthodes exposées et le schéma du modèle correspondant sera affiché dans le coin inférieur droit. Dans le data
zone de texte, il est possible d'écrire une requête HTTP personnalisée. Une fois la demande remplie, cliquez sur le bouton 'Essayer' et la réponse du serveur sera affichée ci-dessous.
Comme mentionné ci-dessus, l'une des entités préconstruites avec LoopBack est la classe User. L'utilisateur possède des méthodes de connexion et de déconnexion et peut être lié à une entité AccessToken qui conserve le jeton de l'utilisateur spécifique. En fait, un système complet d'authentification des utilisateurs est prêt à l'emploi. Si nous essayons d'appeler /Donors/login
à travers Explorateur d'API , voici la réponse que nous obtenons:
{ 'id': '9Kvp4zc0rTrH7IMMeRGwTNc6IqNxpVfv7D17DEcHHsgcAf9Z36A3CnPpZJ1iGrMS', 'ttl': 1209600, 'created': '2015-05-26T01:24:41.561Z', 'userId': '' }
Le id
est en fait la valeur du AccessToken, généré et conservé automatiquement dans la base de données. Comme vous le voyez ici, il est possible de définir un jeton d'accès et de l'utiliser pour chaque demande ultérieure.
Une méthode distante est une méthode statique d'un modèle, exposée sur un point de terminaison REST personnalisé. Les méthodes distantes peuvent être utilisées pour effectuer des opérations non fournies par l'API REST de modèle standard de LoopBack.
En plus des méthodes CRUD que nous sortons de la boîte, nous pouvons ajouter autant de méthodes personnalisées que nous le souhaitons. Tous devraient entrer dans le [model].js
fichier. Dans notre cas, ajoutons une méthode à distance au modèle de cadeau pour vérifier si le cadeau est déjà réservé, et une pour répertorier tous les cadeaux qui ne sont pas réservés.
Tout d'abord, ajoutons une propriété supplémentaire au modèle appelée reserved
. Ajoutez simplement ceci aux propriétés dans gift.json
:
... 'reserved': { 'type': 'boolean' } ...
La méthode distante dans gift.js
devrait ressembler à ceci:
module.exports = function(Gift) { // method which lists all free gifts Gift.listFree = function(cb) { Gift.find({ fields: { reserved: false } }, cb); }; // expose the above method through the REST Gift.remoteMethod('listFree', { returns: { arg: 'gifts', type: 'array' }, http: { path: '/list-free', verb: 'get' } }); // method to return if the gift is free Gift.isFree = function(id, cb) { var response; Gift.find({ fields: { id: id } }, function(err, gift) { if (err) return cb(err); if (gift.reserved) response = 'Sorry, the gift is reserved'; else response = 'Great, this gift can be yours'; }); cb(null, response); }; // expose the method through REST Gift.remoteMethod('isFree', { accepts: { arg: 'id', type: 'number' }, returns: { arg: 'response', type: 'string' }, http: { path: '/free', verb: 'post' } }); };
Ainsi, pour savoir si un cadeau particulier est disponible, le client peut maintenant envoyer une requête POST à /api/Gifts/free
, en passant le id
du cadeau en question.
Parfois, il est nécessaire d'exécuter une méthode avant ou après la méthode distante. Vous pouvez définir deux types de hooks distants:
beforeRemote()
s'exécute avant la méthode distante.afterRemote()
s'exécute après la méthode distante.Dans les deux cas, vous fournissez deux arguments: une chaîne qui correspond à la méthode distante à laquelle vous voulez «accrocher» votre fonction et la fonction de rappel. Une grande partie de la puissance des hooks distants est que la chaîne peut inclure des caractères génériques, elle est donc déclenchée par n'importe quelle méthode de correspondance.
Dans notre cas, définissons un crochet pour imprimer des informations sur la console chaque fois qu’un nouveau donateur est créé. Pour ce faire, ajoutons un hook 'avant la création' dans donor.js
:
module.exports = function(Donor) { Donor.beforeRemote('create', function(context, donor, next) { console.log('Saving new donor with name: ', context.req.body.name); next(); }); };
La requête est appelée avec le context
donné, et le next()
callback dans le middleware (discuté ci-dessous) est appelé après l'exécution du hook.
Les applications LoopBack accèdent aux données via des modèles, donc contrôler l'accès aux données signifie définir des restrictions sur les modèles; c'est-à-dire en spécifiant qui ou quoi peut lire et écrire les données ou exécuter des méthodes sur les modèles. Les contrôles d'accès LoopBack sont déterminés par des listes de contrôle d'accès, ou ACL.
Autorisons les donateurs et les destinataires non connectés à voir les cadeaux, mais seuls les donateurs connectés peuvent les créer et les supprimer.
$ slc loopback:acl
Pour commencer, refusons à tout le monde l’accès à tous les points de terminaison.
? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: All methods and properties ? Select the access type: All (match all types) ? Select the role: All users ? Select the permission to apply: Explicitly deny access
Ensuite, autorisez tout le monde à lire les modèles de cadeaux:
$ slc loopback:acl ? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: All methods and properties ? Select the access type: Read ? Select the role: All users ? Select the permission to apply: Explicitly grant access
Ensuite, nous voulons permettre aux utilisateurs authentifiés de créer des cadeaux:
$ slc loopback:acl ? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: A single method ? Enter the method name: create ? Select the role: Any authenticated user ? Select the permission to apply: Explicitly grant access
Enfin, autorisons le propriétaire du cadeau à apporter des modifications:
$ slc loopback:acl ? Select the model to apply the ACL entry to: Gift ? Select the ACL scope: All methods and properties ? Select the access type: Write ? Select the role: The user owning the object ? Select the permission to apply: Explicitly grant access
Maintenant, lorsque nous examinons gift.json
, tout devrait être en place:
'acls': [ { 'accessType': '*', 'principalType': 'ROLE', 'principalId': '$everyone', 'permission': 'DENY' }, { 'accessType': 'READ', 'principalType': 'ROLE', 'principalId': '$everyone', 'permission': 'ALLOW' }, { 'accessType': 'EXECUTE', 'principalType': 'ROLE', 'principalId': '$authenticated', 'permission': 'ALLOW', 'property': 'create' } ],
Une note importante ici: $authenticated
est un rôle prédéfini qui correspond à tous les utilisateurs du système (à la fois les donateurs et les bénéficiaires), mais nous voulons uniquement permettre aux donateurs de créer de nouveaux cadeaux. Par conséquent, nous avons besoin d'un rôle personnalisé. Comme Role est une entité supplémentaire que nous sortons de la boîte, nous pouvons tirer parti de son appel API pour créer le $authenticatedDonor
rôle dans la fonction de démarrage, puis modifiez simplement pricipalId
dans gift.json
.
Il faudra créer un nouveau fichier, server/boot/script.js
, et ajouter le code suivant:
Role.create({ name: 'authenticatedDonor' }, function(err, role) { if (err) return debug(err); })
L'entité RoleMapping mappe les rôles aux utilisateurs. Assurez-vous que Role et RoleMapping sont tous deux exposés via REST. Dans server/model-config.json
, vérifiez que 'public'
est défini sur true
pour l'entité Role. Ensuite, dans donor.js
, nous pouvons écrire un hook 'before create' qui mappera le userID
et roleID
dans l'appel API POST RoleMapping.
L'intergiciel contient des fonctions qui sont exécutées lorsqu'une demande est adressée au point de terminaison REST. Comme LoopBack est basé sur Express, il utilise le middleware Express avec un concept supplémentaire, appelé «phases middleware». Les phases sont utilisées pour définir clairement l'ordre dans lequel les fonctions du middleware sont appelées.
Voici la liste des phases prédéfinies, telles que fournies dans la documentation LoopBack:
Chaque phase comporte trois sous-phases. Par exemple, les sous-phases de la phase initiale sont:
Jetons un coup d'œil à notre middleware.json par défaut:
{ 'initial:before': { 'loopback#favicon': {} }, 'initial': { 'compression': {}, 'cors': { 'params': { 'origin': true, 'credentials': true, 'maxAge': 86400 } } }, 'session': { }, 'auth': { }, 'parse': { }, 'routes': { }, 'files': { }, 'final': { 'loopback#urlNotFound': {} }, 'final:after': { 'errorhandler': {} } }
Dans la phase initiale, nous appelons loopback.favicon()
(loopback#favicon
est l'identifiant du middleware pour cet appel). Ensuite, les modules npm tiers compression
et cors
sont appelés (avec ou sans paramètres). Dans la phase finale, nous avons deux autres appels. urlNotFound
est un appel LoopBack, et errorhandler
est un module tiers. Cet exemple doit démontrer que de nombreux appels intégrés peuvent être utilisés comme les modules externes npm. Et bien sûr, nous pouvons toujours créer notre propre middleware et les appeler via ce fichier JSON.
loopback-boot
Pour conclure, mentionnons un module qui exporte le boot()
fonction qui initialise l'application. Dans server/server.js
vous trouverez le morceau de code suivant, qui amorce l'application:
boot(app, __dirname, function(err) { if (err) throw err; // start the server if `$ node server.js` if (require.main === module) app.start(); });
Ce script recherchera le server/boot
dossier, et chargez tous les scripts qu'il y trouve par ordre alphabétique. Ainsi, dans server/boot
, nous pouvons spécifier n'importe quel script qui doit être exécuté au démarrage. Un exemple est explorer.js
, qui s'exécute Explorateur d'API , le client que nous avons utilisé pour tester notre API.
Avant de vous quitter, je voudrais mentionner Arc StrongLoop , une interface utilisateur graphique qui peut être utilisée comme alternative à slc
outils de ligne de commande. Il comprend également des outils de création, de profilage et de surveillance des applications Node. Pour ceux qui ne sont pas fans de la ligne de commande, cela vaut vraiment la peine d'essayer. Cependant, StrongLoop Arc est sur le point d'être obsolète et sa fonctionnalité est en cours d'intégration dans le Boîte à outils pour développeurs IBM API Connect .
De manière générale, LoopBack peut vous faire économiser beaucoup de travail manuel, car vous obtenez beaucoup de choses hors de la boîte. Il vous permet de vous concentrer sur les problèmes spécifiques à l'application et la logique métier. Si votre application est basé sur les opérations CRUD et manipuler des entités prédéfinies, si vous en avez assez de réécrire l'infrastructure d'authentification et d'autorisation de l'utilisateur alors que des tonnes de développeurs l'ont écrit avant vous, ou si vous souhaitez tirer parti de tous les avantages d'un excellent framework Web comme Express, créez votre API REST avec LoopBack peut réaliser vos rêves. C’est un morceau de gâteau!