Fix 403 error when loading music files
- Fix path traversal security check by using absolute paths - Remove problematic fetch override that forced JSON headers on all API requests - Add error tracking and visual indicators for failed tracks - Correct music directory resolution for both relative and absolute paths The main issue was the security validation comparing relative paths incorrectly, causing legitimate music file requests to be rejected with 403 errors.
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
:is-active="currentTrack?.name === track.name"
|
||||
:is-playing="currentTrack?.name === track.name && isPlaying"
|
||||
:is-loading="loadingTrack === track.name"
|
||||
:has-error="failedTracks.has(track.name)"
|
||||
@click="handleTrackClick(track, index)"
|
||||
class="track-item-wrapper animate-fade-in-up"
|
||||
/>
|
||||
@@ -38,7 +39,6 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { Music } from 'lucide-vue-next'
|
||||
import TrackListItem from './TrackListItem.client.vue'
|
||||
|
||||
@@ -66,6 +66,10 @@ const props = defineProps({
|
||||
loadingTrack: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
failedTracks: {
|
||||
type: Object, // Set object
|
||||
default: () => new Set()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
{
|
||||
'active': isActive,
|
||||
'loading': isLoading,
|
||||
'has-error': hasError,
|
||||
'animate-pulse-glow': isActive && isPlaying
|
||||
}
|
||||
]"
|
||||
@@ -21,7 +22,8 @@
|
||||
<div class="track-status">
|
||||
<div v-if="isLoading" class="loading-spinner"></div>
|
||||
<div v-else class="status-icon">
|
||||
<Pause v-if="isActive && !isPlaying" class="icon paused" :size="18" />
|
||||
<AlertCircle v-if="hasError" class="icon error" :size="18" />
|
||||
<Pause v-else-if="isActive && !isPlaying" class="icon paused" :size="18" />
|
||||
<Play v-else-if="isActive && isPlaying" class="icon playing" :size="18" />
|
||||
<Music v-else class="icon idle" :size="18" />
|
||||
</div>
|
||||
@@ -36,7 +38,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { Play, Pause, Music } from 'lucide-vue-next'
|
||||
import { Play, Pause, Music, AlertCircle } from 'lucide-vue-next'
|
||||
|
||||
const props = defineProps({
|
||||
track: {
|
||||
@@ -54,6 +56,10 @@ const props = defineProps({
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hasError: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
@@ -133,6 +139,26 @@ const formatTime = (seconds) => {
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Error state styles */
|
||||
.track-item.has-error {
|
||||
opacity: 0.7;
|
||||
background: rgba(239, 68, 68, 0.05);
|
||||
border-color: rgba(239, 68, 68, 0.2);
|
||||
}
|
||||
|
||||
.track-item.has-error:hover {
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
box-shadow:
|
||||
0 4px 12px rgba(239, 68, 68, 0.15),
|
||||
0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.track-item.has-error .track-name {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: line-through;
|
||||
text-decoration-color: rgba(239, 68, 68, 0.5);
|
||||
}
|
||||
|
||||
.track-info {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -184,6 +210,11 @@ const formatTime = (seconds) => {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.icon.error {
|
||||
color: #ef4444;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
Reference in New Issue
Block a user