Chrome में AJAX GET / POST / PUT / DELETE के बजाय विकल्प भेज रहा है?


107

मैं काम पर एक आंतरिक वेब अनुप्रयोग पर काम कर रहा हूं। IE10 में अनुरोध ठीक काम करते हैं, लेकिन क्रोम में AJAX के सभी अनुरोध (जो कि कई हैं) को जो भी परिभाषित विधि दी जाती है, उसके बजाय विकल्प का उपयोग करके भेजा जाता है। तकनीकी रूप से मेरे अनुरोध "क्रॉस डोमेन" हैं। साइट को लोकलहोस्ट पर परोसा जाता है: 6120 और मैं जो सेवा AJAX अनुरोध कर रहा हूं वह 57124 पर है। यह बंद jquery बग समस्या को परिभाषित करता है, लेकिन वास्तविक फिक्स नहीं है।

मैं अजाक्स अनुरोधों में उचित http विधि का उपयोग करने के लिए क्या कर सकता हूं?

संपादित करें:

यह प्रत्येक पृष्ठ के दस्तावेज़ लोड में है:

jQuery.support.cors = true;

और हर AJAX इसी तरह बनाया गया है:

var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
    url: url,
    dataType: "json",
    data: json,
    async: true,
    cache: false,
    timeout: 30000,
    headers: { "x-li-format": "json", "X-UserName": userName },
    success: function (data) {
        // my success stuff
    },
    error: function (request, status, error) {
        // my error stuff
    },
    type: "POST"
});

2
उस बग रिपोर्ट में अंतिम टिप्पणी इसे बहुत अच्छी तरह से समझाती है ...
केविन बी

1
इसने मेरे दिमाग को उड़ा दिया क्योंकि मैं जो कुछ भी कर रहा हूं वह बहुत वैनिला है (और मेरा कोड jquery बग में समान है)। इसके अलावा, यह इसमें शामिल नहीं करने के लिए कोई बहाना नहीं है। BRB, कुछ नमूना कोड को हथियाने।
कोरी ओगबर्न

3
ध्यान दें कि यदि कोई अनुरोध क्रॉस-ऑरिजनल है, तो यह निर्धारित करते समय IE पोर्ट संख्याओं पर विचार नहीं करता है।
रे निकोलस

@ केविनबी: हमारी रीस्ट सेवा http पद्धति के आधार पर विभिन्न चीजों को करने के रूप में विभिन्न अनुरोधों का लाभ उठाती है। GET में सब कुछ स्विच करना एक वैध फिक्स नहीं है। डार्क फाल्कन के जवाब के अनुसार, यह वैसे भी मदद नहीं करेगा, क्योंकि मेरे पास अनुरोधों में एक्स-उपयोगकर्ता नाम और अन्य कस्टम हेडर हैं।
कोरी ओगबर्न

यह इस तथ्य को नहीं बदलता है कि यदि आप क्रॉस-ऑरिजनल रिक्वेस्ट करना चाहते हैं, तो आपको उन सभी नियमों का पालन करना चाहिए, जो ठीक से काम करने के लिए क्रॉस-ऑरिजनल रिक्वेस्ट पर लागू होते हैं। क्रॉस-ऑरिजन अनुरोधों में आम तौर पर एक विकल्प अनुरोध शामिल होता है। इसे ठीक से संभाल लें और समस्या दूर हो जाएगी। इसे हल करने का एकमात्र तरीका (एपीआई को बदले बिना) उसी सर्वर पर एक स्क्रिप्ट है जो प्राथमिक पृष्ठ पर है जो सर्वर-साइड कोड का उपयोग करते हुए एपीआई के साथ इंटरैक्ट करता है।
केविन बी

जवाबों:


136

Chrome, CORS हेडर देखने के लिए अनुरोध को प्राथमिकता दे रहा है । यदि अनुरोध स्वीकार्य है, तो यह वास्तविक अनुरोध भेज देगा। यदि आप यह क्रॉस-डोमेन कर रहे हैं, तो आपको बस इससे निपटना होगा या फिर अनुरोध को गैर-क्रॉस-डोमेन बनाने का एक तरीका खोजना होगा। यही कारण है कि jQuery बग को बंद नहीं किया गया था। यह डिजाइन द्वारा है।

सरल अनुरोधों (ऊपर चर्चा की गई) के विपरीत, "पहले से बताए गए" अनुरोधों को पहले दूसरे डोमेन पर संसाधन के लिए विकल्प विधि द्वारा एक HTTP अनुरोध भेजा जाता है, ताकि यह निर्धारित किया जा सके कि वास्तविक अनुरोध भेजने के लिए सुरक्षित है या नहीं। क्रॉस-साइट अनुरोध इस तरह से पूर्वनिर्धारित हैं क्योंकि उनके उपयोगकर्ता डेटा के लिए निहितार्थ हो सकते हैं। विशेष रूप से, एक अनुरोध पूर्वनिर्धारित है यदि:

  • यह GET, HEAD या POST के अलावा अन्य तरीकों का उपयोग करता है। इसके अलावा, यदि POST का उपयोग एप्लिकेशन / एक्स-www-फॉर्म-यूरलेंकोडेड, मल्टीपार्ट / फॉर्म-डेटा, या टेक्स्ट / प्लेन के अलावा अन्य सामग्री-प्रकार के साथ अनुरोध डेटा भेजने के लिए किया जाता है, जैसे कि यदि पोस्ट अनुरोध सर्वर पर XML पेलोड भेजता है आवेदन / xml या पाठ / xml का उपयोग कर, तो अनुरोध पूर्वनिर्मित है।
  • यह अनुरोध में कस्टम हेडर सेट करता है (जैसे अनुरोध एक्स-पिंगोथ्रर जैसे हेडर का उपयोग करता है)

20
कस्टम हेडर। शायद यही वह है जो प्रीफ़्लाइट ऑप्‍शन कॉल को बंद कर रहा है।
कोरी ओगबर्न

18

इस तथ्य के आधार पर कि अनुरोध डिफ़ॉल्ट पोर्ट 80/443 पर नहीं भेजा गया है, इस अजाक्स कॉल को स्वचालित रूप से एक क्रॉस-ऑरिजिनल संसाधन (कोर) अनुरोध माना जाता है , जिसका दूसरे शब्दों में अर्थ है कि अनुरोध स्वचालित रूप से एक विकल्प अनुरोध जारी करता है जिसके लिए जांच होती है सर्वर / सर्वलेट के पक्ष में कोर हेडर।

यह तब भी होता है जब आप सेट करते हैं

crossOrigin: false;

या भले ही आप इसे ommit करें।

कारण बस इतना ही है localhost != localhost:57124। केवल localhostपोर्ट के बिना इसे भेजने का प्रयास करें - यह विफल हो जाएगा, क्योंकि अनुरोधित लक्ष्य उपलब्ध नहीं होगा, हालांकि ध्यान दें कि यदि डोमेन नाम समान हैं तो अनुरोध के बिना विकल्प अनुरोध के बिना भेजा जाता है।


3

मैं केविन बी से सहमत हूं, बग रिपोर्ट यह सब कहती है। ऐसा लगता है कि आप क्रॉस-डोमेन अजाक्स कॉल करने की कोशिश कर रहे हैं। यदि आप उसी मूल नीति से परिचित नहीं हैं जो आप यहां शुरू कर सकते हैं: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript

यदि यह क्रॉस-डोमेन अजाक्स कॉल करने का इरादा नहीं है, तो अपने लक्ष्य यूआरएल को सापेक्ष बनाने का प्रयास करें और देखें कि क्या समस्या दूर हो जाती है। यदि आप वास्तव में JSONP को देखने के लिए बेताब हैं, लेकिन सावधान रहें, तबाही का आलम है। वास्तव में बहुत अधिक नहीं है कि हम आपकी मदद कर सकें।


1
हमारी प्रणाली संरचना कुछ ऐसी है जिसे मैं बदल नहीं सकता। एक अलग बंदरगाह का उपयोग करना हमारी वास्तुकला की आवश्यकता है। मुझे एक ही मूल नीति मिलती है, लेकिन हमने सोचा था कि हमने जिस कोर को लागू किया था, वह पर्याप्त था। जाहिरा तौर पर नहीं।
कोरी ओगबर्न

2
यदि आपका सर्वर JSON प्रतिक्रिया देता है, तो आप JSONP विधि में देख सकते हैं, बस इसे जिम्मेदारी से उपयोग करें।
गुड़

1
मैं वास्तव में आपके साथ बहस करने की परवाह नहीं करता, लेकिन JSONP किसी अन्य डोमेन से डेटा खींचने के लिए स्क्रिप्ट टैग का उपयोग करता है और फिर कॉलबैक फ़ंक्शन के लिए परिणाम भेजता है। यह बहुत कठिन है अगर परिणाम json नहीं है।
गुड़

1
नहीं, यह बहुत कठिन नहीं है। वास्तव में प्रतिक्रिया किसी भी मामले में वैध JSON नहीं होनी चाहिए। इसके बजाय, सर्वर कुछ इस तरह वापसी करना चाहिए: callbackfunc(somedata)। जैसा कि आप देख सकते हैं, यह वैध JSON नहीं है। और, somedataएक स्ट्रिंग, या एक संख्या, या जो कुछ भी आप चाहते हैं वह हो सकता है।
रे निकोलस

1
मैं पोस्टमैन का उपयोग कर रहा हूं और वहां अनुरोध विधियां सही तरीके से भेजी जाती हैं (जैसे। 'PUT', 'DELETE', आदि)। लेकिन जब मैं इसे अपने कोड से करने की कोशिश करता हूं तो यह उन्हें हमेशा अनुरोध विधि विकल्प के साथ भेजता है। मुझे नहीं पता कि पोस्टमैन यह कैसे कर पा रहा है।
एरविनगो 28

1

यदि यह संभव है कि एक अलग नाम के साथ नियमित रूप से जीईटी / पीओएसटी पास करें और अपने सर्वर साइड कोड को संभाल लें।

मुझे कॉर्स को बायपास करने के लिए अपने स्वयं के प्रॉक्सी के साथ एक समान मुद्दा था और मुझे क्रोम में POST-> विकल्प की एक ही त्रुटि मिली। यह Authorizationमेरे मामले में हेडर था ( "x-li-format"और "X-UserName"आपके मामले में यहां।) मैंने इसे एक डमी प्रारूप में पारित किया है (जैसे AuthorizatinJackGET में) और मैंने अपने प्रॉक्सी के लिए कोड को बदल दिया है ताकि गंतव्य पर कॉल करते समय इसे हेडर में बदल दिया जा सके। । यहाँ यह PHP में है:

if (isset($_GET['AuthorizationJack'])) {
    $request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}

1

मेरे मामले में मैं एडब्ल्यूएस (एपीआई गेटवे) द्वारा होस्ट किया गया एक एपीआई कह रहा हूं। त्रुटि तब हुई जब मैंने एपीआई को स्वयं के डोमेन के अलावा किसी अन्य डोमेन से एपीआई कॉल करने की कोशिश की। चूंकि मैं एपीआई मालिक हूं, इसलिए मैंने परीक्षण वातावरण के लिए कॉर्स को सक्षम किया, जैसा कि अमेज़ॅन डॉक्यूमेंटेशन में वर्णित है ।

उत्पादन में यह त्रुटि नहीं होगी, क्योंकि अनुरोध और एपीआई एक ही डोमेन में होंगे।

मुझे उम्मीद है यह मदद करेगा!


0

जैसा कि @Dark Falcon द्वारा उत्तर दिया गया है, मैं बस इससे निपटता हूं ।

मेरे मामले में, मैं नोड.जेएस सर्वर का उपयोग कर रहा हूं, और यदि यह मौजूद नहीं है तो एक सत्र बना रहा है। चूंकि विकल्प विधि में सत्र विवरण नहीं है, इसलिए इसने प्रत्येक POST विधि अनुरोध के लिए एक नया सत्र तैयार किया।

इसलिए मेरी ऐप रूटीन में सत्र-अगर-मौजूद नहीं है, तो मैंने सिर्फ यह देखने के लिए एक चेक जोड़ा कि क्या विधि है OPTIONS, और यदि ऐसा है, तो बस सत्र बनाने का हिस्सा छोड़ें:

    app.use(function(req, res, next) {
        if (req.method !== "OPTIONS") {
            if (req.session && req.session.id) {
                 // Session exists
                 next();
            }else{
                 // Create session
                 next();
          }
        } else {
           // If request method is OPTIONS, just skip this part and move to the next method.
           next(); 
        }
    }

0

"पूर्वनिर्धारित" अनुरोध सबसे पहले दूसरे डोमेन पर संसाधन के लिए विकल्प विधि द्वारा एक HTTP अनुरोध भेजते हैं, ताकि यह निर्धारित किया जा सके कि वास्तविक अनुरोध भेजने के लिए सुरक्षित है या नहीं। क्रॉस-साइट अनुरोध

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS


1
क्या आप थोड़ी और जानकारी जोड़ सकते हैं? आपका जवाब एक टिप्पणी की तरह लग रहा है। :)
बडाकाडबरा

0

Axios का उपयोग करने पर विचार करें

axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {

  if(res.data.error) {

  } else { 
    doAnything( res.data )
  }

}).catch(function (error) {
   doAnythingError(error)
});

मैं इस मुद्दे को लाने और axios का उपयोग कर पूरी तरह से काम किया था।



0

मैंने एक समान मुद्दे का सामना किया है। मैंने यह समझने के लिए लगभग आधा दिन बिताया कि क्यों सब कुछ फ़ायरफ़ॉक्स में सही ढंग से काम करता है और क्रोम में विफल रहता है। मेरे मामले में यह मेरे अनुरोध हेडर में डुप्लिकेट किए गए (या शायद गलत तरीके से) फ़ील्ड के कारण था।


0

XHR के बजाय फ़िश का उपयोग करें, फिर अनुरोध पूर्व-सूचीबद्ध नहीं होगा यहां तक ​​कि यह क्रॉस-डोमेन भी है।


-1
 $.ajax({
            url: '###',
            contentType: 'text/plain; charset=utf-8',
            async: false,
            xhrFields: {
                withCredentials: true,
                crossDomain: true,
                Authorization: "Bearer ...."
            },

            method: 'POST',

            data: JSON.stringify( request ),
            success: function (data) {
                console.log(data);
            }
        });

सामग्री टाइप: 'पाठ / सादा; charset = utf-8 ', या सिर्फ सामग्री टाइप:' टेक्स्ट / प्लेन ', मेरे लिए काम करता है! सादर!!


प्रश्न से इसका क्या लेना देना है?
कोरी ओगबर्न

नमस्ते, मुझे लगता है कि यह शीर्षक में समस्या को हल करता है, इस सामग्री प्रकार के साथ आप विकल्प विधि पास करते हैं। सादर
डेविड लोप्स

ContentType का विधि से कोई लेना-देना नहीं है।
कोरी ओगबर्न

मुझे पता है कि आप क्या कह रहे हैं, लेकिन इसे आजमाएं। ब्राउज़र के आधार पर आपकी सामग्री-प्रकार आपके अनुरोध को प्रभावित कर सकती है और आपकी विधि बदल सकती है!
डेविड लोप्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.