在Java Play Framework 2.2.x中启用CORS

13

我在Java Play 2.2.x中遇到了启用跨域的问题。

在Java Play 2.1.3中,通过将以下代码放入Global.java文件中可以解决该问题。

public class Global extends GlobalSettings {

  private class ActionWrapper extends Action.Simple {
    public ActionWrapper(Action action) {
     this.delegate = action;
  }

    @Override
    public Result call(Http.Context ctx) throws java.lang.Throwable {
      Result result = this.delegate.call(ctx);
      Http.Response response = ctx.response();
      response.setHeader("Access-Control-Allow-Origin", "*");
      return result;
    }
  }

  @Override
  public Action onRequest(Http.Request request, java.lang.reflect.Method actionMethod) {
    return new ActionWrapper(super.onRequest(request, actionMethod));
  }

}

但是当我尝试在Java Play 2.2.x上编译时,它不再编译。

编译错误信息:

Global.ActionWrapper 不是抽象的,并且没有覆盖 Action 中的 call(Context) 抽象方法...

在Java Play 2.2.x中是否有任何等效的代码?

谢谢。

4个回答

7

它看起来像这样:

import play.GlobalSettings;
import play.libs.F.Promise;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.SimpleResult;

public class Global extends GlobalSettings {
    private class ActionWrapper extends Action.Simple {
        public ActionWrapper(Action<?> action) {
            this.delegate = action;
        }

        @Override
        public Promise<SimpleResult> call(Http.Context ctx) throws java.lang.Throwable {
            Promise<SimpleResult> result = this.delegate.call(ctx);
            Http.Response response = ctx.response();
            response.setHeader("Access-Control-Allow-Origin", "*");
            return result;
        }
    }

    @Override
    public Action<?> onRequest(Http.Request request, java.lang.reflect.Method actionMethod) {
        return new ActionWrapper(super.onRequest(request, actionMethod));
    }
}

我们采用了这种方法,但在请求方面遇到了问题,导致出现错误。我们稍微修改了代码,使得在调用委托之前设置响应头。 - dknaus

6

如果您正在使用Play的2.3.1+版本(截至本文编写时),现在应该使用Promise<Result>而不是Promise<SimpleResult>

import play.GlobalSettings;
import play.libs.F.Promise;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;

public class Global extends GlobalSettings {
    private class ActionWrapper extends Action.Simple {
        public ActionWrapper(Action<?> action) {
            this.delegate = action;
        }

        @Override
        public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable {
            Promise<Result> result = this.delegate.call(ctx);
            Http.Response response = ctx.response();
            response.setHeader("Access-Control-Allow-Origin", "*");
            return result;
        }
    }

    @Override
    public Action<?> onRequest(Http.Request request, java.lang.reflect.Method actionMethod) {
        return new ActionWrapper(super.onRequest(request, actionMethod));
    }
}

2
@alexhanschke提出的解决方案在请求抛出异常(内部服务器错误)时无效,因为当发生这种情况时不会应用过滤器(请参见 https://github.com/playframework/playframework/issues/2429)。为了解决这个问题,您必须包装一个Scala类并将其作为结果返回,如下面的完整示例所示。请注意,这仍然需要指定选项路由和控制器来处理选项请求。
在此处查看整个内容https://gist.github.com/tinusn/38c4c110f7cd1e1ec63f
import static play.core.j.JavaResults.BadRequest;
import static play.core.j.JavaResults.InternalServerError;
import static play.core.j.JavaResults.NotFound;

import java.util.ArrayList;
import java.util.List;

import play.GlobalSettings;
import play.api.mvc.Results.Status;
import play.libs.F.Promise;
import play.libs.Scala;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
import scala.Tuple2;
import scala.collection.Seq;

public class Global extends GlobalSettings {

  private class ActionWrapper extends Action.Simple {
    public ActionWrapper(Action<?> action) {
      this.delegate = action;
    }

    @Override
    public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable {
      Promise<Result> result = this.delegate.call(ctx);
      Http.Response response = ctx.response();
      response.setHeader("Access-Control-Allow-Origin", "*");
      return result;
    }
  }

  /*
  * Adds the required CORS header "Access-Control-Allow-Origin" to successfull requests
  */
  @Override
  public Action<?> onRequest(Http.Request request, java.lang.reflect.Method actionMethod) {
    return new ActionWrapper(super.onRequest(request, actionMethod));
  }

  private static class CORSResult implements Result {
    final private play.api.mvc.Result wrappedResult;

    public CORSResult(Status status) {
      List<Tuple2<String, String>> list = new ArrayList<Tuple2<String, String>>();
      Tuple2<String, String> t = new Tuple2<String, String>("Access-Control-Allow-Origin","*");
      list.add(t);
      Seq<Tuple2<String, String>> seq = Scala.toSeq(list);
      wrappedResult = status.withHeaders(seq);
    }

    public play.api.mvc.Result toScala() {
      return this.wrappedResult;
    }
  }

  /*
  * Adds the required CORS header "Access-Control-Allow-Origin" to bad requests
  */
  @Override
  public Promise<Result> onBadRequest(Http.RequestHeader request, String error) {
    return Promise.<Result>pure(new CORSResult(BadRequest()));
  }

  /*
  * Adds the required CORS header "Access-Control-Allow-Origin" to requests that causes an exception
  */
  @Override
  public Promise<Result> onError(Http.RequestHeader request, Throwable t) {
    return Promise.<Result>pure(new CORSResult(InternalServerError()));
  }

  /*
  * Adds the required CORS header "Access-Control-Allow-Origin" when a route was not found
  */
  @Override
  public Promise<Result> onHandlerNotFound(Http.RequestHeader request) {
    return Promise.<Result>pure(new CORSResult(NotFound()));
  }

}

1

另一个选项可能是使用过滤器。目前只有Scala过滤器可用。然而,正如此帖子所指出的那样,为了简单地修改响应头,您可以复制并粘贴以下内容以启用CORS。

package filters

import play.api.mvc._
import play.mvc.Http.HeaderNames
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

class EnableCORS extends Filter {
  def apply(f: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = {
    val result = f(rh)
    result.map(_.withHeaders(HeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN -> "*"))
  }
}

然后只需在您的 Global.java 中添加过滤器即可:

@Override
public <T extends EssentialFilter> Class<T>[] filters() {
    return new Class[] {EnableCORS.class};
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接