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 =
|
| 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
|
| 19 |
|
| 20 |
-
if (!
|
| 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 =
|
| 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 =
|
| 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 =
|
| 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 =
|
| 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
|