spring mvc rest service redirect / forward / proxy

后端 未结 6 1453
南旧
南旧 2020-11-27 12:02

I have build a web application using spring mvc framework to publish REST services. For example:

@Controller
@RequestMapping(\"/movie\")
public class MovieCo         


        
相关标签:
6条回答
  • 2020-11-27 12:14

    You can mirror/proxy all requests with this:

    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();
    }
    

    This will not mirror any headers.

    0 讨论(0)
  • 2020-11-27 12:14

    If you can get away with using a lower-level solution like mod_proxy that would be the simpler way to go, but if you need more control (e.g. security, translation, business logic) you may want to take a look at Apache Camel: http://camel.apache.org/how-to-use-camel-as-a-http-proxy-between-a-client-and-server.html

    0 讨论(0)
  • 2020-11-27 12:16

    You can use Netflix Zuul to route requests coming to a spring application to another spring application.

    Let's say you have two application: 1.songs-app, 2.api-gateway

    In the api-gateway application, first add the zuul dependecy, then you can simply define your routing rule in application.yml as follows:

    pom.xml

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

    application.yml

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

    and lastly run the api-gateway application like:

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

    Now, the gateway will route all the /api/songs/ requests to http://localhost:8081/songs/.

    A working example is here: https://github.com/muatik/spring-playground/tree/master/spring-api-gateway

    Another resource: http://www.baeldung.com/spring-rest-with-zuul-proxy

    0 讨论(0)
  • 2020-11-27 12:27

    You need something like jetty transparent proxy, which actually will redirect your call, and you get a chance to overwrite the request if you needed. You may get its detail at http://reanimatter.com/2016/01/25/embedded-jetty-as-http-proxy/

    0 讨论(0)
  • 2020-11-27 12:29

    Here's my modified version of the original answer, which differs in four points:

    1. It does not make the request body mandatory, and as such does not let GET requests fail.
    2. It copies all headers present in the original request. If you are using another proxy/web server, this can cause issues due to content length/gzip compression. Limit the headers to the ones you really need.
    3. It does not reencode the query params or the path. We expect them to be encoded anyway. Note that other parts of your URL might also be encoded. If that is the case for you, leverage the full potential of UriComponentsBuilder.
    4. It does return error codes from the server properly.

    @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();
        try {
            return restTemplate.exchange(uri, method, httpEntity, String.class);
        } catch(HttpStatusCodeException e) {
            return ResponseEntity.status(e.getRawStatusCode())
                                 .headers(e.getResponseHeaders())
                                 .body(e.getResponseBodyAsString());
        }
    }
    
    0 讨论(0)
  • 2020-11-27 12:31

    proxy controller with 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);
        }
    
    
    
    0 讨论(0)
提交回复
热议问题