使用Angular 4 App调用Play Framework Web App的CORS问题

时间:2017-08-29 18:57:15

标签: angular http typescript playframework cors

我有一个基于Angular 4和Node.JS构建的前端应用程序堆栈,然后调用使用Play Framework构建的后端API。我现在有CORS过滤器的问题。我在Play框架上启用了CORS过滤器,如下所示:

object MyController extends Controller {

    implicit class RichResult (result: Result) {
    def enableCors =  result.withHeaders(
      "Access-Control-Allow-Origin" -> "*"
      , "Access-Control-Allow-Methods" -> "OPTIONS, GET, POST, PUT, DELETE, HEAD"   // OPTIONS for pre-flight
      , "Access-Control-Allow-Headers" -> "Accept, Content-Type, Origin, X-Json, X-Prototype-Version, X-Requested-With" //, "X-My-NonStd-Option"
      , "Access-Control-Allow-Credentials" -> "true"
    )
  }

  def powerPlantDetails(id: Int) = Action.async {
    dbService.powerPlantById(id).flatMap {
      case None =>
        Future.successful(
          NotFound(s"HTTP 404 :: PowerPlant with ID $id not found").enableCors
        )
      case Some(powerPlantRow) =>
        Future.successful(
          Ok(Json.prettyPrint(
            Json.toJson(toPowerPlantConfig(powerPlantRow)))
          ).enableCors
        )
    }
  }
}

但是当我从我的Angular 4应用程序调用此端点时,我可以从我的Play Framework的服务器日志中看到它确实是作为OPTIONS请求进入的:

[info] application - OPTIONS /powerPlants?onlyActive=false&page=1 took 0ms HTTP status >> 404
[info] application - OPTIONS /powerPlants?onlyActive=false&page=1 took 0ms HTTP status >> 404

这是为什么?我如何确保我的Angular 4应用程序正在执行GET而不是OPTIONS?

编辑:如果我从Chrome中的高级REST客户端调用我的Play Framework应用程序,我会看到以下内容:

 application - GET /powerPlants?onlyActive=false&page=1 took 25694ms HTTP status >> 200
(Access-Control-Allow-Origin,*)
(Access-Control-Allow-Headers,Accept, Content-Type, Origin, X-Json, X-Prototype-Version, X-Requested-With)
(Access-Control-Allow-Methods,OPTIONS, GET, POST, PUT, DELETE, HEAD)
(Access-Control-Allow-Credentials,true)

可以看出它实际上正在发出一个GET请求,但如果我从我的Angular应用程序中调用相同的终点,那么它就不能这样做了,这对我来说很奇怪!

3 个答案:

答案 0 :(得分:0)

不确定此问题,但如果您在提出CORS请求时遇到问题,请使用此chrome extension(允许控制允许来源)。

这样,您无需在headers/config中传递任何额外参数即可发出CORS patch request请求。

  

的缺点是,它不适用于Container container = new Container(new BorderLayout()); Media video = com.codename1.media.MediaManager.createMedia(url, true); // url is the url above video.setNativePlayerMode(true); MediaPlayer mp = new MediaPlayer(video); //place the media player in the container container.add(BorderLayout.CENTER, mp); Component component = Container.encloseIn(new FlowLayout(Container.RIGHT), container);

答案 1 :(得分:0)

好像我已经弄明白了这个问题。这是我的Angular应用程序中的get函数:

get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
    return this.http.get(`${environment.api_url}${path}`, { headers: this.setHeaders(), search: params })
      .catch(this.formatErrors)
      .map((res: Response) => res.json());
  }

这就是setHeaders函数:

private setHeaders(): Headers {
    const headersConfig = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Request-Headers': 'content-type'
  };

我必须彻底删除它!所以我现在看起来像:

get(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
    return this.http.get(`${environment.api_url}${path}`, { search: params })
      .catch(this.formatErrors)
      .map((res: Response) => res.json());
  }

我不确定这是否正确,但确实摆脱了问题!我可以从我的Play服务器日志中看到以下内容:

[info] application - GET /powerPlants?onlyActive=false&page=1 took 1539ms HTTP status >> 200
[info] application - GET /powerPlants?onlyActive=false&page=1 took 1549ms HTTP status >> 200
[info] application - GET /powerPlants?onlyActive=false&page=1 took 1607ms HTTP status >> 200

答案 2 :(得分:0)

您是否知道Play以过滤器的形式提供内置CORS处理?有关详细信息,请参阅https://www.playframework.com/documentation/2.6.x/CorsFilter

这消除了手动处理CORS的负担。