diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ab67c97..1941c9b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,7 +11,7 @@ jobs:
steps:
- name: Check out repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
@@ -24,7 +24,7 @@ jobs:
- name: Upload artifacts
if: ${{ always() }}
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
- name: artifacts
+ name: artifacts-${{ matrix.os }}-${{ matrix.ruby }}
path: artifacts/**
diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml
index ea6c856..55444c7 100644
--- a/.github/workflows/gem-push.yml
+++ b/.github/workflows/gem-push.yml
@@ -13,7 +13,7 @@ jobs:
packages: write
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
diff --git a/CHANGES.md b/CHANGES.md
index 0619781..febeb5a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,8 @@
+# 0.4.3 (2025-11-04)
+
+- BerkeleyLibrary::AV::Metadata::Readers:TIND now uses the /api/v1/search endpoint to retrieve records. The public /search endpoint stopped working for non-browser/human clients in the past week due to TIND changes.
+- BerkeleyLibrary::AV::Util#do_get sources the TIND API key from ENV['LIT_TIND_API_KEY'] if it's set.
+
# 0.4.2 (2024-10-10)
- Add TRANSCRIPTS to `AV::METADATA::FIELDS`
@@ -18,7 +23,7 @@
- `Metadata#player_link_text`
- `Metadata#player_url`
- Remove the following constants:
- - `AV::Constants::RESTRICTIONS_CALNET`
+ - `AV::Constants::RESTRICTIONS_CALNET`
- `AV::Constants::RESTRICTIONS_UCB_IP`
- `AV::Constants::RESTRICTIONS`
- `AV::Constants::RESTRICTIONS_NONE`
diff --git a/lib/berkeley_library/av/core/module_info.rb b/lib/berkeley_library/av/core/module_info.rb
index 52601ae..dad1b11 100644
--- a/lib/berkeley_library/av/core/module_info.rb
+++ b/lib/berkeley_library/av/core/module_info.rb
@@ -8,7 +8,7 @@ class ModuleInfo
SUMMARY = 'UC Berkeley Library audio/video core code'.freeze
DESCRIPTION = 'Gem for UC Berkeley Library shared audio/video code'.freeze
LICENSE = 'MIT'.freeze
- VERSION = '0.4.2'.freeze
+ VERSION = '0.4.3'.freeze
HOMEPAGE = 'https://github.com/BerkeleyLibrary/av-core'.freeze
private_class_method :new
diff --git a/lib/berkeley_library/av/metadata/readers/tind.rb b/lib/berkeley_library/av/metadata/readers/tind.rb
index 3f58a9f..81d092b 100644
--- a/lib/berkeley_library/av/metadata/readers/tind.rb
+++ b/lib/berkeley_library/av/metadata/readers/tind.rb
@@ -22,9 +22,9 @@ def marc_uri_for(record_id)
id_field = id_field_for(record_id)
query_string = URI.encode_www_form(
'p' => "#{id_field}:\"#{record_id}\"",
- 'of' => 'xm'
+ 'format' => 'xml'
)
- URIs.append(base_uri, 'search', '?', query_string)
+ URIs.append(base_uri, 'api/v1/search', '?', query_string)
end
protected
diff --git a/lib/berkeley_library/av/util.rb b/lib/berkeley_library/av/util.rb
index 02ba827..5df9333 100644
--- a/lib/berkeley_library/av/util.rb
+++ b/lib/berkeley_library/av/util.rb
@@ -12,7 +12,11 @@ module Util
DEFAULT_USER_AGENT = "#{Core::ModuleInfo::NAME} #{Core::ModuleInfo::VERSION} (#{Core::ModuleInfo::HOMEPAGE})".freeze
def do_get(uri, ignore_errors: false)
- body = URIs.get(uri, headers: { user_agent: DEFAULT_USER_AGENT })
+ headers = { user_agent: DEFAULT_USER_AGENT }
+ if uri.to_s.start_with?(BerkeleyLibrary::AV::Config.tind_base_uri.to_s) && ENV['LIT_TIND_API_KEY']
+ headers[:authorization] = "Token #{ENV['LIT_TIND_API_KEY']}"
+ end
+ body = URIs.get(uri, headers:)
body && body.scrub
rescue RestClient::Exception
raise unless ignore_errors
diff --git a/spec/lib/berkeley_library/av/metadata/metadata_spec.rb b/spec/lib/berkeley_library/av/metadata/metadata_spec.rb
index 62aa563..9e50700 100644
--- a/spec/lib/berkeley_library/av/metadata/metadata_spec.rb
+++ b/spec/lib/berkeley_library/av/metadata/metadata_spec.rb
@@ -183,7 +183,7 @@ module AV
it 'injects a TIND URL if not present (1/2)' do
tind_035 = '(miscmat)00615'
marc_xml = File.read("spec/data/record-#{tind_035}.xml")
- search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
+ search_url = "https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&format=xml"
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
metadata = Metadata.for_record(record_id: tind_035)
@@ -200,7 +200,7 @@ module AV
it 'injects a TIND URL if not present (2/2)' do
tind_035 = 'physcolloquia-bk00169017b'
marc_xml = File.read("spec/data/record-#{tind_035}.xml")
- search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
+ search_url = "https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&format=xml"
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
metadata = Metadata.for_record(record_id: tind_035)
@@ -218,7 +218,7 @@ module AV
it 'works for TIND records with OskiCat URLs' do
tind_035 = '(pacradio)00107'
marc_xml = File.read("spec/data/record-#{tind_035}.xml")
- search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
+ search_url = "https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&format=xml"
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
metadata = Metadata.for_record(record_id: tind_035)
@@ -239,7 +239,7 @@ module AV
it 'works for TIND-only records' do
tind_035 = 'physcolloquia-bk00169017b'
marc_xml = File.read("spec/data/record-#{tind_035}.xml")
- search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
+ search_url = "https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&format=xml"
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
metadata = Metadata.for_record(record_id: tind_035)
@@ -259,7 +259,7 @@ module AV
it 'returns the values' do
tind_035 = 'physcolloquia-bk00169017b'
marc_xml = File.read("spec/data/record-#{tind_035}.xml")
- search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
+ search_url = "https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&format=xml"
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
metadata = Metadata.for_record(record_id: tind_035)
diff --git a/spec/lib/berkeley_library/av/metadata/source_spec.rb b/spec/lib/berkeley_library/av/metadata/source_spec.rb
index e7eaca6..829e1fa 100644
--- a/spec/lib/berkeley_library/av/metadata/source_spec.rb
+++ b/spec/lib/berkeley_library/av/metadata/source_spec.rb
@@ -161,7 +161,7 @@ class Metadata
before do
AV::Config.tind_base_uri = 'https://digicoll.lib.berkeley.edu'
- @record_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2900107%22&of=xm'
+ @record_url = 'https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22%28pacradio%2900107%22&format=xml'
end
after do
diff --git a/spec/lib/berkeley_library/av/record_spec.rb b/spec/lib/berkeley_library/av/record_spec.rb
index 5ca77c1..562ccb4 100644
--- a/spec/lib/berkeley_library/av/record_spec.rb
+++ b/spec/lib/berkeley_library/av/record_spec.rb
@@ -46,7 +46,7 @@ module AV
it 'returns a player URI based on the record ID for TIND records' do
tind_035 = '(pacradio)01469'
marc_xml = File.read("spec/data/record-#{tind_035}.xml")
- search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
+ search_url = "https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&format=xml"
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
collection = 'Pacifica'
@@ -145,7 +145,7 @@ module AV
it 'returns the TIND ID for TIND records' do
marc_xml = File.read('spec/data/record-(pacradio)01469.xml')
- search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2901469%22&of=xm'
+ search_url = 'https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22%28pacradio%2901469%22&format=xml'
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
record = Record.from_metadata(
@@ -168,7 +168,7 @@ module AV
it 'returns nil for TIND records with no bib number' do
tind_id = '(clir)00020'
marc_xml = File.read('spec/data/record-(clir)00020.xml')
- search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28clir%2900020%22&of=xm'
+ search_url = 'https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22%28clir%2900020%22&format=xml'
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
record = Record.from_metadata(collection: 'Video-Public-Bancroft', record_id: tind_id)
@@ -179,7 +179,7 @@ module AV
describe :from_metadata do
it 'loads the metadata' do
marc_xml = File.read('spec/data/record-(pacradio)01469.xml')
- search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2901469%22&of=xm'
+ search_url = 'https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22%28pacradio%2901469%22&format=xml'
stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
record = Record.from_metadata(collection: 'Pacifica', record_id: '(pacradio)01469')
@@ -223,7 +223,7 @@ module AV
end
it "raises #{AV::RecordNotFound} if the record cannot be found" do
- search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2901469%22&of=xm'
+ search_url = 'https://digicoll.lib.berkeley.edu/api/v1/search?p=035__a%3A%22%28pacradio%2901469%22&format=xml'
stub_request(:get, search_url).to_return(status: 404)
expect do
Record.from_metadata(
diff --git a/spec/lib/berkeley_library/av/util_spec.rb b/spec/lib/berkeley_library/av/util_spec.rb
index 31e5f2c..5fd6249 100644
--- a/spec/lib/berkeley_library/av/util_spec.rb
+++ b/spec/lib/berkeley_library/av/util_spec.rb
@@ -24,6 +24,32 @@ module AV
result = AV::Util.do_get(url, ignore_errors: true)
expect(result).to be_nil
end
+
+ it 'includes authorization header for TIND requests if LIT_TIND_API_KEY is set' do
+ expected_ua = Util::DEFAULT_USER_AGENT
+ expected_auth = 'Token some-long-api-token-value'
+
+ # expect do_get to call URIs.get with the correct headers
+ # but we don't need to actually perform the request
+ allow(BerkeleyLibrary::Util::URIs).to receive(:get).and_return('')
+ allow(AV::Config).to receive(:tind_base_uri).and_return(URI('https://tind.example.edu/'))
+ url = "#{AV::Config.tind_base_uri}/some/api/endpoint"
+ ENV['LIT_TIND_API_KEY'] = 'some-long-api-token-value'
+ AV::Util.do_get(url)
+ expect(BerkeleyLibrary::Util::URIs).to have_received(:get).with(url, headers: { user_agent: expected_ua, authorization: expected_auth })
+ end
+
+ it 'does not include authorization header for non-TIND requests' do
+ expected_ua = Util::DEFAULT_USER_AGENT
+
+ # expect do_get to call URIs.get with the correct headers
+ # but we don't need to actually perform the request
+ allow(BerkeleyLibrary::Util::URIs).to receive(:get).and_return('')
+ url = URI('https://alma.example.edu/some/api/endpoint')
+ ENV['LIT_TIND_API_KEY'] = nil
+ AV::Util.do_get(url)
+ expect(BerkeleyLibrary::Util::URIs).to have_received(:get).with(url, headers: { user_agent: expected_ua })
+ end
end
end
end