Spring REST avec un proxy Zuul

Spring REST avec un proxy Zuul

1. Vue d'ensemble

Dans cet article, nous allons explorer lescommunication between a front-end application and a REST API that are deployed separately.

L'objectif est de contourner CORS et la restriction de la politique de même origine du navigateur et de permettre à l'interface utilisateur d'appeler l'API même si elle ne partage pas la même origine.

Nous allons essentiellement créer deux applications distinctes - une application d'interface utilisateur et une API REST simple, et nous utiliseronsthe Zuul proxy dans l'application d'interface utilisateur pour proxy les appels à l'API REST.

Zuul est un routeur basé sur JVM et un équilibreur de charge côté serveur par Netflix. Et Spring Cloud a une belle intégration avec un proxy Zuul intégré - c'est ce que nous utiliserons ici.

Lectures complémentaires:

Un exemple d'équilibrage de charge avec Zuul et Eureka

Voyez à quoi ressemble l'équilibrage de charge avec Netflix Zuul.

Read more

Configuration de Swagger 2 avec une API Spring REST

Apprenez à documenter une API Spring REST à l'aide de Swagger 2.

Read more

Introduction aux documents REST Spring

Cet article présente Spring REST Docs, un mécanisme piloté par des tests permettant de générer une documentation des services RESTful à la fois précise et lisible.

Read more

2. Configuration Maven

Tout d'abord, nous devons ajouter une dépendance à la prise en charge de zuul de Spring Cloud vers lespom.xml de notre application d'interface utilisateur:


    org.springframework.cloud
    spring-cloud-starter-zuul
    1.0.4.RELEASE

3. Propriétés de Zuul

Ensuite, nous devons configurer Zuul, et puisque nous utilisons Spring Boot, nous allons le faire dans lesapplication.yml:

zuul:
  routes:
    foos:
      path: /foos/**
      url: http://localhost:8081/spring-zuul-foos-resource/foos

Notez que:

4. L'API

Notre application API est une simple application Spring Boot.

Dans cet article, nous allons considérer l'API déployée sur un serveur exécutanton port 8081.

Commençons par définir le DTO de base pour la ressource que nous allons utiliser:

public class Foo {
    private long id;
    private String name;

    // standard getters and setters
}

Et un contrôleur simple:

@Controller
public class FooController {

    @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
    @ResponseBody
    public Foo findById(
      @PathVariable long id, HttpServletRequest req, HttpServletResponse res) {
        return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
    }
}

5. L'application UI

Notre application d'interface utilisateur est également une simple application Spring Boot.

Dans cet article, nous allons considérer l'API déployée sur un serveur exécutanton port 8080.

Commençons par lesindex.html principaux - en utilisant un peu d'AngularJS:








Foo Details

{{foo.id}} {{foo.name}} New Foo

L'aspect le plus important ici est la façon dont nous accédons à l'APIusing relative URLs!

N'oubliez pas que l'application API n'est pas déployée sur le même serveur que l'application d'interface utilisateur,so relative URLs shouldn’t work, et ne fonctionnera pas sans le proxy.

Cependant, avec le proxy, nous accédons aux ressources deFoo via le proxy Zuul, qui est bien sûr configuré pour acheminer ces requêtes vers l'endroit où l'API est réellement déployée.

Et enfin, l'application réellement activée pour le démarrage:

@EnableZuulProxy
@SpringBootApplication
public class UiApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(UiApplication.class, args);
    }
}

Au-delà de la simple annotation de démarrage, notez que nous utilisons également le style d'annotation d'activation pour le proxy Zuul, qui est plutôt cool, propre et concis.

6. Tester le routage

Maintenant - testons notre application d'interface utilisateur - comme suit:

@Test
public void whenSendRequestToFooResource_thenOK() {
    Response response = RestAssured.get("http://localhost:8080/foos/1");

    assertEquals(200, response.getStatusCode());
}

7. Un filtre Zuul personnalisé

Il existe plusieursZuul filters disponibles, et nous pouvons également créer notre propre personnalisé:

@Component
public class CustomZuulFilter extends ZuulFilter {

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.addZuulRequestHeader("Test", "TestSample");
        return null;
    }

    @Override
    public boolean shouldFilter() {
       return true;
    }
    // ...
}

Ce filtre simple ajoute simplement un en-tête appelé «Test» à la requête - mais bien sûr, nous pouvons devenir aussi complexes que nécessaire pour augmenter ici nos requêtes.

8. Tester le filtre Zuul personnalisé

Enfin, vérifions que notre filtre personnalisé fonctionne - nous allons d'abord modifier nosFooController sur le serveur de ressources Foos:

@Controller
public class FooController {

    @GetMapping("/foos/{id}")
    @ResponseBody
    public Foo findById(
      @PathVariable long id, HttpServletRequest req, HttpServletResponse res) {
        if (req.getHeader("Test") != null) {
            res.addHeader("Test", req.getHeader("Test"));
        }
        return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
    }
}

Maintenant, testons notre solution:

@Test
public void whenSendRequest_thenHeaderAdded() {
    Response response = RestAssured.get("http://localhost:8080/foos/1");

    assertEquals(200, response.getStatusCode());
    assertEquals("TestSample", response.getHeader("Test"));
}

9. Conclusion

Dans cet article, nous nous sommes concentrés sur l'utilisation de Zuul pour acheminer les requêtes d'une application d'interface utilisateur vers une API REST. Nous avons travaillé avec succès autour de CORS et de la politique de même origine et nous avons également réussi à personnaliser et augmenter la demande HTTP en transit.

Lesfull implementation de ce didacticiel se trouvent dansthe GitHub project - il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.