Audit qualité : corrections de bugs, nettoyage, lint 0 erreur, tests #4
+2
-2
@@ -18,8 +18,8 @@ NEXT_PUBLIC_EXCLUSIVE_ARTIST_LABEL=OKI Exclusif
|
|||||||
|
|
||||||
# FUNKWHALE VARIABLE
|
# FUNKWHALE VARIABLE
|
||||||
NEXT_PUBLIC_OKI_MIZIK_URL=https://funkwhale-server.com
|
NEXT_PUBLIC_OKI_MIZIK_URL=https://funkwhale-server.com
|
||||||
NEXT_PUBLIC_MIZIK_API_USER=user
|
MIZIK_API_USER=user
|
||||||
NEXT_PUBLIC_MIZIK_API_PASSWORD=password
|
MIZIK_API_PASSWORD=password
|
||||||
|
|
||||||
NEXT_PUBLIC_AWTIS_POU_CHAK_PAJ=6
|
NEXT_PUBLIC_AWTIS_POU_CHAK_PAJ=6
|
||||||
NEXT_PUBLIC_SITE_URL=$SITE_URL
|
NEXT_PUBLIC_SITE_URL=$SITE_URL
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import {describe, it, expect, vi, afterEach} from 'vitest'
|
||||||
|
import {GET} from '../route'
|
||||||
|
|
||||||
|
function fakeUpstreamResponse({status = 200, headers = {}, body = 'audio-bytes'} = {}) {
|
||||||
|
return {
|
||||||
|
status,
|
||||||
|
body,
|
||||||
|
headers: {
|
||||||
|
get: key => headers[key.toLowerCase()] ?? null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('GET /api/mizik-stream/[id]', () => {
|
||||||
|
const originalFetch = global.fetch
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
global.fetch = originalFetch
|
||||||
|
vi.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('n\'expose pas les identifiants au client, uniquement l\'id dans l\'URL amont', async () => {
|
||||||
|
global.fetch = vi.fn(async () => fakeUpstreamResponse())
|
||||||
|
|
||||||
|
const request = new Request('http://localhost/api/mizik-stream/42')
|
||||||
|
await GET(request, {params: Promise.resolve({id: '42'})})
|
||||||
|
|
||||||
|
const [calledUrl] = global.fetch.mock.calls[0]
|
||||||
|
expect(calledUrl).toContain('id=42')
|
||||||
|
expect(calledUrl).toMatch(/[?&]u=/)
|
||||||
|
expect(calledUrl).toMatch(/[?&]p=/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('transmet l\'en-tête Range pour permettre le seek audio', async () => {
|
||||||
|
global.fetch = vi.fn(async () => fakeUpstreamResponse({status: 206, headers: {'content-range': 'bytes 0-99/200'}}))
|
||||||
|
|
||||||
|
const request = new Request('http://localhost/api/mizik-stream/42', {headers: {range: 'bytes=0-99'}})
|
||||||
|
const response = await GET(request, {params: Promise.resolve({id: '42'})})
|
||||||
|
|
||||||
|
const [, options] = global.fetch.mock.calls[0]
|
||||||
|
expect(options.headers.range).toBe('bytes=0-99')
|
||||||
|
expect(response.status).toBe(206)
|
||||||
|
expect(response.headers.get('content-range')).toBe('bytes 0-99/200')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renvoie le flux et le statut renvoyés par le serveur Funkwhale', async () => {
|
||||||
|
global.fetch = vi.fn(async () => fakeUpstreamResponse({status: 200, headers: {'content-type': 'audio/mpeg'}}))
|
||||||
|
|
||||||
|
const request = new Request('http://localhost/api/mizik-stream/7')
|
||||||
|
const response = await GET(request, {params: Promise.resolve({id: '7'})})
|
||||||
|
|
||||||
|
expect(response.status).toBe(200)
|
||||||
|
expect(response.headers.get('content-type')).toBe('audio/mpeg')
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
const MIZIK_URL = process.env.NEXT_PUBLIC_OKI_MIZIK_URL || 'https://funkwhale-server.com'
|
||||||
|
const MIZIK_API_USER = process.env.MIZIK_API_USER || 'user'
|
||||||
|
const MIZIK_API_PASSWORD = process.env.MIZIK_API_PASSWORD || 'password'
|
||||||
|
|
||||||
|
const FORWARDED_HEADERS = ['content-type', 'content-length', 'content-range', 'accept-ranges']
|
||||||
|
|
||||||
|
export async function GET(request, props) {
|
||||||
|
const {id} = await props.params
|
||||||
|
|
||||||
|
const upstreamUrl = `${MIZIK_URL}/rest/stream?u=${encodeURIComponent(MIZIK_API_USER)}&p=${encodeURIComponent(MIZIK_API_PASSWORD)}&id=${encodeURIComponent(id)}`
|
||||||
|
const range = request.headers.get('range')
|
||||||
|
|
||||||
|
const upstreamResponse = await fetch(upstreamUrl, {
|
||||||
|
headers: range ? {range} : {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const headers = new Headers()
|
||||||
|
for (const key of FORWARDED_HEADERS) {
|
||||||
|
const value = upstreamResponse.headers.get(key)
|
||||||
|
if (value) {
|
||||||
|
headers.set(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(upstreamResponse.body, {
|
||||||
|
status: upstreamResponse.status,
|
||||||
|
headers
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ import {Box, CircularProgress} from '@mui/material'
|
|||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
|
|
||||||
const MIZIK_URL = process.env.NEXT_PUBLIC_OKI_MIZIK_URL || 'https://funkwhale-server.com'
|
const MIZIK_URL = process.env.NEXT_PUBLIC_OKI_MIZIK_URL || 'https://funkwhale-server.com'
|
||||||
const MIZIK_API_USER = process.env.NEXT_PUBLIC_MIZIK_API_USER || 'user'
|
|
||||||
const MIZIK_API_PASSWORD = process.env.NEXT_PUBLIC_MIZIK_API_PASSWORD || 'password'
|
|
||||||
|
|
||||||
const DinamikLekte = dynamic(
|
const DinamikLekte = dynamic(
|
||||||
() => import('./lekte'), // eslint-disable-line node/no-unsupported-features/es-syntax
|
() => import('./lekte'), // eslint-disable-line node/no-unsupported-features/es-syntax
|
||||||
@@ -12,7 +10,7 @@ const DinamikLekte = dynamic(
|
|||||||
)
|
)
|
||||||
|
|
||||||
export default function OkiMizik({id, parole}) {
|
export default function OkiMizik({id, parole}) {
|
||||||
const mizikStreamUrl = `${MIZIK_URL}/rest/stream?u=${MIZIK_API_USER}&p=${MIZIK_API_PASSWORD}&id=${id}`
|
const mizikStreamUrl = `/api/mizik-stream/${id}`
|
||||||
const detailsUrl = `${MIZIK_URL}/library/tracks/${id}`
|
const detailsUrl = `${MIZIK_URL}/library/tracks/${id}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user