From 91162ae2e5f552b5de5029fdede43bfd6e0cfc98 Mon Sep 17 00:00:00 2001 From: Martin Fenner Date: Sat, 1 Sep 2018 10:01:12 +0200 Subject: [PATCH] support content-negotiation via link. #108 --- config/routes.rb | 10 ++ .../returns_status_code_200.yml | 73 +++++++++ .../default_style_link/returns_the_Doi.yml | 73 +++++++++ .../returns_status_code_200.yml | 72 +++++++++ .../ieee_style_link/returns_the_Doi.yml | 72 +++++++++ spec/requests/index_spec.rb | 145 ++++++++++++++++++ 6 files changed, 445 insertions(+) create mode 100644 spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_status_code_200.yml create mode 100644 spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_the_Doi.yml create mode 100644 spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_status_code_200.yml create mode 100644 spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_the_Doi.yml diff --git a/config/routes.rb b/config/routes.rb index 366300c96..c8b557710 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -62,6 +62,16 @@ resources :data_centers, only: [:show, :index], constraints: { :id => /.+/ }, path: "/data-centers" # content negotiation + get '/application/vnd.datacite.datacite+xml/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :datacite } + get '/application/vnd.datacite.datacite+json/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :datacite_json } + get '/application/vnd.crosscite.crosscite+json/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :crosscite } + get '/application/vnd.schemaorg.ld+json/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :schema_org } + get '/application/vnd.codemeta.ld+json/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :codemeta } + get '/application/vnd.citationstyles.csl+json/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :citeproc } + get '/application/vnd.jats+xml/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :jats } + get '/application/x-bibtex/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :bibtex } + get '/application/x-research-info-systems/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :ris } + get '/text/x-bibliography/:id', :to => 'index#show', constraints: { :id => /.+/ }, defaults: { format: :citation } resources :index, path: '/', constraints: { :id => /.+/ }, only: [:show, :index] # rescue routing errors diff --git a/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_status_code_200.yml b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_status_code_200.yml new file mode 100644 index 000000000..3f98ae712 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_status_code_200.yml @@ -0,0 +1,73 @@ +--- +http_interactions: +- request: + method: post + uri: https://citation.crosscite.org/format?locale=en-US&style=apa + body: + encoding: UTF-8 + string: |- + { + "type": "article-journal", + "id": "https://handle.test.datacite.org/10.14454/ye3y6b9atvzgt1", + "categories": [ + "datacite", + "doi", + "metadata" + ], + "author": [ + { + "family": "Fenner", + "given": "Martin" + } + ], + "issued": { + "date-parts": [ + [ + 2016, + 12, + 20 + ] + ] + }, + "abstract": "Eating your own dog food is a slang term to describe that an organization should itself use the products and services it provides. For DataCite this means that we should use DOIs with appropriate metadata and strategies for long-term preservation for...", + "DOI": "10.14454/YE3Y6B9ATVZGT1", + "publisher": "DataCite", + "title": "Eating your own Dog Food", + "version": "1.0" + } + headers: + User-Agent: + - Mozilla/5.0 (compatible; Maremma/4.1.1; +https://github.com/datacite/maremma) + Content-Type: + - application/json;charset=UTF-8 + Accept: + - text/html,application/json,application/xml;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5 + response: + status: + code: 200 + message: OK + headers: + Date: + - Sat, 01 Sep 2018 07:58:18 GMT + Content-Type: + - text/plain + Connection: + - keep-alive + Status: + - 200 OK + X-Powered-By: + - Phusion Passenger 5.2.3 + Server: + - nginx/1.12.2 + Phusion Passenger 5.2.3 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Headers: + - Content-Type,Accept,Accept-Encoding,Origin,User-Agent,Cache-Control,Keep-Alive + body: + encoding: ASCII-8BIT + string: 'Fenner, M. (2016). Eating your own Dog Food (Version 1.0). https://doi.org/10.14454/YE3Y6B9ATVZGT1 + +' + http_version: + recorded_at: Sat, 01 Sep 2018 07:58:18 GMT +recorded_with: VCR 3.0.3 diff --git a/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_the_Doi.yml b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_the_Doi.yml new file mode 100644 index 000000000..f6dbeaa10 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/default_style_link/returns_the_Doi.yml @@ -0,0 +1,73 @@ +--- +http_interactions: +- request: + method: post + uri: https://citation.crosscite.org/format?locale=en-US&style=apa + body: + encoding: UTF-8 + string: |- + { + "type": "article-journal", + "id": "https://handle.test.datacite.org/10.14454/yqzokpgyfddvly9", + "categories": [ + "datacite", + "doi", + "metadata" + ], + "author": [ + { + "family": "Fenner", + "given": "Martin" + } + ], + "issued": { + "date-parts": [ + [ + 2016, + 12, + 20 + ] + ] + }, + "abstract": "Eating your own dog food is a slang term to describe that an organization should itself use the products and services it provides. For DataCite this means that we should use DOIs with appropriate metadata and strategies for long-term preservation for...", + "DOI": "10.14454/YQZOKPGYFDDVLY9", + "publisher": "DataCite", + "title": "Eating your own Dog Food", + "version": "1.0" + } + headers: + User-Agent: + - Mozilla/5.0 (compatible; Maremma/4.1.1; +https://github.com/datacite/maremma) + Content-Type: + - application/json;charset=UTF-8 + Accept: + - text/html,application/json,application/xml;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5 + response: + status: + code: 200 + message: OK + headers: + Date: + - Sat, 01 Sep 2018 07:58:18 GMT + Content-Type: + - text/plain + Connection: + - keep-alive + Status: + - 200 OK + X-Powered-By: + - Phusion Passenger 5.2.3 + Server: + - nginx/1.12.2 + Phusion Passenger 5.2.3 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Headers: + - Content-Type,Accept,Accept-Encoding,Origin,User-Agent,Cache-Control,Keep-Alive + body: + encoding: ASCII-8BIT + string: 'Fenner, M. (2016). Eating your own Dog Food (Version 1.0). https://doi.org/10.14454/YQZOKPGYFDDVLY9 + +' + http_version: + recorded_at: Sat, 01 Sep 2018 07:58:18 GMT +recorded_with: VCR 3.0.3 diff --git a/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_status_code_200.yml b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_status_code_200.yml new file mode 100644 index 000000000..e17cc1579 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_status_code_200.yml @@ -0,0 +1,72 @@ +--- +http_interactions: +- request: + method: post + uri: https://citation.crosscite.org/format?locale=en-US&style=ieee + body: + encoding: UTF-8 + string: |- + { + "type": "article-journal", + "id": "https://handle.test.datacite.org/10.14454/wvac367ocurdntx", + "categories": [ + "datacite", + "doi", + "metadata" + ], + "author": [ + { + "family": "Fenner", + "given": "Martin" + } + ], + "issued": { + "date-parts": [ + [ + 2016, + 12, + 20 + ] + ] + }, + "abstract": "Eating your own dog food is a slang term to describe that an organization should itself use the products and services it provides. For DataCite this means that we should use DOIs with appropriate metadata and strategies for long-term preservation for...", + "DOI": "10.14454/WVAC367OCURDNTX", + "publisher": "DataCite", + "title": "Eating your own Dog Food", + "version": "1.0" + } + headers: + User-Agent: + - Mozilla/5.0 (compatible; Maremma/4.1.1; +https://github.com/datacite/maremma) + Content-Type: + - application/json;charset=UTF-8 + Accept: + - text/html,application/json,application/xml;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5 + response: + status: + code: 200 + message: OK + headers: + Date: + - Sat, 01 Sep 2018 07:58:19 GMT + Content-Type: + - text/plain + Connection: + - keep-alive + Status: + - 200 OK + X-Powered-By: + - Phusion Passenger 5.2.3 + Server: + - nginx/1.12.2 + Phusion Passenger 5.2.3 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Headers: + - Content-Type,Accept,Accept-Encoding,Origin,User-Agent,Cache-Control,Keep-Alive + body: + encoding: ASCII-8BIT + string: !binary |- + WzFdTS4gRmVubmVyLCDigJhFYXRpbmcgeW91ciBvd24gRG9nIEZvb2TigJksIERlYy4gMjAxNi4K + http_version: + recorded_at: Sat, 01 Sep 2018 07:58:19 GMT +recorded_with: VCR 3.0.3 diff --git a/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_the_Doi.yml b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_the_Doi.yml new file mode 100644 index 000000000..00fbe5651 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/content_negotation/text/x-bibliography/ieee_style_link/returns_the_Doi.yml @@ -0,0 +1,72 @@ +--- +http_interactions: +- request: + method: post + uri: https://citation.crosscite.org/format?locale=en-US&style=ieee + body: + encoding: UTF-8 + string: |- + { + "type": "article-journal", + "id": "https://handle.test.datacite.org/10.14454/nofsl19iw8", + "categories": [ + "datacite", + "doi", + "metadata" + ], + "author": [ + { + "family": "Fenner", + "given": "Martin" + } + ], + "issued": { + "date-parts": [ + [ + 2016, + 12, + 20 + ] + ] + }, + "abstract": "Eating your own dog food is a slang term to describe that an organization should itself use the products and services it provides. For DataCite this means that we should use DOIs with appropriate metadata and strategies for long-term preservation for...", + "DOI": "10.14454/NOFSL19IW8", + "publisher": "DataCite", + "title": "Eating your own Dog Food", + "version": "1.0" + } + headers: + User-Agent: + - Mozilla/5.0 (compatible; Maremma/4.1.1; +https://github.com/datacite/maremma) + Content-Type: + - application/json;charset=UTF-8 + Accept: + - text/html,application/json,application/xml;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5 + response: + status: + code: 200 + message: OK + headers: + Date: + - Sat, 01 Sep 2018 07:58:18 GMT + Content-Type: + - text/plain + Connection: + - keep-alive + Status: + - 200 OK + X-Powered-By: + - Phusion Passenger 5.2.3 + Server: + - nginx/1.12.2 + Phusion Passenger 5.2.3 + Access-Control-Allow-Origin: + - "*" + Access-Control-Allow-Headers: + - Content-Type,Accept,Accept-Encoding,Origin,User-Agent,Cache-Control,Keep-Alive + body: + encoding: ASCII-8BIT + string: !binary |- + WzFdTS4gRmVubmVyLCDigJhFYXRpbmcgeW91ciBvd24gRG9nIEZvb2TigJksIERlYy4gMjAxNi4K + http_version: + recorded_at: Sat, 01 Sep 2018 07:58:18 GMT +recorded_with: VCR 3.0.3 diff --git a/spec/requests/index_spec.rb b/spec/requests/index_spec.rb index f1e66d079..592d7423f 100644 --- a/spec/requests/index_spec.rb +++ b/spec/requests/index_spec.rb @@ -47,6 +47,22 @@ end end + context "application/vnd.jats+xml link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/vnd.jats+xml/#{doi.doi}" } + + it 'returns the Doi' do + jats = Maremma.from_xml(response.body).fetch("element_citation", {}) + expect(jats.dig("publication_type")).to eq("journal") + expect(jats.dig("article_title")).to eq("Eating your own Dog Food") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/vnd.datacite.datacite+xml" do before { get "/#{doi.doi}", headers: { "HTTP_ACCEPT" => "application/vnd.datacite.datacite+xml", 'Authorization' => 'Bearer ' + bearer } } @@ -62,6 +78,23 @@ end end + context "application/vnd.datacite.datacite+xml link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/vnd.datacite.datacite+xml/#{doi.doi}" } + + it 'returns the Doi' do + data = Maremma.from_xml(response.body).to_h.fetch("resource", {}) + expect(data.dig("xmlns")).to eq("http://datacite.org/schema/kernel-4") + expect(data.dig("publisher")).to eq("DataCite") + expect(data.dig("titles", "title")).to eq("Eating your own Dog Food") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/vnd.datacite.datacite+xml schema 3" do let(:xml) { Base64.strict_encode64(file_fixture('datacite_schema_3.xml').read) } let(:doi) { create(:doi, xml: xml, client: client) } @@ -118,6 +151,20 @@ end end + context "application/vnd.datacite.datacite+json link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/vnd.datacite.datacite+json/#{doi.doi}" } + + it 'returns the Doi' do + expect(json["doi"]).to eq(doi.doi) + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/vnd.crosscite.crosscite+json" do before { get "/#{doi.doi}", headers: { "HTTP_ACCEPT" => "application/vnd.crosscite.crosscite+json", 'Authorization' => 'Bearer ' + bearer } } @@ -130,6 +177,20 @@ end end + context "application/vnd.crosscite.crosscite+json link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/vnd.crosscite.crosscite+json/#{doi.doi}" } + + it 'returns the Doi' do + expect(json["doi"]).to eq(doi.doi) + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/vnd.schemaorg.ld+json" do before { get "/#{doi.doi}", headers: { "HTTP_ACCEPT" => "application/vnd.schemaorg.ld+json", 'Authorization' => 'Bearer ' + bearer } } @@ -142,6 +203,20 @@ end end + context "application/vnd.schemaorg.ld+json link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/vnd.schemaorg.ld+json/#{doi.doi}" } + + it 'returns the Doi' do + expect(json["@type"]).to eq("ScholarlyArticle") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/vnd.citationstyles.csl+json" do before { get "/#{doi.doi}", headers: { "HTTP_ACCEPT" => "application/vnd.citationstyles.csl+json", 'Authorization' => 'Bearer ' + bearer } } @@ -154,6 +229,20 @@ end end + context "application/vnd.citationstyles.csl+json link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/vnd.citationstyles.csl+json/#{doi.doi}" } + + it 'returns the Doi' do + expect(json["type"]).to eq("article-journal") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/x-research-info-systems" do before { get "/#{doi.doi}", headers: { "HTTP_ACCEPT" => "application/x-research-info-systems", 'Authorization' => 'Bearer ' + bearer } } @@ -166,6 +255,20 @@ end end + context "application/x-research-info-systems link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/x-research-info-systems/#{doi.doi}" } + + it 'returns the Doi' do + expect(response.body).to start_with("TY - RPRT") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/x-bibtex" do before { get "/#{doi.doi}", headers: { "HTTP_ACCEPT" => "application/x-bibtex", 'Authorization' => 'Bearer ' + bearer } } @@ -178,6 +281,20 @@ end end + context "application/x-bibtex link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/application/x-bibtex/#{doi.doi}" } + + it 'returns the Doi' do + expect(response.body).to start_with("@article{https://handle.test.datacite.org/#{doi.doi.downcase}") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "application/x-bibtex nasa gsfc" do let(:xml) { Base64.strict_encode64(file_fixture('datacite_gsfc.xml').read) } let(:doi) { create(:doi, xml: xml, client: client) } @@ -206,6 +323,20 @@ end end + context "default style link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/text/x-bibliography/#{doi.doi}" } + + it 'returns the Doi' do + expect(response.body).to start_with("Fenner, M. (2016)") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "ieee style" do before { get "/#{doi.doi}?style=ieee", headers: { "HTTP_ACCEPT" => "text/x-bibliography", 'Authorization' => 'Bearer ' + bearer } } @@ -218,6 +349,20 @@ end end + context "ieee style link" do + let(:doi) { create(:doi, xml: xml, client: client, aasm_state: "findable") } + + before { get "/text/x-bibliography/#{doi.doi}?style=ieee" } + + it 'returns the Doi' do + expect(response.body).to start_with("[1]M. Fenner") + end + + it 'returns status code 200' do + expect(response).to have_http_status(200) + end + end + context "style and locale" do before { get "/#{doi.doi}?style=vancouver&locale=de", headers: { "HTTP_ACCEPT" => "text/x-bibliography", 'Authorization' => 'Bearer ' + bearer } }