小程序重定向302请求解决方案、调试面板示例:
小程序通过请求服务端提供的接口,服务端对接口做了重定向处理,返回状态码302后,去取Location 值。
代码示例:
function parseRedirectURL(url, callback) {
var self = this;
wx.request({
url: url,
redirect: 'manual', // 拦截重定向
header: {
'token': "用户登录token", // 用户登录token
'lang': 'zh_CN',
},
}).onHeadersReceived(res => {
console.log("重定向 res=>", res)
// 这里要 注意 Location 和 location,避免服务器或环境问题返回接收一下子大写,一下子小写,让你彻底怀疑人生,服务器会说是通用的,
// 前端要兼容,即便微信文档是大写 Location
let Location = res.header.Location || res.header.location ;
if(typeof callback == "function") {
callback(Location);
}
})
}
参考文档:https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html
工作中遇到需要使用该方案的场景:
1、后台,需要配置一个动态的网页跳转链接
2、苹果APP,安卓APP,小程序,需要调用接口获取后台配置的网页跳转链接,跳转打开使用。
3、服务端,需要提供一个可重定向的接口,把后台动态配置的链接给到前端。
---------------------------------------------------------------------------------------------------------------------------------------------------
4、因为每个用户请求动态的网页跳转链接,后面所携带的参数是不一样的。但是后台只能配置一个链接,后端通过携带Token来拼接参数返回,并且兼容旧APP 未升级,直接打开网页的逻辑。所以,采用该方式。
APP的 webview 可以携带 header 信息,打开网页后,服务器实现了重定向,因此可以直接打开
小程序的webview 组件无法携带 Header 信息,所以需要通过 ajax 请求方式 redirect: 'manual', // 拦截重定向
注意:如果是 vue 项目中,通过 fetch 或者 axios 方式,会可能面临跨域问题,或者是无法拿到 重定向,status 返回 0 的现象。针对这个,要确保H5 不需要直接做这个302 接口请求方式,如果是H5网页嵌入到 APP,或者 小程序,可采用 调用APP提供的方法,或小程序的方法来实现。
直接H5里面调用请求无法拿到重定向地址的,以下代码无法拿到 Location,但可以多试试。
fetch(url, {
method: 'GET',
headers: customHeaders,
redirect: 'manual'
})
.then(response => {
console.log('response fetching redirect URL:', response);
if (response.status === 301) {
const redirectUrl = response.headers.get('Location');
console.log('Redirect URL:', redirectUrl);
}
})
.catch(error => {
console.error('Error fetching redirect URL:', error);
});
// 在 axios 配置中设置 validateStatus
axios.get( url , {
validateStatus: (status) => status === 302, // 允许接收 302 响应
maxRedirects: 0 // 禁止自动重定向
})
.then(response => {
const location = response.headers.location;
console.log('Redirect Location:', location);
// 手动发起新请求到 location
return axios.get(location);
})
.then(finalResponse => {
// 处理最终响应...
console.log("处理最终响应 finalResponse=>", finalResponse)
})
.catch(error => {
console.error('Error:', error);
});