node.js - 无需身份验证调用 GCloud 函数
问题描述
我对使用 gcloud 功能很陌生。
我有一个谷歌云函数,它应该启动一个 VM 实例,但我想在发送 HTTP 请求时从一个没有身份验证的网站调用这个函数(现在)。我怎样才能做到这一点?
我也不需要发送任何参数,只需要调用函数
这是我的一个简单网站调用云功能的代码,虽然这似乎使用了我不想做的身份验证,但我在控制台中创建该功能时禁用了身份验证:
<!DOCTYPE html>
<html lang="en">
<body>
<div class="bordered-text-block">
<h1>VM Controls</h1>
<button id="id_start_button" onclick="startVM()">Start
</button>
<button id="id_stop_button" onclick="stopVM()">Stop
</button>
</div>
<script>
function startVM() {
const fetch = require('node-fetch');
// TODO(developer): set these values
const REGION = '<my region>';
const PROJECT_ID = '<project name>';
const RECEIVING_FUNCTION = '<function name>';
// Constants for setting up metadata server request
// See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
const functionURL = `https://${REGION}-${PROJECT_ID}.cloudfunctions.net/${RECEIVING_FUNCTION}`;
const metadataServerURL =
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
const tokenUrl = metadataServerURL + functionURL;
exports.callingFunction = async (req, res) => {
// Fetch the token
const tokenResponse = await fetch(tokenUrl, {
headers: {
'Metadata-Flavor': 'Google',
},
});
const token = await tokenResponse.text();
// Provide the token in the request to the receiving function
try {
const functionResponse = await fetch(functionURL, {
headers: { Authorization: `bearer ${token}` },
});
res.status(200).send(await functionResponse.text());
} catch (err) {
console.error(err);
res.status(500).send('An error occurred! See logs for more details.');
}
};
}
</script>
</body>
</html>
解决方案
跟进我的评论,这是最简单的答案。
注意我认为您必须确保您的 Cloud Functions 返回适当的 CORS 标头
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
我用 Golang 写了一个云函数:
package p
import (
"encoding/json"
"net/http"
)
type Message struct {
Name string `json:"name"`
}
func WebPage(w http.ResponseWriter, r *http.Request) {
m := Message{
Name: "Freddie",
}
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET")
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(m)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
}
我部署了这个功能:
PROJECT="<your-project>"
REGION="<your-region>"
FUNCTION="<your-function>"
gcloud projects create ${PROJECT}
BILLING=$(gcloud beta billing accounts list --format="value(name)")
gcloud beta billing projects link ${PROJECT} --billing-account=${BILLING}
for SERVICE in "cloudbuild" "cloudfunctions"
do
gcloud services enable ${SERVICE}.googleapis.com \
--project=${PROJECT}
done
gcloud functions deploy ${FUNCTION} \
--entry-point=WebPage \
--source=. \
--project=${PROJECT} \
--allow-unauthenticated \
--region=${REGION} \
--runtime=go113 \
--trigger-http
您可以在 curl 中获取函数的端点:
URL=$(\
gcloud functions describe ${FUNCTION} \
--project=${PROJECT} \
--format="value(httpsTrigger.url)")
curl \
--silent \
--include \
--header "Accept: application/json" \
--request GET \
${URL}
产量:
HTTP/2 200
access-control-allow-methods: GET
access-control-allow-origin: *
content-type: application/json
...
{"name":"Freddie"}
然后您可以GET
将值放入 HTML 中id
:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="result">/div>
<script>
const PROJECT = "<your-project>";
const REGION = "<your-region>";
const FUNCTION = "<your-function>";
const ID = "result";
const URL = `https://${REGION}-${PROJECT}.cloudfunctions.net/${FUNCTION}`;
fetch(URL,{
method: "GET",
headers: {
"Accept": "application/json"
}
})
.then(resp => resp.json())
.then(json => JSON.stringify(json))
.then(html => document.getElementById(ID).innerHTML = html);
</script>
</body>
</html>
我使用 Caddy 测试了这个(本地):
docker run \
--rm \
--name=caddy \
--interactive --tty \
--publish=80:80 \
--volume=$PWD/index.html:/usr/share/caddy/index.html \
--volume=caddy_data:/data \
caddy
然后浏览http://localhost:80
,我得到:
{"name":"Freddie"}
推荐阅读
- python - python整数溢出解决方案
- angularjs - 将 res.json() 转为 Angular $http.get() 格式问题
- python - 如何向 Python 中的各个线程发送 CTRL-C 信号?
- android - 要为 Android Auto 实现 DVD 播放器功能,我应该扩展 TV HAL 吗?
- valgrind - valgrind 附加软件包有什么作用?
- android-studio - 错误:无法解决:运行时
- c++ - 具有多个结构的链表
- probability - 如何定义概率分布
- opengl-es - 如何根据与相机的距离将颜色与背景混合
- bash - 使用带有 ipython 的 jupyter 与 R (irkernel) 的 bash 的区别