Caso alguém passe por aqui com problemas de acesso Cross-Domain (CORS) com VRaptor segue solução:
Basicamente a solução é acrescentar o Header abaixo para todas as requisições HTTP (inclusive OPTIONS):
Access-Control-Allow-Origin:*
Onde * libera requisições de qualquer origem. No lugar do * pode ser um ou mais domínios em específico (mais seguro).
E nas requisições HTTP OPTIONS, além do Header acima, é necessário incluir tb:
Access-Control-Allow-Methods: [GET, POST, OPTIONS]
Access-Control-Allow-Headers: Content-Type, accept, authorization, origin
Inicialmente eu havia feito um Filter e um Interceptor para tratar dessa questão.
O interceptor sozinho não resolve o problema porque o VRaptor responde automaticamente a requisições HTTP OPTIONS e o Interceptor nunca é chamado.
Com o Filter não consigo saber quais métodos de fato deveriam ser permitidos para determinada URI, o que me forçava a liberar sempre todos.
Hoje estava refatorando o código e achei mais prático substituir o Filter por um controller:
@Resource
public class CORSController {
private final Result result;
private final Router router;
private final RequestInfo requestInfo;
public CORSController(Result result, Router router, RequestInfo requestInfo) {
this.result = result;
this.router = router;
this.requestInfo = requestInfo;
}
@Options @Path("/*")
public void options() {
Set<HttpMethod> allowed = router.allowedMethodsFor(requestInfo.getRequestedUri());
result.use(Results.status()).header("Allow", allowed.toString().replaceAll("\\[|\\]", ""));
result.use(Results.status()).header("Access-Control-Allow-Origin", "*");
result.use(Results.status()).header("Access-Control-Allow-Methods", allowed.toString().replaceAll("\\[|\\]", ""));
result.use(Results.status()).header("Access-Control-Allow-Headers", "Content-Type, accept, authorization, origin");
result.use(Results.status()).noContent();
}
}
Dessa forma tenho maior controle sobre a requisição, o que me permitiu dinamizar qualquer um dos headers tal qual fiz com o Access-Control-Allow-Methods.
A desvantagem dessa abordagem é que ainda preciso do interceptor para adicionar o Access-Control-Allow-Origin as requisições dos outros métodos HTTP (GET, POST, etc).
Outra desvatagem é que em agora todos interceptors existentes no projeto serão executados quando receberem uma requisição HTTP OPTIONS, e dependendo do que seu interceptor faz, talvez você tenha que tratar isso. Por exemplo, ocorreu comigo que não queria que o interceptor que valida as credenciais de acesso fosse executado qd com requisições HTTP OPTIONS.
Enfim.. é isso.. #FikADik