Obecnie uczę się, jak korzystać z nowych funkcji Cloud Functions dla Firebase, a problem, który mam, polega na tym, że nie mogę uzyskać dostępu do funkcji, którą napisałem, za pośrednictwem żądania AJAX. Pojawia się błąd „Nie 'Access-Control-Allow-Origin'”. Oto przykład funkcji, którą napisałem:
exports.test = functions.https.onRequest((request, response) => {
response.status(500).send({test: 'Testing functions'});
})
Funkcja znajduje się w tym adresie URL: https://us-central1-fba-shipper-140ae.cloudfunctions.net/test
Dokumentacja Firebase sugeruje dodanie oprogramowania pośredniczącego CORS do funkcji, próbowałem, ale to nie działa dla mnie: https://firebase.google.com/docs/functions/http-events
Oto jak to zrobiłem:
var cors = require('cors');
exports.test = functions.https.onRequest((request, response) => {
cors(request, response, () => {
response.status(500).send({test: 'Testing functions'});
})
})
Co ja robię źle? Byłbym wdzięczny za każdą pomoc w tym.
AKTUALIZACJA:
Odpowiedź Douga Stevensona pomogła. Dodanie ({origin: true}) rozwiązało problem, musiałem też zmienić, response.status(500)
do response.status(200)
którego początkowo całkowicie tęskniłem.
źródło
Odpowiedzi:
Istnieją dwie przykładowe funkcje udostępnione przez zespół Firebase, które demonstrują użycie CORS:
Druga próbka wykorzystuje inny sposób pracy z kordami niż obecnie.
Rozważ importowanie w ten sposób, jak pokazano na przykładach:
const cors = require('cors')({origin: true});
Ogólna forma twojej funkcji będzie wyglądać następująco:
exports.fn = functions.https.onRequest((req, res) => { cors(req, res, () => { // your function body here - use the provided req and res from cors }) });
źródło
origin: true
umożliwia dostęp dowolnej domenie? ( npmjs.com/package/cors ) @Doug Stevenson Czy myślisz, że Firebase mógłby napisać dokument o podstawach potrzebnych do obsługi funkcji https klient / serwer? Repozytorium sampli jest dobre, ale przegapiliśmy ten dodatkowy element.Możesz ustawić CORS w funkcji chmury w ten sposób
response.set('Access-Control-Allow-Origin', '*');
Nie ma potrzeby importowania
cors
pakietuźródło
Authorization
nagłówek. Wydaje się, że powyższe działa poprawnie.Dla każdego, kto próbuje to zrobić w skrypcie Typescript, jest to kod:
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 });
źródło
Dodatkowa informacja, tylko ze względu na tych, którzy szukają tego po pewnym czasie: Jeśli korzystasz z hostingu Firebase, możesz również skonfigurować przepisywanie, aby na przykład adres URL taki jak (firebase_hosting_host) / api / myfunction przekierował do ( firebase_cloudfunctions_host) / doStuff. W ten sposób, ponieważ przekierowanie jest przezroczyste i po stronie serwera, nie musisz zajmować się procesorami.
Możesz to ustawić za pomocą sekcji przepisywania w firebase.json:
"rewrites": [ { "source": "/api/myFunction", "function": "doStuff" } ]
źródło
Mam mały dodatek do odpowiedzi @Andreys na jego własne pytanie.
Wygląda na to, że nie musisz wywoływać funkcji zwrotnej w
cors(req, res, cb)
funkcji, więc możesz po prostu wywołać moduł cors u góry funkcji, bez osadzania całego kodu w funkcji zwrotnej. Jest to znacznie szybsze, jeśli chcesz później wdrożyć cors.exports.exampleFunction = functions.https.onRequest((request, response) => { cors(request, response, () => {}); return response.send("Hello from Firebase!"); });
Nie zapomnij zainicjować cors, jak wspomniano w poście otwierającym:
const cors = require('cors')({origin: true});
źródło
cors(request, response, () => { return response.send("Hello from Firebase!"); });
Żadne rozwiązania CORS nie działały dla mnie ... do teraz!
Nie jestem pewien, czy ktoś inny napotkał ten sam problem, co ja, ale skonfigurowałem CORS na 5 różnych sposobów z przykładów, które znalazłem, i wydawało się, że nic nie działa. Ustawiłem minimalny przykład z Plunkerem, aby sprawdzić, czy to naprawdę błąd, ale przykład działał pięknie. Postanowiłem sprawdzić dzienniki funkcji Firebase (znalezione w konsoli Firebase), aby sprawdzić, czy to może mi coś powiedzieć. Wystąpiło kilka błędów w kodzie mojego serwera węzła , które nie były związane z CORS , które podczas debugowania zwolniły mój komunikat o błędzie CORS . Nie wiem, dlaczego błędy kodu niezwiązane z CORS zwracają odpowiedź błędu CORS, ale doprowadziło mnie to do niewłaściwej króliczej nory przez dobrą liczbę godzin ...
tl; dr - sprawdź dzienniki funkcji Firebase, jeśli żadne rozwiązania CORS nie działają, i debuguj wszelkie błędy, które masz
źródło
Error: quota exceeded (Quota exceeded for quota group 'NetworkIngressNonbillable' and limit 'CLIENT_PROJECT-1d' of service 'cloudfunctions.googleapis.com
więc w zasadzie wolna kwota została przekroczona i funkcje zwrócił błąd Corsaccess to external network resources not allowed if the billing account is not enabled
. Po włączeniu konta rozliczeniowego działa idealnie. Jest to również jeden z przykładów niezwiązanych z cors, ale wyrzucany jest błąd cors.To może być pomocne. Stworzyłem funkcję chmury Firebase HTTP z Express (niestandardowy adres URL)
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);
Upewnij się, że dodałeś sekcje przepisywania
"rewrites": [ { "source": "/api/v1/**", "function": "functionName" } ]
źródło
Właśnie opublikowałem mały artykuł na ten temat:
https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html
Ogólnie rzecz biorąc, powinieneś używać pakietu Express CORS , który wymaga trochę hakowania, aby spełnić wymagania GCF / Firebase Functions.
Mam nadzieję, że to pomoże!
źródło
Znalazłem sposób na włączenie oprogramowania cors bez importowania biblioteki „cors”. Działa również
Typescript
i przetestował go w wersji Chrome 81.0.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(); });
źródło
res.set("Access-Control-Allow-Origin", "*")
; tylko nie działałores.set("Access-Control-Allow-Headers", "Content-Type");
rozwiązało mój problemcors
pakiet (lub odtworzyćOPTIONS
specjalną odpowiedź, któraTylko w ten sposób działa dla mnie, ponieważ mam autoryzację w mojej prośbie:
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) } )};
źródło
Jeśli są ludzie tacy jak ja: Jeśli chcesz wywołać funkcję chmury z tego samego projektu, co sama funkcja chmury, możesz zainicjować sdk bazy firebase i użyć metody onCall. Poradzi sobie ze wszystkim za Ciebie:
exports.newRequest = functions.https.onCall((data, context) => { console.log(`This is the received data: ${data}.`); return data; })
Wywołaj tę funkcję w ten sposób:
// Init the firebase SDK first const functions = firebase.functions(); const addMessage = functions.httpsCallable(`newRequest`);
Dokumenty Firebase: https://firebase.google.com/docs/functions/callable
Jeśli nie możesz zainicjować SDK, oto esencja innych sugestii:
źródło
Jeśli nie możesz / nie możesz użyć wtyczki cors,
setCorsHeaders()
zadziała również wywołanie funkcji jako pierwszej rzeczy w funkcji obsługi.Podczas odpowiadania użyj także funkcji respondSuccess / Error.
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)); }
źródło
Cóż to jest warte, miałem ten sam problem podczas przechodzenia
app
doonRequest
. Uświadomiłem sobie, że problem dotyczy końcowego ukośnika w adresie URL żądania dla funkcji Firebase. Express szukał,'/'
ale nie mam końcowego ukośnika w funkcji[project-id].cloudfunctions.net/[function-name]
. Błąd CORS był fałszywie ujemny. Kiedy dodałem końcowy ukośnik, otrzymałem oczekiwaną odpowiedź.źródło
[project-id]
ponieważ był to problem, z którym miałem do czynieniaJeśli lokalnie testujesz aplikację Firebase, musisz wskazać funkcje
localhost
zamiast chmury. Domyślniefirebase serve
lubfirebase emulators:start
wskazuje funkcje na serwer zamiast hosta lokalnego, gdy używasz go w aplikacji sieci Web.Dodaj poniższy skrypt w nagłówku html po skrypcie inicjującym firebase:
<script> firebase.functions().useFunctionsEmulator('http://localhost:5001') </script>
źródło
Zmiana
true
przez"*"
załatwiła mi sprawę, więc tak to wygląda:const cors = require('cors')({ origin: "*" })
Wypróbowałem to podejście, ponieważ generalnie tak jest ustawiony ten nagłówek odpowiedzi:
'Access-Control-Allow-Origin', '*'
Pamiętaj, że pozwoli to każdej domenie na wywoływanie twoich punktów końcowych, dlatego NIE jest to bezpieczne.
Dodatkowo możesz przeczytać więcej w dokumentach: https://github.com/expressjs/cors
źródło
Jeśli nie używasz Express lub po prostu chcesz używać CORS. Poniższy kod pomoże rozwiązać problem
const cors = require('cors')({ origin: true, }); exports.yourfunction = functions.https.onRequest((request, response) => { return cors(request, response, () => { // *Your code* }); });
źródło
Proste rozwiązanie za pomocą panelu Google Cloud Console:
Wybierz swoją funkcję chmury, np. „MyFunction”, po prawej stronie powinno pojawić się boczne menu pokazujące ustawienia kontroli dostępu do niej
Kliknij „Add Member”, wpisz „allUsers” i wybierz rolę „Cloud Function Invoker”
Zapisz to -> teraz na liście funkcji Twojej chmury powinna pojawić się uwaga „Zezwalaj na nieuwierzytelnione”
Dostęp jest teraz dostępny dla wszystkich z internetu z poprawną konfiguracją do projektu GCP lub Firebase. ( Uważaj )
źródło
W moim przypadku błąd był spowodowany ograniczeniem dostępu wywoływacza funkcji chmury. Dodaj allUsers do wywołującego funkcje chmury. Proszę złap link . Więcej informacji można znaleźć w artykule
źródło
Jeśli żadne z pozostałych rozwiązań nie działa, możesz spróbować dodać poniższy adres na początku połączenia, aby włączyć CORS - przekierowanie:
Przykładowy kod z żądaniem JQuery AJAX:
$.ajax({ url: 'https://cors-anywhere.herokuapp.com/https://fir-agilan.web.app/[email protected], type: 'GET' });
źródło
Dodaję moje doświadczenie. Spędziłem godziny, próbując znaleźć przyczynę błędu CORS.
Zdarza się, że zmieniłem nazwę mojej funkcji chmury (pierwsza, którą próbowałem po dużym uaktualnieniu).
Więc kiedy moja aplikacja Firebase wywoływała funkcję chmury z niepoprawną nazwą, powinna zgłosić błąd 404, a nie błąd CORS.
Naprawienie nazwy funkcji chmury w mojej aplikacji Firebase rozwiązało problem.
Wypełniłem tutaj raport o błędzie na ten temat https://firebase.google.com/support/troubleshooter/report/bugs
źródło