UCD.js Docs
FS BridgeBridges

HTTP Bridge

Read-only file system bridge for accessing files over HTTP/HTTPS

HTTP File System Bridge

The HTTP File System Bridge provides read-only access to files served over HTTP or HTTPS. It's designed to work with APIs that serve file contents and directory listings, making it ideal for accessing remote Unicode data files.

Import

import HTTPFileSystemBridge from "@ucdjs/fs-bridge/bridges/http";

Configuration

The bridge requires a baseUrl option that specifies the base URL for all operations:

const bridge = HTTPFileSystemBridge({
  baseUrl: new URL("https://api.ucdjs.dev/api/v1/files")
});

Options:

  • baseUrl (URL, optional): The base URL for file operations. Defaults to https://api.ucdjs.dev/api/v1/files if not provided.

You can also pass a string URL, which will be automatically converted to a URL object:

const bridge = HTTPFileSystemBridge({
  baseUrl: "https://api.ucdjs.dev/api/v1/files"
});

Capabilities

The HTTP bridge is read-only and supports only read operations:

OperationSupportedNotes
readFetches file contents via HTTP GET
existsUses HTTP HEAD request to check existence
listdirExpects JSON response with file entries
writeNot supported (read-only bridge)
mkdirNot supported (read-only bridge)
rmNot supported (read-only bridge)

Usage Examples

Reading Files

const bridge = HTTPFileSystemBridge({
  baseUrl: new URL("https://api.ucdjs.dev/api/v1/files")
});

// Read a file
const content = await bridge.read("16.0.0/ucd/UnicodeData.txt");
console.log(content);

// Read a file in a subdirectory
const nestedContent = await bridge.read("16.0.0/ucd/Blocks.txt");

Listing Directories

const bridge = HTTPFileSystemBridge({
  baseUrl: new URL("https://api.ucdjs.dev/api/v1/files")
});

// List directory contents (non-recursive)
const entries = await bridge.listdir("16.0.0/ucd");
for (const entry of entries) {
  if (entry.type === "file") {
    console.log(`File: ${entry.name} at ${entry.path}`);
  } else {
    console.log(`Directory: ${entry.name}`);
  }
}

// List directory contents recursively
const allEntries = await bridge.listdir("16.0.0/ucd", true);

When listing recursively, the bridge makes additional HTTP requests to fetch nested directory contents. Each directory entry will have its children array populated.

Checking Existence

const bridge = HTTPFileSystemBridge({
  baseUrl: new URL("https://api.ucdjs.dev/api/v1/files")
});

// Check if a file exists
const fileExists = await bridge.exists("16.0.0/ucd/UnicodeData.txt");

// Check if a directory exists
const dirExists = await bridge.exists("16.0.0/ucd");

The exists operation uses an HTTP HEAD request, which is more efficient than fetching the full file content.

Using Default Configuration

If you don't provide a baseUrl, the bridge uses the default UCD.js API URL:

// Uses https://api.ucdjs.dev/api/v1/files by default
const bridge = HTTPFileSystemBridge();

const content = await bridge.read("16.0.0/ucd/UnicodeData.txt");

API Requirements

The HTTP bridge expects the API to follow specific conventions:

File Reading

  • Endpoint: GET {baseUrl}/{path}
  • Response: File contents as text (Content-Type: text/plain or similar)
  • Status Codes:
    • 200 OK: File exists and content is returned
    • 404 Not Found: File doesn't exist (throws error)
    • Other errors: Throws error with status text

Directory Listing

  • Endpoint: GET {baseUrl}/{path}
  • Headers: Accept: application/json
  • Response: JSON array of file entries matching FileEntrySchema:
[
  {
    type: "file",
    name: "UnicodeData.txt",
    path: "UnicodeData.txt"
  },
  {
    type: "directory",
    name: "subdirectory",
    path: "subdirectory"
  }
]
  • Status Codes:
    • 200 OK: Directory listing returned
    • 404 Not Found: Returns empty array (directory doesn't exist)
    • 403 Forbidden: Returns empty array (access denied)
    • 500 Internal Server Error: Throws error
    • Other errors: Throws error with status text

File Existence Check

  • Endpoint: HEAD {baseUrl}/{path}
  • Response: No body, only headers
  • Status Codes:
    • 200 OK: File exists
    • 404 Not Found: File doesn't exist
    • Other errors: Returns false (doesn't throw)

Error Handling

The bridge handles various HTTP error scenarios:

const bridge = HTTPFileSystemBridge({
  baseUrl: new URL("https://api.example.com/files")
});

try {
  const content = await bridge.read("file.txt");
} catch (error) {
  if (error.message.includes("Failed to read remote file")) {
    // Handle read error
  }
}

try {
  const entries = await bridge.listdir("directory");
} catch (error) {
  if (error.message.includes("Server error")) {
    // Handle server error
  } else if (error.message.includes("Invalid response schema")) {
    // Handle invalid API response format
  }
}

Common Error Scenarios

  1. File Not Found (404): When reading a non-existent file, the bridge throws an error.

  2. Directory Not Found (404): When listing a non-existent directory, the bridge returns an empty array instead of throwing an error.

  3. Access Denied (403): When listing a directory with insufficient permissions, the bridge returns an empty array.

  4. Server Error (500): When the server encounters an error, the bridge throws an error with the server's status text.

  5. Invalid Response Schema: When the API returns a directory listing that doesn't match the expected schema, the bridge throws an error with validation details.

Path Safety

The bridge uses resolveSafePath internally to prevent path traversal attacks. All paths are resolved relative to the baseUrl.pathname, ensuring that operations cannot access files outside the base path.

Recursive Directory Listing

When listing directories recursively, the bridge:

  1. Fetches the initial directory listing
  2. For each directory entry, makes an additional request to fetch its children
  3. Builds a tree structure with parent-child relationships

Note: Recursive listing can result in many HTTP requests for deeply nested directory structures. Consider the performance implications when using recursive listing.

Best Practices

  1. Use appropriate base URLs: Set the baseUrl to match your API's file serving endpoint.

  2. Handle network errors: Network requests can fail. Always wrap operations in try-catch blocks.

  3. Cache responses when possible: Since the bridge is read-only, consider implementing caching for frequently accessed files.

  4. Use HEAD requests efficiently: The exists operation uses HEAD requests, which are more efficient than GET for existence checks.

  5. Monitor API rate limits: If your API has rate limits, be mindful of recursive directory listings which make multiple requests.

  6. Validate API responses: Ensure your API returns responses that match the expected schema for directory listings.

Hooks

The bridge supports all bridge hooks for monitoring and debugging operations. See the Hooks documentation for complete details and examples.

Use Cases

The HTTP bridge is ideal for:

  • Remote Unicode Data Access: Accessing Unicode data files from a remote API
  • CDN Integration: Reading files from content delivery networks
  • API-Based File Systems: Interacting with APIs that serve file contents
  • Browser Environments: Using file system operations in browser/worker environments where Node.js fs is not available

Limitations

  • Read-only: Write, mkdir, and rm operations are not supported
  • Network dependency: Requires network connectivity and a functioning API
  • API compatibility: The API must follow the expected response formats
  • Performance: Recursive directory listing can be slow due to multiple HTTP requests

On this page