You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Turtle-native Solid client (e.g. umai) fetching `//.meta` from a JSS pod (conneg enabled) gets JSON-LD back instead of Turtle, and errors with `MalformedSolidDocumentError: Malformed Turtle document ... Expected entity but got { on line 2`.
Reproduced today against ewingson's `test.solidweb.app` (JSS 0.0.144, `conneg: true`).
Root cause
`getContentType(filePath)` in `src/utils/url.js:216` maps extensions to MIME types. The map is extension-based and has no entry for `.meta` or `.acl`:
`path.extname('/a/.meta')` returns `''` (leading-dot files have no extension per node:path), so the fallback hits. `.meta` and `.acl` both end up tagged `application/octet-stream`.
Downstream: `handleGet`'s conneg branch is gated on `isRdfContentType(storedContentType)` (`src/handlers/resource.js:411`). `application/octet-stream` isn't an RDF type, so conneg never kicks in for these files — they're served verbatim as stored, regardless of `Accept`.
Mirror bug in .acl
Same issue applies to `.acl`. It hasn't shown up visibly because:
JSS's own `parseAcl()` (`src/wac/parser.js:38-49`) is forgiving — tries JSON first, falls back to Turtle. So server-side WAC checks work on either format.
Most clients don't GET `.acl` via HTTP — they read `wac-allow` on the protected resource. Only ACL-editing tools fetch `.acl`, and the few that do mostly accept JSON-LD.
But the latent bug is real: JSS writes `.acl` as JSON-LD via `serializeAcl()` → `JSON.stringify()`. A strict-Turtle ACL editor pointed at any existing JSS pod today would hit the exact same parser error.
Conneg handles the translation for Turtle-native clients automatically — `handleGet` already has a working `fromJsonLd(jsonLd, 'text/turtle', ...)` path for JSON-LD-stored files.
The PUT side already handles the inverse: `handlePut:639` converts `text/turtle` bodies to JSON-LD before storing when `--conneg` is enabled.
So the round-trip lands for both client families with no further code change:
Client request
Today
After fix
umai: `PUT text/turtle .meta`
Stored as Turtle bytes (silent)
Converted to JSON-LD, stored
umai: `GET .meta Accept: text/turtle`
Gets JSON-LD, parser errors
Gets Turtle, parser happy
pilot: `GET .meta Accept: application/ld+json`
Served raw (happens to be JSON-LD)
Served raw (explicit)
Back-compat
Existing pods have JSON-LD `.acl` files on disk (written by `createPodStructure` via `serializeAcl`). Zero migration: the fix recognises them, conneg reads them correctly, Turtle clients start working immediately.
Scope
Two lines. Tests around `conneg.test.js` / `ldp.test.js` can add a case per file type (PUT Turtle, GET Turtle, both succeed; PUT JSON-LD, GET Turtle, convert) — straightforward to bolt onto existing fixtures.
Symptom
A Turtle-native Solid client (e.g. umai) fetching `//.meta` from a JSS pod (conneg enabled) gets JSON-LD back instead of Turtle, and errors with `MalformedSolidDocumentError: Malformed Turtle document ... Expected entity but got { on line 2`.
Reproduced today against ewingson's `test.solidweb.app` (JSS 0.0.144, `conneg: true`).
Root cause
`getContentType(filePath)` in `src/utils/url.js:216` maps extensions to MIME types. The map is extension-based and has no entry for `.meta` or `.acl`:
```js
const types = {
'.jsonld': 'application/ld+json',
'.json': 'application/json',
'.ttl': 'text/turtle',
// ... no '.meta' or '.acl'
};
return types[ext] || 'application/octet-stream';
```
`path.extname('/a/.meta')` returns `''` (leading-dot files have no extension per node:path), so the fallback hits. `.meta` and `.acl` both end up tagged `application/octet-stream`.
Downstream: `handleGet`'s conneg branch is gated on `isRdfContentType(storedContentType)` (`src/handlers/resource.js:411`). `application/octet-stream` isn't an RDF type, so conneg never kicks in for these files — they're served verbatim as stored, regardless of `Accept`.
Mirror bug in .acl
Same issue applies to `.acl`. It hasn't shown up visibly because:
But the latent bug is real: JSS writes `.acl` as JSON-LD via `serializeAcl()` → `JSON.stringify()`. A strict-Turtle ACL editor pointed at any existing JSS pod today would hit the exact same parser error.
Fix
Two-line change to `getContentType`:
```diff
const types = {
'.jsonld': 'application/ld+json',
'.json': 'application/json',
...
};
```
We tag them as `application/ld+json` (not `text/turtle`) because:
So the round-trip lands for both client families with no further code change:
Back-compat
Existing pods have JSON-LD `.acl` files on disk (written by `createPodStructure` via `serializeAcl`). Zero migration: the fix recognises them, conneg reads them correctly, Turtle clients start working immediately.
Scope
Two lines. Tests around `conneg.test.js` / `ldp.test.js` can add a case per file type (PUT Turtle, GET Turtle, both succeed; PUT JSON-LD, GET Turtle, convert) — straightforward to bolt onto existing fixtures.
Happy to PR.