web-dev-qa-db-fra.com

Code pour obtenir un servlet Java pour agir en tant que proxy?

J'ai deux applications Web Java qui ont un seul servlet qui est mappé à une URL spécifique:

red.war/
    WEB-INF/classes
        com.me.myorg.red.RedServlet (maps to http://red.example.com/doStuff)
blue.war/
    WEB-INF/classes
        com.me.myorg.blue.BlueServlet (maps to http://blue.example.com/doStuff)

Je souhaite placer ces applications (je les appelle mes "applications dorsales") derrière une "application proxy" (servlet) qui décidera laquelle de ces deux applications servira en définitive une demande côté client.

Cette application Web proxy prendrait une requête HTTP entrante et déterminera à laquelle des 2 "applications dorsales" (rouge ou bleue) la redirection. La demande serait ensuite transmise à http://red.example.com/doStuff (puis traitée par RedServlet#doGet(...)) ou http://blue.example.com/doStuff (puis traitée par BlueServlet#doGet(...)). La réponse renvoyée par l'application principale (à nouveau, soit RedServlet#doGet(...) ou BlueServlet#doGet(...)) serait ensuite renvoyée au servlet proxy et finalement renvoyée au client.

En d'autres termes, en pseudo-code:

public class ProxyServlet extends HttpServlet {
    @Override
    public doGet(HttpServletRequest request, HttpServletResponse response) {
        String forwardingAddress;
        if(shouldBeRed(request))
            forwardingAddress = "http://red.example.com/doStuff";
        else
            forwardingAddress = "http://blue.example.com/doStuff";

        PrintWriter writer = response.getWriter();

        writer.write(getResponseFromBackend(forwardingAddress, request));
    }

    private String getResponseFromBackend(String addr, HttpServletRequest req) {
        // Somehow forward req to addr and get HTML response...
    }
}

Est-ce possible? Si oui, comment et quel code aurais-je besoin d'écrire pour que cela fonctionne?

21
IAmYourFaja

Vous pouvez utiliser une variable RequestDispatcher pour transmettre votre demande de la manière suivante:

RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(forwardingAddress);

// here you have the choice whether to use include(..) or forward(..) see below
if(useInclude)
    dispatcher.include(httpRequest, httpResponse);
else
    dispatcher.forward(httpRequest, httpResponse);

... où useInlcude est défini sur votre choix avec les options suivantes:

  • comprendre
    C’est probablement ce que vous voulez faire: Chargez le contenu de la forwardingAdress dans votre réponse .
    • Cela signifie que vous pouvez même inclure plusieurs cibles dans une seule réponse.
    • Le client ne réalisera même pas cette procédure et n'aura pas besoin de voir le document cible.
  • vers l'avant
    Envoyer un transfert à la forwardingAddress. Cela indiquera au client de soumettre une nouvelle demande à l'URL spécifiée .
    • Si vous le faites dans un navigateur avec des outils de développement, vous verrez une deuxième demande.
    • Le client doit pouvoir voir et charger l'URL cible.
    • Vous ne pouvez transférer que vers une seule cible.

Voir aussi les liens suivants:

  • RequestDispatcher javadoc , en particulier pour les notes:
    • forward doit être appelé avant que la réponse ait été envoyée au client (avant que la sortie du corps de la réponse n'ait été vidée). Si la réponse a déjà été validée, cette méthode lève une exception IllegalStateException. La sortie non validée dans le tampon de réponse est automatiquement effacée avant le transfert.
    • include: les paramètres de requête et de réponse doivent être les mêmes objets que ceux qui ont été transmis à la méthode de service du servlet appelant ou être des sous-classes des classes ServletRequestWrapper ou ServletResponseWrapper qui les encapsulent.
  • Exemple avec URLRewriteFilter
    bien que cet exemple soit implémenté en utilisant un Filter au lieu d'un Servlet, le comportement est le même (Remarque: cet exemple fait partie d'un framework de la mienne et contient donc une surcharge dans les classes parentes. Jetez un coup d'œil à la section pertinente ... )
11
ultimate

Comme il n’ya pas encore de réponse approuvée, j’essaie d’écrire comment je vois la solution à cette demande en utilisant la bibliothèque Apache-http-commons. En outre, je suggère d'ajouter une couleur sur l'écrivain.

public class ProxyServlet extends HttpServlet {
@Override
public doGet(HttpServletRequest request, HttpServletResponse response) {
    String forwardingAddress;
    if(shouldBeRed(request))
        forwardingAddress = "http://red.example.com/doStuff";
    else
        forwardingAddress = "http://blue.example.com/doStuff";

    PrintWriter writer = response.getWriter();

    writer.write(getResponseFromBackend(forwardingAddress, request));
    **writer.flush();**
}

private String getResponseFromBackend(String addr, HttpServletRequest req) {
        HttpClient client = new HttpClient();
        HttpMethod method = new GetMethod(url);
        client.executeMethod(method);
        String body=method.getResponseBodyAsString();
        return body;

}

}

0
ivan.rosina