Firebase 용 Cloud 함수에서 CORS 활성화


141

현재 Firebase에 새로운 Cloud Functions를 사용하는 방법을 배우고 있으며 AJAX 요청을 통해 작성한 기능에 액세스 할 수 없다는 문제가 있습니다. "No 'Access-Control-Allow-Origin'"오류가 발생합니다. 내가 작성한 함수의 예는 다음과 같습니다.

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

이 URL에 기능이 있습니다 : https://us-central1-fba-shipper-140ae.cloudfunctions.net/test

Firebase 문서는 함수 내에 CORS 미들웨어를 추가하도록 제안했지만 시도했지만 작동하지 않습니다 : https://firebase.google.com/docs/functions/http-events

이것이 내가 한 방법입니다.

var cors = require('cors');    

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

내가 뭘 잘못하고 있죠? 이것에 대한 도움을 주셔서 감사합니다.

최신 정보:

Doug Stevenson 의 답변이 도움이되었습니다. ({origin : true})를 추가하면 문제가 해결 되었으며 처음에는 완전히 놓친 부분 으로 변경 response.status(500)해야 response.status(200)했습니다.


또한 문서의 샘플 여기
카토

제공된 솔루션으로 작동하는 일부 함수가 있지만 이제는 기본적으로 index.html 맨 위에 열린 그래프를 추가하고 업데이트 된 index.html을 반환하는 새 함수를 시도하고 있습니다. 액세스 제어 --- 오류
TheeBen

2
위와 같이 cors ()로 들어오는 요청을 래핑하는 것이 저에게
효과적

cors 미들웨어가 필요하다는 것을 강조하기 위해 "업데이트"를 편집 할 수 있습니까? 이것은 어떤 사람들에게 약간의 시간을 절약 할 수
앙투안 웨버

답변:


151

CORS 사용을 보여주기 위해 Firebase 팀에서 제공하는 두 가지 샘플 기능 이 있습니다.

두 번째 샘플은 현재 사용중인 것과 다른 방식으로 작업합니다.

또한 샘플에 표시된대로 다음과 같이 가져 오기를 고려하십시오.

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

2
감사합니다! ({origin : true}) 추가가 도움이되었습니다.
Andrey Pokrovskiy

2
니스, 당신 origin: true은 그것을 떠나면 이것이 작동하지 않을 것이기 때문에 분명히 필요 합니다
Scott

4
액세스를 허용 할 도메인의 허용 목록이 정의되어있는 것 같습니다. 그리고 설정 origin: true하면 모든 도메인에 액세스 할 수 있습니까? ( npmjs.com/package/cors ) @Doug 스티븐슨 마 당신은 중포 기지는 클라이언트 / 서버 HTTPS 기능에 필요한 기본에 문서를 쓸 수 있다고 생각? 샘플 저장소는 좋지만이 추가 요구 사항을 놓쳤습니다.
Alan

9
백엔드에 CORS 지원을 추가하려는 사람은 결과 및 결과를 올바르게 구성하는 방법을 이해해야합니다. "origin : true"는 테스트를 위해 멋지지만 전체 목적을
무효화합니다

1
구글 클라우드 기능은 와일드 카드 원점을 허용하지 않습니다 : cloud.google.com/functions/docs/writing/…
Corey Cole

73

클라우드 기능에서 CORS를 다음과 같이 설정할 수 있습니다

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

cors패키지 를 가져올 필요가 없습니다


2
이것은 Mailchimp API를 XHR로 호출하는 클라우드 기능 인 제 경우에 완벽하게 작동합니다.
elverde

1
그것이 필요한 답입니다.
지미 케인

1
구글 클라우드 기능은 와일드 카드 원점을 허용하지 않습니다 : cloud.google.com/functions/docs/writing/…
Corey Cole

4
@CoreyCole 내가 생각하는 당신은 추가해야하는 경우 그 단지의 Authorization헤더를. 위의 내용은 정상적으로 작동합니다.
Stuart Memo

이 코드 줄을 어디에 배치합니까? 클라우드 기능의 어느 부분입니까?
Antonio Ooi

41

Typescript 에서이 작업을 수행하려는 사람은 다음과 같습니다.

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
솔루션은 클라우드 기능 (매우 나쁨) 및 적절한 비동기 / 대기 기능에 대한 로깅을 잃어 버릴 수 있습니다. 장거리 통화의 콜백 내에서 기능 내용이 조기에 종료 될 위험이 있습니다.
Oliver Dixon

2
구글 클라우드 기능은 와일드 카드 원점을 허용하지 않습니다 : cloud.google.com/functions/docs/writing/…
Corey Cole

29

Firebase 호스팅을 사용하는 경우 예를 들어 (firebase_hosting_host) / api / myfunction과 같은 URL이 ( firebase_cloudfunctions_host) / doStuff 함수입니다. 이렇게하면 리디렉션이 투명하고 서버 측이므로 cors를 처리 할 필요가 없습니다.

firebase.json의 rewrites 섹션에서이를 설정할 수 있습니다.

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

1
imo, 이것은 추가적인 보안 문제를 추가하지 않고 실제 문제를 해결하기 때문에 가장 좋은 대답입니다. 이런 식으로 클라우드 기능이 나머지 도메인과 동일한 도메인에서 제공되며 어떤 cors도 필요하지 않습니다.
koljaTM

3
이것은 실제로 훌륭한 기능이지만 기능이 기본 지역 (us-central1)에있는 경우에만 작동합니다. 지연 시간 때문에 europe-west1에 함수를 배포하고 github.com/firebase/firebase-tools/issues/842
Alex Suzuki

리디렉션이 제대로 작동하고 URL을 더 깨끗하게 만들지 만 GET 매개 변수를 전달하는 방법을 알지 못했습니다. 함수가 (다시 쓰기 후) 매개 변수없이 호출 된 것 같습니다.
royappa

20

지금까지 CORS 솔루션이 효과가 없었습니다.

다른 사람이 내가 한 것과 같은 문제에 부딪 쳤는지 확실하지 않지만 찾은 예제와 다른 5 가지 방법으로 CORS를 설정했지만 아무것도 작동하지 않는 것 같습니다. 나는 그것이 실제로 버그인지 확인하기 위해 Plunker와 함께 최소한의 예제를 설정했지만 예제는 아름답게 실행되었습니다. 나는 firebase 기능 로그 (firebase 콘솔에 있음)를 확인하여 그것이 무엇인지 알 수 있는지 확인하기로 결정했습니다. 내 노드 서버 코드에서 몇 가지 오류를했다 , 관련 고르하지 , 그 나는 디버깅 할 때 내 CORS 오류 메시지 나에게 출시 . CORS와 관련이없는 코드 오류가 CORS 오류 응답을 반환하는 이유를 모르겠지만 좋은 시간 동안 잘못된 토끼 구멍을 내 렸습니다 ...

tl; dr-CORS 솔루션이 작동하지 않으면 Firebase 기능 로그를 확인하고 오류를 디버그하십시오.


1
이것은 나를 미치게했다. 내 경우에는 코드에서 오류가 없었습니다! 그것은되었다 Error: quota exceeded (Quota exceeded for quota group 'NetworkIngressNonbillable' and limit 'CLIENT_PROJECT-1d' of service 'cloudfunctions.googleapis.com 그래서 기본적으로 무료 할당량을 초과했습니다 및 기능 고르 오류를 반환
Stanislau Buzunko을

여기에 몇 번 발생하면 cors와 마찬가지로 서버에서 동일한 오류가 반환됩니다. Error : internal은 기본적으로 오류입니다. 이 오류는 함수 이름을 잘못 입력하는 것과 같이 잘못된 함수를 실행하는 경우에도 발생합니다.
Henrik Bøgelund Lavstsen

클라우드 기능 내에서 Google reCAPTCHA 확인을 요청하려고하면 브라우저에서 CORS 오류가 발생합니다. Firebase 콘솔 기능 로그를 확인하면이 표시 access to external network resources not allowed if the billing account is not enabled됩니다. 결제 계정을 활성화하면 완벽하게 작동합니다. 이것은 cors와 관련되지 않은 예제 중 하나이지만 cors 오류가 발생합니다.
Antonio Ooi

19

나는 자신의 질문에 @Andreys 답변에 약간의 추가를했습니다.

cors(req, res, cb)함수 에서 콜백을 호출하지 않아도되므로 콜백에 모든 코드를 포함시키지 않고 함수 상단의 cors 모듈을 호출 할 수 있습니다. 나중에 cors를 구현하려는 경우 훨씬 빠릅니다.

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

오프닝 포스트에서 언급했듯이 cors를 초기화하는 것을 잊지 마십시오.

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


1
이것은 헤더를 수동으로 설정하는 다른 SO 답변이 그렇지 않은 경우 작동했습니다.
Jim Factor

작동하지만 TSlint를 사용하도록 설정했고 firebase에 배포 할 수없는 경우 TSlint 오류가 발생할 수 있습니다. 답을 극복하기 위해 cors 클로저 안에 반응을 두십시오cors(request, response, () => { return response.send("Hello from Firebase!"); });
Spiral Out

1
여기 2 오류가 있습니다. 첫 번째. cors 함수 뒤의 모든 것은 두 번 실행됩니다 (첫 번째 요청은 프리 플라이트이므로). 안좋다. 둘째, @SpiralOut 솔루션은 클라우드 기능 (매우 나쁨) 및 적절한 비동기 / 대기 기능에 대한 로깅을 잃어 버릴 수 있으므로 콜백 내에서 기능 내용이 조기에 종료 될 위험이 있습니다.
Oliver Dixon

@SpiralOut tslint를 비활성화 할 수 있습니다
Vlad

1
작년에 gcf에 대해 많이 배웠으므로 더 이상이 답변을 권장하지 않습니다. 빠른 프로토 타입에는 유용 ​​할 수 있지만 실제 프로덕션에서는이를 피하십시오
Jaap Weijland

11

도움이 될 수 있습니다. express (custom URL)로 firebase HTTP 클라우드 기능을 만들었습니다.

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);

다시 쓰기 섹션을 추가했는지 확인하십시오

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

1
당신의 대답은 내 친구가 너무 적어서 가장 좋은 대답입니다.
Avram Virgil

감사. @AvramVirgil
Sandy

가장 빠르고 쉬운 방법이었습니다. 감사합니다!
Gaurav Kakkar

8

나는 그것에 대해 약간의 글을 발표했다.

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

일반적으로 Express CORS 패키지를 사용해야 합니다 를 사용해야합니다. GCF / Firebase Functions의 요구 사항을 충족하려면 약간의 해킹이 필요합니다.

희망이 도움이됩니다!


4
해킹의 의미를 잘 모르시겠습니까? 조금 정교하게 신경써? 귀하의 게시물을 읽으십시오. 그러나 당신이 그것을 언급하는 것을 보지 못합니다
TheeBen

1
여기 cors 모듈의 저자; 말리고 프 스키 (Mhaligowski)는 단순히 콜 모듈을 호출하여 Express가 미들웨어를 호출하는 방식과 일치하도록 (즉, req & res 후 세 번째 매개 변수로 기능을 제공) cors 모듈로 랩해야 함을 의미했습니다.
Troy

4

나와 같은 사람들이 있다면 : 자체 클라우드 기능과 동일한 프로젝트에서 클라우드 기능을 호출하려는 경우 firebase sdk를 초기화하고 onCall 메소드를 사용할 수 있습니다. 그것은 당신을 위해 모든 것을 처리합니다 :

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

이 함수를 다음과 같이 호출하십시오.

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

Firebase 문서 : https://firebase.google.com/docs/functions/callable

SDK를 초기화 할 수없는 경우 다른 제안의 핵심 요소는 다음과 같습니다.


3
실제로 브라우저에서 onCall func를 사용할 때 cors 오류가 발생했습니다. 이 요청에서 costom 헤더를 설정할 수 있습니까?
Viktor Hardubej

4

'cors'라이브러리를 가져 오지 않고 cors를 활성화하는 방법을 찾았습니다. 또한 Typescript크롬 버전 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();
});

3

가치가있는 것에 대해 전달할 때 동일한 문제가 발생 app했습니다 onRequest. firebase 함수에 대한 요청 URL의 문제가 슬래시라는 것을 알았습니다. Express가 찾고 '/'있었지만 함수에 후행 슬래시가 없었습니다 [project-id].cloudfunctions.net/[function-name]. CORS 오류는 잘못된 음성입니다. 후행 슬래시를 추가했을 때 예상했던 응답을 받았습니다.


또한 확실히 당신은 당신을 추가 만든다 [project-id]이 있었다으로 내가 직면 한 문제
분리

3

요청에 승인이있을 때만이 방법이 효과적입니다.

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)
} )};

구글 클라우드 기능은 와일드 카드 원점을 허용하지 않습니다 : cloud.google.com/functions/docs/writing/…
Corey Cole

3

cors 플러그인을 사용하지 않거나 사용할 수없는 경우 setCorsHeaders() 핸들러 함수에서 먼저 함수를 해도 작동합니다.

회신 할 때 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));
}

2

Firebase 앱을 로컬에서 테스트하는 경우 localhost클라우드 대신 함수를 가리켜 야합니다 . 기본적으로, firebase serve또는firebase emulators:start 웹 앱에서 사용할 때 localhost 대신 서버를 가리키는 함수를 가리 킵니다.

firebase init 스크립트 뒤에 html head에 아래 스크립트를 추가하십시오.

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

서버에 코드를 배포 할 때이 스 니펫을 제거하십시오.


2

true의해 변경 하는 "*"것은 나를 위해 트릭을 했으므로 다음과 같이 보입니다.

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

일반적 으로이 응답 헤더가 설정되는 방식 이므로이 방법을 시도했습니다.

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

이렇게하면 모든 도메인이 엔드 포인트를 호출 할 수 있으므로 안전하지 않습니다.

또한 https://github.com/expressjs/cors 문서에서 자세한 내용을 읽을 수 있습니다.


1

Express를 사용하지 않거나 단순히 CORS를 사용하려는 경우. 다음 코드는 해결하는 데 도움이됩니다.

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

0

내 경우에는 오류가 클라우드 함수 호출자 제한 액세스로 인해 발생했습니다. 클라우드 함수 호출자에 모든 사용자를 추가하십시오. 링크를 잡아주세요 . 자세한 내용은 기사 를 참조하십시오


답변에 링크 된 자료에 대한 설명을 제공하십시오. 왜 관련이 있는지
Firefly

0

다른 솔루션이 작동하지 않으면 통화 시작시 아래 주소를 추가하여 CORS-리디렉션을 활성화 할 수 있습니다.

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

JQuery AJAX 요청이 포함 된 샘플 코드 :

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

0

내 경험을 추가합니다. CORS 오류가 발생한 이유를 찾으려고 몇 시간을 보냈습니다.

이 것을 어떻게 내 클라우드 기능을 이름을 변경했습니다 (맨 처음 내가 큰 업그레이드 후 시도하고 있었다).

따라서 내 firebase 앱이 잘못된 이름으로 클라우드 함수를 호출했을 때 CORS 오류가 아닌 404 오류가 발생했을 것입니다.

내 Firebase 앱에서 클라우드 기능 이름을 수정하면 문제가 해결되었습니다.

https://firebase.google.com/support/troubleshooter/report/bugs에 대한 버그 보고서를 작성했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.