Skip to content

Restore DOI content-negotiation redirect parity for wildcard and XML/RDF/Turtle Accept headers#1528

Closed
Copilot wants to merge 2 commits into
masterfrom
copilot/update-content-negotiation-parity
Closed

Restore DOI content-negotiation redirect parity for wildcard and XML/RDF/Turtle Accept headers#1528
Copilot wants to merge 2 commits into
masterfrom
copilot/update-content-negotiation-parity

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 13, 2026

This updates DOI content negotiation to match current DataCite CN parity for unsupported XML/RDF/Turtle-style Accept headers. Requests with */*, application/xml, application/rdf+xml, text/turtle, and application/x-turtle now redirect to doi.url instead of attempting to render a body or failing with 500.

  • Controller behavior

    • Treat unregistered/unknown negotiated formats as redirect cases before respond_to
    • Keep 303 See Other redirect behavior
    • Preserve safe cross-site redirect handling with allow_other_host: true
  • Parity-aligned Accept handling

    • Accept: */* no longer falls into a 500 path
    • Accept: application/xml
    • Accept: application/rdf+xml
    • Accept: text/turtle
    • Accept: application/x-turtle
    • All now resolve to redirect behavior rather than RDF/XML or Turtle rendering
  • Specs

    • Add request coverage asserting redirect behavior for the headers above
    • Leave existing supported content types unchanged
def show
  # ...
  if request.format.symbol.nil?
    redirect_to_doi(doi)
    return
  end

  respond_to do |format|
    format.html { redirect_to_doi(doi) }
    # supported formats unchanged
  end
rescue ActionController::UnknownFormat, ActionController::RoutingError
  redirect_to_doi(doi)
end
Original prompt

Update PR #1518 in repository datacite/lupo to match current DataCite Content Negotiation (CN) parity behavior.

Context / desired parity:

  • Current CN behavior for https://api.datacite.org/[doi] with Accept headers like application/xml, application/rdf+xml, and text/turtle is a 303 See Other redirect (not a 200 response with RDF/Turtle bodies).
  • Current production returns 500 for Accept: /; treat that as a bug and fix it in Lupo.
  • Lupo should NOT generate RDF/XML or Turtle bodies in this PR. RDF/XML/Turtle output may be a future feature.
  • doi.graph can be nil; do not call graph.dump(...) via rdf/turtle renderers.

Required changes:

  1. Keep wildcard Accept handling: Accept: / must NOT return 500 and should fall back to normal redirect behavior (302/303 acceptable, prefer 303). Keep redirect safety (allow_other_host: true).
  2. Ensure Accept: application/xml, application/rdf+xml, text/turtle, application/x-turtle all redirect like CN: status 303 See Other with Location header set to doi.url. Do not render bodies.
  3. Remove RDF/Turtle support introduced by this PR:
    • Remove MIME registrations for application/rdf+xml and text/turtle/application/x-turtle.
    • Remove ActionController renderers for :rdf_xml and :turtle.
    • Remove link-form routes for RDF/Turtle (/application/rdf+xml/:id, /text/turtle/:id, /application/x-turtle/:id).
    • Remove controller wiring that renders :rdf_xml or :turtle.
    • Remove Doi model methods ensure_bolognese_meta!, rdf_xml, turtle (and any RDF-related meta population added for this).
  4. Update specs:
    • Remove specs expecting 200 for RDF/XML/Turtle and any body expectations (rdf:RDF, @Prefix schema:).
    • Add/update specs asserting redirect behavior for Accept: application/xml, application/rdf+xml, text/turtle, application/x-turtle.
    • Keep/add spec for Accept: / asserting no 500 and redirect.
    • Do not require DOI fixture to have non-nil graph to pass parity tests.

Notes:

  • The existing unsafe redirect fix in IndexController#show format.html should be kept.
  • Keep allow_other_host: true for redirects.
  • Keep behavior for existing supported formats (datacite XML/JSON, schemaorg, etc.) unchanged.

Acceptance criteria:

  • Request specs should reflect redirect parity for the formats above.
  • Wildcard Accept should not return 500.
  • No RDF/Turtle bodies are generated or rendered in controller/renderers.
  • All tests pass.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: i have not applied crosssite solution

Assistant: Apply the Crosscitable require fix; that’s the single change that consistently eliminates NameError: uninitialized constant JSON::LD::Context in your request-spec runtime (where initializers weren’t reliably helping).

1) Update app/models/concerns/crosscitable.rb

Add these requires at the very top of the file (before the module definition). This guarantees the constants bolognese references are loaded whenever Doi is loaded.

# frozen_string_literal: true

# Ensure RDF + JSON-LD dependencies used by Bolognese::MetadataUtils#graph are loaded
# in all runtimes (incl. request specs where initializers may not be executed).
require "rdf"
require "json/ld"
require "json/ld/context"
require "json/ld/api"

# Ensure RDF::Graph#dump supports the serialization formats used by bolognese writers
require "rdf/rdfxml"
require "rdf/turtle"

module Crosscitable
  extend ActiveSupport::Concern

  included do
    include Bolognese::MetadataUtils
    # ... keep the rest of your existing includes/code here unchanged ...
  end

  # ... rest of the file unchanged ...
end

Notes:

  • If your file already has # frozen_string_literal: true, keep it once.
  • If the file already starts with other requires, place these with them.
  • If require "rdf/rdfxml" raises LoadError, you’ll need to add gem rdf-rdfxml to the Gemfile. Try first.

2) Remove any temporary “debug graph” monkeypatches

Delete any initializer or override you added that redefines Bolognese::MetadataUtils#graph to “not rescue NameError”. That debug code will now cause 500s and is no longer needed.

3) Keep Doi#rdf_xml and #turtle returning 406 when graph can’t be built

Make sure you have (or revert to) this:

def rdf_xml
  ensure_bolognese_meta!
  raise ActionController::UnknownFormat, "RDF representation is not available for this DOI" if graph.nil?
  super
end

def turtle
  ensure_bolognese_meta!
  raise ActionController::UnknownFormat, "RDF representation is not available for this DOI" if graph.nil?
  super
end

4) Re-run the failing specs

bundle exec rspec spec/requests/index_spec.rb:351

If it still fails after this, paste the new failure output; at that point the most likely remaining issue will be either:

  • missing rdf-rdfxml gem (LoadError from rdf/rdfxml), or
  • the...

This pull request was created from Copilot chat.

…ders

Agent-Logs-Url: https://github.com/datacite/lupo/sessions/2f1737e6-3f1e-4b0f-a444-096fd3046d3b

Co-authored-by: ashwinisukale <1137325+ashwinisukale@users.noreply.github.com>
Copilot AI changed the title [WIP] Update PR to match current DataCite Content Negotiation parity behavior Restore DOI content-negotiation redirect parity for wildcard and XML/RDF/Turtle Accept headers May 13, 2026
Copilot AI requested a review from ashwinisukale May 13, 2026 10:41
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.

2 participants