jQuery xml त्रुटि 'नहीं' पहुंच-नियंत्रण-अनुमति-उत्पत्ति 'शीर्ष लेख अनुरोधित संसाधन पर मौजूद है।'


89

मैं केवल मनोरंजन के लिए मेरी इस निजी परियोजना पर काम कर रहा हूं, जहां मैं एक xml फ़ाइल पढ़ना चाहता हूं, जो http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml पर स्थित है और xml को पार्स कर रहा है मुद्राओं के बीच मूल्यों को परिवर्तित करने के लिए इसका उपयोग करें।

अब तक मैं नीचे दिए गए कोड के साथ आया हूं जो कि xml को पढ़ने के लिए काफी बुनियादी है लेकिन मुझे निम्नलिखित त्रुटि मिलती है।

XMLHttpRequest को लोड नहीं किया जा सकता ****। अनुरोधित संसाधन पर कोई 'एक्सेस-कंट्रोल-अनुमति-उत्पत्ति' हेडर मौजूद नहीं है। इसलिए ' http://run.jsbin.com ' की उत्पत्ति की अनुमति नहीं है।

$(document).ready( 
    function() {     
        $.ajax({          
            type:  'GET',
            url:   'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',
            dataType: 'xml',              
            success: function(xml){
                alert('aaa');
            }
         });
    }
);

मुझे अपने कोड में कुछ भी गलत नहीं दिखाई दे रहा है, इसलिए मैं उम्मीद कर रहा हूं कि कोई मुझे बता सकता है कि मैं अपने कोड के साथ क्या गलत कर रहा हूं और मैं इसे कैसे ठीक कर सकता हूं।


2
मेरा सुझाव है कि आप के बारे में पढ़ें एक ही मूल नीति और CORS
jmoerdyk

त्रुटि बताती है कि गलत क्या है, शब्द के लिए शब्द। आपका कोड ठीक है, समस्या उस सर्वर के साथ है जिसे आप एक्सेस कर रहे हैं।
केविन बी

जवाबों:


163

आप समान-मूल नीति के कारण http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xmlपरिनियोजित फ़ाइल से एक अजाक्स कॉल करने में सक्षम नहीं होंगे ।http://run.jsbin.com


स्रोत (उर्फ उत्पत्ति ) पृष्ठ और लक्ष्य URL विभिन्न डोमेन ( run.jsbin.comऔर www.ecb.europa.eu) पर हैं, आपका कोड वास्तव में एक क्रॉस-डोमेन (CORS) अनुरोध करने का प्रयास कर रहा है , न कि एक सामान्य GET

कुछ शब्दों में, समान-मूल नीति कहती है कि ब्राउज़र को केवल HTML पृष्ठ के समान डोमेन पर सेवाओं के लिए अजाक्स कॉल की अनुमति देनी चाहिए ।


उदाहरण:

एक पेज http://www.example.com/myPage.htmlकेवल सेवाओं पर सीधे अनुरोध कर सकता है http://www.example.com, जैसे कि http://www.example.com/api/myService। यदि सेवा को किसी अन्य डोमेन (कहते हैं http://www.ok.com/api/myService) पर होस्ट किया जाता है , तो ब्राउज़र सीधे कॉल नहीं करेगा (जैसा कि आप उम्मीद करेंगे)। इसके बजाय, यह एक CORS अनुरोध करने का प्रयास करेगा।

इसे शीघ्र ही डालने के लिए, अलग-अलग डोमेन में, अपने ब्राउज़र में (कोर) अनुरोध * करने के लिए:

  • Originमूल अनुरोध में एक हेडर शामिल होगा (मूल्य के रूप में पृष्ठ के डोमेन के साथ) और इसे हमेशा की तरह निष्पादित करें; और फिर
  • यदि केवल उस अनुरोध के लिए सर्वर प्रतिक्रिया में पर्याप्त हेडर होते हैं ( उनमें Access-Control-Allow-Originसे एक है ) कॉर्स अनुरोध की अनुमति देता है, तो ब्राउज़ कॉल को पूरा करेगा (लगभग उसी तरह अगर यह HTML पेज एक ही डोमेन पर था)।
    • यदि अपेक्षित हेडर नहीं आते हैं, तो ब्राउज़र बस छोड़ देता है (जैसे कि यह आपने किया था)।


* ऊपर एक सरल अनुरोध में चरणों को दर्शाया गया है , जैसे GETकोई फैंसी हेडर के साथ नियमित रूप से। अनुरोध सरल नहीं है (जैसे एक POSTसाथ application/jsonसामग्री प्रकार के रूप में), ब्राउज़र यह एक पल का आयोजन करेगा, और, यह पूरा करने से पहले, पहले एक भेज देंगे OPTIONSलक्ष्य यूआरएल के लिए अनुरोध। ऊपर की तरह, यह केवल तभी जारी रहेगा जब इस OPTIONSअनुरोध की प्रतिक्रिया में कॉर्स हेडर शामिल हैं। यहOPTIONS कॉल को प्रीफ़लाइट अनुरोध के रूप में जाना जाता है ।
** मैं लगभग कह रहा हूं क्योंकि नियमित कॉल और कॉर्स कॉल के बीच अन्य अंतर हैं। एक महत्वपूर्ण यह है कि कुछ हेडर, भले ही प्रतिक्रिया में मौजूद हों, अगर वेAccess-Control-Expose-Headers हेडर में शामिल नहीं हैं, तो उन्हें ब्राउज़र द्वारा नहीं उठाया जाएगा


इसे कैसे जोड़ेंगे?

क्या यह सिर्फ एक टाइपो था? कभी-कभी जावास्क्रिप्ट कोड लक्ष्य डोमेन में सिर्फ एक टाइपो होता है। आपने जाँच कर ली है क्या? यदि पृष्ठ इस पर www.example.comहै तो केवल नियमित कॉल करेगा www.example.com! जैसे अन्य यूआरएल, api.example.comया यहाँ तक कि example.comया www.example.com:8080माना जाता है अलग ब्राउज़र द्वारा डोमेन! हाँ, यदि पोर्ट अलग है, तो यह एक अलग डोमेन है!

हेडर जोड़ें। कॉर्स को सक्षम करने का सबसे सरल तरीका Access-Control-Allow-Originसर्वर की प्रतिक्रियाओं में आवश्यक हेडर (जैसे ) जोड़कर है । (प्रत्येक सर्वर / भाषा के पास ऐसा करने का एक तरीका है - कुछ समाधान यहां देखें )

अखिरी सहारा: यदि आपके पास सेवा के लिए सर्वर-साइड एक्सेस नहीं है, तो आप इसे मिरर भी कर सकते हैं (टूल जैसे कि रिवर्स प्रॉक्सीज़ के माध्यम से ), और वहां सभी आवश्यक हेडर शामिल करें।


2
धन्यवाद, यह बहुत सारी जानकारी है। अब मैं आगे बढ़ने के लिए आवश्यक शोध कर सकता हूं।
बेज़िंगा B।

1
हाय acdcjunior, मैं उस वेब सेवा को कैसे प्रतिबिंबित कर सकता हूं जिसे मैं एक्सेस करना चाहता हूं?
फ्रेंवा

2
@Franva आपको एक HTTP सर्वर (जैसे कि Tomcat, PHP के साथ Apache, ASP के साथ ASP) सेटअप करना होगा और वहाँ एक पेज रखना होगा, जो हर अनुरोध के लिए, यह वास्तविक सेवा (आप मिररिंग कर रहे हैं सेवा) के लिए एक सॉकेट खोलता है, वास्तविक डेटा का अनुरोध करता है और फिर प्रतिक्रिया के रूप में देता है। बेशक, आप कोड (जावा, पीएचपी, एएसपी, आदि) के माध्यम से ऐसा करेंगे।
एकड्यूजनिओर

अगर मेरी समझ सही है तो @acdcjunior कृपया मुझे सुधारें। अगर मैं सीधे ब्राउज़र में कुछ URL दर्ज करता हूं, तो यह एक्सेस-कंट्रोल-अनुमति-उत्पत्ति के बिना स्वचालित रूप से नए डोमेन url पर रीडायरेक्ट करेगा । उदाहरण के लिए, WIF का उपयोग करते समय, उपयोगकर्ता पहली बार लॉगिन करने पर तीसरे पक्ष के लॉगिन पृष्ठ पर पुनर्निर्देशित किया जाएगा।
मशीनिनारियम

@machinarium मुझे यकीन नहीं है अगर मैं समझता हूं कि आपका क्या मतलब है, लेकिन मैं जवाब देने की कोशिश करूंगा (मुझे बताएं कि क्या मुझे कुछ गलत मिला है): यदि आप ब्राउज़र के एड्रेस बार में URL दर्ज करते हैं, तो Access-Control-Allow-Originउस URL की उपस्थिति या अनुपस्थिति हेडर बिल्कुल भी मायने नहीं रखेगा - ब्राउज़र हमेशा की तरह URL खोलेगा। समान-मूल नीति (और Access-Control-Allow-Originशीर्ष लेख की आवश्यकता ) केवल अजाक्स कॉल पर लागू होती है।
एकडजुनियर

29

यदि आपके सर्वर पर php सक्षम है, तो इसे करने के लिए एक तरह का हैक-टैस्टिक तरीका है। इस पंक्ति को बदलें:

url:   'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',

इस लाइन के लिए:

url: '/path/to/phpscript.php',

और फिर php स्क्रिप्ट में (यदि आपके पास file_get_contents () फ़ंक्शन का उपयोग करने की अनुमति है)

<?php

header('Content-type: application/xml');
echo file_get_contents("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

?>

अगर वह url एक अलग मूल से है तो Php का मन नहीं लगता है। जैसा कि मैंने कहा, यह एक घिनौना जवाब है, और मुझे यकीन है कि इसमें कुछ गड़बड़ है, लेकिन यह मेरे लिए काम करता है।

संपादित करें: यदि आप php में परिणाम को कैश करना चाहते हैं, तो यहां php फ़ाइल का उपयोग किया जाएगा:

<?php

$cacheName = 'somefile.xml.cache';
// generate the cache version if it doesn't exist or it's too old!
$ageInSeconds = 3600; // one hour
if(!file_exists($cacheName) || filemtime($cacheName) > time() + $ageInSeconds) {
  $contents = file_get_contents('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml');
  file_put_contents($cacheName, $contents);
}

$xml = simplexml_load_file($cacheName);

header('Content-type: application/xml');
echo $xml;

?>

यहां से कैशिंग कोड लेते हैं


3
इससे भी बेहतर उपाय यह होगा कि सर्वर साइड पर XML फाइल को कैश करें और केवल file_get_contentsकॉल करें यदि सबसे हाल की XML फाइल पर्याप्त रूप से दिनांकित है। इसके अलावा, अपने कंटेंट-टाइप हेडर को न भूलें :-)
sffc

इस जवाब पर अड़ गए। प्रश्न: PHP फ़ाइल को GET डेटा लेने के लिए कैसे कहा जाता है और इसे उक्त URL में सबमिट करना है? क्या यह POSTed डेटा के साथ भी काम करेगा?
13

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