节点,如何从嵌套的HTTP请求将结果发送回客户端



我使用ReactJS运行前端,并使用Express作为后端。我想使用"获取"命令向我的后端发出获取请求/paas";路径,以获得在Rancher(Kubernetes(中的命名空间内运行的所有pod的列表。

然后后端需要能够向我的Rancher API端点发出https请求,并将结果返回到前端。我可以成功地调用Rancher API,并在后台的屏幕上看到数据打印,但当我试图将这些数据发送到前端并在浏览器中注销控制台时,我会迷路。

由于";飞行前";错误,我不能直接调用App.js文件中的Rancher端点。点击此处了解更多信息。所以我需要走自定义后端路线。无论如何,这似乎应该很简单。如有任何指导,我们将不胜感激。

App.js:

import React, { useEffect } from "react"
import axios from "axios"
function App() {

useEffect(() => {
const fecthPods = async () => {
try {
const response = await axios.get(`http://localhost:3001/paas`)
console.log(response.data)
} catch (err) {
if (err.response) {
// Not in the 200 response range
console.log(err.response.data)
console.log(err.response.status)
console.log(err.response.headers)
} else {
console.log(`Error: ${err.message}`)
}
}
} 
fecthPods()
},[])
return (
<div>
Hello World!
</div>
);
}
export default App;

后端服务器.js:

import express from "express"
import cors from "cors"
import https from "https"
import bodyParser from "body-parser";
const app = express()
app.use(cors())
app.use("/data", (req, res) => {
res.json({ name: "Minion", favFood: "pizza"})
})
app.get("/paas", bodyParser.json(), (req, res) => {
const options = {
hostname: "k8.fqdn.com",
port: 443,
path: "/k8s/clusters/c-wwfc/v1/pods/mynamespace",
method: "GET",
headers: {
Authorization: "Bearer token:12345"
}
}

const request = https.get(options, (res) => {
let responseBody = ""
res.setEncoding("UTF-8")
res.on("data", (chunk) => {
console.log("---chunk", chunk.length);
responseBody += chunk;
});
res.on("end", () => {
let json = JSON.parse(responseBody)
// console.log(responseBody)
console.log("Response finished");
res.json({data: responseBody})
});
});
request.end()
res.json({ status: "complete", data: request.data})
})
app.listen(3001) 
console.log("backend up on 3001")

我在您的后端代码中看到了几个错误。

首先,为express中间件以及https模块接收到的响应命名res变量。这样,您就失去了在on.('end')回调中访问express response object的可能性。

其次,您需要多次响应客户端(在on.('end')回调中,也可以直接在带有指令res.json({ status: "complete", data: request.data})的express中间件中(。此外,请考虑,在调用k8s集群之前,您编写的代码正在向客户端进行响应。响应将始终是一个JSON,其中包含以下数据:{ "status": "complete", "data": undefined}.

要修复所有问题,请尝试使用此代码(我将尝试注释所有编辑(:

app.get("/paas", bodyParser.json(), (req, res) => {
const options = {
hostname: "k8.fqdn.com",
port: 443,
path: "/k8s/clusters/c-wwfc/v1/pods/mynamespace",
method: "GET",
headers: {
Authorization: "Bearer token:12345"
}
}

const k8sRequest = https.get(options, (k8sResponse ) => { // as you can see I renamed request and res to k8sRequest and k8sResponse, to avoid loosing the scope on req and res express middleware variables
let responseBody = ""
res.setEncoding("UTF-8")
k8sResponse.on("data", (chunk) => { // here use k8sResponse to collect chunks
console.log("---chunk", chunk.length);
responseBody += chunk;
});
k8sResponse.on("end", () => { // here use k8sResponse again
let json = JSON.parse(responseBody)
// console.log(responseBody)
console.log("Response finished");
res.json({ status: "complete", data: responseBody}) // here use the express res variable, to reply to the client. 
});
});
k8sRequest.end() // here use the k8sRequest variable to make the https call to the k8s cluster
// here I deleted  the res.json instruction
})

上面的代码应该可以正常工作。无论如何,我建议您在后端服务中也使用axios。您已经在React中使用了它,所以您知道如何使用它。语法非常简单,可以使用async/await方法。

Axios解决方案:

import axios from "axios"
app.get("/paas", bodyParser.json(), async (req, res) => {
try {
const url = 'https://k8.fqdn.com/k8s/clusters/c-wwfc/v1/pods/mynamespace'

const k8sResponse = await axios.get(url, headers: {
Authorization: "Bearer token:12345"
})


res.json({ status: "complete", data: k8sResponse.data })
} catch (e) {
res.json({status: "error", data: e.response.data})
}


})

您应该将axios调用封装在try/catch块中,以便像处理React实现一样正确地处理错误。如果您仍然需要本机node.jshttps模块,也应该实现错误处理

相关内容

最新更新