具有对外部基本身份验证的获取请求的 Firebase 云功能 api

Firebase cloud function with fetch request with basic auth to external api

我似乎无法从 firebase 云函数中的提取调用获得预期响应。我确定这是因为我对响应、承诺等如何运作缺乏了解。

我正在尝试使用 atlassian crowd's rest api 进行 SSO。如果我使用邮递员,我可以从请求中得到想要的结果。所以我知道它的一部分正在工作。

促使我使用云函数的原因是使用 fetch 发出相同的请求会导致本地主机出现 CORS 问题。我想如果我可以将浏览器排除在外,那么 CORS 问题就会消失。他们有,但我没有得到想要的回应。

我的云函数如下所示:

const functions = require('firebase-functions');
const fetch = require('node-fetch');
const btoa = require('btoa');
const cors = require('cors')({origin:true});

const app_name = "app_name";
const app_pass = "app_password";

exports.crowdAuthentication = functions.https.onRequest((request, response)=>
{
    cors(request, response, () =>{

        let _uri = "https://my.server.uri/crowd/rest/usermanagement/1/session";
        let _headers = {
            'Content-Type':'application/json',
            'Authorization':`Basic ${btoa(`${app_name}:${app_pass}`)}`
        }


        let _body = {
            username: request.body.username,
            password: request.body.password
        }

        const result = fetch(_uri, {
            method: 'POST',
            headers: _headers,
            body: JSON.stringify(_body),
            credentials: 'include'
        })

        response.send(result);
    })
})

然后我在我的应用程序中使用 fetch 调用 firebase 端点并传递 username/password:

fetch('https://my.firebase.endpoint/functionName',{
            method: 'POST',
            body: JSON.stringify({username:"myusername",password:"mypassword"}),
            headers: {
                'Content-Type':'application/json'
            }
        })
        // get the json from the readable stream
        .then((res)=>{return res.json();})
        // log the response - {size:0, timeout:0}
        .then((res)=>
        {
            console.log('response: ',res)
        })
        .catch(err=>
        {
            console.log('error: ',err)
        })

感谢观看。

2020 年 5 月编辑

请注意 request-promise 已弃用,我建议使用 axios


根据我们在下方评论中的讨论进行更新

它似乎不适用于 node-fetch 库,您应该使用另一个库,例如 request-promise

因此您应该按如下方式调整您的代码:

//......
var rp = require('request-promise');


exports.crowdAuthentication = functions.https.onRequest((request, response) => {

    cors(request, response, () => {

        let _uri = "https://my.server.uri/crowd/rest/usermanagement/1/session";
        let _headers = {
            'Content-Type': 'application/json',
            'Authorization': `Basic ${btoa(`${app_name}:${app_pass}`)}`
        }

        let _body = {
            username: request.body.username,
            password: request.body.password
        }

        var options = {
            method: 'POST',
            uri: _uri,
            body: _body,
            headers: _headers,
            json: true
        };

        rp(options)
            .then(parsedBody => {
                response.send(parsedBody);
            })
            .catch(err => {
                response.status(500).send(err)
                //.... Please refer to the following official video: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3
            });

    });

});

初步回答node-fetch

fetch() 方法是异步的,returns 是一个 Promise。因此,您需要等待此 Promise 解决,然后再发回响应,如下所示:

exports.crowdAuthentication = functions.https.onRequest((request, response)=>
{
    cors(request, response, () =>{

        let _uri = "https://my.server.uri/crowd/rest/usermanagement/1/session";
        let _headers = {
            'Content-Type':'application/json',
            'Authorization':`Basic ${btoa(`${app_name}:${app_pass}`)}`
        }


        let _body = {
            username: request.body.username,
            password: request.body.password
        }

        fetch(_uri, {
            method: 'POST',
            headers: _headers,
            body: JSON.stringify(_body),
            credentials: 'include'
        })
        .then(res => {
          res.json()
        })
        .then(json => {
          response.send(json);
        }
        .catch(error => {
            //.... Please refer to the following official video: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3
        });
        
    })
})

此外,请注意,您需要加入“Flame”或“Blaze”定价计划。

事实上,免费的“Spark”计划“只允许对 Google-owned 服务的出站网络请求”。请参阅 https://firebase.google.com/pricing/(将鼠标悬停在“云功能”标题后面的问号上)