2013-01-20 17 views
13

Tôi có ứng dụng Play 2.0.1 mà tôi muốn gọi bằng cách sử dụng Javascript được lưu trữ trên các tên miền khác. Cuộc gọi Javascript của tôi không thành công với:Chơi 2.0.1 và cài đặt Access-Control-Allow-Origin

Origin http://mydomain.com is not allowed by Access-Control-Allow-Origin. 

Tôi đã tìm thấy một số ví dụ về cách đặt tiêu đề HTTP chính xác trong Play 1, nhưng chưa tìm thấy gì cho Play 2.0.1. Sau khi đọc các tài liệu hướng dẫn (http://www.playframework.org/documentation/2.0.2/JavaResponse) Tôi đã thử những điều sau đây chỉ để có được những thứ làm việc:

public static Result myJsonWebService() { 
    ... 
    response().setHeader("Access-Control-Allow-Origin", "*"); 
    return ok(toJson(jsonObject)); 
} 

nhưng JS gọi dịch vụ web của tôi vẫn là thất bại.

Tôi cần làm gì để làm việc này?

Trả lời

11

Dưới đây là một số thông tin cơ bản ...

  • 1) http://www.html5rocks.com/en/tutorials/cors/ - Lưu ý rằng bạn cần phải đọc chút thông tin về "không đơn giản như vậy yêu cầu "như JSon rơi vào thể loại này.
  • 2) http://stackoverflow.com/questions//cors-access-control-allow-origin-despite-correct-headers?rq=1
  • 3) http://caniuse.com/# search = CORS - Thông tin chi tiết trình duyệt hỗ trợ CORS
  • 4) http://stackoverflow.com/questions/10748537/access-control-allow-origin-on-playframework (ví Chơi 1 KHÔNG Chơi 2)

Vì vậy, dưới đây là những gì tôi đã triển khai:

Do yêu cầu không đơn giản (xem 1 ở trên) thực hiện cuộc gọi trước chuyến bay, bạn cần phải thêm thông tin sau vào tệp tuyến:

POST /url_to_json_webservice  controllers.myJsonWebServices.myJsonWebService 
OPTIONS /url_to_json_webservice  controllers.myJsonWebServices.checkPreFlight 

và sau đó thiết lập các phương pháp sau đây trong điều khiển của bạn:

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(); 
} 

Lưu ý tôi có thể thiết lập nhiều tiêu đề hơn cần thiết ở đây, vì vậy hãy kiểm tra những người thân mà bạn cần !!

Cũng nên nhớ để thêm dòng sau vào cuối của phương pháp điều khiển của bạn mà trả về thực sự kết quả JSON (như trong câu hỏi của tôi ở trên):

public static Result myJsonWebService() { 
    ... 
    response().setHeader("Access-Control-Allow-Origin", "*"); 
    return ok(toJson(jsonObject)); 
} 
3

Một cách tốt đẹp để làm điều này là bằng cách mở rộng 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); 
} 

} 

Sau đó, trong bộ điều khiển của bạn thêm dòng này:

@With(CorsAction.class) 

Sau đó, một Các yêu cầu ll ok() sẽ trả lời với các tiêu đề ở trên.

14

Chỉ cần cho Scala guys, đây là việc thực hiện Tôi hiện đang sử dụng:

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" 
      )) 
     } 
    } 
} 

Để sử dụng nó chỉ trang trí hành động của bạn theo cách sau:

def myAction = WithCors("GET", "POST") { 
    Action { request => 
    ??? 
    } 
} 
+1

Tôi muốn cải thiện câu trả lời của bạn trên trang web của bạn. Nhưng tôi không thể đăng nhập. – Nick

+1

Cảm ơn Nick, tôi đã tích hợp các cải tiến của bạn –

1

thực hiện như một bộ lọc Scala (phát 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) {...} 
Các vấn đề liên quan