Purpose: Motivation is that we want to maintain SEO through this transition. We want people who find our content on Google Scholar or have saved links (on their own site or bookmarks) to continue for some period of time after go-live date.
Background:
- https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections#keeping_links_alive
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Redirections#apache
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status#redirection_messages
Solutions:
- Maintain an application (modified jupiter, derivative of audit) that would have at launch redirects for current assets.
- Apache redirects for some patterns using 303 See Other to redirect to a search query.
Verb | URI Pattern | Feasible? |
---|---|---|
GET | /items/:id/download/:file_set_id | ❌ |
GET | /items/:id/view/:file_set_id/*file_name | ✅/search?query=:file_name |
GET | /items/:id(.:format) | ✅/search?query=:id |
GET | /communities/:community_id/collections/:id(.:format) | ✅/search?query=:id |
GET | /communities(.:format) | ✅/community-list |
GET | /communities/:id(.:format) | ❓/search?query=:id |
GET | /files/:noid(.:format) | ❓/search?query=:noid |
GET | /downloads/:noid(.:format) | ❓/search?query=:noid |
GET | /files/:noid/:filename(.:format) | ✅/search?query=:filename |
GET | /collections/:noid(.:format) | ❓/search?query=:noid |
GET | /public/view/item/:uuid(.:format) | ❓/search?query=":uuid" |
GET | /public/view/item/:uuid/:ds(.:format) | ❓/search?query=":uuid" |
GET | /public/view/item/:uuid/:ds/:filename(.:format) | ❓/search?query=":uuid" ❓/search?query=:filename |
GET | /public/datastream/get/:uuid/:ds(.:format) | ❓/search?query=":uuid" |
GET | /public/datastream/get/:uuid/:ds/:filename(.:format) | ❓/search?query=":uuid" ❓/search?query=:filename |
GET | /public/view/collection/:uuid(.:format) | ✅/search?query=":uuid" |
GET | /public/view/community/:uuid(.:format) | ❓/search?query=":uuid" |
Examples:
- https://era.library.ualberta.ca/items/02704d35-5019-4cae-a5e1-c778aa82a828
- https://era.library.ualberta.ca/items/02704d35-5019-4cae-a5e1-c778aa82a828/view/625592b2-3f2d-4ca8-b467-176841034029/Dickson_Sarah_J_202205_MA.pdf
- https://era.library.ualberta.ca/communities/db9a4e71-f809-4385-a274-048f28eb6814/collections/f42f3da6-00c3-4581-b785-63725c33c7ce
Generally, if we can isolate the identifier we can use it to search for the item like this:
- Before: https://era.library.ualberta.ca/items/fc83bb92-bbc6-4cce-9a81-b55f00ad3285
- After: http://198.168.187.81:4000/search?query=fc83bb92-bbc6-4cce-9a81-b55f00ad3285
And its bitstream by filename:
- Before: https://era.library.ualberta.ca/items/fc83bb92-bbc6-4cce-9a81-b55f00ad3285/view/04665821-7a73-4d44-b553-b6587c9420e1/Fraser_Rochelle_2014_MPS.pdf
- After: 198.168.187.81:4000/search?query=Fraser_Rochelle_2014_MPS.pdf
Furthermore, if we can isolate collection identifier we can use it to search for the collection like this:
- Before: https://era.library.ualberta.ca/communities/dc1bf7d9-701c-4e46-8637-91854194c1a7/collections/4ab95ef6-a554-4387-8105-d9bfe0fe76e5
- After: https://ualberta-dev.scholaris.ca/search?query=4ab95ef6-a554-4387-8105-d9bfe0fe76e5
We can search by community id, but it will find the collections rather than the community. (I suspect this is because we were only able to store the metadata in the collection)
- Before: https://era.library.ualberta.ca/communities/30ae3d88-e1d1-49d8-9e8d-897bdcf202ee
- After: https://ualberta-dev.scholaris.ca/search?query=30ae3d88-e1d1-49d8-9e8d-897bdcf202ee&spc.page=1
Seems fedora3_uuid can also be used in search. The quotation marks are important here.
- Before: https://era.library.ualberta.ca/public/view/item/uuid:53748d94-6a74-4a6f-a7d8-10550150a2a6
- After: http://198.168.187.81:4000/search?query=%22uuid:53748d94-6a74-4a6f-a7d8-10550150a2a6%22
Same with hydranorth noids
- Before:https://era.library.ualberta.ca/files/c8p58pd373
- After: http://198.168.187.81:4000/search?query=%22c8p58pd373%22
This works for a collection
- Before: https://era.library.ualberta.ca/public/view/collection/uuid:d64eb93e-7fd5-4dad-a515-4b18b52c1b1b
- After: https://ualberta-dev.scholaris.ca/search?query=%22uuid:d64eb93e-7fd5-4dad-a515-4b18b52c1b1b%22
And hydranorth noid will find collection
- Before:https://era.library.ualberta.ca/collections/44558s029
- After: http://198.168.187.81:4000/search?query=44558s029
And sort of for the community (see above)
- Before:https://era.library.ualberta.ca/public/view/community/uuid:d04b3b74-211d-4939-9660-c390958fa2ee
- After: https://ualberta-dev.scholaris.ca/search?query=%22uuid:d04b3b74-211d-4939-9660-c390958fa2ee%22
rails routes
Prefix Verb URI Pattern Controller#Action
oaisys /oai Oaisys::Engine {:subdomain=>"era"}
root GET / welcome#index {:subdomain=>"era"}
create_draft_items POST /items/create_draft(.:format) items/draft#create {:subdomain=>"era"}
item_delete_draft DELETE /items/:item_id/delete_draft(.:format) items/draft#destroy {:subdomain=>"era"}
item_draft GET /items/:item_id/draft/:id(.:format) items/draft#show {:subdomain=>"era"}
PATCH /items/:item_id/draft/:id(.:format) items/draft#update {:subdomain=>"era"}
PUT /items/:item_id/draft/:id(.:format) items/draft#update {:subdomain=>"era"}
set_thumbnail_item_file PATCH /items/:item_id/files/:id/set_thumbnail(.:format) items/files#set_thumbnail {:subdomain=>"era"}
item_files POST /items/:item_id/files(.:format) items/files#create {:subdomain=>"era"}
item_file DELETE /items/:item_id/files/:id(.:format) items/files#destroy {:subdomain=>"era"}
file_download_item GET /items/:id/download/:file_set_id Inline handler (Proc/Lambda) {:subdomain=>"era"}
file_view_item GET /items/:id/view/:file_set_id/*file_name Inline handler (Proc/Lambda) {:subdomain=>"era"}
edit_item GET /items/:id/edit(.:format) items#edit {:subdomain=>"era"}
item GET /items/:id(.:format) items#show {:subdomain=>"era"}
search GET /search(.:format) search#index {:subdomain=>"era"}
profile GET /profile(.:format) profile#index {:subdomain=>"era"}
community_collection GET /communities/:community_id/collections/:id(.:format) collections#show {:subdomain=>"era"}
communities GET /communities(.:format) communities#index {:subdomain=>"era"}
community GET /communities/:id(.:format) communities#show {:subdomain=>"era"}
admin_root GET /admin(.:format) admin/dashboard#index {:subdomain=>"era"}
suspend_admin_user PATCH /admin/users/:id/suspend(.:format) admin/users#suspend {:subdomain=>"era"}
unsuspend_admin_user PATCH /admin/users/:id/unsuspend(.:format) admin/users#unsuspend {:subdomain=>"era"}
grant_admin_admin_user PATCH /admin/users/:id/grant_admin(.:format) admin/users#grant_admin {:subdomain=>"era"}
revoke_admin_admin_user PATCH /admin/users/:id/revoke_admin(.:format) admin/users#revoke_admin {:subdomain=>"era"}
login_as_user_admin_user POST /admin/users/:id/login_as_user(.:format) admin/users#login_as_user {:subdomain=>"era"}
admin_users GET /admin/users(.:format) admin/users#index {:subdomain=>"era"}
admin_user GET /admin/users/:id(.:format) admin/users#show {:subdomain=>"era"}
admin_community_collections POST /admin/communities/:community_id/collections(.:format) admin/collections#create {:subdomain=>"era"}
new_admin_community_collection GET /admin/communities/:community_id/collections/new(.:format) admin/collections#new {:subdomain=>"era"}
edit_admin_community_collection GET /admin/communities/:community_id/collections/:id/edit(.:format) admin/collections#edit {:subdomain=>"era"}
admin_community_collection GET /admin/communities/:community_id/collections/:id(.:format) admin/collections#show {:subdomain=>"era"}
PATCH /admin/communities/:community_id/collections/:id(.:format) admin/collections#update {:subdomain=>"era"}
PUT /admin/communities/:community_id/collections/:id(.:format) admin/collections#update {:subdomain=>"era"}
DELETE /admin/communities/:community_id/collections/:id(.:format) admin/collections#destroy {:subdomain=>"era"}
admin_communities GET /admin/communities(.:format) admin/communities#index {:subdomain=>"era"}
POST /admin/communities(.:format) admin/communities#create {:subdomain=>"era"}
new_admin_community GET /admin/communities/new(.:format) admin/communities#new {:subdomain=>"era"}
edit_admin_community GET /admin/communities/:id/edit(.:format) admin/communities#edit {:subdomain=>"era"}
admin_community GET /admin/communities/:id(.:format) admin/communities#show {:subdomain=>"era"}
PATCH /admin/communities/:id(.:format) admin/communities#update {:subdomain=>"era"}
PUT /admin/communities/:id(.:format) admin/communities#update {:subdomain=>"era"}
DELETE /admin/communities/:id(.:format) admin/communities#destroy {:subdomain=>"era"}
reset_doi_admin_item PATCH /admin/items/:id/reset_doi(.:format) admin/items#reset_doi {:subdomain=>"era"}
admin_items GET /admin/items(.:format) admin/items#index {:subdomain=>"era"}
admin_item DELETE /admin/items/:id(.:format) admin/items#destroy {:subdomain=>"era"}
create_draft_admin_theses POST /admin/theses/create_draft(.:format) admin/theses/draft#create {:subdomain=>"era"}
admin_thesis_delete_draft DELETE /admin/theses/:thesis_id/delete_draft(.:format) admin/theses/draft#destroy {:subdomain=>"era"}
admin_thesis_draft GET /admin/theses/:thesis_id/draft/:id(.:format) admin/theses/draft#show {:subdomain=>"era"}
PATCH /admin/theses/:thesis_id/draft/:id(.:format) admin/theses/draft#update {:subdomain=>"era"}
PUT /admin/theses/:thesis_id/draft/:id(.:format) admin/theses/draft#update {:subdomain=>"era"}
set_thumbnail_admin_thesis_file PATCH /admin/theses/:thesis_id/files/:id/set_thumbnail(.:format) admin/theses/files#set_thumbnail {:subdomain=>"era"}
admin_thesis_files POST /admin/theses/:thesis_id/files(.:format) admin/theses/files#create {:subdomain=>"era"}
admin_thesis_file DELETE /admin/theses/:thesis_id/files/:id(.:format) admin/theses/files#destroy {:subdomain=>"era"}
admin_announcements GET /admin/announcements(.:format) admin/announcements#index {:subdomain=>"era"}
POST /admin/announcements(.:format) admin/announcements#create {:subdomain=>"era"}
admin_announcement DELETE /admin/announcements/:id(.:format) admin/announcements#destroy {:subdomain=>"era"}
new_admin_google_session GET /admin/google_sessions/new(.:format) admin/google_sessions#new {:subdomain=>"era"}
admin_batch_ingests GET /admin/batch_ingests(.:format) admin/batch_ingests#index {:subdomain=>"era"}
POST /admin/batch_ingests(.:format) admin/batch_ingests#create {:subdomain=>"era"}
new_admin_batch_ingest GET /admin/batch_ingests/new(.:format) admin/batch_ingests#new {:subdomain=>"era"}
admin_batch_ingest GET /admin/batch_ingests/:id(.:format) admin/batch_ingests#show {:subdomain=>"era"}
logout_as_user POST /logout_as_user(.:format) sessions#logout_as_user {:subdomain=>"era"}
login GET|POST /auth/:provider/callback(.:format) sessions#create {:subdomain=>"era"}
auth_failure GET|POST /auth/failure(.:format) sessions#failure {:subdomain=>"era"}
logout GET|POST /logout(.:format) sessions#destroy {:subdomain=>"era"}
auth_system POST /auth/system(.:format) sessions#system_login {:subdomain=>"era"}
sidekiq_web /sidekiq Sidekiq::Web {:subdomain=>"era"}
flipper /flipper Flipper::UI {:subdomain=>"era"}
sitemapindex GET /sitemap.xml(.:format) sitemap#index {:subdomain=>"era", :format=>:xml}
communities_sitemap GET /sitemap-communities.xml(.:format) sitemap#communities {:subdomain=>"era", :format=>:xml}
collections_sitemap GET /sitemap-collections.xml(.:format) sitemap#collections {:subdomain=>"era", :format=>:xml}
items_sitemap GET /sitemap-items.xml(.:format) sitemap#items {:subdomain=>"era", :format=>:xml}
theses_sitemap GET /sitemap-theses.xml(.:format) sitemap#theses {:subdomain=>"era", :format=>:xml}
GET /robots.txt(.:format) robots#robots {:subdomain=>"era"}
about GET /about(.:format) static_pages#about {:subdomain=>"era"}
policies GET /policies(.:format) static_pages#policies {:subdomain=>"era"}
contact GET /contact(.:format) static_pages#contact {:subdomain=>"era"}
GET /files/:noid(.:format) redirect#hydra_north_item {:subdomain=>"era"}
GET /downloads/:noid(.:format) redirect#hydra_north_item {:subdomain=>"era"}
GET /files/:noid/:filename(.:format) redirect#hydra_north_file {:subdomain=>"era", :filename=>/[^\/]+/}
GET /collections/:noid(.:format) redirect#hydra_north_community_collection {:subdomain=>"era"}
GET /public/view/item/:uuid(.:format) redirect#fedora3_item {:subdomain=>"era"}
GET /public/view/item/:uuid/:ds(.:format) redirect#fedora3_datastream {:subdomain=>"era"}
GET /public/view/item/:uuid/:ds/:filename(.:format) redirect#fedora3_datastream {:subdomain=>"era", :filename=>/[^\/]+/}
GET /public/datastream/get/:uuid/:ds(.:format) redirect#fedora3_datastream {:subdomain=>"era"}
GET /public/datastream/get/:uuid/:ds/:filename(.:format) redirect#fedora3_datastream {:subdomain=>"era", :filename=>/[^\/]+/}
GET /public/view/collection/:uuid(.:format) redirect#fedora3_collection {:subdomain=>"era"}
GET /public/view/community/:uuid(.:format) redirect#fedora3_community {:subdomain=>"era"}
aip_v1_collection GET /aip/v1/collections/:id(.:format) aip/v1/collections#show {:subdomain=>"era", :format=>:n3}
aip_v1_community GET /aip/v1/communities/:id(.:format) aip/v1/communities#show {:subdomain=>"era", :format=>:n3}
aip_v1_entity GET /aip/v1/:entity/:id(.:format) aip/v1/entities#show {:subdomain=>"era", :format=>:n3}
aip_v1_entity_filesets GET /aip/v1/:entity/:id/filesets(.:format) aip/v1/entities#file_sets {:subdomain=>"era", :format=>:n3}
aip_v1_entity_file_paths GET /aip/v1/:entity/:id/file_paths(.:format) aip/v1/entities#file_paths {:subdomain=>"era", :format=>:n3}
aip_v1_entity_file_set GET /aip/v1/:entity/:id/filesets/:file_set_id(.:format) aip/v1/entities#file_set {:subdomain=>"era", :format=>:n3}
aip_v1_entity_fileset_fixity GET /aip/v1/:entity/:id/filesets/:file_set_id/fixity(.:format) aip/v1/entities#fixity_file {:subdomain=>"era", :format=>:n3}
GET /bibliography/:peel_id(/*page)(.:format) digitization/redirect#peel_book {:subdomain=>"digitalcollections"}
GET /bibliography/:peel_id.:part_number(/*page)(.:format) digitization/redirect#peel_book {:subdomain=>"digitalcollections"}
GET /bibliography/:peel_id.:run.:part_number(/*page)(.:format) digitization/redirect#peel_book {:subdomain=>"digitalcollections"}
GET /newspapers/:publication_code/:year/:month/:day(/*page)(.:format) digitization/redirect#peel_newspaper {:subdomain=>"digitalcollections"}
GET /magee/:peel_image_id(.:format) digitization/redirect#peel_image {:subdomain=>"digitalcollections"}
GET /postcards/:peel_image_id(.:format) digitization/redirect#peel_image {:subdomain=>"digitalcollections"}
GET /maps/:peel_map_id(.:format) digitization/redirect#peel_map {:subdomain=>"digitalcollections", :peel_map_id=>/M[0-9]{6}/}
file_download_digitization_book GET /books/:id/download/:file_set_id Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
file_view_digitization_book GET /books/:id/view/:file_set_id/*file_name Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
digitization_books GET /books(.:format) digitization/books#index {:subdomain=>"digitalcollections"}
digitization_book GET /books/:id(.:format) digitization/books#show {:subdomain=>"digitalcollections"}
file_download_digitization_newspaper GET /newspapers/:id/download/:file_set_id Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
file_view_digitization_newspaper GET /newspapers/:id/view/:file_set_id/*file_name Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
digitization_newspapers GET /newspapers(.:format) digitization/newspapers#index {:subdomain=>"digitalcollections"}
digitization_newspaper GET /newspapers/:id(.:format) digitization/newspapers#show {:subdomain=>"digitalcollections"}
file_download_digitization_image GET /images/:id/download/:file_set_id Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
file_view_digitization_image GET /images/:id/view/:file_set_id/*file_name Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
digitization_images GET /images(.:format) digitization/images#index {:subdomain=>"digitalcollections"}
digitization_image GET /images/:id(.:format) digitization/images#show {:subdomain=>"digitalcollections"}
file_download_digitization_map GET /maps/:id/download/:file_set_id Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
file_view_digitization_map GET /maps/:id/view/:file_set_id/*file_name Inline handler (Proc/Lambda) {:subdomain=>"digitalcollections"}
digitization_maps GET /maps(.:format) digitization/maps#index {:subdomain=>"digitalcollections"}
digitization_map GET /maps/:id(.:format) digitization/maps#show {:subdomain=>"digitalcollections"}
healthcheck GET /healthcheck(.:format) healthcheck#index
rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create
rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create
rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create
rails_mandrill_inbound_health_check GET /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#health_check
rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create
rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create
rails_conductor_inbound_emails GET /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#index
POST /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#create
new_rails_conductor_inbound_email GET /rails/conductor/action_mailbox/inbound_emails/new(.:format) rails/conductor/action_mailbox/inbound_emails#new
rails_conductor_inbound_email GET /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#show
new_rails_conductor_inbound_email_source GET /rails/conductor/action_mailbox/inbound_emails/sources/new(.:format) rails/conductor/action_mailbox/inbound_emails/sources#new
rails_conductor_inbound_email_sources POST /rails/conductor/action_mailbox/inbound_emails/sources(.:format) rails/conductor/action_mailbox/inbound_emails/sources#create
rails_conductor_inbound_email_reroute POST /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) rails/conductor/action_mailbox/reroutes#create
rails_conductor_inbound_email_incinerate POST /rails/conductor/action_mailbox/:inbound_email_id/incinerate(.:format) rails/conductor/action_mailbox/incinerates#create
rails_service_blob GET /rails/active_storage/blobs/redirect/:signed_id/*filename(.:format) active_storage/blobs/redirect#show
rails_service_blob_proxy GET /rails/active_storage/blobs/proxy/:signed_id/*filename(.:format) active_storage/blobs/proxy#show
GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs/redirect#show
rails_blob_representation GET /rails/active_storage/representations/redirect/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/redirect#show
rails_blob_representation_proxy GET /rails/active_storage/representations/proxy/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/proxy#show
GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/redirect#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
to restart httpd in docker container
/usr/local/apache2/bin/apachectl -k restart