Skip to content

feat(engines): add worker-side HTTP range loading - #814

Open
RooTooRD wants to merge 1 commit into
embedpdf:v2from
nuqayah:range-loading-v2
Open

RooTooRD wants to merge 1 commit into
embedpdf:v2from
nuqayah:range-loading-v2

Conversation

@RooTooRD

@RooTooRD RooTooRD commented Sep 13, 2026 •

Copy link
Copy Markdown

Summary

Add incremental HTTP byte-range loading for URL-based PDFs in the PDFium worker engine.

  • Open remote PDFs through FPDF_LoadCustomDocument
  • Request and cache aligned 256 KiB byte ranges as PDFium needs them
  • Route supported openDocumentUrl() calls through the worker
  • Preserve custom headers, credentials, custom fetchers, passwords, rotation normalization, permissions, and editing behavior
  • Use strong ETags or Last-Modified with If-Range when available
  • Fall back to a complete fetch when range loading is unavailable or a range fails
  • Reject changed representations instead of mixing bytes from different revisions
  • Release custom callbacks, file-access structures, documents, and WASM allocations during close and destruction
  • Replace an existing document safely when reopening the same document ID
  • Document the loading and fallback behavior

Why this runs in the worker

PDFium's FPDF_FILEACCESS.GetBlock callback is synchronous. Serving uncached ranges therefore requires synchronous network reads.

The range implementation is enabled only in the dedicated PDFium worker so these reads never block the browser's main thread. The direct engine continues using full-fetch loading.

Compatibility and fallbacks

Full-fetch loading is retained when:

  • mode: 'full-fetch' is selected
  • the direct engine is used
  • credentials: 'omit' is requested
  • a custom engine fetcher is configured
  • the server ignores or rejects range requests
  • a malformed or incomplete 206 response is received

If a range fails after the document opens, the worker synchronously requests the complete file and continues only when its length and all previously cached bytes match. If the complete response conflicts with bytes PDFium has already consumed, the current operation rejects instead of silently producing incomplete output.

Relative URLs are resolved before crossing the worker boundary, while malformed URLs reject through the returned PdfTask.

The current WASM FPDF_FILEACCESS layout uses a 32-bit file length, so custom range loading is limited to PDFs smaller than 4 GiB.

Validation

  • pnpm --filter @embedpdf/engines test — 4 suites and 22 tests
  • Prettier check for every changed supported file
  • pnpm --filter @embedpdf/engines... build
  • Unit coverage for aligned caching, full fallback, malformed responses, representation conflicts, request routing, explicit full-fetch mode, credentials, custom fetchers, malformed URLs, same-ID replacement, callback cleanup, close, destroy, and opening failures
  • Browser integration test opening and rendering the first page of a 14-page PDF using only two initial partial requests:
    • bytes=0-262143
    • bytes=786432-1016314
  • Browser test rendering all 14 pages and lazily fetching the remaining chunks
  • Browser runtime-failure test where a later range returns 416, a complete GET is validated against cached bytes, and every page renders identically to the normal range path
  • Browser representation-change test confirming conflicting complete content rejects the current render operation
  • Browser saveAsCopy() and close test for a range-backed document
  • Browser password tests confirming successful protected-PDF loading and PDFium error code 4 without a password

Closes #7
Closes #287
Closes #540

@vercel

vercel Bot commented Sep 13, 2026

Copy link
Copy Markdown

@RooTooRD is attempting to deploy a commit to the CloudPDF Team on Vercel.

A member of the Team first needs to authorize it.

@RooTooRD
RooTooRD force-pushed the range-loading-v2 branch 2 times, most recently from aa0abd1 to 629dd20 Compare September 15, 2026 05:50

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant