File size: 3,734 Bytes
abd54b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
00a956c
 
 
 
 
 
 
 
abd54b8
6e4988e
abd54b8
00a956c
 
 
 
 
 
 
 
6e4988e
00a956c
abd54b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { NextRequest, NextResponse } from 'next/server';

/**
 * Generic proxy API route for Hugging Face requests with authentication
 * Handles both JSON and binary (Parquet) files
 * Supports GET and HEAD methods
 */
export async function GET(request: NextRequest) {
  return handleRequest(request, 'GET');
}

export async function HEAD(request: NextRequest) {
  return handleRequest(request, 'HEAD');
}

async function handleRequest(request: NextRequest, method: 'GET' | 'HEAD') {
  const searchParams = request.nextUrl.searchParams;
  const url = searchParams.get('url');
  
  if (!url) {
    return NextResponse.json(
      { error: 'url parameter is required' },
      { status: 400 }
    );
  }

  // Get token from environment variable (set in Hugging Face Space secrets)
  // Try multiple possible variable names that Hugging Face Spaces might use
  const token = 
    process.env.HF_TOKEN || 
    process.env.HUGGINGFACE_TOKEN || 
    process.env.HF_API_TOKEN ||
    process.env.HUGGING_FACE_HUB_TOKEN ||
    // Also check if it's available in the request headers (for debugging)
    request.headers.get('x-hf-token') || null;
  
  // Log token status for debugging (don't log actual token value)
  if (!token) {
    const envKeys = Object.keys(process.env).filter(k => 
      k.includes('HF') || k.includes('TOKEN') || k.includes('HUGGING')
    );
    console.error('❌ HF_TOKEN not found!');
    console.error('Checked: HF_TOKEN, HUGGINGFACE_TOKEN, HF_API_TOKEN, HUGGING_FACE_HUB_TOKEN');
    console.error('Available env vars with HF/TOKEN:', envKeys.length > 0 ? envKeys.join(', ') : 'NONE');
    console.error('⚠️  Requests to private repos will fail with 401');
    console.error('💡 Make sure HF_TOKEN secret is added in Space Settings → Variables and secrets');
  } else {
    console.log('✓ HF_TOKEN found (length:', token.length, 'chars, starts with:', token.substring(0, 5) + '...')');
  }

  try {
    const headers: HeadersInit = {
      'Cache-Control': 'no-store',
    };
    
    // Add authentication if token is available
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }
    
    const response = await fetch(url, {
      method,
      headers,
      cache: 'no-store',
    });

    if (!response.ok) {
      // Return error with status code
      const errorText = await response.text().catch(() => 'Unknown error');
      return NextResponse.json(
        { error: `Failed to fetch: ${response.status} ${response.statusText}`, details: errorText },
        { status: response.status }
      );
    }

    // For HEAD requests, just return status without body
    if (method === 'HEAD') {
      return new NextResponse(null, {
        status: response.status,
        headers: {
          'Content-Type': response.headers.get('content-type') || '',
          'Content-Length': response.headers.get('content-length') || '0',
        },
      });
    }

    // Check content type to determine if it's binary or JSON
    const contentType = response.headers.get('content-type') || '';
    
    if (contentType.includes('application/json')) {
      // Return JSON
      const data = await response.json();
      return NextResponse.json(data);
    } else {
      // Return binary data (for Parquet files, videos, etc.)
      const arrayBuffer = await response.arrayBuffer();
      return new NextResponse(arrayBuffer, {
        headers: {
          'Content-Type': contentType,
          'Content-Length': arrayBuffer.byteLength.toString(),
        },
      });
    }
  } catch (error) {
    console.error('Proxy error:', error);
    return NextResponse.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      { status: 500 }
    );
  }
}