Primavera serviço resto mvc redirecionamento / avançar / proxy

votos
36

Eu tenho construir uma aplicação web usando Spring framework MVC para publicar serviços REST. Por exemplo:

@Controller
@RequestMapping(/movie)
public class MovieController {

@RequestMapping(value = /{id}, method = RequestMethod.GET)
public @ResponseBody Movie getMovie(@PathVariable String id, @RequestBody user) {

    return dataProvider.getMovieById(user,id);

}

Agora eu preciso para implantar o meu aplicativo, mas eu tenho o seguinte problema: Os clientes não têm acesso directo ao computador no qual reside o aplicativo (Há um firewall). Portanto eu preciso de uma camada de redirecionamento em uma máquina proxy (acessíveis pelos clientes) que chama o serviço descanso efectivo.

Eu tentei fazer uma nova chamada usando RestTemplate: Por exemplo:

@Controller
@RequestMapping(/movieProxy)
public class MovieProxyController {

    private String address= http://xxx.xxx.xxx.xxx:xx/MyApp;

    @RequestMapping(value = /{id}, method = RequestMethod.GET)
    public @ResponseBody Movie getMovie(@PathVariable String id,@RequestBody user,final HttpServletResponse response,final HttpServletRequest request) {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.exchange( address+ request.getPathInfo(), request.getMethod(), new HttpEntity<T>(user, headers), Movie.class);

}

Este é ok, mas eu preciso reescrever cada método no controlador para usar o resttemplate. Além disso, isso faz com que redundante serialização / desserialização na máquina proxy.

Eu tentei escrever uma função genérica usando restemplate, mas não deu certo:

@Controller
@RequestMapping(/movieProxy)
public class MovieProxyController {

    private String address= http://xxx.xxx.xxx.xxx:xx/MyApp;

    @RequestMapping(value = /**)
    public ? redirect(final HttpServletResponse response,final HttpServletRequest request) {        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.exchange( address+ request.getPathInfo(), request.getMethod(), ? , ?);

}

Eu não poderia encontrar um método de resttemplate que trabalha com solicitação e resposta objetos.

Eu também tentei redirecionamento primavera e para a frente. Mas redirecionar não alterar o endereço IP do cliente do pedido, então eu acho que é inútil neste caso. Eu não poderia avançar para uma outra URL também.

Existe uma maneira mais adequada para conseguir isso? Desde já, obrigado.

Publicado 06/02/2013 em 10:55
fonte usuário
Em outras línguas...                            


6 respostas

votos
1

Se você pode ir longe com o uso de uma solução de nível inferior como mod_proxy que seria a maneira mais simples para ir, mas se você precisar de mais controle (por exemplo, segurança, tradução, lógica de negócio), você pode querer dar uma olhada em Apache Camel: http : //camel.apache.org/how-to-use-camel-as-a-http-proxy-between-a-client-and-server.html

Respondeu 04/01/2014 em 00:09
fonte usuário

votos
44

Você pode espelhar / proxy todas as solicitações com este:

private String server = "localhost";
private int port = 8080;

@RequestMapping("/**")
@ResponseBody
public String mirrorRest(@RequestBody String body, HttpMethod method, HttpServletRequest request) throws URISyntaxException
{
    URI uri = new URI("http", null, server, port, request.getRequestURI(), request.getQueryString(), null);

    ResponseEntity<String> responseEntity =
        restTemplate.exchange(uri, method, new HttpEntity<String>(body), String.class);

    return responseEntity.getBody();
}

Isto não irá espelhar quaisquer cabeçalhos.

Respondeu 19/05/2014 em 12:25
fonte usuário

votos
7

Você pode usar Netflix Zuul para encaminhar solicitações provenientes de uma aplicação de Primavera para outra aplicação primavera.

Vamos dizer que você tem duas aplicações: 1.songs app, 2.api gateway

Na aplicação api-gateway, primeiro adicione a ser dependente Zuul, então você pode simplesmente definir sua regra de roteamento no application.yml da seguinte forma:

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
    <version>LATEST</version>
</dependency>

application.yml

server:
  port: 8080
zuul:
  routes:
    foos:
      path: /api/songs/**
      url: http://localhost:8081/songs/

e por fim executar a aplicação api gateway como:

@EnableZuulProxy
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Agora, o gateway irá encaminhar todas as /api/songs/solicitações para http://localhost:8081/songs/.

Um exemplo de trabalho é aqui: https://github.com/muatik/spring-playground/tree/master/spring-api-gateway

Outro recurso: http://www.baeldung.com/spring-rest-with-zuul-proxy

Respondeu 13/03/2017 em 09:31
fonte usuário

votos
2

Aqui está a minha versão modificada da resposta original, que difere em três pontos:

  1. Não faz o corpo da solicitação obrigatória, e como tal não deixa requisições GET falhar.
  2. Ele copia todos os cabeçalhos presentes no pedido inicial. Se você estiver usando outro servidor proxy / web, isso pode causar problemas devido ao conteúdo de compressão comprimento / gzip. Limitar os cabeçalhos para o que você realmente precisa.
  3. Ele não reencode os parâmetros de consulta ou o caminho. Esperamos que eles sejam codificados de qualquer maneira. Note-se que outras partes do seu URL também pode ser codificado. Se for esse o caso para você, aproveitar todo o potencial da UriComponentsBuilder.

@RequestMapping("/**")
public ResponseEntity mirrorRest(@RequestBody(required = false) String body, 
    HttpMethod method, HttpServletRequest request, HttpServletResponse response) 
    throws URISyntaxException {

    String requestUrl = request.getRequestURI();

    URI uri = new URI("http", null, server, port, null, null, null);
    uri = UriComponentsBuilder.fromUri(uri).path(requestUrl)
        .query(request.getQueryString()).build(true).toUri();

    HttpHeaders headers = new HttpHeaders();
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
        String headerName = headerNames.nextElement();
        headers.set(headerName, request.getHeader(headerName));
    }

    HttpEntity<String> httpEntity = new HttpEntity<>(body, headers);

    RestTemplate restTemplate = new RestTemplate();
    return restTemplate.exchange(uri, method, httpEntity, String.class);
}
Respondeu 22/03/2018 em 13:13
fonte usuário

votos
0

Você precisa de algo como jetty transparent proxy, o que realmente vai redirecionar sua chamada, e você tem a chance de substituir o pedido, se você necessário. Você pode obter os seus detalhes na http://reanimatter.com/2016/01/25/embedded-jetty-as-http-proxy/

Respondeu 17/12/2018 em 11:39
fonte usuário

votos
0

controlador de proxy com oauth2

@RequestMapping("v9")
@RestController
@EnableConfigurationProperties
public class ProxyRestController {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails;

    @Autowired
    private ClientCredentialsResourceDetails clientCredentialsResourceDetails;

    @Autowired
    OAuth2RestTemplate oAuth2RestTemplate;


    @Value("${gateway.url:http://gateway/}")
    String gatewayUrl;

    @RequestMapping(value = "/proxy/**")
    public String proxy(@RequestBody(required = false) String body, HttpMethod method, HttpServletRequest request, HttpServletResponse response,
                        @RequestHeader HttpHeaders headers) throws ServletException, IOException, URISyntaxException {

        body = body == null ? "" : body;
        String path = request.getRequestURI();
        String query = request.getQueryString();
        path = path.replaceAll(".*/v9/proxy", "");
        StringBuffer urlBuilder = new StringBuffer(gatewayUrl);
        if (path != null) {
            urlBuilder.append(path);
        }
        if (query != null) {
            urlBuilder.append('?');
            urlBuilder.append(query);
        }
        URI url = new URI(urlBuilder.toString());
        if (logger.isInfoEnabled()) {
            logger.info("url: {} ", url);
            logger.info("method: {} ", method);
            logger.info("body: {} ", body);
            logger.info("headers: {} ", headers);
        }
        ResponseEntity<String> responseEntity
                = oAuth2RestTemplate.exchange(url, method, new HttpEntity<String>(body, headers), String.class);
        return responseEntity.getBody();
    }


    @Bean
    @ConfigurationProperties("security.oauth2.client")
    @ConditionalOnMissingBean(ClientCredentialsResourceDetails.class)
    public ClientCredentialsResourceDetails clientCredentialsResourceDetails() {
        return new ClientCredentialsResourceDetails();
    }

    @Bean
    @ConditionalOnMissingBean
    public OAuth2RestTemplate oAuth2RestTemplate() {
        return new OAuth2RestTemplate(clientCredentialsResourceDetails);
    }


Respondeu 22/01/2019 em 07:22
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more