mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-11 09:23:36 +01:00
fix(build): rename .mjs assets to .js to avoid MIME errors on self-hosted setups
This commit is contained in:
1 parent
7a6cd61286
commit
c6ea2ca595
6 files changed
+158
No files matched your search
@@ -207,6 +207,32 @@ Ensure MIME type is configured:
|
|||||||
AddType application/wasm .wasm
|
AddType application/wasm .wasm
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sign PDF or Form Filler Shows a Blank Viewer (`.mjs` MIME error)
|
||||||
|
|
||||||
|
If the browser console shows:
|
||||||
|
|
||||||
|
```
|
||||||
|
Failed to load module script: The server responded with a non-JavaScript
|
||||||
|
MIME type of "application/octet-stream". Strict MIME type checking is
|
||||||
|
enforced for module scripts per HTML spec.
|
||||||
|
```
|
||||||
|
|
||||||
|
…and the failing request ends in `.mjs`, your Apache config is missing the `.mjs → application/javascript` mapping. The bundled PDF viewer ships ES module files with a `.mjs` extension, and Apache's stock `mime.types` doesn't include them by default.
|
||||||
|
|
||||||
|
Add to your VirtualHost or `.htaccess`:
|
||||||
|
|
||||||
|
```apache
|
||||||
|
AddType application/javascript .mjs
|
||||||
|
```
|
||||||
|
|
||||||
|
Then reload Apache:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apache2ctl configtest && sudo systemctl reload apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
To confirm: in browser DevTools → Network tab, find the failing `.mjs` request and check the `Content-Type` response header. It should now be `application/javascript`, not `application/octet-stream`.
|
||||||
|
|
||||||
### Rewrite Not Working
|
### Rewrite Not Working
|
||||||
|
|
||||||
Check that mod_rewrite is enabled:
|
Check that mod_rewrite is enabled:
|
||||||
|
|||||||
@@ -39,6 +39,17 @@ aws s3 cp s3://your-bentopdf-bucket/ s3://your-bentopdf-bucket/ \
|
|||||||
--include "*.wasm" \
|
--include "*.wasm" \
|
||||||
--content-type "application/wasm" \
|
--content-type "application/wasm" \
|
||||||
--metadata-directive REPLACE
|
--metadata-directive REPLACE
|
||||||
|
|
||||||
|
# Set correct MIME type for ES module files (.mjs)
|
||||||
|
# S3 defaults .mjs to application/octet-stream, which browsers refuse to
|
||||||
|
# execute as ES modules. The bundled PDF viewer (Sign PDF, Form Filler)
|
||||||
|
# ships ES modules with .mjs extensions and will fail without this step.
|
||||||
|
aws s3 cp s3://your-bentopdf-bucket/ s3://your-bentopdf-bucket/ \
|
||||||
|
--recursive \
|
||||||
|
--exclude "*" \
|
||||||
|
--include "*.mjs" \
|
||||||
|
--content-type "application/javascript" \
|
||||||
|
--metadata-directive REPLACE
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 3: Create CloudFront Distribution
|
## Step 3: Create CloudFront Distribution
|
||||||
|
|||||||
@@ -183,6 +183,64 @@ Choose your platform:
|
|||||||
- [Kubernetes](/self-hosting/kubernetes)
|
- [Kubernetes](/self-hosting/kubernetes)
|
||||||
- [CORS Proxy](/self-hosting/cors-proxy) - Required for digital signatures
|
- [CORS Proxy](/self-hosting/cors-proxy) - Required for digital signatures
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Word / ODT / Excel / PowerPoint to PDF Hangs (SharedArrayBuffer Unavailable)
|
||||||
|
|
||||||
|
**Symptom**: LibreOffice-based document conversions (Word, ODT, Excel, PowerPoint to PDF) hang at ~55% or fail to start. The browser console may show:
|
||||||
|
|
||||||
|
> `ReferenceError: SharedArrayBuffer is not defined`
|
||||||
|
|
||||||
|
…or `window.crossOriginIsolated` reports `false`, or the WASM compilation reports `expected magic word 00 61 73 6d, found 1f 8b 08 08`.
|
||||||
|
|
||||||
|
**Cause**: LibreOffice WASM requires `SharedArrayBuffer`, which the browser only enables when the page is **cross-origin isolated** AND served from a **secure context**. That means two things must be true:
|
||||||
|
|
||||||
|
1. Every response includes both headers:
|
||||||
|
- `Cross-Origin-Embedder-Policy: require-corp`
|
||||||
|
- `Cross-Origin-Opener-Policy: same-origin`
|
||||||
|
2. The page is served from `https://...` or `http://localhost`. Plain HTTP on a LAN IP (e.g. `http://192.168.x.x`) does NOT count as secure — browsers disable `SharedArrayBuffer` there.
|
||||||
|
|
||||||
|
The `00 61 73 6d / 1f 8b 08 08` mismatch is a separate sub-symptom: the pre-compressed `.wasm.gz` / `.data.gz` files are missing the `Content-Encoding: gzip` response header, so the browser receives raw gzip bytes instead of decompressed WASM.
|
||||||
|
|
||||||
|
**Fix**: see your platform-specific deployment guide for the exact configuration:
|
||||||
|
|
||||||
|
- [Nginx →](/self-hosting/nginx#word-odt-excel-to-pdf-not-working)
|
||||||
|
- [Apache →](/self-hosting/apache#word-odt-excel-to-pdf-not-working)
|
||||||
|
- [AWS S3 + CloudFront →](/self-hosting/aws#step-3b-response-headers-policy-required-for-libreoffice-wasm)
|
||||||
|
- [Cloudflare Pages →](/self-hosting/cloudflare#configuration-file) (`_headers` file)
|
||||||
|
- [Netlify →](/self-hosting/netlify#word-odt-excel-to-pdf-stuck-at-55) (`netlify.toml`)
|
||||||
|
- [Vercel →](/self-hosting/vercel#word-odt-excel-to-pdf-not-working) (`vercel.json`)
|
||||||
|
- [Hostinger →](/self-hosting/hostinger#libreoffice-tools-not-working) (`.htaccess`)
|
||||||
|
- [Kubernetes →](/self-hosting/kubernetes#ensuring-the-sharedarraybuffer-headers-still-work-ingress-gateway)
|
||||||
|
- **Docker**: handled automatically by the bundled nginx config — no action needed.
|
||||||
|
|
||||||
|
**Verify**: open DevTools Console on any BentoPDF page and run:
|
||||||
|
|
||||||
|
```js
|
||||||
|
console.log(window.crossOriginIsolated); // should be true
|
||||||
|
console.log(typeof SharedArrayBuffer); // should be "function"
|
||||||
|
```
|
||||||
|
|
||||||
|
If the page is HTTPS or `http://localhost` AND both COEP/COOP headers are present on every response, both checks pass. If you're on `http://192.168.x.x` or another non-loopback HTTP origin, terminate it with HTTPS — there is no header-only fix.
|
||||||
|
|
||||||
|
### `.mjs` Files Served as `application/octet-stream`
|
||||||
|
|
||||||
|
**Symptom**: Sign PDF / Form Filler / certain other tools show a blank viewer or fail to load. The browser console reports:
|
||||||
|
|
||||||
|
> `Failed to load module script: The server responded with a non-JavaScript MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.`
|
||||||
|
|
||||||
|
**Cause**: Your web server or reverse proxy doesn't have a MIME-type mapping for `.mjs` files (the bundled PDF viewer ships ES modules with that extension). Many stock server configs default to `application/octet-stream` for unrecognized extensions, which browsers refuse to execute as ES modules.
|
||||||
|
|
||||||
|
**Fix**: see your platform-specific deployment guide for the exact snippet:
|
||||||
|
|
||||||
|
- [Nginx →](/self-hosting/nginx#sign-pdf-or-form-filler-shows-a-blank-viewer-mjs-mime-error)
|
||||||
|
- [Apache →](/self-hosting/apache#sign-pdf-or-form-filler-shows-a-blank-viewer-mjs-mime-error)
|
||||||
|
- [AWS S3 + CloudFront →](/self-hosting/aws#step-2-build-and-upload) (see `aws s3 cp ... --include "*.mjs"`)
|
||||||
|
- [Kubernetes →](/self-hosting/kubernetes#mjs-mime-type-errors-sign-pdf-form-filler-iframe-blank)
|
||||||
|
- **Docker, Vercel, Netlify, Cloudflare Pages, Hostinger**: handled automatically — no action needed.
|
||||||
|
|
||||||
|
**Verify**: open DevTools → Network tab, find the failing `.mjs` request, check the `Content-Type` response header. It should be `application/javascript`. If it's still `application/octet-stream`, an outer reverse proxy or CDN may be re-sniffing the type — check each layer in your serving chain.
|
||||||
|
|
||||||
## WASM Configuration (AGPL Components)
|
## WASM Configuration (AGPL Components)
|
||||||
|
|
||||||
BentoPDF **does not bundle** AGPL-licensed processing libraries in its source code, but **pre-configures CDN URLs** so all features work out of the box — no manual setup needed.
|
BentoPDF **does not bundle** AGPL-licensed processing libraries in its source code, but **pre-configures CDN URLs** so all features work out of the box — no manual setup needed.
|
||||||
|
|||||||
@@ -130,6 +130,23 @@ ingress:
|
|||||||
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `.mjs` MIME-type errors (Sign PDF / Form Filler iframe blank)
|
||||||
|
|
||||||
|
If the browser console shows `Failed to load module script: ... non-JavaScript MIME type "application/octet-stream"` on a `.mjs` request, an Ingress/Gateway controller in front of the BentoPDF nginx is replacing the upstream `Content-Type` header with `application/octet-stream`.
|
||||||
|
|
||||||
|
The BentoPDF image's nginx already serves `.mjs` as `application/javascript`. The fix is to stop the controller from stripping/replacing it. For nginx-ingress:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ingress:
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||||
|
location ~* \.mjs$ {
|
||||||
|
types {} default_type application/javascript;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use a `ResponseHeaderModifier` filter in Gateway API to set `Content-Type: application/javascript` for `.mjs` paths. Verify with DevTools → Network tab: the failed `.mjs` request should now show `content-type: application/javascript`.
|
||||||
|
|
||||||
### If you’re using Gateway API and want to force-add headers
|
### If you’re using Gateway API and want to force-add headers
|
||||||
|
|
||||||
Gateway API supports a `ResponseHeaderModifier` filter. You can attach it in `httpRoute.rules[*].filters`:
|
Gateway API supports a `ResponseHeaderModifier` filter. You can attach it in `httpRoute.rules[*].filters`:
|
||||||
|
|||||||
@@ -174,6 +174,43 @@ types {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sign PDF or Form Filler Shows a Blank Viewer (`.mjs` MIME error)
|
||||||
|
|
||||||
|
If the browser console shows:
|
||||||
|
|
||||||
|
```
|
||||||
|
Failed to load module script: The server responded with a non-JavaScript
|
||||||
|
MIME type of "application/octet-stream". Strict MIME type checking is
|
||||||
|
enforced for module scripts per HTML spec.
|
||||||
|
```
|
||||||
|
|
||||||
|
…and the failing request ends in `.mjs`, your nginx is missing the `.mjs → application/javascript` mapping. The bundled PDF viewer (used by Sign PDF, Form Filler, and a few other tools) ships ES module files with a `.mjs` extension, and nginx's stock `mime.types` doesn't include them by default.
|
||||||
|
|
||||||
|
Fix it by adding `mjs` to the existing `application/javascript` line in `/etc/nginx/mime.types`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
application/javascript js mjs;
|
||||||
|
```
|
||||||
|
|
||||||
|
> Do NOT append a _second_ `application/javascript` line — nginx parses `mime.types` line-by-line and only one type-to-extension mapping wins, so a second line is silently ignored on some versions. Edit the existing line to add `mjs` alongside `js`.
|
||||||
|
|
||||||
|
Or override locally inside your server block (no global file edit):
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
types {
|
||||||
|
application/javascript js mjs;
|
||||||
|
application/wasm wasm;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload nginx after the change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nginx -t && sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
To confirm: in browser DevTools → Network tab, find the failing `.mjs` request and check the `Content-Type` response header. It should now be `application/javascript`, not `application/octet-stream`.
|
||||||
|
|
||||||
### Word/ODT/Excel to PDF Not Working
|
### Word/ODT/Excel to PDF Not Working
|
||||||
|
|
||||||
LibreOffice WASM requires `SharedArrayBuffer`, which needs `Cross-Origin-Embedder-Policy` and `Cross-Origin-Opener-Policy` headers. It also needs a secure context, so `http://localhost` works for local testing but `http://192.168.x.x` or other LAN IPs usually require HTTPS. Note that nginx `add_header` directives in a `location` block **override** server-level `add_header` directives — they don't merge. Every `location` block with its own `add_header` must include the COEP/COOP headers.
|
LibreOffice WASM requires `SharedArrayBuffer`, which needs `Cross-Origin-Embedder-Policy` and `Cross-Origin-Opener-Policy` headers. It also needs a secure context, so `http://localhost` works for local testing but `http://192.168.x.x` or other LAN IPs usually require HTTPS. Note that nginx `add_header` directives in a `location` block **override** server-level `add_header` directives — they don't merge. Every `location` block with its own `add_header` must include the COEP/COOP headers.
|
||||||
|
|||||||
@@ -760,6 +760,15 @@ export default defineConfig(() => {
|
|||||||
'src/pages/bates-numbering.html'
|
'src/pages/bates-numbering.html'
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
output: {
|
||||||
|
assetFileNames: (assetInfo) => {
|
||||||
|
const name = assetInfo.names?.[0] ?? '';
|
||||||
|
if (name.endsWith('.mjs')) {
|
||||||
|
return 'assets/[name]-[hash].js';
|
||||||
|
}
|
||||||
|
return 'assets/[name]-[hash][extname]';
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
|
|||||||
Reference in new issue
Block a user