2017-09-03 4 views
1

Je voudrais savoir comment faire un point final en cours d'exécution comme RunKit does.Comment créer un point de terminaison API en cours d'exécution?

Dans cette page de RunKit, il génère une URL associée à un code. L'ouverture de cette URL dans un navigateur verra le response défini par le code. De plus, les modifications apportées au code seront reflétées en temps réel.

Est-ce que quelqu'un sait comment ils y parviennent?

Je sais définir une API fixe dans un site web de pile-moyenne. Par exemple, https://myexample.com/api/add/3/5 peut être appelée en raison du code suivant. Mais je ne sais pas comment faire une API dont la fonction peut être modifiée en temps réel.

router.get('/api/add/:a/:b', function (req, res, next) { 
    var r = Number(req.params.a) + Number(req.params.b); 
    res.json(r) 
}) 
+0

merci ... il est la « mise à jour automatique » partie que je ne vois pas comment ils mettent en œuvre ... – SoftTimur

+0

Je vois ... Je l'ai vu des gens utiliser nodemon. Maintenant, ce que je veux savoir, c'est comment ils passent le contenu de la fonction mise à jour dans le navigateur dans 'router.get (...)' avant de déclencher la mise à jour automatique. – SoftTimur

Répondre

0

L'idée de base est, vous créez une base de données de fonctions stockées sous forme de chaînes. Puisque JS vous permet de créer une fonction à partir d'une chaîne à l'aide du constructeur Function(), vous pouvez générer dynamiquement une fonction à la demande. J'ai fourni un point de terminaison POST pour enregistrer la fonction.

var express = require("express"); 
var app = express(); 
var bodyParser = require('body-parser'); 
var router = express.Router(); 
var mongoose = require('mongoose'); 

db = mongoose.connect('mongodb://localhost:27017/login1'); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: true })); 

var data = new mongoose.Schema({ 
    "name": String, 
    "content": String 
}); 
model = mongoose.model("functions", data); 

router.post('/create', (req, res) => { 
    // Insert validation for security and removing duplicates etc. 
    model.insertMany({"name": req.body.name, "content": req.body.content}).then((d, err) => { 
     res.status(200).send({'result': "Added"}); 
    }); 
}); 

router.get('/:func/*', (req, res) => { 
    var func = req.params.func; 
    var args = req.params['0'].split('/'); 
    model.findOne({"name": func}).then((d, err) => { 
     if (err) {return res.status(404).send({'result': "Error with database"});} 
     else if (d === null) {return res.status(202).send({'result': "Function not present"});} 
     var func = Function(d.content); 
     res.status(200).send({'result': func(...args)}); 
    }); 
}); 

app.use("/", router); 
var port = process.env.PORT || 3000; 

var server = app.listen(port, function() { 
    console.log('Express server listening on port ' + port); 
}); 

permet de tester ceci:

$ node server.js 
Express server listening on port 3000 

De postier ou d'une autre fenêtre de terminal:

$ curl -X GET "http://localhost:3000/add/1/2/3" 
{"result":"Function not present"} 

permet maintenant enregistrer la fonction add (qui est sum of arguments):

$ curl -X POST "http://localhost:3000/create/" -H "content-type:application/json" -d '{"name": "add", "content": "return [...arguments].reduce((i, j) => i+=parseInt(j), 0);"}' 
{'result': "Added"} 

La fonction enregistrée ici peut être beaucoup plus compliquée. N'oubliez pas que vous pouvez obtenir tous les arguments passés à la fonction en utilisant la variable Agruments.

Testez:

$ curl -X GET "http://localhost:3000/add/1/2/3" 
{"result": 6} 

$ curl -X GET "http://localhost:3000/add/100/3/5/10/9/2" 
{"result": 129} 
+0

Merci pour cela, et désolé pour la réponse tardive. Ce que vous faites est de stocker toutes les fonctions et leurs paramètres dans un objet de hachage, puis appelez la bonne fonction basée sur le routeur. Mais, je veux quelque chose de plus flexible: je veux qu'une fonction soit créée dynamiquement avec la chaîne entrée par les utilisateurs dans le navigateur. Je suppose que quelque part construire une fonction avec une chaîne JS est nécessaire. – SoftTimur

+0

Je stocke les fonctions dans un objet de hachage, ce qui signifie que si je prends en charge n fonctions, vous pouvez les appeler dynamiquement à partir du point de terminaison api. Les paramètres de la fonction proviennent directement de l'URL elle-même. Ils supportent en outre un moyen d'ajouter une fonction à l'objet de hachage, ce qui le rend dynamique. Je vais essayer d'ajouter cela aussi. – TheChetan

+0

Si vous pouvez ajouter une fonction construite dynamiquement par une chaîne JS, ce sera bien. Si vous pouvez vous assurer que votre code fonctionne, ce sera génial. – SoftTimur

1

Les middlewares express sont juste des fonctions JS régulières.

Afin d'avoir des routes avec des fonctionnalités changeantes, vous n'avez pas besoin de changer la fonction de middleware à l'exécution, vous avez juste besoin de changer son comportement.

Je vais essayer de démontrer une solution possible ici.
Veuillez noter que c'est juste une preuve de concept, pas une solution prête pour la production et/ou sécurisée.


Supposons que vous avez une sorte d'éditeur de code en ligne sur votre site Web qui permet aux utilisateurs d'écrire du code JS et l'enregistrer sur votre base de données.

Vous pouvez configurer vos itinéraires point final comme celui-ci:

router.get('/endpoint/:id', (req, res) => { 
    // this id identifies a previously saved code wrote by a user 
    let id = req.params.id   

    // NOTE: THIS IS NOT ACTUAL WORKING JS CODE 
    // fetch the previously saved code from your database as a string 
    let code = database.getDocumentById(id) 

    // you can construct an actual JS function form the string, using the `Function()` constructor 
    let f = Function(code) 

    // now you can call the function, do whatever you like with it and finally send the user the results 
    let result = f() 
    res.send(result) 
}) 

Vous devez probablement créer une fonction wrapper pour le code fourni utilisateur et contrôler ce qui sera exécuté et quels seront les résultats.


P.S.
Consultez également ce message SO à créer des fonctions à partir de chaînes JS:
Is there a way to create a function from a string with javascript?