• 8 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 21/02/2022

Créez une API Gateway pour votre application ZUUL

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

ZUUL va se positionner comme le point d'entrée unique de notre application. Ainsi, quand ClientUi, par exemple, voudra appeler les microservices, il passera par ZUUL. Ce dernier s'occupe de dispatcher, modifier et appliquer des filtres et des règles à ces requêtes.

 ZUUL se positionne comme le point d'entrée unique de notre application. Il s'occupe de dispatcher, modifier et appliquer des filtres et des règles aux requêtes passées.

Ajoutez ZUUL à l'application

Rendez-vous sur Spring Initializr, et choisissez les composants suivants :

Ensuite, ajoutez cette dépendance à votre pom nouvellement généré.

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

Téléchargez et importez le microservice dans le projet, comme vous l'avez fait pour les autres microservices.

Renommez application.properties en bootstrap.properties, puis ajoutez ceci :

spring.application.name=zuul-server
spring.cloud.config.uri=http://localhost:9101

Créez dans le dépôt distant zuul-server.properties :

server.port 9004
#Eureka
eureka.client.serviceUrl.defaultZone: http://localhost:9102/eureka/

Activez ZUUL ainsi que le client Eureka :

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}

Démarrez ZUUL et vérifiez qu'Eureka le reconnaît bien :

Instances actuellement enregistré avec Eureka

ZUUL fonctionne nativement avec Eureka. Il récupère la liste de tous les microservices disponibles dans Eureka, et les expose via l'URL  localhost:9004/nom-du-microservice.

Ainsi, pour récupérer la liste des produits, il suffit d'appeler  localhost:9004/microservice-produits/Produits.

Vous récupérez alors la liste des produits, comme si vous aviez appelé Microservice-produits directement.

Appliquez des filtres

Les filtres sont une des fonctionnalités les plus importantes de ZUUL. Quand un client appelle ZUUL, celui-ci vous offre la possibilité d'appliquer un filtre à cette requête avant de la passer au microservice concerné.

Dans votre filtre, vous pouvez manipuler, modifier ou adapter une requête selon les besoins. Par exemple, vous pouvez faire un contrôle de sécurité afin de vérifier que le client a bien le droit d'appeler tel ou tel microservice.

Créons alors un premier filtre ZUUL. Ce filtre va tout simplement utiliser un logger SL4j afin d'afficher un message dans la console.

Créez une classe, appelez-la LogFilter et mettez-la dans un package "filters" :

package com.mcommerce.zuulserver.filters;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
@Component
public class LogFilter extends ZuulFilter
{
@Override
public String filterType()
{
return null;
}
@Override
public int filterOrder()
{
return 0;
}
@Override
public boolean shouldFilter()
{
return false;
}
@Override
public Object run() throws ZuulException
{
return null;
}
}

Explications :

  • Un filtre ZUUL est simplement une classe qui hérite de   ZuulFilter  . Vous devez implémenter les 4 méthodes obligatoires.

  • filterType  : cette méthode sert à déterminer le type de filtre à appliquer, elle propose 4 possibilités :

    • pre : permet d'exécuter du code avant la redirection de la requête vers sa destination finale.

    • post : permet d'exécuter du code après que la requête a été redirigée.

    • route : permet d'agir sur la façon de rediriger les requêtes.

    • error : permet d'agir en cas d'erreur lors de la redirection de la requête.

  • filterOrder  : dans votre API Gateway ZUUL, vous aurez forcément des dizaines de filtres. Cette méthode détermine l'ordre d'exécution de ces filtres.

  • shouldFilter  : permet d'écrire les conditions qui doivent être remplies pour que le filtre s'exécute.

  • run  : c'est ici que va la logique de votre filtre.

Modifiez alors le filtre afin de déterminer toutes ces options :

package com.mcommerce.zuulserver.filters;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
@Component
public class LogFilter extends ZuulFilter
{
@Override
public String filterType()
{
return null;
}
@Override
public int filterOrder()
{
return 0;
}
@Override
public boolean shouldFilter()
{
return false;
}
@Override
public Object run() throws ZuulException
{
return null;
}
}
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@Component
public class LogFilter extends ZuulFilter
{
Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public String filterType()
{
return "pre";
}
@Override
public int filterOrder()
{
return 1;
}
@Override
public boolean shouldFilter()
{
return true;
}
@Override
public Object run() throws ZuulException
{
HttpServletRequest req = RequestContext.getCurrentContext().getRequest();
log.info("**** Requête interceptée ! L'URL est : {} " , req.getRequestURL());
return null;
}
}

Explications :

  • Afin de logger les requêtes reçues, on crée une instance du logger de SL4J.

  • On retourne "pre" de   filterType  afin d'afficher notre message avant que la requête ne soit redirigée.

  • On retourne true directement dansshouldFilter  afin d'exécuter ce filtre sur toutes les requêtes sans conditions.

  • run()  : On récupère la requête grâce à RequestContext  qui est utilisé par les filtres dans ZUUL, afin de manipuler les requêtes en attendant leur redirection. On affiche ensuite un message avec l'URL de la requête reçue.

Lancez ZUUL et tous les microservices, puis rendez-vous par exemple à localhost:9004/microservice-produits/Produits afin de tester ZUUL.

Vous devriez voir votre message de log s'afficher dans la console de ZUUL dans IntelliJ à chaque nouvelle requête :

Vous pouvez également créer un autre filtre qui s'exécute à la réponse de la requête, par exemple :

package com.mcommerce.zuulserver.filters;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class ReponseFilter extends ZuulFilter
{
Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public String filterType()
{
return "post";
}
@Override
public int filterOrder()
{
return 1;
}
@Override
public boolean shouldFilter()
{
return true;
}
@Override
public Object run() throws ZuulException
{
HttpServletResponse response = RequestContext.getCurrentContext().getResponse();
response.setStatus(400);
log.info(" CODE HTTP {} ", response.getStatus());
return null;
}
}

Ce filtre récupère toutes les réponses et change le code en 400. Redémarrez ZUUL et envoyez via Postman des requêtes vers n'importe quel microservice ; vous recevrez invariablement un code HTTP 400 Bad Request.

Connectez le client à ZUUL

Nous avons mis en place un filtre qui intercepte les requêtes, pour les logger avant de les rediriger vers leur destination finale. Nous souhaitons à présent que ClientUI puisse faire appel aux différents microservices via ZUUL

Afin que notre client passe par ZUUL, nous devons indiquer aux proxy Feign qu'il faut contacter ZUUL, et non les microservices directement.

Remplacez alors le nom du microservice de destination par celui de ZUUL :

@FeignClient(name = "zuul-server")
@RibbonClient(name = "microservice-produits")
public interface MicroserviceProduitsProxy
{
@GetMapping(value = "/microservice-produits/Produits")
List<ProductBean> listeDesProduits();
/** Notez ici la notation @PathVariable("id") qui est différente de celle qu'on utlise dans le contrôleur
**/
@GetMapping( value = "/microservice-produits/Produits/{id}")
ProductBean recupererUnProduit(@PathVariable("id") int id);
}

On ajoute /microservice-produits/ devant tous les URI. Feign ira alors contacter ZUUL avec l'URI "/microservice-produits/Produits". Comme ZUUL extrait alors le nom du microservice concerné de l'URL "microservice-produits", il pourra rediriger la requête vers la destination voulue. 

Redémarrez le client et testez. Vous devriez voir, dans la console de ZUUL, le log de toutes les requêtes et la liste des produits s'afficher.

Faites de même avec tous les proxies, et votre application devrait fonctionner normalement tout en passant par ZUUL.

En résumé

  • Zuul permet de rediriger les requêtes à l’intérieur de notre application.

Il est temps de sécuriser notre application ! C'est parti !

Exemple de certificat de réussite
Exemple de certificat de réussite