如何创建通过 Firebase Cloud Functions 托管的 Node.js 代理服务器?
How do I create a Node.js proxy server hosted through Firebase Cloud Functions?
我有一个应用程序使用 YouTube API 键在 YouTube 上搜索视频并将它们显示在我的页面上。我刚刚了解到,向客户公开任何秘密都是 不好。因此,我正在考虑的解决方案是让客户端改为将请求发送到 Firebase 云函数。云函数将作为代理存储我的 API 密钥,而不是将其存储在客户端中。
如何设置?
首先,我尝试记录 request
对象,但我收到了一条神秘的错误消息。
error: SUPERVISOR clientError { Error: Parse Error bytesParsed: 0, code: 'HPE_INVALID_METHOD' } connecting=false, _hadError=false, bytesRead=193, , fd=
-1, reading=true, $ref=$, onread=function onread(nread, buffer) {
这是生成上述错误消息的客户端发送的 GET
请求
https://localhost:5000/jpls-youtube-viewer/us-central1/helloWorld?part=snippet&type=video&q=Linkin+Park
这是我的应用程序的存储库:https://github.com/jpls93/jpls-youtube-viewer
我通过将客户端请求指向我的 Firebase 数据库 URL 解决了这个问题,然后我让 Firebase 数据库 URL 向 YouTube REST 发出请求 API URL并解决对我的客户的回应。我遇到了 CORS 问题,但通过允许 access-control-origin/methods
即可轻松解决
exports.helloWorld = functions.https.onRequest((request, response) => {
var term = request.query.q;
// See https://howtofirebase.com/firebase-cloud-functions-753935e80323
// why we're requiring it inside the function
var YT_URL = "https://www.googleapis.com/youtube/v3/search";
const axios = require("axios");
axios
.get(YT_URL, {
params: {
part: "snippet",
type: "video",
key: require("./secret"),
q: term
}
})
.then(YouTubeData => {
response.set("Access-Control-Allow-Origin", "*");
response.set("Access-Control-Allow-Methods", "GET, POST");
response.status(200).send(YouTubeData.data.items);
})
.catch(err => console.error(err));
});
const https = require('https');
const buffer = require('buffer');
exports.proxyURL = functions.https.onRequest(async (req, res) => {
const url = req.query.url;
await https.get(url, (resp) => {
let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {
let ctype = resp.headers["content-type"];
if (ctype.includes("charset=ISO-8859-1"))
{
const latin1Buffer = buffer.transcode(Buffer.from(chunk), "latin1", "utf8");
data += latin1Buffer.toString("utf8");
}else{
data += chunk;
}
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
res.contentType('application/xml; charset=UTF-8');
res.write(data);
return res.status(200).end();
});
}).on("error", (err) => {
console.log("Error: " + err.message);
return res.status(500).end();
});
});
我有一个应用程序使用 YouTube API 键在 YouTube 上搜索视频并将它们显示在我的页面上。我刚刚了解到,向客户公开任何秘密都是 不好。因此,我正在考虑的解决方案是让客户端改为将请求发送到 Firebase 云函数。云函数将作为代理存储我的 API 密钥,而不是将其存储在客户端中。
如何设置?
首先,我尝试记录 request
对象,但我收到了一条神秘的错误消息。
error: SUPERVISOR clientError { Error: Parse Error bytesParsed: 0, code: 'HPE_INVALID_METHOD' } connecting=false, _hadError=false, bytesRead=193, , fd=
-1, reading=true, $ref=$, onread=function onread(nread, buffer) {
这是生成上述错误消息的客户端发送的 GET
请求
https://localhost:5000/jpls-youtube-viewer/us-central1/helloWorld?part=snippet&type=video&q=Linkin+Park
这是我的应用程序的存储库:https://github.com/jpls93/jpls-youtube-viewer
我通过将客户端请求指向我的 Firebase 数据库 URL 解决了这个问题,然后我让 Firebase 数据库 URL 向 YouTube REST 发出请求 API URL并解决对我的客户的回应。我遇到了 CORS 问题,但通过允许 access-control-origin/methods
即可轻松解决exports.helloWorld = functions.https.onRequest((request, response) => {
var term = request.query.q;
// See https://howtofirebase.com/firebase-cloud-functions-753935e80323
// why we're requiring it inside the function
var YT_URL = "https://www.googleapis.com/youtube/v3/search";
const axios = require("axios");
axios
.get(YT_URL, {
params: {
part: "snippet",
type: "video",
key: require("./secret"),
q: term
}
})
.then(YouTubeData => {
response.set("Access-Control-Allow-Origin", "*");
response.set("Access-Control-Allow-Methods", "GET, POST");
response.status(200).send(YouTubeData.data.items);
})
.catch(err => console.error(err));
});
const https = require('https');
const buffer = require('buffer');
exports.proxyURL = functions.https.onRequest(async (req, res) => {
const url = req.query.url;
await https.get(url, (resp) => {
let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {
let ctype = resp.headers["content-type"];
if (ctype.includes("charset=ISO-8859-1"))
{
const latin1Buffer = buffer.transcode(Buffer.from(chunk), "latin1", "utf8");
data += latin1Buffer.toString("utf8");
}else{
data += chunk;
}
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
res.contentType('application/xml; charset=UTF-8');
res.write(data);
return res.status(200).end();
});
}).on("error", (err) => {
console.log("Error: " + err.message);
return res.status(500).end();
});
});