请问我在构建多租户SaaS解决方案时遇到问题。对于每个租户,我希望他们使用一个子域,这样我就可以从URL中获取该子域,并调用返回该租户数据的REST API。
例如
tenant1
。 tenant1.localhost:3000
。我得到的URL,并获得域名。然后,我与域进行通话以获取租户的主题(该主题存储在localStorage中)。不幸的是,我们在我公司的k8上进行了部署,所以我无法模仿这种行为。因此,devOps团队建议我在上下文中使用子域,从而拥有localhost:3000/tenant1
。记住承租人是动态的,所以我尝试了这个:
<BrowserRouter basename={"/:tenant"}>
<Switch>
<Route exact path="/login" name="Login" component={Login} />
<Route exact path="/set-password/:token" name="Set Password" component={SetPassword} />
<PrivateRoute path="/" name="Default Layout" component={DefaultLayout} />
</Switch>
</BrowserRouter>
但是上述解决方案使我的URL进入localhost:3000 /:tenant / login
请问我如何在路由器中使用动态基名,以便它可以接受:
localhost:3000/tenant1
localhost:3000/tenant3
localhost:3000/tenant2
等
它可以允许任何我的应用处理输入的错误域
答案 0 :(得分:1)
这对我来说可以使用react> 16和react-router-dom v5
export const App = () => {
return (
<BrowserRouter>
<Switch>
<Route path="/:tenantId?" component={LayoutRoot} />
</Switch>
</BrowserRouter>
);
};
export const LayoutRoot = () => {
var { tenantId } = useParams();
//TODO: add some validation here and inform user if tenant is invalid
return (
<BrowserRouter basename={tenantId}>
<Switch>
<Route path="/login" component={LoginComponent} />
<Route path="/dashboard" component={DashboardComponent} />
</Switch>
</BrowserRouter>
);
};
答案 1 :(得分:0)
我终于在下面的代码中使用了动态租户
class App extends Component {
state = {
domain: ""
}
componentWillMount () {
const { domain } = this.state;
const parsedData = window.location.pathname.split("/");
let domain = parsedData[1];
this.setState({ domain: domain })
this.props.onGetTenant(domain);
}
render () {
const { domain } = this.state;
return () {
<BrowserRouter basename={"/"+domain}>
<Switch>
<Route exact path="/login" name="Login" component={Login} />
<Route exact path="/set-password/:token" name="Set Password" component={SetPassword} />
<PrivateRoute domain={domain} path="/" name="Default Layout" component={DefaultLayout} />
</Switch>
</BrowserRouter>
}
const mapStateToProps = state => {
const { tenant} = state;
return { tenant};
};
const mapDispatchToProps = (dispatch) => {
return {
onGetTenant: bindActionCreators( tenantActions.get, dispatch)
}
};
export default connect(mapStateToProps, mapDispatchToProps)(App)
答案 2 :(得分:0)
这是我编写的代码沙盒和实用程序:
https://codesandbox.io/s/react-router-dom-dynamic-basename-xq9tj?file=/index.js
import urlJoin from 'url-join';
// it's important to have an identifier in their app
export const APP_ROOT_URL = '/my-app';
export const getBaseUrlPath = () => {
const currentPath = document.location.pathname || APP_ROOT_URL;
const startOfAppBase = currentPath.indexOf(APP_ROOT_URL);
let base = currentPath;
if (startOfAppBase !== -1) {
base = currentPath.substr(0, startOfAppBase);
}
base = urlJoin(base, APP_ROOT_URL);
return base;
};