diff --git a/packages/backend/src/routes/music.ts b/packages/backend/src/routes/music.ts index 3889e26..ea49d2c 100644 --- a/packages/backend/src/routes/music.ts +++ b/packages/backend/src/routes/music.ts @@ -371,20 +371,75 @@ router.get('/:id/stream', async (req, res) => { return res.status(404).json({ error: 'Music file not found' }); } - // Use presigned URL for secure access instead of direct URL - const presignedUrl = await storageService.getPresignedUrl(musicFile.s3Key, 3600); // 1 hour expiry - - res.json({ - streamingUrl: presignedUrl, - musicFile, - contentType: musicFile.contentType || undefined, - }); + // For WebDAV, use a proxy endpoint to handle authentication + // For S3, use presigned URL for direct access + const config = await StorageProviderFactory.loadConfig(); + if (config.provider === 'webdav') { + // Use proxy endpoint for WebDAV to handle authentication + const proxyUrl = `${req.protocol}://${req.get('host')}/api/music/${musicFile._id}/proxy`; + res.json({ + streamingUrl: proxyUrl, + musicFile, + contentType: musicFile.contentType || undefined, + }); + } else { + // Use presigned URL for S3 + const presignedUrl = await storageService.getPresignedUrl(musicFile.s3Key, 3600); // 1 hour expiry + res.json({ + streamingUrl: presignedUrl, + musicFile, + contentType: musicFile.contentType || undefined, + }); + } } catch (error) { console.error('Streaming error:', error); res.status(500).json({ error: 'Failed to get streaming URL' }); } }); +/** + * Proxy endpoint for WebDAV streaming with authentication + */ +router.get('/:id/proxy', async (req, res) => { + try { + const musicFile = await MusicFile.findById(req.params.id); + if (!musicFile) { + return res.status(404).json({ error: 'Music file not found' }); + } + + // Set appropriate headers for audio streaming + res.setHeader('Content-Type', musicFile.contentType || 'audio/mpeg'); + res.setHeader('Accept-Ranges', 'bytes'); + res.setHeader('Cache-Control', 'public, max-age=3600'); + + // Get the file content from WebDAV + const fileBuffer = await storageService.getFileContent(musicFile.s3Key); + + // Handle range requests for seeking + const range = req.headers.range; + if (range) { + const fileSize = fileBuffer.length; + const parts = range.replace(/bytes=/, "").split("-"); + const start = parseInt(parts[0], 10); + const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1; + const chunksize = (end - start) + 1; + const chunk = fileBuffer.slice(start, end + 1); + + res.status(206); + res.setHeader('Content-Range', `bytes ${start}-${end}/${fileSize}`); + res.setHeader('Content-Length', chunksize.toString()); + res.end(chunk); + } else { + // No range request, send entire file + res.setHeader('Content-Length', fileBuffer.length.toString()); + res.end(fileBuffer); + } + } catch (error) { + console.error('Proxy streaming error:', error); + res.status(500).json({ error: 'Failed to stream music file' }); + } +}); + /** * Get presigned URL for secure access */