Aceitando URLs com ou sem barra no final
por Tomaz Lavieri, adaptado para VRaptor 4
Para quem teve dificuldade em conseguir determinar urls como:
@Path("produto/{produto.id}")
public void visualiza(Produto produto) {...}
quando digitava a URI /produto/1/ e o link não funcionava, segue abaixo duas maneiras de corrigir o problema.
Nota: Isso não é necessariamente um problema, pois a URL /abc é diferente da /abc/. Portanto o comportamento de dar 404 é o esperado.
A primeira maneira é colocar os dois tipos de URL (com e sem barra) na anotação @Path
, assim:
@Path(value = {"produto/{produto.id}", "produto/{produto.id}/"})
public void visualiza(Produto produto) {...}
Note que esta modificação só irá funcionar para o método que possui a anotação @Path
. Os outros métodos não serão afetados por esta mudança.
A outra maneira é escrever a classe abaixo. Desta forma, diferentemente da primeira, fará com que as duas URLs (com ou sem barra) sejam equivalentes.
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Specializes;
import javax.inject.Inject;
import javax.servlet.FilterChain;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.events.ControllerNotFound;
import br.com.caelum.vraptor.http.MutableRequest;
import br.com.caelum.vraptor.http.MutableResponse;
import br.com.caelum.vraptor.http.route.ControllerNotFoundException;
import br.com.caelum.vraptor.http.route.Router;
import br.com.caelum.vraptor.view.Results;
@RequestScoped
@Specializes
public class Error404 extends DefaultControllerNotFoundHandler {
private final Router router;
private final Result result;
/**
* @deprecated CDI eyes only
*/
protected Error404() {
this(null, null, null);
}
@Inject
public Error404(Router router, Result result, Event<ControllerNotFound> event) {
super(event);
this.router = router;
this.result = result;
}
@Override
public void couldntFind(FilterChain chain,
MutableRequest request, MutableResponse response) {
try {
String uri = request.getRequestedUri();
if (uri.endsWith("/")) {
tryMovePermanentlyTo(request, uri.substring(0, uri.length()-1));
} else {
tryMovePermanentlyTo(request, uri + "/");
}
} catch (ControllerNotFoundException ex) {
super.couldntFind(chain, request, response);
}
}
private void tryMovePermanentlyTo(MutableRequest request, String newUri) {
router.parse(newUri, HttpMethod.of(request), request);
result.use(Results.status()).movedPermanentlyTo(newUri);
}
}