Solicitud Ajax con JAX-RS/RESTEasy implementando CORS
json (4)
Tengo dos servidores (Apache y JBoss AS7) y necesito proporcionar acceso a todos los métodos http a un cliente. Todas estas solicitudes deben enviarse a través de ajax. Ejemplo del código de cliente:
$.ajax({
type: "get",
url: "http://localhost:9080/myproject/services/mobile/list",
crossDomain: true,
cache: false,
dataType: "json",
success: function(response) {
console.log(response);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(textStatus);
console.log(jqXHR.responseText);
console.log(errorThrown);
}
});
En JBoss AS7 estoy usando RESTEasy, implementando CORS de la siguiente manera:
@Path("/mobile")
@Provider
@ServerInterceptor
public class GroupMobile implements MessageBodyWriterInterceptor {
@Inject
private GroupDAO groupDAO;
@GET
@Path("/list")
@Produces(MediaType.APPLICATION_JSON)
public List<Group> getGroups() {
return groupDAO.listAll();
}
@Override
public void write(MessageBodyWriterContext context) throws IOException,
WebApplicationException {
context.getHeaders().add("Access-Control-Allow-Origin", "*");
context.proceed();
}
@OPTIONS
@Path("/{path:.*}")
public Response handleCORSRequest(
@HeaderParam("Access-Control-Request-Method") final String requestMethod,
@HeaderParam("Access-Control-Request-Headers") final String requestHeaders) {
final ResponseBuilder retValue = Response.ok();
if (requestHeaders != null)
retValue.header("Access-Control-Allow-Headers", requestHeaders);
if (requestMethod != null)
retValue.header("Access-Control-Allow-Methods", requestMethod);
retValue.header("Access-Control-Allow-Origin", "*");
return retValue.build();
}
}
web.xml y beans.xml son archivos vacíos. Cuando accedo a MyIP: 8080 (Apache), aparece el mensaje de error:
XMLHttpRequest cannot load http://localhost:9080/myproject/services/mobile/list?_=1359480354190. Origin http://MyIP:8080 is not allowed by Access-Control-Allow-Origin.
¿Alguien sabe lo que está mal?
El problema que está teniendo es que está intentando hacer scripts de sitios cruzados. Usted accedió a la página en http://MyIP:8080
y, por lo tanto, el navegador le impide acceder a recursos fuera de ese dominio. Esto es muy específico para el navegador y las soluciones basadas en el navegador serán todas diferentes (puede deshabilitar la seguridad en Chrome de forma global, y en cada sitio en IE).
Si carga la página como http://localhost:8080
, debería permitirle acceder a la consulta. Alternativamente, puede implementar un proxy que reenviará la solicitud.
Parece que el problema está relacionado con https://issues.jboss.org/browse/RESTEASY-878 . Es posible que no pueda detectar las solicitudes de verificación previa de CORS con MessageBodyWriterInterceptor
. Intente utilizar filtros de servlet ( @WebFilter
) en su lugar.
Bueno, he implementado una pequeña solución, primero hago un interceptor en mi proyecto Web Creé una clase llamada "CORSInterceptor", la clase es del camino.
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.MessageBodyWriterContext;
import org.jboss.resteasy.spi.interception.MessageBodyWriterInterceptor;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@Provider
@ServerInterceptor
public class CorsInterceptor implements PreProcessInterceptor, MessageBodyWriterInterceptor {
/**
* The Origin header set by the browser at each request.
*/
private static final String ORIGIN = "Origin";
/**
* The Access-Control-Allow-Origin header indicates which origin a resource it is specified for can be
* shared with. ABNF: Access-Control-Allow-Origin = "Access-Control-Allow-Origin" ":" source origin string | "*"
*/
private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
//
private static final ThreadLocal<String> REQUEST_ORIGIN = new ThreadLocal<String>();
//
private final Set<String> allowedOrigins;
public CorsInterceptor(){
this.allowedOrigins = new HashSet<String>();
this.allowedOrigins.add("*");
}
@Override
public ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException {
if (!allowedOrigins.isEmpty()) {
REQUEST_ORIGIN.set(request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN));
}
return null;
}
@Override
public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException {
if (!allowedOrigins.isEmpty() && (allowedOrigins.contains(REQUEST_ORIGIN.get()) || allowedOrigins.contains("*"))) {
context.getHeaders().add(ACCESS_CONTROL_ALLOW_ORIGIN, REQUEST_ORIGIN.get());
}
context.proceed();
}
}
En File Web.xml , lo agrego
<context-param>
<param-name>resteasy.providers</param-name>
<param-value><package>.CorsInterceptor</param-value>
</context-param>
paquete : ubicación de la clase.
Solicite JQuery que he usado.
$.ajax({
type: ''GET'',
dataType: "json",
crossDomain : true,
cache:false,
url: "http://localhost:12005/ProyectoWebServices/ws/servicioTest",
success: function (responseData, textStatus, jqXHR) {
alert("Successfull: "+responseData);
},
error: function (responseData, textStatus, errorThrown) {
alert("Failed: "+responseData);
}
});
funcionó bien para mí. Espero que pueda ayudarte.
El último resteasy (3.0.9-Final) incluye una clase de utilidad org.jboss.resteasy.plugins.interceptors.CorsFilter
.
Puede agregar el objeto CorsFilter al conjunto de objetos singleton de la Aplicación o agregarlo directamente a ProviderFactory en ResteasyDeployment.
La siguiente es la clase de aplicación de muestra:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import org.jboss.resteasy.plugins.interceptors.CorsFilter;
@ApplicationPath("/api")
public class RestApplication extends javax.ws.rs.core.Application {
Set<Object> singletons;
@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> clazzes = new HashSet<>();
clazzes.add(VersionService.class);
return clazzes;
}
@Override
public Set<Object> getSingletons() {
if (singletons == null) {
CorsFilter corsFilter = new CorsFilter();
corsFilter.getAllowedOrigins().add("*");
singletons = new LinkedHashSet<Object>();
singletons.add(corsFilter);
}
return singletons;
}
}