Neden bir GET isteği yerine OPTIONS isteği alıyorum?


289
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script>
$.get("http://example.com/", function(data) {
     alert(data);
});
</script>

söz konusu URL'ye bir SEÇENEK isteğinde bulunur ve geri arama hiçbir zaman hiçbir zaman çağrılmaz.

Alanlar arası olmadığında, iyi çalışır.

JQuery sadece bir <script>düğüm ile çağrı yapmak ve daha sonra yüklendiğinde geri arama yapmak gerekir? Sonucu elde edemeyeceğimi anlıyorum (alanlar arası olduğu için), ancak sorun değil; Sadece aramanýn geçmesini istiyorum. Bu bir hata mı, yoksa yanlış bir şey mi yapıyorum?


2
Web alanları arası olabilir. Örneğin, yerel dosya kullanmak yerine Dosya: // PATH_TO_WEBSITE / WEBSITE_LINK
James111 22:15

Yanıtlar:


263

MDN'ye göre ,

Ön ödemeli istekler

Basit isteklerden farklı olarak (yukarıda tartışılmıştır), "ön ödemeli" istekler, gerçek isteğin gönderilmesinin güvenli olup olmadığını belirlemek için önce diğer etki alanındaki kaynağa bir HTTP OPTIONS istek başlığı gönderir. Siteler arası talepler, kullanıcı verileri üzerinde etkileri olabileceğinden bu şekilde ön ödemelidir. Özellikle, aşağıdaki durumlarda bir istek önceden belirtilir:

  • GET veya POST dışındaki yöntemleri kullanır. Ayrıca, POST istek verilerini application / x-www-form-urlencoded, çoklu bölüm / form verileri veya metin / düz dışında bir İçerik Türü ile göndermek için kullanılırsa, örneğin POST isteği sunucuya XML yükü gönderiyorsa application / xml veya text / xml kullanarak, istek önceden düzenlenir.
  • İstekte özel üstbilgiler ayarlar (örneğin, istek X-PINGOTHER gibi bir üstbilgi kullanır)

44
Bu, "uygulama / json" dan "metin / düz" olarak değiştirerek sorunumuzu çözdü korkunç seçenekleri isteği durdurdu
Keeno

10
ne anlamadım tarayıcı neden sadece gerçek isteği göndermek güvenli olduğunu kontrol etmek için SEÇENEKLER yöntemi ile soruyor. ama ne anlamda? Yani sunucu da neden bu gerekli bazı yanıt başlıkları ile kısıtlamalar koyabilirsiniz demek?
hardik

11
@hardik CORS ekleyerek, sunucunuzdaki verileri istekler yoluyla (POST, PUT, DELETE vb.) manipüle edebilecekleri potansiyel olarak herkesten gelen istekleri kabul ettiğinizi unutmayın. Bu gibi durumlarda, özel üstbilgiler kullanılırken olduğu gibi, tarayıcı ilk önce sunucuyla, sunucunun istenmeyen istekleri göndermeden önce isteği kabul etmeye istekli olduğunu kontrol eder ve verileriniz için gerçekten tehlikeli olabilir. tarayıcı bunları kabul etmek istemiyorsa potansiyel olarak büyük yükler gönderen nokta, dolayısıyla uçuş öncesi SEÇENEKLER kontrolü.
davidnknight

6
@davidnknight verilerinizin sunucuya gönderilmesi tehlikeli olabilir, yani sunucunun güvenliği tehlikeye girebilir, o zaman elbette kötü niyetli sunucu SEÇENEKLERİNİZİN isteğine "Elbette, her şeyi gönderin!" Bu güvenlik nasıl? (dürüst soru)
Matt

3
"ön kontrol istekleri bir güvenlik meselesi değildir. Aksine, kuralları değiştirmeyen bir şeydir." - Ön Kontrol Taleplerini
Getirmenin


9

POST yapmaya çalışıyorsanız

JSON.stringifyForm verilerinize emin olun ve farklı gönderin text/plain.

<form id="my-form" onSubmit="return postMyFormData();">
    <input type="text" name="name" placeholder="Your Name" required>
    <input type="email" name="email" placeholder="Your Email" required>
    <input type="submit" value="Submit My Form">
</form>

function postMyFormData() {

    var formData = $('#my-form').serializeArray();
    formData = formData.reduce(function(obj, item) {
        obj[item.name] = item.value;
        return obj;
    }, {});
    formData = JSON.stringify(formData);

    $.ajax({
        type: "POST",
        url: "https://website.com/path",
        data: formData,
        success: function() { ... },
        dataType: "text",
        contentType : "text/plain"
    });
}

2

Böyle bir URL verildiğinde jQuery sadece bir JSONP isteği yapacak inanmıyorum. Bununla birlikte, bir geri arama için hangi bağımsız değişkenin kullanılacağını söylediğinizde bir JSONP isteği yapar:

$.get("http://metaward.com/import/http://metaward.com/u/ptarjan?jsoncallback=?", function(data) {
     alert(data);
});

Bu argümanı ("jsoncallback" olarak adlandırılması gerekmez) kullanmak tamamen alıcı komut dosyasına bağlıdır, bu durumda işlev asla çağrılmaz. Ancak, metaward.com'daki komut dosyasının yürütülmesini istediğinizi belirttiğiniz için, bunu başarabilirsiniz.


MY callback, komut dosyası öğesinin tam olarak yüklendiği konusunda hala bilgilendirilir mi? Ben sadece API için sorgulamadan önce güncellemenin gerçekleştiğinden emin olmak istiyorum.
Paul Tarjan

Alıcı komut dosyasının JSONP'yi destekleyip desteklemediğini ve belirlediğiniz işlevi çağırmak isteyip istemediğinizi göreceksiniz. Komut dosyası başka davranışa sahip olmayan bir JSON verisi bloğu oluşturmaktan başka bir şey yapmazsa, yükleme işleminin ne zaman yapıldığını söyleyemezsiniz. Yükleme işleminin ne zaman tamamlandığını söylemek gerekiyorsa, kendi sunucunuza proxy gibi davranan bir komut dosyası uygulamayı düşünebilirsiniz.
VoteyDisciple

1

Aslında, güvenlik nedeniyle web alanları arası AJAX (XMLHttp) isteklerine izin verilmez (istemci tarafından "kısıtlanmış" bir web sayfasını getirmeyi ve sunucuya geri göndermeyi düşünün - bu bir güvenlik sorunu olacaktır).

Tek geçici çözüm geri aramalardır. Bu: yeni bir komut dosyası oluşturmak ve src'yi JSON değerleri (myFunction ({data}) ile bir geri arama olan uç taraftaki JavaScript'e yönlendirmek) myFunction, verilerle bir şeyler yapan bir işlevdir (örneğin, değişken).


1
sağ, ancak bir <script src = ""> veya <img src = ""> yükleyebilirim ve tarayıcı mutlu bir şekilde vuracak. Ben sadece ithalat sonucu için sorgulamak böylece tam olarak yüklendiğinde bilmek istiyorum.
Paul Tarjan

1

Sadece "application / json" ifadesini "text / plain" olarak değiştirin ve JSON.stringify (istek) işlevini unutmayın:

var request = {Company: sapws.dbName, UserName: username, Password: userpass};
    console.log(request);
    $.ajax({
        type: "POST",
        url: this.wsUrl + "/Login",
        contentType: "text/plain",
        data: JSON.stringify(request),

        crossDomain: true,
    });

1

Ben de aynı problemi yaşadım. Benim düzeltme, sadece bet ortamında mevcut olan PHP betiğime üstbilgi eklemek oldu.

Bu, alanlar arası isteklere izin verir:

header("Access-Control-Allow-Origin: *");

Bu, ön kontrol isteğine, istemcinin istediği başlıkları göndermesinin uygun olduğunu bildirir:

header("Access-Control-Allow-Headers: *");

Bu şekilde isteği değiştirmeye gerek kalmaz.

Geliştirme veritabanınızda sızması muhtemel hassas verileriniz varsa, bunun hakkında iki kez düşünebilirsiniz.


1

Benim durumumda, aynı web sunucusuna bir jQuery POST yayınladığım için sorun CORS ile ilgisizdi. Veri JSON oldu ama ben dataType: 'json' parametresini atlamıştı.

Yukarıdaki David Lopes cevabında gösterildiği gibi bir contentType parametresi yoktu (ne de ekledim).


0

Firefox ve Opera'ya benziyor (Mac'te de test edildi) bunun çapraz etki alanını sevmiyor (ancak Safari bununla iyi durumda).

Uzak sayfayı kıvırmak için yerel sunucu tarafı kodunu aramanız gerekebilir.


0

Aşağıdaki başlıklar yardımıyla düzeltmeyi başardım

Access-Control-Allow-Origin
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
Access-Control-Allow-Methods

Nodejs üzerindeyseniz, kopyalayabileceğiniz / yapıştırabileceğiniz kod aşağıdadır.

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin','*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH');
  next();
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.