英文:
Problem with Superset dashboard embedding in web app
问题
我正在遵循这个教程https://www.tetranyde.com/blog/embedding-superset,试图在React Js应用程序中嵌入Superset仪表板。
我认为我的代码没问题,但仪表板没有在前端渲染出来...
这是错误信息:Front
我也附上了我的服务器代码:server.js
import express from "express";
import fetch from "node-fetch";
import cors from "cors";
const PORT = 3001;
const app = express();
// 启用CORS
app.use(cors());
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
});
async function fetchAccessToken() {
try {
const body = {
username: "admin",
password: "admin",
provider: "db",
refresh: true,
};
const response = await fetch(
"http://localhost:8088/api/v1/security/login",
{
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
}
);
const jsonResponse = await response.json();
return jsonResponse?.access_token;
} catch (e) {
console.error(error);
}
}
async function fetchGuestToken() {
const accessToken = await fetchAccessToken();
try {
const body = {
resources: [
{
type: "dashboard",
id: "2962c53b-3364-4ad9-b4bd-35f0ff69e909",
},
],
rls: [],
user: {
username: "guest",
first_name: "Guest",
last_name: "User",
},
};
const response = await fetch(
"http://localhost:8088/api/v1/security/guest_token",
{
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
}
);
const jsonResponse = await response.json();
return jsonResponse?.token;
} catch (error) {
console.error(error);
}
}
app.get("/guest-token", async (req, res) => {
const token = await fetchGuestToken();
res.json(token);
});
以及我的React Home组件代码:
import React from 'react';
import { useEffect } from "react";
import { embedDashboard } from "@superset-ui/embedded-sdk";
function Home() {
const getToken = async () => {
const response = await fetch("/guest-token");
const token = await response.json();
return token;
}
useEffect(() => {
const embed = async () => {
await embedDashboard({
id: "2962c53b-3364-4ad9-b4bd-35f0ff69e909", // 由Superset嵌入UI提供
supersetDomain: "http://localhost:8088",
mountPoint: document.getElementById("dashboard"), // 在其中呈现iframe的HTML元素
fetchGuestToken: () => getToken(),
dashboardUiConfig: {
hideTitle: true,
hideChartControls: true,
hideTab: true,
},
});
}
if (document.getElementById("dashboard")) {
embed();
}
}, []);
return (
<div className="App">
<h1>如何嵌入Superset仪表板</h1>
<div id="dashboard" style={{ width: '100%', height: '800px' }} />
</div>
)
}
export default Home;
我认为问题可能出在服务器上,但我无法弄清楚。
英文:
I'm following this tutorial https://www.tetranyde.com/blog/embedding-superset trying to embed superset dashboard in react Js app.
I think my code is fine but the dashboard is not rendered in the front..
Here is the error :Front
I'm also joining my server code : server.js
import express from "express"
import fetch from "node-fetch"
import cors from "cors"
const PORT = 3001
const app = express()
// Enable CORS
app.use(cors())
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})
async function fetchAccessToken() {
try {
const body = {
username: "admin",
password: "admin",
provider: "db",
refresh: true,
}
const response = await fetch(
"http://localhost:8088/api/v1/security/login",
{
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
}
)
const jsonResponse = await response.json()
return jsonResponse?.access_token
} catch (e) {
console.error(error)
}
}
async function fetchGuestToken() {
const accessToken = await fetchAccessToken()
try {
const body = {
resources: [
{
type: "dashboard",
id: "2962c53b-3364-4ad9-b4bd-35f0ff69e909",
},
],
rls: [],
user: {
username: "guest",
first_name: "Guest",
last_name: "User",
},
}
const response = await fetch(
"http://localhost:8088/api/v1/security/guest_token",
{
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
}
)
const jsonResponse = await response.json()
return jsonResponse?.token
} catch (error) {
console.error(error)
}
}
app.get("/guest-token", async (req, res) => {
const token = await fetchGuestToken()
res.json(token)
})
and my react Home component code :
import React from 'react'
import { useEffect } from "react"
import { embedDashboard } from "@superset-ui/embedded-sdk"
function Home() {
const getToken = async () => {
const response = await fetch("/guest-token")
const token = await response.json()
return token
}
useEffect(() => {
const embed = async () => {
await embedDashboard({
id: "2962c53b-3364-4ad9-b4bd-35f0ff69e909", // given by the Superset embedding UI
supersetDomain: "http://localhost:8088",
mountPoint: document.getElementById("dashboard"), // html element in which iframe render
fetchGuestToken: () => getToken(),
dashboardUiConfig: {
hideTitle: true,
hideChartControls: true,
hideTab: true,
},
})
}
if (document.getElementById("dashboard")) {
embed()
}
}, [])
return (
<div className="App">
<h1>How to Embed Superset Dashboard </h1>
<div id="dashboard" style={{width:'100%',height:'800px'}}/>
</div>
)
}
export default Home
I think that there is a problem with the server but I can't figure it out
答案1
得分: 3
拷贝错误文本以提高可读性:
> 拒绝显示 'http://localhost/8088'
在框架中,因为它将 'X-Frame-Options' 设置为 'SAMEORIGIN'
这是因为服务器的响应将 iframe 安全性设置为强制同源。从理论上讲,您应该能够编辑 superset_config.py
文件,如下所示:
OVERRIDE_HTTP_HEADERS = {'X-Frame-Options': 'ALLOWALL'}
但这对我不起作用。相反,罪魁祸首是 Superset 服务器正在使用的 Talisman 库,它默认为 iframes 设置了相同的源设置。
要解决这个问题,您要么修改默认的 Talisman 设置,要么通过配置关闭 Talisman,如下所示:
TALISMAN_ENABLED = False
> 无法执行 'postMessage' 在 'DOMWindow' 上:所提供的目标起源
('http://localhost:8088') 与接收窗口的起源
(null) 不匹配。
这是因为之前的错误,由于 iframe 未加载,iframe 起源是 null
,因此会出现异常。
英文:
Pasting the error text here for readability:
> Refused to display 'http://localhost/8088'
in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'
This is happening because the response from the server is setting the iframe security to force same origin. Theoretically you should be able to edit the superset_config.py
file with
OVERRIDE_HTTP_HEADERS = {'X-Frame-Options': 'ALLOWALL'}
but that wasn't working for me. Instead, the culprit is the Talisman library the Superset server is using which defaults the same origin setting for iframes.
To get around that, you have to either modify the default Talisman settings or turn off Talisman via config by
TALISMAN_ENABLED = False
> Failed to execute 'postMessage' on 'DOMWindow': The target origin provided
('http://localhost:8088') does not match the recipient window's origin
(null).
This is happening because of the error before, since the iframe doesn't load the iframe origin is null
and thus the exception.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论