0

Which is the best way to do a server side redirect for a REST call?

Consider the following scenario:

@RestController
@RequestMapping("/first")
public class FirstController {

    @GetMapping
    public String duStuff(){
        //Redirect to SecondController's doStuff()
    }

}

@RestController
@RequestMapping("/second")
public class SecondController {

    @GetMapping
    public String doStuff(){
        //Redirect here from FirstController's do stuff()
    }

}

I know the HTTP specs state that 3XX response status codes should be used for redirection, but to my understanding that is done on client side (by the client invoking the URI specified by the Location response header).

The only way I've managed to implement this was by using a RestTemplate that does a request from the endpoint in FirstController to the endpoint in SecondController. It works, but I am curious if there is a better way of achieving this.

@RestController
@RequestMapping("/first")
public class FirstController {

    @Autowired
    private RestTemplate template;

    @GetMapping
    public String duStuff(){
        /** Is there a better way of doing this, considering I don't want 
            to get the client involved in the redirect to `second`? */
        return template.getForEntity("second", String.class).getBody();
    }

}

Note: This is not a Spring MVC application (so I can't redirect via return new ModelAndView("redirect:/redirectUrl", model) or RedirectView)

Thanks for your help!

  • If you autowire a `SecondController` you can just use it's functions in your `FirstController` as you would do with any non-rest java class. – T A Sep 24 '18 at 12:33
  • Thanks for your answer! My two endpoints are in different JVMs and there is no code dependency between the microservice exposing `FirstController` and the microservice exposing `SecondController`. –  Sep 24 '18 at 12:37
  • By using [RedirectView](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/view/RedirectView.html)? [example](https://www.baeldung.com/spring-redirect-and-forward) – m4gic Sep 24 '18 at 12:41
  • That works for Spring MVC apps. –  Sep 24 '18 at 13:59
  • HttpClient.execute for post/put can be used, but I personally prefer restTemplate. Its functions handle response in a better an easier way without having to read from buffer reader, adding it to string and then mapping it to correct bean using object mapper (which is the case with httpClient) – Nutan Sep 24 '18 at 16:08
  • Which fwk are you using ? If none, you can try to interacte directly with the response itself : public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{ response.sendRedirect("http://www.google.com"); } – Fabien MIFSUD Sep 24 '18 at 16:09
  • @NathanHughes What I am trying to achieve is implementing a `307 Temporary Redirect` behavior without getting the client involved (instead of relying on the client invoking the URI from the response `Location` header, I want to do the redirect myself on server side). I do not expect /first to have any side effects. Thanks. –  Sep 25 '18 at 02:40
  • @FabienMIFSUD Thanks for your suggestion, but I think `response.sendRedirect("google.com")` still relies on the client invoking "google.com". As per documentation, `response.sendRedirect() sends a temporary redirect response to the client using the specified redirect location URL and clears the buffer`. Regarding the framework, I am using the Spring stack. –  Sep 25 '18 at 02:44
  • @Nutan I am considering using a `RestTemplate` in the `FirstController`'s `doStuff` method, and manually invoking `SecondController`'s `doStuff` method via a REST call. I was curious if there was a way better way of achieving this (something that would work without me manually forwarding the request). Will update the question to make this more clear. Thanks. –  Sep 25 '18 at 02:49
  • 1
    @alexrolea, a redirect in a http point of view is : client request an url to a server, this server send a response to the client to tell him that the resource is available at an another url, the client call automatically the new url. A redirect can be permanent or not. If you want a redirect, this is the good way. If you want your server to call another url at server side, use restTemplate to call the other resource and send it back to the client. – Fabien MIFSUD Sep 25 '18 at 07:36
  • 1
    @FabienMIFSUD thanks for the answer! –  Sep 25 '18 at 07:41

3 Answers3

1

For reference: Redirect to an external URL from controller action in Spring MVC

 @RequestMapping(value = "/redirect", method = RequestMethod.GET)
    public void method(HttpServletResponse httpServletResponse) {
        httpServletResponse.setHeader("Location", projectUrl);
        httpServletResponse.setStatus(302);
    }
Nutan
  • 1,287
  • 11
  • 15
  • I have mentioned the reference – Nutan Sep 24 '18 at 16:36
  • Thanks for your answer, but I think that works by the client invoking the URI from the `Location` header, making the redirect itself implemented by the client. I am looking to do a redirect without involving the client. –  Sep 25 '18 at 02:30
0

Sounds like a design flaw. I would extract what is common between the two @Controllers into a @Service and then invoke the @Service from the @Controllers.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • What I am trying to achieve is implementing a `307 Temporary Redirect` behavior without getting the client involved (instead of relying on the client invoking the URI from the response `Location` header, I want to do the redirect myself on server side). No additional design constraints. –  Sep 25 '18 at 02:37
0

If somebody is aware of a good method of achieving this please leave an answer and I will accept it.

There is no out-of-the-box support for a REST server-side redirect.

For a Spring MVC application, you can use ModelAndView("redirect:/redirectUrl", model) or RedirectView.

For REST, you have two options.

  1. Rely on the 3XX status codes and the Location header. This would result in the REST client doing the redirect by invoking the URL from the Location header.
  2. Use a RestTemplate (or another HTTP client) on your server and manually invoke the URL you want to redirect to.