如何使用带有Resteasy,Angular和Wildfly10的JAX-RS处理CORS

问题描述 投票:0回答:3

我在与我的角度客户端相同的机器上的野生动物10上有一个重新安装的web服务。

  • 获取请求有效
  • 根据我的理解,放置和删除被称为2次,因为预检请求已完成。 curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i在没有两次请求的情况下运行良好。相反,当使用angular客户端调用时,restWebService被调用两次!

我试图添加一个corsFilter,但不仅仅是帮助我能够获得请求它还没有帮助我解决我的问题

package com.solarity.app; // {{ groupId}}.app

import com.solarity.rest.CompanyRestService;
import com.solarity.rest.PersonRestService;
import org.jboss.resteasy.plugins.interceptors.CorsFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

@ApplicationPath("/")
public class InitApplication extends Application {

    /**
    * 
    */
    Set<Object> singletons;
    HashSet<Class<?>> webServiceClasses;

    public InitApplication() {
        super();
        webServiceClasses = new HashSet<>();
        webServiceClasses.add(PersonRestService.class);
        webServiceClasses.add(CompanyRestService.class);


        singletons = new LinkedHashSet<>();
        singletons.add(this.getCorsFilter());

    }

    @Override
    public Set<Class<?>> getClasses() {
        return webServiceClasses;
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }

    private CorsFilter getCorsFilter() {
        CorsFilter result = new CorsFilter();
        result.getAllowedOrigins().add("http://localhost:4200");

        return result;
    }
}

我试图在我的webservice中实现一个选项方法,但没有成功......

package com.solarity.rest; // Note your package will be {{ groupId }}.rest

import com.solarity.entities.CompanyEntity;
import com.solarity.entities.PersonEntity;
import com.solarity.service.CompanyService;
import com.solarity.service.PersonService;
import com.solarity.util.ResponseUtil;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
* 
*
*/
@Path("/company")
public class CompanyRestService {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private CompanyService companyService = new CompanyService();



    @GET // This annotation indicates GET request
    @Path("/")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAll() {
        Object response = null;
        String errMsg = null;
        int responseStatus = -1;
        try {
            this.logger.debug("companyServcfindAll----------------debug");
            this.logger.warn("companyServcfindAll----------------WARN");
            response = companyService.findAll();
        } catch (Exception e) {
            errMsg = "Error getting all persons";
            logger.error(errMsg, e);
        }
        return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.GET);
    }


    /**
    * curl -X DELETE http://localhost:8080/resteasyWebServices-1.0-SNAPSHOT/company/57 -i
    *
    * @param id
    * @return
    */
    @DELETE
    @Path("/{param}")
    public Response delete(@PathParam("param") Integer id){
        Object response = null;
        String errMsg = null;
        int responseStatus = -1;
        try {
            logger.debug("Deleting entity", id);
            companyService.delete(id);
            responseStatus = HttpStatus.SC_OK;
        } catch (Exception e) {
            errMsg = "Error Deleting Entity:" + id;
            logger.error(errMsg, e);
            response = errMsg;
            responseStatus = HttpStatus.SC_METHOD_FAILURE;
        }

        return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.DELETE);
    }

    /**
    * Not working
    * @return
    */
    @OPTIONS
    @Path("{path : .*}")
    public Response options() {
        return Response.ok("")
                .header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
                .header("Access-Control-Allow-Credentials", "true")
                .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
                .header("Access-Control-Max-Age", "1209600")
                .build();
    }

}//end Class

这是我的ResponseUtils类

package com.solarity.util;

import org.apache.http.HttpStatus;

import javax.ws.rs.core.Response;

public class ResponseUtil {


    /**
    *
        Built to counter a Angular cross-reference problem
            Adapted for Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/dlssResteasy1-1.0-SNAPSHOT/person/getPersonsAsJSON. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
            source answer https://stackoverflow.com/questions/23450494/how-to-enable-cross-domain-requests-on-jax-rs-web-services?answertab=votes#tab-top

        More Documentation about CORS on https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS


    * @param param the object to send if errorMsg is null
    * @param errorMsg if not null sends an error code with error Message
    * @param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
    * @return an altered response which is customized
    */
    public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
        Response result = null;
        int rStatus = responseStatus;
        if (errorMsg != null && responseStatus <= 0) {
            rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
        } else if (errorMsg == null && responseStatus <= 0){
            rStatus = HttpStatus.SC_OK;
        }
        if ( errorMsg == null ) {
            result = Response
                    .status(rStatus)
                    .entity(param)
                    .build();
        }else{
            result = Response.status(rStatus)
                    .entity(errorMsg)
                    .build();
        }
        return result;
    }

}

这是调试到FF enter image description here的结果

java cors resteasy wildfly-10
3个回答
1
投票
  • 观察OPTIONS请求和响应,并确保来自服务器的OPTION响应具有正确的信息。它告诉客户端服务器正在接受什么
  • 稍后观察实际请求PUT GET POST等到服务器。它有你想要的所有标题吗?
  • 您不需要创建和OPTIONS路由。请参阅RFC https://www.w3.org/TR/cors/

向该线程添加OPTIONS请求和响应的副本(不是您创建的那个,而是您正在使用的包中的那个,如果您没有使用包,请查找一个),以查看配置有什么问题。

还添加下一个POST,GET,PUT等请求和响应


0
投票

首先,有一个documentation about CORS我已经阅读了解,我无法避免,因为我希望...

来自Angular的两个电话

我问题的部分答案实际上来自Angular的两个调用。

我不明白每次在subscribe上调用httpclient.put()都会完成呼叫!

HttpClient Documentation

调用subscribe()方法执行observable,这是启动DELETE请求的原因。

所以我做的是:

  1. 打电话给methodResult = httpclient.put('someUrl', someData, someHeader).subscribe({ data => { console.log('added') });
  2. 在这个方法的调用者再次调用abovePutMethod.subscribe( data => { doSomeThingWithComponentRefresh })

所以只做一次订阅电话解决了我的两次通话问题


对于CORS协议的其余部分

Angular Client

//UrlHelper
public static putHttpRequestOptions = {
    headers: new HttpHeaders({
    'Content-Type': 'application/json',
    })
};

//Function call somewhere
const result = this.httpClient.put(url, jsonStringValues, UrlHelper.putHttpRequestOptions);

Java Resteasy server

// InitApplication extends Application

public InitApplication() {
    super();
    webServiceClasses = new HashSet<>();
    webServiceClasses.add(PersonRestService.class);
    webServiceClasses.add(CompanyRestService.class);


    singletons = new LinkedHashSet<>();
    singletons.add(this.getCorsFilter());

}

private CorsFilter getCorsFilter() {
    CorsFilter result = new CorsFilter();
    result.getAllowedOrigins().add("*");
    result.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
    result.setCorsMaxAge(86400);//Max in FF 86400=24h https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
    //
    return result;
}


// RestWebService
@PUT
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
public Response put(CompanyEntity entity ){
    Object response = null;
    String errMsg = null;
    int responseStatus = -1;
    try {
        logger.debug("Received entity", entity);
        companyService.persist(entity);
        responseStatus = HttpStatus.SC_CREATED;
    } catch (Exception e) {
        errMsg = "Error adding Entity:" + entity;
        logger.error(errMsg, e);
        response = errMsg;
        responseStatus = HttpStatus.SC_METHOD_FAILURE;
    }

    return ResponseUtil.getAlteredResponse(response, errMsg, responseStatus, HttpMethod.PUT);
}

// Called on result of all RestWebServices (I'm sure there are better/best practices, feel free to comment me this section)
/**
 * @param param the object to send if errorMsg is null
 * @param errorMsg if not null sends an error code with error Message
 * @param responseStatus response status which can be found from HttpStatus.* (if <= 0 will be taken from errorMsg, or ok)
 * @return an altered response which is customized
 */
public static Response getAlteredResponse( Object param, String errorMsg, int responseStatus, String httpMethod ) {
    Response result = null;
    int rStatus = responseStatus;
    if (errorMsg != null && responseStatus <= 0) {
        rStatus = HttpStatus.SC_UNPROCESSABLE_ENTITY;
    } else if (errorMsg == null && responseStatus <= 0){
        rStatus = HttpStatus.SC_OK;
    }
    String accessControlAllowMethods = "GET, POST, PUT, DELETE, OPTIONS, HEAD";
    if ( errorMsg == null ) {
        result = Response
                .status(rStatus)
                .header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
                .header("Access-Control-Allow-Methods", accessControlAllowMethods)
                .header("Access-Control-Max-Age", "1728000")
                .entity(param)
                .build();
    }else{
        result = Response.status(rStatus)
                .header("Access-Control-Allow-Origin", "*") //TODO: fix permission here!
                .header("Access-Control-Allow-Methods", accessControlAllowMethods)
                .header("Access-Control-Max-Age", "1728000")
                .entity(errorMsg)
                .build();
    }
    return result;
}

0
投票

您可以在“网络”标签中查看Chrome DevTools的流量

© www.soinside.com 2019 - 2024. All rights reserved.