Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

'Access-Control-Allow-Origin' Ao consumir a API em aplicações externas

Olá, Tentei consumir nossa API(exportando JSON) via ajax com um projeto React como testes, contudo recebo um erro de Cross no browser:

Fetch API cannot load http://localhost:8080/loja/webapi/carrinhos/2. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Alguém poderia me dizer que configurações devo fazer na aplicação WS para que os cross seja permitido? Eu tentei algumas soluções mão nenhum surtiu efeito

Desde já obrigado!

2 respostas

Olhei a documentação do jersey, pois cada tecnologia configura de um jeito os headers para liberar a chamada...

https://jersey.java.net/documentation/latest/client.html

Parece que você precisa definir uma propriedade da aplicação chamada sun.net.http.allowRestrictedHeaders. Olha rapidinho a documentação e testa?

solução!

Obigado Alberto pela diga, consegui chegar na solução com algumas configurações.

Eu adicionei o 'Access-Control-Allow-Origin'no header da resposta no método que retorna a lista de carrinhos.

IMPLEMENTAÇÃO 1: Classe CarrinhoResouce

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response carrinhos() {
        //implementação da  busca de carrinhos via dao
        return Response.status(200).entity(gson.toJson(listaArtigos)).header("Access-Control-Allow-Origin", "*").build();
    }

No header

    Access-Control-Allow-Origin:*   <--------
    Content-Length:1498
    Content-Type:application/json
    Date:Wed, 22 Feb 2017 12:09:34 GMT

Tudo já esta ok, mas para evitar de ter que repetir .header("Access-Control-Allow-Origin", "*") para todos os métodos subsequentes procurei na documentação a forma de padronizar essa informação via filter por meio da criação da classe br.com.alura.loja.ResponseFilter

public class ResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
    }
}

E na classe Servidor bata registar ResponseFilter

public class Servidor {
    public static void main(String[] args) throws IOException {
        HttpServer server = inicializaServer();
        System.in.read();
        server.stop();
    }


    private static HttpServer inicializaServer() {
        ResourceConfig config = new ResourceConfig().packages("br.com.alura.loja");
        config.register(ResponseFilter.class);

        URI uri = URI.create("http://localhost:8080/");
        HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri, config);
        System.out.println("Servidor rodando na porta: "+uri);
        return server;
    }    
}

Com isso, toda resposta agora terá o "Access" padronizado como "*";

Agora o método de retorno dos carrinho pode ficar assim:

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response carrinhos() {
        //implementação da  busca de carrinhos via dao
        return Response.status(200).entity(gson.toJson(carrinhos)).build();
    }

ou mesmo assim

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String carrinhos() {
        //implementação da  busca de carrinhos via dao
        return gson.toJson(carrinhos);
    }

Prefiro a primeira para ter as informações do Response pra testes e etc.