javascript 播放 2.0.1 并设置 Access-Control-Allow-Origin
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14430119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Play 2.0.1 and setting Access-Control-Allow-Origin
提问by mstreffo
I have a Play 2.0.1 application that I want to call using Javascript hosted on other domains. My Javascript call is failing with:
我有一个 Play 2.0.1 应用程序,我想使用托管在其他域上的 Javascript 调用它。我的 Javascript 调用失败:
Origin http://mydomain.com is not allowed by Access-Control-Allow-Origin.
I have found a number of examples of how to set the correct HTTP header in Play 1, but have not found anything for Play 2.0.1. After reading the documentation (http://www.playframework.org/documentation/2.0.2/JavaResponse) I've tried the following just to get things working:
我已经找到了许多关于如何在 Play 1 中设置正确 HTTP 标头的示例,但没有找到适用于 Play 2.0.1 的任何内容。在阅读了文档 (http://www.playframework.org/documentation/2.0.2/JavaResponse) 后,我尝试了以下操作只是为了让事情正常工作:
public static Result myJsonWebService() {
...
response().setHeader("Access-Control-Allow-Origin", "*");
return ok(toJson(jsonObject));
}
but my JS web service call is still failing.
但是我的 JS Web 服务调用仍然失败。
What do I need to do to get this working?
我需要做什么才能让它发挥作用?
回答by Lord of the Goo
Just for Scala guys, this is the implementation I'm currently using:
仅适用于 Scala 人员,这是我目前正在使用的实现:
import play.api.mvc._
import scala.concurrent._
import play.api.http.HeaderNames._
/**
* Action decorator that provide CORS support
*
* @author Giovanni Costagliola, Nick McCready
*/
case class WithCors(httpVerbs: String*)(action: EssentialAction) extends EssentialAction with Results {
def apply(request: RequestHeader) = {
implicit val executionContext: ExecutionContext = play.api.libs.concurrent.Execution.defaultContext
val origin = request.headers.get(ORIGIN).getOrElse("*")
if (request.method == "OPTIONS") { // preflight
val corsAction = Action {
request =>
Ok("").withHeaders(
ACCESS_CONTROL_ALLOW_ORIGIN -> origin,
ACCESS_CONTROL_ALLOW_METHODS -> (httpVerbs.toSet + "OPTIONS").mkString(", "),
ACCESS_CONTROL_MAX_AGE -> "3600",
ACCESS_CONTROL_ALLOW_HEADERS -> s"$ORIGIN, X-Requested-With, $CONTENT_TYPE, $ACCEPT, $AUTHORIZATION, X-Auth-Token",
ACCESS_CONTROL_ALLOW_CREDENTIALS -> "true")
}
corsAction(request)
} else { // actual request
action(request).map(res => res.withHeaders(
ACCESS_CONTROL_ALLOW_ORIGIN -> origin,
ACCESS_CONTROL_ALLOW_CREDENTIALS -> "true"
))
}
}
}
To use it just decorate your action in the following way:
要使用它,只需按以下方式装饰您的操作:
def myAction = WithCors("GET", "POST") {
Action { request =>
???
}
}
回答by mstreffo
Here is some background information...
这是一些背景信息...
- 1) http://www.html5rocks.com/en/tutorials/cors/ - Note that you need to read the bit about "not so simple requests" as JSon falls into this category.
- 2) http://stackoverflow.com/questions/9613210/cors-access-control-allow-origin-despite-correct-headers?rq=1
- 3) http://caniuse.com/#search=cors - Details browsers that support CORS
- 4) http://stackoverflow.com/questions/10748537/access-control-allow-origin-on-playframework (for Play 1 NOT Play 2)
- 1) http://www.html5rocks.com/en/tutorials/cors/ - 请注意,您需要阅读有关“不那么简单的请求”的内容,因为 Json 属于此类。
- 2)http://stackoverflow.com/questions/9613210/cors-access-control-allow-origin-despite-correct-headers?rq=1
- 3) http://caniuse.com/#search=cors - 支持 CORS 的浏览器详情
- 4)http://stackoverflow.com/questions/10748537/access-control-allow-origin-on-playframework(用于播放 1 不播放 2)
So here is what I implemented:
所以这是我实现的:
As not-so-simple-requests (see 1 above) make a pre-flight call, you need to add the following to the routes file:
由于不那么简单的请求(参见上面的 1)进行飞行前调用,您需要将以下内容添加到路由文件中:
POST /url_to_json_webservice controllers.myJsonWebServices.myJsonWebService
OPTIONS /url_to_json_webservice controllers.myJsonWebServices.checkPreFlight
and then set up the following method in your controller:
然后在您的控制器中设置以下方法:
public static Result checkPreFlight() {
response().setHeader("Access-Control-Allow-Origin", "*"); // Need to add the correct domain in here!!
response().setHeader("Access-Control-Allow-Methods", "POST"); // Only allow POST
response().setHeader("Access-Control-Max-Age", "300"); // Cache response for 5 minutes
response().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); // Ensure this header is also allowed!
return ok();
}
Note i may have set more headers than needed here, so please check which ones you need!!
请注意,我在这里设置的标题可能多于所需的标题,因此请检查您需要哪些标题!!
Also remember to add the following to the end of your controller method that returns the actually JSon result (as in my question above):
还要记住将以下内容添加到返回实际 JSon 结果的控制器方法的末尾(如我上面的问题):
public static Result myJsonWebService() {
...
response().setHeader("Access-Control-Allow-Origin", "*");
return ok(toJson(jsonObject));
}
回答by Skeep
A nice way of doing this is by extending the Actions:
这样做的一个好方法是扩展操作:
package actions;
import play.*;
import play.mvc.*;
import play.mvc.Http.Context;
import play.mvc.Http.Response;
public class CorsAction extends Action.Simple {
public Result call(Context context) throws Throwable{
Response response = context.response();
response.setHeader("Access-Control-Allow-Origin", "*");
//Handle preflight requests
if(context.request().method().equals("OPTIONS")) {
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Auth-Token");
response.setHeader("Access-Control-Allow-Credentials", "true");
return ok();
}
response.setHeader("Access-Control-Allow-Headers","X-Requested-With, Content-Type, X-Auth-Token");
return delegate.call(context);
}
}
Then in your controllers add this line:
然后在您的控制器中添加这一行:
@With(CorsAction.class)
Then all ok() requests will respond with the above headers.
然后所有 ok() 请求都将使用上述标头进行响应。
回答by Mads Lundeland
Implemented as a Scala Filter (play 2.2.x):
实现为 Scala 过滤器(播放 2.2.x):
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.mvc._
import play.api.mvc.Results._
import play.api.http.HeaderNames._
object Cors extends Filter {
def apply(next: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = {
val origin = request.headers.get(ORIGIN).getOrElse("*")
if (request.method == "OPTIONS") {
val response = Ok.withHeaders(
ACCESS_CONTROL_ALLOW_ORIGIN -> origin,
ACCESS_CONTROL_ALLOW_METHODS -> "POST, GET, OPTIONS, PUT, DELETE",
ACCESS_CONTROL_MAX_AGE -> "3600",
ACCESS_CONTROL_ALLOW_HEADERS -> s"$ORIGIN, X-Requested-With, $CONTENT_TYPE, $ACCEPT, $AUTHORIZATION, X-Auth-Token",
ACCESS_CONTROL_ALLOW_CREDENTIALS -> "true"
)
Future.successful(response)
} else {
next(request).map {
res => res.withHeaders(
ACCESS_CONTROL_ALLOW_ORIGIN -> origin,
ACCESS_CONTROL_ALLOW_CREDENTIALS -> "true"
)
}
}
}
}
object Global extends WithFilters(Cors) {...}