CORS POST 요청은 일반 JavaScript에서 작동하지만 jQuery에서는 작동하지 않는 이유는 무엇입니까?


87

Cross Origin 게시물 요청을 만들려고하는데 JavaScript다음과 같이 평범하게 작동 합니다.

var request = new XMLHttpRequest();
var params = "action=something";
request.open('POST', url, true);
request.onreadystatechange = function() {if (request.readyState==4) alert("It worked!");};
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", params.length);
request.setRequestHeader("Connection", "close");
request.send(params);

하지만을 (를) 사용 jQuery하고 싶지만 작동 할 수 없습니다. 이것이 내가 시도하는 것입니다.

$.ajax(url, {
    type:"POST",
    dataType:"json",
    data:{action:"something"}, 
    success:function(data, textStatus, jqXHR) {alert("success");},
    error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});

이로 인해 실패가 발생합니다. 왜 jQuery작동하지 않는지 아는 사람이 있으면 모두 알려주십시오. 감사.

( jQuery1.5.1 및 Firefox 4.0을 사용하고 있으며 서버가 적절한 Access-Control-Allow-Origin헤더로 응답하고 있습니다 )


이것은 나 (사용 자바 스크립트의 XMLHttpRequest의)에 대한 솔루션을하는 동안 이온 프레임 워크 (3)와 함께 CORS 문제에 직면
jeudyx

답변:


73

업데이트 : TimK가 지적했듯이 jquery 1.5.2에서는 더 이상 필요하지 않습니다. 그러나 사용자 지정 헤더를 추가하거나 자격 증명 (사용자 이름, 암호 또는 쿠키 등) 사용을 허용하려면 계속 읽으십시오.


답을 찾은 것 같아요! (4 시간 후 많은 저주)

//This does not work!!
Access-Control-Allow-Headers: *

수락 할 모든 헤더를 수동으로 지정해야합니다 (적어도 FF 4.0 및 Chrome 10.0.648.204에서 저에게 해당됨).

jQuery의 $ .ajax 메소드는 모든 교차 도메인 요청에 대해 "x-requested-with"헤더를 보냅니다 (나는 유일한 교차 도메인이라고 생각합니다).

따라서 OPTIONS 요청에 응답하는 데 필요한 누락 된 헤더는 다음과 같습니다.

//no longer needed as of jquery 1.5.2
Access-Control-Allow-Headers: x-requested-with

"단순"이 아닌 헤더를 전달하는 경우 목록에 포함해야합니다 (하나 더 보냅니다).

//only need part of this for my custom header
Access-Control-Allow-Headers: x-requested-with, x-requested-by

그래서 그것을 모두 모으기 위해 여기에 내 PHP가 있습니다.

// * wont work in FF w/ Allow-Credentials
//if you dont need Allow-Credentials, * seems to work
header('Access-Control-Allow-Origin: http://www.example.com');
//if you need cookies or login etc
header('Access-Control-Allow-Credentials: true');
if ($this->getRequestMethod() == 'OPTIONS')
{
  header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
  header('Access-Control-Max-Age: 604800');
  //if you need special headers
  header('Access-Control-Allow-Headers: x-requested-with');
  exit(0);
}

5
jQuery 1.5.2는 동작을 변경했습니다. 더 이상 "X-Requested-With"헤더를 추가하지 않으므로 더 이상 문제가되지 않을 수 있습니다. blog.jquery.com/2011/03/31/jquery-152-released (Bug 8423)
Magmatic

1
@ 팀 K, 당신이 맞아요! 나는 그들이 1.5.2를 릴리스한다는 것을 알지 못했습니다. 즉, 사전 비행이 필요한 경우에도 작동합니다. 내 답변을 업데이트했습니다.
Will Mason

그래서 혼란 스럽습니다. 어쨌든 중간 PHP 스크립트를 작성해야 했습니까? 따라서 Ajax 사용에 대해 걱정할 필요가 없습니다. 아니면 내가 뭔가를 놓치고 있습니까. JavaScript 전용 솔루션이 없습니까?
Elisabeth

1
@Elisabeth이 방법은 요청 된 대상을 제어하는 ​​경우에만 작동합니다. 중간 스크립트가 아닙니다. 요청한 위치의 PHP 상단입니다. 그게 더 말이 되나요?
Will Mason

2
예! 고마워 윌. 클라이언트 측에서 모든 것을 제어 할 수 있다고 생각했지만 양쪽 끝을 모두 제어해야하는 것 같습니다.
Elisabeth

18

또 다른 가능성은 설정으로 dataType: json인해 JQuery가 Content-Type: application/json헤더 를 전송한다는 것 입니다. 이것은 CORS에 의해 비표준 헤더로 간주되며 CORS 프리 플라이트 요청이 필요합니다. 따라서 몇 가지 시도 할 수 있습니다.

1) 적절한 프리 플라이트 응답을 보내도록 서버를 구성하십시오. 이 같은 추가 헤더의 형태로 될 것입니다 Access-Control-Allow-MethodsAccess-Control-Allow-Headers.

2) dataType: json설정을 삭제합니다 . JQuery는 Content-Type: application/x-www-form-urlencoded기본적으로 요청해야 하지만 확실히하기 위해 다음 dataType: json으로 대체 할 수 있습니다.contentType: 'application/x-www-form-urlencoded'


아이디어 주셔서 감사합니다. 나는 데이터 유형을 설정하고 그것을로 설정하지 않는 시도 application/x-www-form-urlencoded조차 text/plain. 그리고 Access-Control-Allow-Methods "POST, GET, OPTIONS"Nothing works 라는 응답 헤더를 추가해 보았습니다 .
Magmatic 2011

JavaScript 오류 콘솔 (또는 Firebug의 콘솔)에서 요청 중에 오류가 있는지 확인할 수 있습니까? 또한 Wireshark를 사용하는 방법을 알고 있다면이를 사용하여 실제 HTTP 요청을 확인할 수 있습니다.
monsur 2011

1
"또 다른 가능성은 dataType : json을 설정하면 JQuery가 Content-Type : application / json 헤더를 전송하게하는 것입니다."— 이것은 발생하지 않습니다. 요청 헤더에는 dataType영향을 미치지 만 Accept요청 헤더에는 영향을 주지 않습니다 Content-Type.
Quentin

9

js에서 "params"를 보내고 있습니다. request.send(params);

그러나 jquery의 "data". 데이터가 정의되어 있습니까? : data:data,

또한 URL에 오류가 있습니다.

$.ajax( {url:url,
         type:"POST",
         dataType:"json",
         data:data, 
         success:function(data, textStatus, jqXHR) {alert("success");},
         error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});

$ .post에 대한 구문과 구문을 혼합하고 있습니다.


업데이트 : monsur 답변을 기반으로 검색 중이며 추가해야 함을 발견했습니다 Access-Control-Allow-Headers: Content-Type(아래는 전체 단락입니다)

http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/

CORS 작동 방식

CORS는 Flash의 crossdomain.xml 파일과 매우 유사하게 작동합니다. 기본적으로 브라우저는 HTTP 헤더 Origin을 요청 서버로 설정하여 크로스 도메인 요청을 서비스에 보냅니다. 이 서비스에는 그러한 요청이 허용되는지 여부를 나타내는 Access-Control-Allow-Origin과 같은 몇 가지 헤더가 포함되어 있습니다.

BOSH 연결 관리자의 경우 Access-Control-Allow-Origin 값을 *로 설정하여 모든 출처가 허용되도록 지정하는 것으로 충분합니다. Content-Type 헤더는 Access-Control-Allow-Headers 헤더에서도 허용 목록에 포함되어야합니다.

마지막으로 BOSH 연결 관리자 요청을 포함한 특정 유형의 요청에 대해 권한 검사가 사전에 수행됩니다. 브라우저는 OPTIONS 요청을 수행하고 어떤 출처가 허용되는지, 어떤 메소드가 허용되는지,이 권한이 얼마나 오래 지속되는지를 나타내는 일부 HTTP 헤더를 반환 할 것으로 예상합니다. 예를 들어 다음은 내가 OPTIONS에 대해 반환 한 Punjab 및 ejabberd 패치입니다.

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type 
Access-Control-Max-Age: 86400

1
죄송합니다. 예. var data = {action:"something"}
Magmatic 2011-04-07

여기에서 두 함수의 구문을 비교할 수 있습니다. api.jquery.com/jQuery.post
Aleadam 2011

설정의 URL로 시도했지만 같은 문제입니다. .ajax 함수는 어느 쪽이든 취할 수 있습니다.
Magmatic 2011

이미 두 개의 헤더가 있습니다. 다른 두 개를 추가했습니다. jQuery에서 여전히 "실패"합니다. 일반 자바 스크립트는 여전히 작동합니다.
Magmatic 2011

마지막으로 생각할 수있는 것은 api.jquery.com/jQuery.ajaxSetup 을 사용 하여 jQuery.ajaxSetup({'beforeSend': function(xhr) {xhr.setRequestHeader(string, string)}})전송 된 다른 헤더 를 설정 하고 재생하는 것입니다 (예 : railscasts.com/episodes/136-jquery )
Aleadam

1

Cors는 요청 방법을 완료하기 전에 POST에서 OPTIONS로 변경하므로 게시 데이터가 전송되지 않습니다. 이 cors 문제를 처리하기 위해 일한 방법은 OPTIONS 메서드를 지원하지 않는 ajax로 요청을 수행하는 것입니다. 예제 코드 :

        $.ajax({
            type: "POST",
            crossdomain: true,
            url: "http://localhost:1415/anything",
            dataType: "json",
            data: JSON.stringify({
                anydata1: "any1",
                anydata2: "any2",
            }),
            success: function (result) {
                console.log(result)
            },
            error: function (xhr, status, err) {
                console.error(xhr, status, err);
            }
        });

C # 서버에서이 헤더로 :

                    if (request.HttpMethod == "OPTIONS")
                    {
                          response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
                          response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                          response.AddHeader("Access-Control-Max-Age", "1728000");
                    }
                    response.AppendHeader("Access-Control-Allow-Origin", "*");

-2

다음과 같은 방법으로 Jquery를 수정하십시오.

$.ajax({
            url: someurl,
            contentType: 'application/json',
            data: JSONObject,
            headers: { 'Access-Control-Allow-Origin': '*' }, //add this line
            dataType: 'json',
            type: 'POST',                
            success: function (Data) {....}
});

Ajax callas를 동기식으로 만드는 이유는 무엇입니까?
Radko Dinev

contentType: 'application/json', data: JSONObject,— 서버가 JSON을 예상하지 않으므로 JSON을 보내는 것은 의미가 없습니다. 또한 JSON 객체와 같은 것은 없습니다 .
Quentin

1
headers: { 'Access-Control-Allow-Origin': '*' }, //add this line절대 하지 마십시오 . 요청 헤더 Access-Control-Allow-Origin가 아니라 응답 헤더입니다. 기껏해야 아무 일도하지 않습니다. 최악의 경우 요청을 간단한 요청에서 사전 요청으로 변환하여 서버에서 처리하기가 더 어려워집니다.
Quentin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.