Dynamic Intelligence commited on
Commit
9b45fba
·
1 Parent(s): e612ce5

Fix 401 error: Add authenticated API proxy for private datasets

Browse files
src/app/[org]/[dataset]/[episode]/fetch-data.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
  } from "@/utils/parquetUtils";
9
  import { pick } from "@/utils/pick";
10
  import { getDatasetVersion, buildVersionedUrl } from "@/utils/versionUtils";
 
11
 
12
  const SERIES_NAME_DELIMITER = " | ";
13
 
@@ -241,7 +242,7 @@ async function getEpisodeDataV2(
241
  try {
242
  const tasksUrl = buildVersionedUrl(repoId, version, "meta/tasks.jsonl");
243
  // Use proxy for authenticated requests
244
- const proxyUrl = `/api/hf-proxy?url=${encodeURIComponent(tasksUrl)}`;
245
  const tasksResponse = await fetch(proxyUrl);
246
 
247
  if (tasksResponse.ok) {
 
8
  } from "@/utils/parquetUtils";
9
  import { pick } from "@/utils/pick";
10
  import { getDatasetVersion, buildVersionedUrl } from "@/utils/versionUtils";
11
+ import { buildProxyUrl } from "@/utils/apiHelpers";
12
 
13
  const SERIES_NAME_DELIMITER = " | ";
14
 
 
242
  try {
243
  const tasksUrl = buildVersionedUrl(repoId, version, "meta/tasks.jsonl");
244
  // Use proxy for authenticated requests
245
+ const proxyUrl = buildProxyUrl(tasksUrl);
246
  const tasksResponse = await fetch(proxyUrl);
247
 
248
  if (tasksResponse.ok) {
src/app/api/hf-proxy/route.ts CHANGED
@@ -15,15 +15,28 @@ export async function HEAD(request: NextRequest) {
15
 
16
  async function handleRequest(request: NextRequest, method: 'GET' | 'HEAD') {
17
  const searchParams = request.nextUrl.searchParams;
18
- const url = searchParams.get('url');
19
 
20
- if (!url) {
21
  return NextResponse.json(
22
  { error: 'url parameter is required' },
23
  { status: 400 }
24
  );
25
  }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  // Get token from environment variable (set in Hugging Face Space secrets)
28
  // Try multiple possible variable names that Hugging Face Spaces might use
29
  const token =
 
15
 
16
  async function handleRequest(request: NextRequest, method: 'GET' | 'HEAD') {
17
  const searchParams = request.nextUrl.searchParams;
18
+ const urlParam = searchParams.get('url');
19
 
20
+ if (!urlParam) {
21
  return NextResponse.json(
22
  { error: 'url parameter is required' },
23
  { status: 400 }
24
  );
25
  }
26
 
27
+ // Decode and validate URL
28
+ let url: string;
29
+ try {
30
+ url = decodeURIComponent(urlParam);
31
+ // Validate it's a proper URL
32
+ new URL(url); // This will throw if invalid
33
+ } catch (error) {
34
+ return NextResponse.json(
35
+ { error: `Invalid URL: ${urlParam}. ${error instanceof Error ? error.message : 'Failed to parse URL'}` },
36
+ { status: 400 }
37
+ );
38
+ }
39
+
40
  // Get token from environment variable (set in Hugging Face Space secrets)
41
  // Try multiple possible variable names that Hugging Face Spaces might use
42
  const token =
src/app/explore/page.tsx CHANGED
@@ -6,6 +6,7 @@ import {
6
  formatStringWithVars,
7
  } from "@/utils/parquetUtils";
8
  import { getDatasetVersion, buildVersionedUrl } from "@/utils/versionUtils";
 
9
 
10
  export default async function ExplorePage({
11
  searchParams,
@@ -73,7 +74,7 @@ export default async function ExplorePage({
73
  const url = buildVersionedUrl(repoId, version, videoPath);
74
  // Check if videoUrl exists (status 200) - use proxy for authenticated requests
75
  try {
76
- const proxyUrl = `/api/hf-proxy?url=${encodeURIComponent(url)}`;
77
  const headRes = await fetch(proxyUrl, { method: "HEAD" });
78
  if (headRes.ok) {
79
  videoUrl = url;
 
6
  formatStringWithVars,
7
  } from "@/utils/parquetUtils";
8
  import { getDatasetVersion, buildVersionedUrl } from "@/utils/versionUtils";
9
+ import { buildProxyUrl } from "@/utils/apiHelpers";
10
 
11
  export default async function ExplorePage({
12
  searchParams,
 
74
  const url = buildVersionedUrl(repoId, version, videoPath);
75
  // Check if videoUrl exists (status 200) - use proxy for authenticated requests
76
  try {
77
+ const proxyUrl = buildProxyUrl(url);
78
  const headRes = await fetch(proxyUrl, { method: "HEAD" });
79
  if (headRes.ok) {
80
  videoUrl = url;
src/utils/parquetUtils.ts CHANGED
@@ -1,4 +1,5 @@
1
  import { parquetRead, parquetReadObjects } from "hyparquet";
 
2
 
3
  export interface DatasetMetadata {
4
  codebase_version: string;
@@ -26,7 +27,7 @@ export interface DatasetMetadata {
26
 
27
  export async function fetchJson<T>(url: string): Promise<T> {
28
  // Use API proxy for authenticated requests (handles private repos)
29
- const proxyUrl = `/api/hf-proxy?url=${encodeURIComponent(url)}`;
30
  const res = await fetch(proxyUrl);
31
  if (!res.ok) {
32
  const errorData = await res.json().catch(() => ({}));
@@ -47,7 +48,7 @@ export function formatStringWithVars(
47
  // Fetch and parse the Parquet file
48
  export async function fetchParquetFile(url: string): Promise<ArrayBuffer> {
49
  // Use API proxy for authenticated requests (handles private repos)
50
- const proxyUrl = `/api/hf-proxy?url=${encodeURIComponent(url)}`;
51
  const res = await fetch(proxyUrl);
52
 
53
  if (!res.ok) {
 
1
  import { parquetRead, parquetReadObjects } from "hyparquet";
2
+ import { buildProxyUrl } from './apiHelpers';
3
 
4
  export interface DatasetMetadata {
5
  codebase_version: string;
 
27
 
28
  export async function fetchJson<T>(url: string): Promise<T> {
29
  // Use API proxy for authenticated requests (handles private repos)
30
+ const proxyUrl = buildProxyUrl(url);
31
  const res = await fetch(proxyUrl);
32
  if (!res.ok) {
33
  const errorData = await res.json().catch(() => ({}));
 
48
  // Fetch and parse the Parquet file
49
  export async function fetchParquetFile(url: string): Promise<ArrayBuffer> {
50
  // Use API proxy for authenticated requests (handles private repos)
51
+ const proxyUrl = buildProxyUrl(url);
52
  const res = await fetch(proxyUrl);
53
 
54
  if (!res.ok) {
src/utils/versionUtils.ts CHANGED
@@ -2,6 +2,8 @@
2
  * Utility functions for checking dataset version compatibility
3
  */
4
 
 
 
5
  const DATASET_URL = process.env.DATASET_URL || "https://huggingface.co/datasets";
6
 
7
  /**
@@ -32,7 +34,7 @@ export async function getDatasetInfo(repoId: string): Promise<DatasetInfo> {
32
  const testUrl = `${DATASET_URL}/${repoId}/resolve/main/meta/info.json`;
33
 
34
  // Use API proxy for authenticated requests
35
- const proxyUrl = `/api/hf-proxy?url=${encodeURIComponent(testUrl)}`;
36
 
37
  const controller = new AbortController();
38
  const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
 
2
  * Utility functions for checking dataset version compatibility
3
  */
4
 
5
+ import { buildProxyUrl } from './apiHelpers';
6
+
7
  const DATASET_URL = process.env.DATASET_URL || "https://huggingface.co/datasets";
8
 
9
  /**
 
34
  const testUrl = `${DATASET_URL}/${repoId}/resolve/main/meta/info.json`;
35
 
36
  // Use API proxy for authenticated requests
37
+ const proxyUrl = buildProxyUrl(testUrl);
38
 
39
  const controller = new AbortController();
40
  const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout