Spaces:
Paused
Paused
| import { BaseProxy, ProxyStream } from './base.js'; | |
| import { createLogger, maskSensitiveInfo } from '../utils/index.js'; | |
| import { config as appConfig } from '../config/index.js'; | |
| import path from 'path'; | |
| const logger = createLogger('mediaflow'); | |
| export class MediaFlowProxy extends BaseProxy { | |
| protected generateProxyUrl(endpoint: string): URL { | |
| const proxyUrl = new URL(this.config.url.replace(/\/$/, '')); | |
| proxyUrl.pathname = `${proxyUrl.pathname === '/' ? '' : proxyUrl.pathname}${endpoint}`; | |
| if (endpoint === '/proxy/ip') { | |
| proxyUrl.searchParams.set('api_password', this.config.credentials); | |
| } | |
| return proxyUrl; | |
| } | |
| protected getPublicIpEndpoint(): string { | |
| return '/proxy/ip'; | |
| } | |
| protected getPublicIpFromResponse(data: any): string | null { | |
| return data.ip || null; | |
| } | |
| protected getHeaders(): Record<string, string> { | |
| return { | |
| 'Content-Type': 'application/json', | |
| }; | |
| } | |
| protected async generateStreamUrls( | |
| streams: ProxyStream[], | |
| encrypt?: boolean | |
| ): Promise<string[] | null> { | |
| const proxyUrl = this.generateProxyUrl('/generate_urls'); | |
| const data = { | |
| mediaflow_proxy_url: this.config.url.replace(/\/$/, ''), | |
| api_password: appConfig.proxy.encryption.mediaflow | |
| ? this.config.credentials | |
| : undefined, | |
| urls: streams.map((stream) => ({ | |
| endpoint: '/proxy/stream', | |
| filename: stream.filename || path.basename(stream.url), | |
| query_params: appConfig.proxy.encryption.mediaflow | |
| ? undefined | |
| : { | |
| api_password: this.config.credentials, | |
| }, | |
| destination_url: stream.url, | |
| request_headers: stream.headers?.request, | |
| response_headers: stream.headers?.response, | |
| })), | |
| }; | |
| logger.trace( | |
| { | |
| endpoint: `${proxyUrl.protocol}//${maskSensitiveInfo(proxyUrl.hostname)}/generate_urls`, | |
| count: streams.length, | |
| }, | |
| 'generating mediaflow proxy urls' | |
| ); | |
| const response = await fetch(proxyUrl.toString(), { | |
| method: 'POST', | |
| headers: this.getHeaders(), | |
| body: JSON.stringify(data), | |
| signal: AbortSignal.timeout(30000), | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`${response.status}: ${response.statusText}`); | |
| } | |
| let responseData: any; | |
| try { | |
| responseData = await response.json(); | |
| } catch (error) { | |
| const text = await response.text(); | |
| logger.debug({ body: text }, 'failed to parse mediaflow json response'); | |
| throw new Error('Failed to parse JSON response from MediaFlow'); | |
| } | |
| if (responseData.error) { | |
| throw new Error(responseData.error); | |
| } | |
| if (responseData.urls) { | |
| return responseData.urls; | |
| } else { | |
| throw new Error('No URLs were returned from MediaFlow'); | |
| } | |
| } | |
| } | |