Skip to content

Authenticated GET on a container returns Turtle body with application/ld+json content-type, ignoring Accept #325

@melvincarvalho

Description

@melvincarvalho

Summary

With --conneg enabled, an authenticated GET on a container returns a Turtle body but labels the response Content-Type: application/ld+json, regardless of the requested Accept. The same request without auth correctly returns JSON-LD. This breaks any client that trusts either the Accept negotiation or the Content-Type header (which is most of them).

Repro

Server:

JSS_SINGLE_USER_PASSWORD=hunter2 jss start --port 4443 --root ~/main --single-user --idp --conneg

Get a token:

TOKEN=$(curl -s -X POST http://localhost:4443/idp/credentials \
  -H "Content-Type: application/json" \
  -d '{"username":"me","password":"hunter2"}' | jq -r .access_token)

Without auth — JSON-LD body, JSON-LD content-type ✓

$ curl -sI -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/profile/card.jsonld | grep -i content-type
content-type: application/ld+json; charset=utf-8

$ curl -s -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/ | head -3
{
  "@context": {
    "ldp": "http://www.w3.org/ns/ldp#",

With auth — Turtle body, JSON-LD content-type

$ curl -sI -H "Authorization: Bearer $TOKEN" -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/ | grep -i content-type
content-type: application/ld+json

$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/ld+json, text/turtle;q=0.5" http://localhost:4443/me/ | head -3
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.

The body is plainly Turtle, the header says JSON-LD. Even when I request Accept: application/ld+json explicitly (no Turtle in the Accept at all), the auth path still serves Turtle.

Expected

Either:

  • Body matches Accept — auth path honors the same q-weighted negotiation as the anonymous path. Default to JSON-LD (the documented native format) when client prefers it.
  • Header matches body — at minimum, the Content-Type label should reflect what's actually in the body.

Probably both. JSON-LD is JSS's native format; Turtle should only come back when the client asks for it.

Why it matters

Clients that do if (contentType.includes('json')) JSON.parse(body) get a parse error on perfectly conformant requests. The mislabel is the worst part — a sniff (e.g. "first non-whitespace char is { or @") can route around it, but every consumer shouldn't have to.

Environment

  • jss 0.0.155 (latest published)
  • node v24.5.0
  • Linux x86_64

Likely a divergence between two response paths inside the auth middleware vs. the anonymous handler. Happy to look at the conneg layer if you want a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions