如何从外部Node/Express服务器重定向页面

3
我有一个运行中的React/Node/Express网络应用程序,其中有两个独立的服务器。React在localhost:8080上运行,并代理API请求到运行在localhost:3000上的node服务器。这将是我的生产设置,如果可能的话,我想保留这种结构。
我遇到的问题是我的API的一部分需要重定向用户到一个页面,从Spotify API获取令牌,然后在成功验证后重定向回我的正确页面。
API调用代理是这样完成的:
const axios = require('axios');

const axiosInstance = axios.create({
    baseURL: process.env.NODE === 'production' ? '' : 'http://localhost:3000'
});

module.exports = axiosInstance;

到目前为止,这个方案非常好,因为我可以完全分离我的React和Node服务器。
如我上面提到的,我需要通过后端API调用将我的React前端重定向到另一个页面(Spotify认证),以对用户进行身份验证,然后Spotify在用户允许或拒绝访问他们的Spotify帐户之后将其重定向回我的站点。
在我的前端 - localhost:8080上,用户点击一个按钮,调用这个函数。
authenticate = () => {
    axios.get('/login')
        .then(data => console.log(data));
}

这个端点在localhost:3000上被调用。

router.get('/', (req, res) => {
    let scopes = 'user-read-private user-read-email';
    let client = process.env.SPOTIFY_CLIENT;
    let redirect = 'http://localhost:3000/login/redirect';

    res.redirect(`https://accounts.spotify.com/authorize?response_type=code'
                &client_id=${client}${scopes ? `&scope=${encodeURIComponent(scopes)}` : ''}
                &redirect_uri=${encodeURIComponent(redirect)}&state=${state}`);
});

当我在前端点击登录按钮时,会得到以下响应,我认为这是来自Spotify的响应,因为我可以成功地向我的API请求其他端点的跨源请求。
无法加载... 请求的资源上不存在“Access-Control-Allow-Origin”标头。 因此,来自“null”的来源不允许访问。
然而,当我手动导航到localhost:3000/login时,重定向有效,并且我被发送到Spotify身份验证页面。
此外,我尝试将我的前端重定向到任何URL,但都没有成功。
因此,我的问题是,如何通过不服务于我的静态前端内容的服务器从API调用重定向我的前端?

您尝试过使用任何 CORS 包吗?例如 https://www.npmjs.com/package/cors ? - Gavin Thomas
你已经在拥有令牌的 Spotify 帐户中注册了重定向 URL 吗?https://github.com/spotify/web-api-auth-examples? - Gavin Thomas
由于直接请求有效,请尝试向Spotify发出新请求并返回响应,而不是重定向原始的8080请求。Spotify可能会检测请求URL(应该读取8080),而不是在此处指定的3000 ==> redirect_uri=${encodeURIComponent(redirect)}。如果所有对该API的请求都将被代理,则将查询中的端口更改为8080。 - I Want Answers
@IWantAnswers 好的,下班后我会试试看。 - 23k
@IWantAnswers 我试过了,我确实从Spotify那里得到了响应,但里面没有任何有用的内容。我认为重定向是必要的,因为我必须亲自点击“批准”按钮,才能让Spotify返回所需的密钥以进行请求。所以,我的问题目前仍未得到答复。 - 23k
显示剩余6条评论
1个回答

4
这不起作用的原因是你的axios.get('/login')是对服务器的AJAX请求,然后服务器告诉AJAX请求重定向到Spotify,但Spotify没有注册你的前端服务器,因此你会得到CORS错误,因为你的请求是在前端服务器URL上启动的。 你的AJAX请求正在遵循给定的重定向, 而不是尝试在http://localhost:3000上加载你的浏览器,然后将其重定向到Spotify授权页面。
现在,不要再这样做:
authenticate = () => {
    axios.get('/login')
        .then(data => console.log(data));
}

你可以这样做:

authenticate = () => {
    window.location.href = "http://localhost:3000"
}

这将指示您的前端应用程序访问 API 服务器的 URL 并立即跟随重定向到 Spotify,然后您可以授权并被重定向回到 API 服务器,然后 API 服务器可以重定向回到您的前端应用程序。说实话,这有点过头了,因为假定您的 React 应用程序和 Node 应用程序看起来像是在同一个域之外运行,给定您正在使用的相对 URL。如果您使用的是 create-react-app,则应按照它们的说明通过this或手动方式通过this配置代理。简而言之,您需要调整代理的配置方式或者从那里更改为直接转到 /login(不进行 AJAX 请求)。

这个方法可行。我曾考虑在package.json中指定代理,但决定尝试一下这个方法(我没有使用CRA)。我确实明白你的观点,这有点过度设计了。我主要是为了灵活性而设置这个项目,可以用任何语言编写后端。之前我做了一些关于查询不同后端的研究,这就是我发现设置axios基础URL的方法。 - 23k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接