Skip to content
4 changes: 3 additions & 1 deletion app/controllers/index_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def show
respond_to do |format|
format.html do
# forward to URL registered in handle system for no content negotiation
redirect_to doi.url, status: :see_other
redirect_to doi.url, status: :see_other, allow_other_host: true
end
format.citation do
# extract optional style and locale from header
Expand All @@ -37,8 +37,10 @@ def show
:datacite,
:datacite_json,
:jats,
:rdf_xml,
:ris,
:schema_org,
:turtle,
) { render request.format.to_sym => doi }
header = %w[
doi
Expand Down
23 changes: 23 additions & 0 deletions app/models/doi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2826,6 +2826,29 @@ def handle_resource_type(types)
end
end

# Ensure Bolognese metadata is populated from stored DataCite XML before
# calling Bolognese RDF writers. This is local-only (no network calls).
def ensure_bolognese_meta!
return meta if meta.present?
return meta if xml.blank?

@meta = parse_xml(xml, doi: doi)
end

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

private
def update_publisher_from_hash
symbolized_publisher_hash = publisher_before_type_cast.symbolize_keys
Expand Down
10 changes: 10 additions & 0 deletions config/initializers/mime_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
Mime::Type.register "application/x-bibtex", :bibtex
Mime::Type.register "application/x-research-info-systems", :ris
Mime::Type.register "text/x-bibliography", :citation
Mime::Type.register "application/rdf+xml", :rdf_xml
Mime::Type.register "text/turtle", :turtle, %w[application/x-turtle]

# register renderers for these Mime types
# :citation and :datacite is handled differently
Expand Down Expand Up @@ -83,3 +85,11 @@
ActionController::Renderers.add :csv do |obj, options|
options[:header].to_csv + Array.wrap(obj).map { |o| o.send("csv") }.join("")
end

ActionController::Renderers.add :rdf_xml do |obj, _options|
Array.wrap(obj).map { |o| o.rdf_xml }.join("\n")
end

ActionController::Renderers.add :turtle do |obj, _options|
Array.wrap(obj).map { |o| o.turtle }.join("\n")
end
6 changes: 6 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
to: "index#show", constraints: { id: /.+/ }, defaults: { format: :bibtex }
get "/application/x-research-info-systems/:id",
to: "index#show", constraints: { id: /.+/ }, defaults: { format: :ris }
get "/application/rdf+xml/:id",
to: "index#show", constraints: { id: /.+/ }, defaults: { format: :rdf_xml }
get "/application/x-turtle/:id",
to: "index#show", constraints: { id: /.+/ }, defaults: { format: :turtle }
get "/text/turtle/:id",
to: "index#show", constraints: { id: /.+/ }, defaults: { format: :turtle }
get "/text/csv/:id",
to: "index#show", constraints: { id: /.+/ }, defaults: { format: :csv }
get "/text/x-bibliography/:id",
Expand Down
5 changes: 5 additions & 0 deletions spec/factories/doi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
"lang": "en",
}
end

trait :with_datacite_xml do
xml { file_fixture("datacite.xml").read }
end

creators do
[
{
Expand Down
98 changes: 98 additions & 0 deletions spec/requests/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

describe IndexController, type: :request do
let(:doi) { create(:doi, aasm_state: "findable") }
let(:doi_with_xml) { create(:doi, :with_datacite_xml, aasm_state: "findable") }

describe "content_negotation" do
context "application/vnd.jats+xml" do
Expand Down Expand Up @@ -337,5 +338,102 @@
expect(last_response.headers["Location"]).to eq(doi.url)
end
end

context "wildcard Accept: */*" do
it "redirects without 500" do
get "/#{doi.doi}", nil, { "HTTP_ACCEPT" => "*/*" }

expect(last_response.status).not_to eq(500)
expect([200, 302, 303]).to include(last_response.status)
end
end

context "application/rdf+xml" do
it "returns the Doi as RDF/XML" do
get "/#{doi_with_xml.doi}", nil, { "HTTP_ACCEPT" => "application/rdf+xml" }

expect(last_response.status).to eq(200)
expect(last_response.headers["Content-Type"]).to include("application/rdf+xml")
expect(last_response.body).to include("rdf:RDF")
end

it "returns 406 when RDF representation is not available" do
get "/#{doi.doi}", nil, { "HTTP_ACCEPT" => "application/rdf+xml" }

expect(last_response.status).to eq(406)
expect(json["errors"]).to eq(
[
{
"status" => "406",
"title" => "RDF representation is not available for this DOI",
},
],
)
end
end

context "application/rdf+xml link" do
it "returns the Doi as RDF/XML" do
get "/application/rdf+xml/#{doi_with_xml.doi}"

expect(last_response.status).to eq(200)
expect(last_response.headers["Content-Type"]).to include("application/rdf+xml")
expect(last_response.body).to include("rdf:RDF")
end
end

context "text/turtle" do
it "returns the Doi as Turtle" do
get "/#{doi_with_xml.doi}", nil, { "HTTP_ACCEPT" => "text/turtle" }

expect(last_response.status).to eq(200)
expect(last_response.headers["Content-Type"]).to include("text/turtle")
expect(last_response.body).to include("@prefix schema:")
end

it "returns 406 when RDF representation is not available" do
get "/#{doi.doi}", nil, { "HTTP_ACCEPT" => "text/turtle" }

expect(last_response.status).to eq(406)
expect(json["errors"]).to eq(
[
{
"status" => "406",
"title" => "RDF representation is not available for this DOI",
},
],
)
end
end

context "application/x-turtle" do
it "returns the Doi as Turtle" do
get "/#{doi_with_xml.doi}", nil, { "HTTP_ACCEPT" => "application/x-turtle" }

expect(last_response.status).to eq(200)
expect(last_response.headers["Content-Type"]).to include("turtle")
expect(last_response.body).to include("@prefix schema:")
end
end

context "text/turtle link" do
it "returns the Doi as Turtle" do
get "/text/turtle/#{doi_with_xml.doi}"

expect(last_response.status).to eq(200)
expect(last_response.headers["Content-Type"]).to include("text/turtle")
expect(last_response.body).to include("@prefix schema:")
end
end

context "application/x-turtle link" do
it "returns the Doi as Turtle" do
get "/application/x-turtle/#{doi_with_xml.doi}"

expect(last_response.status).to eq(200)
expect(last_response.headers["Content-Type"]).to include("turtle")
expect(last_response.body).to include("@prefix schema:")
end
end
end
end
Loading