Firebase için Cloud Functions'da CORS'u Etkinleştirme


141

Şu anda Firebase için yeni Cloud Functions'ı nasıl kullanacağımı öğreniyorum ve yaşadığım sorun, AJAX isteği aracılığıyla yazdığım işleve erişememem. "Erişim Kontrolü-Menşe İzin Ver" hatası alıyorum. İşte yazdığım fonksiyonun bir örneği:

exports.test = functions.https.onRequest((request, response) => {
  response.status(500).send({test: 'Testing functions'});
})

İşlev şu url'de bulunur: https://us-central1-fba-shipper-140ae.cloudfunctions.net/test

Firebase belgeleri, işlevin içine CORS ara yazılım eklemeyi öneriyor, denedim ama benim için çalışmıyor: https://firebase.google.com/docs/functions/http-events

Ben böyle yaptım:

var cors = require('cors');    

exports.test = functions.https.onRequest((request, response) => {
   cors(request, response, () => {
     response.status(500).send({test: 'Testing functions'});
   })
})

Neyi yanlış yapıyorum? Bununla ilgili herhangi bir yardım için minnettar olurum.

GÜNCELLEME:

Doug Stevenson'ın cevabı yardımcı oldu. Ekleme ({köken: true}) Soruna sabit, ben de değişime vardı response.status(500)için response.status(200)tamamen ilk başta cevapsız hangi.


Ayrıca dokümanlar örnek bir burada
Kato

Sağlanan çözümle çalışan bazı işlevlerim var, ancak şimdi esasen index.html'imin en üstüne açık grafikler ekleyen ve güncellenmiş index.html'yi döndüren yeni bir işlevi deniyorum ve çalışmaya devam edemiyorum :( ACCESS-CONTROL --- hata
TheeBen

2
gelen talebi yukarıdaki gibi cors () ile sarmalamak benim için işe yarayan tek şeydi
Charles Harring

"güncellemenizi" cors middleware'in gerekli olduğunun altını çizecek şekilde düzenleyebilir misiniz? Bu, bazı insanlara biraz zaman kazandıracak
Antoine Weber,

Yanıtlar:


151

Firebase ekibi tarafından sağlanan, CORS kullanımını gösteren iki örnek işlev vardır :

İkinci örnek, korselerle şu anda kullandığınızdan farklı bir çalışma yöntemi kullanıyor.

Ayrıca, örneklerde gösterildiği gibi şu şekilde içe aktarmayı düşünün:

const cors = require('cors')({origin: true});

2
Teşekkür ederim! ({Origin: true}) eklenmesi yardımcı oldu.
Andrey Pokrovskiy

2
Güzel, origin: truebunu dışarıda bırakmak bunun işe
Scott

4
Erişime izin verilecek alanların beyaz listesinin tanımlandığı yer burası gibi görünüyor? Ayar origin: trueherhangi bir etki alanının erişmesine izin veriyor mu? ( npmjs.com/package/cors ) @Doug Stevenson Firebase'in istemci / sunucu https işlevleri için gereken temel bilgiler hakkında bir belge yazabileceğini düşünüyor musunuz? Numune deposu iyi, ancak bu fazladan gereksinimi kaçırmıştık.
Alan

9
Arka uçlarına CORS desteği eklemeye istekli herkes için: lütfen sonuçlarını ve nasıl düzgün şekilde yapılandırılacağını anladığınızdan emin olun. "origin: true" test etmek için harika ama tüm amacı
geçersiz kılıyor

1
google bulut işlevleri joker karakter kaynağına izin vermiyor: cloud.google.com/functions/docs/writing/…
Corey Cole

73

CORS'u bulut işlevinde şu şekilde ayarlayabilirsiniz

response.set('Access-Control-Allow-Origin', '*');

corsPaketi içe aktarmaya gerek yok


2
Bu benim durumum için mükemmel çalışıyor, Mailchimp API'ye XHR çağrısı yapan bir bulut işlevi.
elverde

1
Gerekli cevap budur.
Jimmy Kane

1
google bulut işlevleri joker karakter kaynağına izin vermiyor: cloud.google.com/functions/docs/writing/…
Corey Cole

4
@CoreyCole Bence bu sadece Authorizationbaşlığı eklemeniz gerekiyorsa . Yukarıdakiler iyi çalışıyor gibi görünüyor.
Stuart Memo

Bu kod satırı nereye yerleştirilir? Bulut işlevinin hangi bölümü?
Antonio Ooi

41

Bunu Typescript'te yapmaya çalışan herkes için kod budur:

import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const exampleFunction= functions.https.onRequest(async (request, response) => {
       corsHandler(request, response, () => {});
       //Your code here
});

3
Çözüm, bulut işlevlerinde oturum açmanızı (çok kötü) ve uygun eşzamansız / bekleme işlevselliğini kaybetmenize neden olur, işlev içeriğinin uzun aramalarda geri arama içinde zamanından önce sona erme riskini alırsınız.
Oliver Dixon

2
google bulut işlevleri joker karakter kaynağına izin vermiyor: cloud.google.com/functions/docs/writing/…
Corey Cole

29

Bir süre sonra bunu googling yapanların iyiliği için ek bir bilgi parçası: Firebase barındırma kullanıyorsanız, yeniden yazımları da ayarlayabilirsiniz, böylece örneğin (firebase_hosting_host) / api / myfunction gibi bir url ( firebase_cloudfunctions_host) / doStuff işlevi. Bu şekilde, yönlendirme şeffaf ve sunucu tarafı olduğundan, korselerle uğraşmanıza gerek kalmaz.

Firebase.json'daki yeniden yazmalar bölümüyle bunu ayarlayabilirsiniz:

"rewrites": [
        { "source": "/api/myFunction", "function": "doStuff" }
]

1
imo, bu en iyi cevaptır, çünkü gerçek sorunu herhangi bir ek güvenlik sorunu eklemeden çözer. Bu şekilde, bulut işlevleri diğerleriyle aynı etki alanından sunulur ve herhangi bir kordona bile ihtiyacınız olmaz.
koljaTM

3
Bu gerçekten harika bir özellik, ancak şu anda yalnızca işlevler varsayılan bölgede (us-central1) yaşıyorsa çalışır. Gecikme nedeniyle işlevlerimi europe-west1'e dağıtmak istedim ve şu sorunla karşılaştım: github.com/firebase/firebase-tools/issues/842
Alex Suzuki

Yönlendirme iyi çalışıyor ve URL'yi daha temiz hale getiriyor, ancak GET parametrelerini nasıl geçireceğimi bulamadım. İşlev (yeniden yazmadan sonra) parametresiz çağrılıyor gibi görünüyor.
royappa

20

Benim için hiçbir CORS çözümü işe yaramadı ... şimdiye kadar!

Başka birinin yaptığım aynı sorunu yaşayıp yaşamadığından emin değilim, ancak CORS'u bulduğum örneklerden 5 farklı şekilde kurdum ve hiçbir şey işe yaramadı. Gerçekten bir hata olup olmadığını görmek için Plunker ile minimal bir örnek oluşturdum, ancak örnek çok güzel geçti. Bana bir şey anlatıp anlatamayacağını görmek için firebase fonksiyon günlüklerini (firebase konsolunda bulunan) kontrol etmeye karar verdim. Benim düğümlü sunucu kodunda bir çift hatalar vardı , CORS ilgili olmayan ben debug zaman, benim CORS hata mesajının beni serbest . CORS ile ilgisi olmayan kod hatalarının neden bir CORS hata yanıtı verdiğini bilmiyorum, ama beni birkaç saat boyunca yanlış tavşan deliğine götürdü ...

tl; dr - hiçbir CORS çözümü çalışmıyorsa firebase işlev günlüklerinizi kontrol edin ve sahip olduğunuz hataların hatalarını ayıklayın


1
bu beni deli etti. benim durumumda kodda hata bile değildi! o Error: quota exceeded (Quota exceeded for quota group 'NetworkIngressNonbillable' and limit 'CLIENT_PROJECT-1d' of service 'cloudfunctions.googleapis.com kadar temelde ücretsiz kota aşıldı ve işlevler cors hatası verdi
Stanislau Buzunko

Burada birkaç kez olur, aynı hata sunucudan cors ile birlikte döndürülür: Hata: dahili temelde bir hatadır. Bu hata, örneğin bir işlev adını yanlış yazmanız gibi yanlış işlevi çalıştırdığınızda da ortaya çıkar
Henrik Bøgelund Lavstsen

Bulut işlevi içinde Google reCAPTCHA doğrulaması talep etmeye çalıştığınızda, tarayıcı size CORS hatası da verir. Firebase Console işlev günlüğünü kontrol ettiğimde diyor access to external network resources not allowed if the billing account is not enabled. Faturalandırma hesabını etkinleştirdikten sonra mükemmel çalışıyor. Bu da cors ile ilgili olmayan örneklerden biridir ancak bir cors hatası atılır.
Antonio Ooi

19

@Andreys'in kendi sorusuna cevabına biraz ek var.

Görünüşe göre cors(req, res, cb)işlevde geri aramayı çağırmanız gerekmiyor , bu nedenle tüm kodunuzu geri aramaya eklemeden işlevinizin üst kısmındaki cors modülünü çağırabilirsiniz. Daha sonra cors uygulamak istiyorsanız bu çok daha hızlıdır.

exports.exampleFunction = functions.https.onRequest((request, response) => {
    cors(request, response, () => {});
    return response.send("Hello from Firebase!");
});

Açılış gönderisinde belirtildiği gibi cors'u başlatmayı unutmayın:

const cors = require('cors')({origin: true});


1
bu, başlıkları manuel olarak ayarlayan diğer SO cevapları işe yaramadığında işe yaradı
Jim Factor

Bu çalışır, ancak etkinleştirdiyseniz ve firebase'e dağıtamazsanız TSlint hatasına neden olabilir. Yanıtı, üstesinden gelmek için kapağın içine koyuncors(request, response, () => { return response.send("Hello from Firebase!"); });
Spiral Out

1
Burada 2 hata beyler. Birincisi. Cors işlevinden sonraki her şey iki kez çalışacaktır (ilk istek ön kontrol olduğundan). İyi değil. İkinci olarak, @SpiralOut çözümünüz bulut işlevlerinde oturum açmanızı kaybetmenize (çok kötü) ve uygun eşzamansız / bekleme işlevselliğini kaybetmenize neden olur, işlev içeriğinin geri arama içinde erken sona erme riskini alırsınız.
Oliver Dixon

@SpiralOut sadece tslint'i devre dışı bırakabilirsiniz
Vlad

1
Geçen yıl gcf hakkında çok şey öğrendiğim için artık bu cevabı tavsiye etmiyorum. Hızlı prototipler için kullanışlı olabilir, ancak gerçek üretim vakalarında bundan kaçının
Jaap Weijland

11

Bu yardımcı olabilir. Express (özel URL) ile firebase HTTP bulut işlevini oluşturdum

const express = require('express');
const bodyParser = require('body-parser');
const cors = require("cors");
const app = express();
const main = express();

app.post('/endpoint', (req, res) => {
    // code here
})

app.use(cors({ origin: true }));
main.use(cors({ origin: true }));
main.use('/api/v1', app);
main.use(bodyParser.json());
main.use(bodyParser.urlencoded({ extended: false }));

module.exports.functionName = functions.https.onRequest(main);

Lütfen yeniden yazma bölümleri eklediğinizden emin olun

"rewrites": [
      {
        "source": "/api/v1/**",
        "function": "functionName"
      }
]

1
Cevabınız çok düşük dostum, açık ara en iyi cevap.
Avram Virgil

Teşekkürler. @AvramVirgil
Sandy

Bu en hızlı ve en kolayı oldu, Teşekkürler!
Gaurav Kakkar

8

Bununla ilgili küçük bir parça yayınladım:

https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html

Genel olarak, GCF / Firebase İşlevlerindeki gereksinimleri karşılamak için biraz hackleme gerektiren Express CORS paketini kullanmalısınız .

Umarım yardımcı olur!


4
Bilgisayar korsanlığı ile ne demek istediğinizden emin değil misiniz? Biraz detaylandırmak ister misin?
Gönderinizi

1
cors modülünün yazarı burada; mhaligowski "hackleme" derken, Express'in ara yazılım çağırma biçimiyle eşleşmesini sağlamak için çağrıyı cors modülüne sarması gerektiği anlamına geliyordu (yani, req & res'ten sonra üçüncü parametre olarak bir işlev sağla)
Troy

4

Dışarıda benim gibi insanlar varsa: Bulut işlevini aynı projeden bulut işlevi olarak çağırmak istiyorsanız, firebase sdk'yi başlatabilir ve onCall yöntemini kullanabilirsiniz. Sizin için her şeyi halledecek:

exports.newRequest = functions.https.onCall((data, context) => {
    console.log(`This is the received data: ${data}.`);
    return data;
})

Bu işlevi şöyle çağırın:

// Init the firebase SDK first    
const functions = firebase.functions();
const addMessage = functions.httpsCallable(`newRequest`);

Firebase belgeleri: https://firebase.google.com/docs/functions/callable

SDK'yı başlatamıyorsanız, işte diğer önerilerin özü:


3
aslında tarayıcıda onCall func kullandığımda cors hatası aldım. Bu istekte costom başlıkları ayarlayabilir miyim?
Viktor Hardubej

4

Herhangi bir "cors" kitaplığını içe aktarmadan cors'u etkinleştirmenin bir yolunu buldum. Ayrıca Typescript, Chrome 81.0 sürümünde de çalışır ve test edilmiştir.

exports.createOrder = functions.https.onRequest((req, res) => {
// browsers like chrome need these headers to be present in response if the api is called from other than its base domain
  res.set("Access-Control-Allow-Origin", "*"); // you can also whitelist a specific domain like "http://127.0.0.1:4000"
  res.set("Access-Control-Allow-Headers", "Content-Type");

  // your code starts here

  //send response
  res.status(200).send();
});

3

Ne olursa olsun, appiçeri girerken aynı sorunu yaşıyordum onRequest. Firebase işlevi için istek url'sinde sorunun sonda bir eğik çizgi olduğunu fark ettim. Ekspres arıyordu '/'ama fonksiyonun sonundaki eğik çizgiye sahip değildim [project-id].cloudfunctions.net/[function-name]. CORS hatası yanlış negatifti. Sondaki eğik çizgiyi eklediğimde, beklediğim yanıtı aldım.


Ayrıca istediğiniz zaman hesabınıza ekleyin yapmak [project-id]bu gibi i yüz sorunu
takılı

3

İsteğimde yetkim olduğu için sadece bu yol benim için işe yarar:

exports.hello = functions.https.onRequest((request, response) => {
response.set('Access-Control-Allow-Origin', '*');
response.set('Access-Control-Allow-Credentials', 'true'); // vital
if (request.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    response.set('Access-Control-Allow-Methods', 'GET');
    response.set('Access-Control-Allow-Headers', 'Content-Type');
    response.set('Access-Control-Max-Age', '3600');
    response.status(204).send('');
} else {
    const params = request.body;
    const html = 'some html';
    response.send(html)
} )};

google bulut işlevleri joker karakter kaynağına izin vermiyor: cloud.google.com/functions/docs/writing/…
Corey Cole

3

Eğer cors eklentisini kullanmıyorsanız / kullanamıyorsanız setCorsHeaders(), eylemci fonksiyonunda ilk olarak fonksiyonu çağırmak da işe yarayacaktır.

Ayrıca yanıt verirken responseSuccess / Error işlevlerini kullanın.

const ALLOWED_ORIGINS = ["http://localhost:9090", "https://sub.example.com", "https://example.com"]


// Set CORS headers for preflight requests
function setCorsHeaders (req, res) {
  var originUrl = "http://localhost:9090"


  if(ALLOWED_ORIGINS.includes(req.headers.origin)){
    originUrl = req.headers.origin
  }

  res.set('Access-Control-Allow-Origin', originUrl);
  res.set('Access-Control-Allow-Credentials', 'true');

  if (req.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    res.set('Access-Control-Allow-Methods', 'GET,POST','PUT','DELETE');
    res.set('Access-Control-Allow-Headers', 'Bearer, Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
  }
}

function respondError (message, error, code, res) {
  var response = {
    message: message,
    error: error
  }
  res.status(code).end(JSON.stringify(response));
}


function respondSuccess (result, res) {
  var response = {
    message: "OK",
    result: result
  }
  res.status(200).end(JSON.stringify(response));
}

2

Firebase uygulamasını yerel olarak test ediyorsanız localhost, bulut yerine işlevleri işaretlemeniz gerekir . Varsayılan olarak firebase serveveya firebase emulators:startweb uygulamanızda kullandığınızda işlevleri localhost yerine sunucuya yönlendirir.

Firebase init betiğinden sonra html başlığına aşağıdaki betiği ekleyin:

 <script>
      firebase.functions().useFunctionsEmulator('http://localhost:5001')
 </script> 

Kodu sunucuya dağıtırken bu parçacığı kaldırdığınızdan emin olun.


2

Değişen truetarafından "*"bu ne kadar benziyor yani benim için hile mi:

const cors = require('cors')({ origin: "*" })

Bu yaklaşımı denedim çünkü genel olarak bu yanıt başlığı şu şekilde ayarlanır:

'Access-Control-Allow-Origin', '*'

Bunun, herhangi bir alanın uç noktalarınızı aramasına izin vereceğini ve bu nedenle güvenli OLMADIĞINI unutmayın.

Ek olarak, dokümanlar hakkında daha fazlasını okuyabilirsiniz: https://github.com/expressjs/cors


1

Express kullanmıyorsanız veya sadece CORS kullanmak istiyorsanız. Aşağıdaki kod çözülmesine yardımcı olacaktır

const cors = require('cors')({ origin: true, });   
exports.yourfunction = functions.https.onRequest((request, response) => {  
   return cors(request, response, () => {  
        // *Your code*
    });
});

0

Benim durumumda, hata bulut işlevi çağırıcı sınır erişiminden kaynaklanıyordu. Lütfen allUsers'ı cloud function invoker'e ekleyin. Lütfen bağlantıyı yakalayın . Daha fazla bilgi için lütfen makaleye bakın


Lütfen cevabınızda bağlantılı materyal hakkında bazı açıklamalar sunun, neden alakalı ve böyle
Firefly

0

Diğer çözümlerden hiçbiri işe yaramazsa, CORS - yönlendirmeyi etkinleştirmek için çağrının başlangıcına aşağıdaki adresi eklemeyi deneyebilirsiniz:

https://cors-anywhere.herokuapp.com/

JQuery AJAX isteğiyle örnek kod:

$.ajax({
   url: 'https://cors-anywhere.herokuapp.com/https://fir-agilan.web.app/gmail?mail=asd@gmail.com,
   type: 'GET'
});

0

Deneyimimi ekliyorum. Neden CORS hatası aldığımı bulmak için saatler harcadım.

O olur benim bulut fonksiyonunu yeniden adlandırdık (ilk ben büyük yükseltmeden sonra çalışıyordu).

Dolayısıyla, firebase uygulamam bulut işlevini yanlış bir adla çağırdığında, bir CORS hatası değil, bir 404 hatası vermesi gerekirdi.

Firebase uygulamamdaki bulut işlevi adını düzeltmek sorunu çözdü.

Bu konuda https://firebase.google.com/support/troubleshooter/report/bugs adresinden bir hata raporu doldurdum

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.