Api REST/JSON
Exposez une API REST/JSON
Les lambdas from exécutées à partir de www.mddynamics.fr/app sont automatiquement exposées sur l'URL générique
http[s]://$HOST:$PORT/app/
du node
caution
Il est recommandé d'utiliser des URL spécifiques à vos projets pour les lambdas qui n'ont pas besoin d'être exposées à l'extérieur. De cette façon, leurs URLs ne seront accessibles que depuis le réseau interne de la plateforme. Cette rupture protocolaire offre un niveau de sécurité supplémentaire.
Etapes
- Codez une api stateless
GET /demo/api
etPOST /demo/api
- Associer des ressources d'exécution
- Créer un token d'accès
- Tester l'api
- Entêtes HTTP
- Paramètres HTTP
- Payload
- Réponse HTTP
Codez l'api
Dans cet exemple, l'api est exposée sur http://localhost:8080/app/demo/api
et :
- émet un log à la réception de la requête
- retourne
POST request received at <datetime>
pour une requête POST - retourne
GET request received at <datetime>
pour une requête GET - retourne une erreur
400 BAD REQUEST
pour les autres méthodes HTTP
Plus d'informations ici URL, Payload, Headers, Paramètres
package org.mddynamics.link.stream.custom;
import org.mddynamics.network.dynamic.StreamDefinitionException;
import org.mddynamics.network.stream.JavaStreamMaker;
import org.mddynamics.network.stream.LinkStream;
import org.mddynamics.util.rdf.Resource;
import org.mddynamics.util.rdf.Registry;
import org.mddynamics.util.HTTPResponse;
import org.mddynamics.network.stream.Event;
import org.mddynamics.util.rdf.MDDynamicsLink;
import org.mddynamics.network.stream.util.Asset;
import org.mddynamics.network.stream.util.Aggregation;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;
import org.joda.time.DateTime;
public class CompleteApi extends JavaStreamMaker {
public CompleteApi() {
}
@Override
public void build() throws Exception {
make("api")
.from("REST/JSON demo", "www.mddynamics.fr/app/demo/api", (stream, request) -> {
stream.info("request received: %s", request);
return request;
})
.when("POST /demo/api", (stream, request) -> request.headers.getOrDefault("mddynamics-api", ""))
.reply("ok", (stream, request) -> ok(stream, "POST request received at %s", DateTime.now()))
.when("GET /demo/api", (stream, request) -> request.headers.getOrDefault("mddynamics-api", ""))
.reply("ok", (stream, request) -> ok(stream, "GET request received at %s", DateTime.now()))
.otherwise("error")
.reply("error", (stream, request) -> error(stream, 400, "Bad request", "Request not supported"));
}
private Resource ok(LinkStream stream, String message, Object... args) {
return stream.registry().getResource("response")
.set("status", 200)
.set("payload/app", "APP32")
.set("payload/message", String.format(message, args));
}
private Resource error(LinkStream stream, int statusCode, String code, String message, Object... args) {
return stream.registry().getResource("response")
.set("status", statusCode)
.set("payload/app", "APP32")
.set("payload/error/code", code)
.set("payload/error/message", String.format(message, args));
}
}
Vous pouvez compléter les lambdas :
- from pour valider la requête par exemple
- reply(200 OK) pour exécuter vos traitements
Il est également possible de distribuer les traitements de l'api sur d'autres endpoints et nodes à l'aide des clauses to ou parallel par exemple, avant de retourner une réponse avec reply
Associer des ressources d'exécution
Dans l'onglet packages, sélectionnez 10 endpoints et 1 node pour l'url de la lambda from
Si vous avez besoin de plus de performance, il suffit simplement d'ajouter plus d'endpoints ou de sélectionner d'autres nodes sans modifier votre code.
caution
Les requêtes HTTP sont automatiquement load-balancées sur les ressources (endpoints et nodes) associés à la lambda from. Vos traitements doivent donc être stateless
Créer un token d'accès
Tous les streams sont protégés par token d'accès. Pour obtenir un token il faut s'abonner au stream:
- cliquer sur
Publier
(onglet général) pour autoriser les abonnements au stream - cliquer sur
s'abonner
(onglet général) pour créer un abonnement et générer le token
Vous pouvez exécutez plusieurs streams ou versions de streams (api, service, etc.) sur la même URL ; c'est le token utilisé qui déterminera le stream et la version exécutée. Rien de plus simple pour changer de version à chaud!
Tester
GET http://localhost:8080/app/demo/api
Envoyez la requête suivante, en remplaçant $token
par le token de votre abonnement
- La requête transite par
from/when('GET /demo/api')/reply('ok')
et retourne une réponse nominale200 OK
curl -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X GET http://localhost:8080/app/demo/api
Réponse
{
"status": "OK",
"statusCode": 200,
"message": "GET request received at 2020-04-20T21:32:57.095+02:00"
}
POST http://localhost:8080/app/demo/api
Envoyez la requête suivante, en remplaçant $token
par le token de votre abonnement
- La requête transite par
from/when('POST /demo/api')/reply('ok')
et retourne une réponse nominale200 OK
après avoir tracé le payload en logs
curl -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X POST http://localhost:8080/app/demo/api
Réponse
{
"status": "OK",
"statusCode": 200,
"message": "POST request received at 2020-04-20T21:35:14.313+02:00"
}
PUT http://localhost:8080/app/demo/api
Envoyez la requête suivante, en remplaçant $token
par le token de votre abonnement
- La requête transite par
from/otherwise('BAD REQUEST')/reply('error')
et retourne uneerreur 400
curl -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X PUT http://localhost:8080/app/demo/api
Réponse
{
"app": "APP32",
"error": {
"code": "Bad request",
"message": "Request not supported"
}
}