Skip to content

Commit

Permalink
Make IIIF canvases and annotations resolvable over HTTP using a more …
Browse files Browse the repository at this point in the history
…permanent url scheme
  • Loading branch information
cbeer committed Jan 19, 2017
1 parent 88c9631 commit c78c35d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 13 deletions.
30 changes: 29 additions & 1 deletion app/controllers/purl_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def show
end
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity

def manifest
return unless stale?(last_modified: @purl.updated_at.utc, etag: @purl.cache_key + "/#{@purl.updated_at.utc}")
Expand All @@ -61,6 +60,35 @@ def manifest
end
end

def canvas
return unless stale?(last_modified: @purl.updated_at.utc, etag: @purl.cache_key + "/#{@purl.updated_at.utc}")

if @purl.iiif_manifest?
manifest = Rails.cache.fetch([@purl, @purl.updated_at.utc], expires_in: Settings.resource_cache.lifetime) do
@purl.iiif_manifest.canvas(controller: self, resource_id: params[:resource_id]).to_ordered_hash
end

render json: manifest
else
head :not_found
end
end

def annotation
return unless stale?(last_modified: @purl.updated_at.utc, etag: @purl.cache_key + "/#{@purl.updated_at.utc}")

if @purl.iiif_manifest?
manifest = Rails.cache.fetch([@purl, @purl.updated_at.utc], expires_in: Settings.resource_cache.lifetime) do
@purl.iiif_manifest.annotation(controller: self, annotation_id: params[:annotation_id]).to_ordered_hash
end

render json: manifest
else
head :not_found
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity

private

# validate that the id is of the proper format
Expand Down
43 changes: 32 additions & 11 deletions app/models/iiif_presentation_manifest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,32 +89,54 @@ def body(controller = nil)
manifest.thumbnail = thumbnail_resource

# for each resource image, create a canvas
page_images.each_with_index do |resource, count|
page_images.each do |resource|
next unless purl_resource.rights.world_rights_for_file(resource.filename).first ||
purl_resource.rights.stanford_only_rights_for_file(resource.filename).first

sequence.canvases << canvas_for_resource(purl_base_uri, resource, count)
sequence.canvases << canvas_for_resource(purl_base_uri, resource)
end

manifest.sequences << sequence
manifest
end

##
# @param [Integer] count This is the i_th (image) resource
def canvas_for_resource(purl_base_uri, resource, count)
url = stacks_iiif_base_url(resource.druid, resource.filename)
def canvas(controller: nil, resource_id:)
controller ||= Rails.application.routes.url_helpers
purl_base_uri = controller.purl_url(druid)

resource = page_images.find { |image| image.id == resource_id }

canvas_for_resource(purl_base_uri, resource)
end

def annotation(controller: nil, annotation_id:)
controller ||= Rails.application.routes.url_helpers
purl_base_uri = controller.purl_url(druid)

resource = page_images.find { |image| image.id == annotation_id }

annotation_for_resource(purl_base_uri, resource)
end

def canvas_for_resource(purl_base_uri, resource)
canv = IIIF::Presentation::Canvas.new
canv['@id'] = "#{purl_base_uri}/iiif/canvas-#{count}"
canv['@id'] = "#{purl_base_uri}/iiif/canvas/#{resource.id}"
canv.label = resource.label
canv.label = 'image' unless canv.label.present?
canv.height = resource.height
canv.width = resource.width

anno = IIIF::Presentation::Annotation.new
anno['@id'] = "#{purl_base_uri}/iiif/anno-#{count}"
anno = annotation_for_resource(purl_base_uri, resource)
anno['on'] = canv['@id']
canv.images << anno
canv
end

def annotation_for_resource(purl_base_uri, resource)
url = stacks_iiif_base_url(resource.druid, resource.filename)

anno = IIIF::Presentation::Annotation.new
anno['@id'] = "#{purl_base_uri}/iiif/annotation/#{resource.id}"

img_res = IIIF::Presentation::ImageResource.new
img_res['@id'] = "#{url}/full/full/0/default.jpg"
Expand All @@ -139,8 +161,7 @@ def canvas_for_resource(purl_base_uri, resource, count)
end

anno.resource = img_res
canv.images << anno
canv
anno
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

Expand Down
4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@

get ':id' => 'purl#show', as: :purl
get ':id/embed', to: redirect("/iframe/?url=#{Settings.embed.url % { druid: '%{id}' }}")
get '/:id/iiif/manifest.json' => 'purl#manifest', as: :iiif_manifest
get '/:id/iiif/manifest' => 'purl#manifest', as: :iiif_manifest
get '/:id/iiif/canvas/:resource_id' => 'purl#canvas', as: :iiif_canvas
get '/:id/iiif/annotation/:annotation_id' => 'purl#annotation', as: :iiif_annotation
end
24 changes: 24 additions & 0 deletions spec/integration/purl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@
end
end

describe 'canvas' do
it 'renders the json for manifest' do
visit "/#{@manifest_object}/iiif/canvas/bc854fy5899_1.json"
json_body = JSON.parse(page.body)
expect(json_body['label']).to eq('John Wyclif and his followers, Tracts in Middle English')
end
it 'renders nil for a non-manifest' do
visit "/#{@file_object}/iiif/canvas/bc854fy5899_fdsa.json"
expect(page.status_code).to eq(404)
end
end

describe 'annotation' do
it 'renders the json for manifest' do
visit "/#{@manifest_object}/iiif/annotation/bc854fy5899_1.json"
json_body = JSON.parse(page.body)
expect(json_body['label']).to eq('John Wyclif and his followers, Tracts in Middle English')
end
it 'renders nil for a non-manifest' do
visit "/#{@file_object}/iiif/annotation/bc854fy5899_fdsa.json"
expect(page.status_code).to eq(404)
end
end

context 'incomplete/unpublished object (not in stacks)' do
it 'gives 404 with unavailable message' do
visit "/#{@unpublished_object}"
Expand Down

0 comments on commit c78c35d

Please sign in to comment.