Module: RelatonDoi::Crossref

Extended by:
Crossref
Included in:
Crossref
Defined in:
lib/relaton_doi/crossref.rb

Constant Summary collapse

HEADER =
{
  "User-Agent" => "Relaton/RelatonDoi (https://www.relaton.org/guides/doi/; mailto:open.source@ribose.com)"
}.freeze
MAX_REDIRECTS =
5

Instance Method Summary collapse

Instance Method Details

#get(doi) ⇒ RelatonBib::BibliographicItem, ...

Get a document by DOI from the CrossRef API.

Parameters:

  • doi (String)

    The DOI.

Returns:

  • (RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem, RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliographicItem)

    The bibitem.



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/relaton_doi/crossref.rb', line 23

def get(doi)
  Util.info "Fetching from search.crossref.org ...", key: doi
  id = doi.sub(%r{^doi:}, "")
  message = get_by_id id
  if message
    Util.info "Found: `#{message['DOI']}`", key: doi
    Parser.parse message
  else
    Util.info "Not found.", key: doi
    nil
  end
end

#get_by_id(id) ⇒ Hash

Get a document by DOI from the CrossRef API.

Parameters:

  • id (String)

    The DOI.

Returns:

  • (Hash)

    The document.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/relaton_doi/crossref.rb', line 43

def get_by_id(id) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
  n = 0
  redirects = 0
  url = "https://api.crossref.org/works/#{CGI.escape(id)}"
  loop do
    resp = Faraday.get url, nil, HEADER
    case resp.status
    when 200
      work = JSON.parse resp.body
      return work["message"] if work["status"] == "ok"
    when 404 then return nil
    when 301, 302
      raise RelatonBib::RequestError, "Crossref error: too many redirects" if redirects >= MAX_REDIRECTS

      location = resp.headers["location"] || resp.headers["Location"]
      raise RelatonBib::RequestError, "Crossref error: redirect without Location" if location.nil? || location.empty?

      url = URI.join(url, location).to_s
      redirects += 1
      next
    end

    if n > 1
      raise RelatonBib::RequestError, "Crossref error: #{resp.body}"
    end

    n += 1
    sleep resp.headers["x-rate-limit-interval"].to_i * n
  end
end