Angular PWA集成share_target API失败,请求返回504错误求助
解决方案:Angular PWA对接WhatsApp语音分享504/405错误修复
问题定位
核心问题是share_target的POST请求在Service Worker中处理逻辑不当:
- 导入
ngsw-worker.js在底部时,自定义拦截逻辑未及时响应请求导致超时触发504 - 导入在顶部时,Angular SW未拦截POST请求,直接透传到服务器触发nginx 405(服务器不允许POST方法)
分步修复方案
1. 编写自定义Service Worker拦截逻辑
创建src/custom-sw.js,先处理POST请求再导入Angular官方SW,确保请求不会透传也不会超时:
// 拦截share_target的POST请求 self.addEventListener('POST', (event) => { // 匹配manifest中配置的share_target action路径 if (event.request.url.endsWith('/share-target')) { event.respondWith( (async () => { // 解析表单数据,提取WhatsApp分享的语音文件 const formData = await event.request.formData(); const audioFile = formData.get('file'); // 将音频文件存入专用缓存,供应用后续读取 const cache = await caches.open('shared-audio-cache'); await cache.put('latest-voice', new Response(audioFile)); // 返回成功响应,避免WhatsApp端超时判定 return new Response(JSON.stringify({ status: 'success' }), { headers: { 'Content-Type': 'application/json' } }); })() ); } }); // 导入Angular官方Service Worker,处理其余请求 importScripts('./ngsw-worker.js');
2. 修正Manifest的share_target配置
确保manifest.json中的参数与拦截逻辑匹配:
"share_target": { "action": "/share-target", "method": "POST", "enctype": "multipart/form-data", "params": { "files": [ { "name": "file", "accept": ["audio/*"] } ] } }
3. 调整Angular构建配置
在angular.json中指定自定义SW,并确保其被打包到产物中:
"projects": { "your-project-name": { "architect": { "build": { "options": { "serviceWorker": true, "ngswConfigPath": "src/ngsw-config.json", "assets": [ "src/favicon.ico", "src/assets", "src/manifest.json", "src/custom-sw.js" // 添加自定义SW到资源列表 ] } } } } }
4. 配置Angular SW排除共享路径
在ngsw-config.json中,让官方SW不处理/share-target路径:
"navigationUrls": [ "!/share-target", // 排除该路径 "/**" ]
5. 应用端读取缓存的音频文件
在Angular组件中,读取缓存的语音文件并调用Whisper API:
async loadSharedAudio() { const cache = await caches.open('shared-audio-cache'); const response = await cache.match('latest-voice'); if (response) { const audioBlob = await response.blob(); // 调用OpenAI Whisper API转写音频 this.transcribeAudio(audioBlob); } } async transcribeAudio(blob: Blob) { const formData = new FormData(); formData.append('file', blob, 'voice-message.mp3'); formData.append('model', 'whisper-1'); try { const response = await fetch('https://api.openai.com/v1/audio/transcriptions', { method: 'POST', headers: { 'Authorization': `Bearer ${yourOpenAIKey}` }, body: formData }); const result = await response.json(); console.log('转写结果:', result.text); } catch (err) { console.error('转写失败:', err); } }
关键说明
- 先处理POST请求再导入官方SW,既避免请求透传触发405,又能及时返回响应防止504超时
- 用缓存存储音频文件,确保应用启动后能获取到分享的内容
- 无需在nginx配置中允许
/share-target的POST方法,因为请求已被SW拦截处理
内容的提问来源于stack exchange,提问作者Paul R.
相关产品推荐
相关产品推荐

