From ed14ad6edaf5a7c76b168ca2e624e05719830162 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Fri, 7 Jan 2022 18:50:04 -0500 Subject: [PATCH] LP#1951021: account for change in OverDrive checkout response The OverDrive circulation API soon will stop providing a direct download link in favor of displaying a separate fulfillment page (either as an iframe or a redirect). This patch implements this change with the redirect option. Additional information on the API change can be found at http://developer.overdrive.com/overdrive-api-notices/01-sep-2021-coming-soon-changes-to-overdrive-checkouts-api Signed-off-by: Galen Charlton Signed-off-by: Jeff Davis Signed-off-by: Garry Collum --- .../perlmods/lib/OpenILS/Application/EbookAPI.pm | 8 +++-- .../lib/OpenILS/Application/EbookAPI/OverDrive.pm | 34 ++++++++++++++++++++-- .../src/perlmods/lib/OpenILS/Utils/HTTPClient.pm | 5 +++- .../web/js/ui/default/opac/ebook_api/loggedin.js | 9 +++++- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI.pm index bc968b5586..6102b312dc 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI.pm @@ -326,6 +326,7 @@ sub request { my $self = shift; my $req = shift; my $session_id = shift; + my $do_not_redirect = shift; my $uri; if (!defined ($req->{uri})) { @@ -365,7 +366,9 @@ sub request { $uri, $headers, $content, - $request_timeout + $request_timeout, + undef, + $do_not_redirect ); if (!defined ($res)) { $logger->error('EbookAPI: no HTTP response received'); @@ -375,7 +378,8 @@ sub request { return { is_success => $res->is_success, status => $res->status_line, - content => OpenSRF::Utils::JSON->JSON2perl($res->decoded_content) + content => OpenSRF::Utils::JSON->JSON2perl($res->decoded_content), + location => $res->header('Location') }; } } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI/OverDrive.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI/OverDrive.pm index 6eca31eedf..9853c5b0ee 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI/OverDrive.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/EbookAPI/OverDrive.pm @@ -156,13 +156,15 @@ sub initialize { sub handle_http_request { my $self = shift; my $req = shift; + my $session_id = shift; + my $do_not_redirect = shift; # Prep our request using defaults. $req->{method} = 'GET' if (!$req->{method}); $req = $self->set_http_headers($req); # Send the request. - my $res = $self->request($req, $self->{session_id}); + my $res = $self->request($req, $self->{session_id}, $do_not_redirect); $logger->info("EbookAPI: raw OverDrive HTTP response: " . Dumper $res); @@ -182,7 +184,7 @@ sub handle_http_request { # Now we can update our headers with our fresh client/patron tokens # and re-send our request. $req = $self->set_http_headers($req); - return $self->request($req, $self->{session_id}); + return $self->request($req, $self->{session_id}, $do_not_redirect); } # For any non-401 response (including no response at all), @@ -555,6 +557,18 @@ sub checkout { } $checkout->{formats} = $formats; } + if ($res->{content}->{links}->{downloadRedirect}->{href}) { + my $redir = $res->{content}->{links}->{downloadRedirect}->{href}; + my $req2 = { + method => 'GET', + uri => $redir + }; + if (my $res2 = $self->handle_http_request($req2, $self->{session_id}, 1)) { + if ($res2->{location}) { + $checkout->{download_redirect} = $res2->{location}; + } + } + } return $checkout; } $logger->error("EbookAPI: checkout failed for OverDrive title $title_id"); @@ -680,12 +694,26 @@ sub get_patron_checkouts { my $ftype = $f->{formatType}; $formats->{$ftype} = $f->{linkTemplates}->{downloadLink}->{href}; }; + my $download_redirect = ''; + my $redirect = $checkout->{links}->{downloadRedirect}->{href}; + if ($redirect) { + my $req2 = { + method => 'GET', + uri => $redirect + }; + if (my $res2 = $self->handle_http_request($req2, $self->{session_id}, 1)) { + if ($res2->{location}) { + $download_redirect = $res2->{location}; + } + } + } push @$checkouts, { title_id => $title_id, due_date => $checkout->{expires}, title => $title_info->{title}, author => $title_info->{author}, - formats => $formats + formats => $formats, + download_redirect => $download_redirect } }; $self->{checkouts} = $checkouts; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HTTPClient.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HTTPClient.pm index 64745866c4..a0f6eae566 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HTTPClient.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HTTPClient.pm @@ -67,7 +67,7 @@ sub _initialize { # Use $res->content to get response content. # sub request { - my ($self, $method, $uri, $headers, $content, $request_timeout, $useragent) = @_; + my ($self, $method, $uri, $headers, $content, $request_timeout, $useragent, $do_not_redirect) = @_; my $ua = new LWP::UserAgent; $request_timeout = $request_timeout || $self->{default_timeout} || 60; @@ -75,6 +75,9 @@ sub request { $useragent = $useragent || $self->{useragent} || 'SameOrigin/1.0'; $ua->agent($useragent); + if ($do_not_redirect) { + $ua->requests_redirectable([]); + } my $h = HTTP::Headers->new(); foreach my $k (keys %$headers) { diff --git a/Open-ILS/web/js/ui/default/opac/ebook_api/loggedin.js b/Open-ILS/web/js/ui/default/opac/ebook_api/loggedin.js index 569260c4f4..9b7323a0f2 100644 --- a/Open-ILS/web/js/ui/default/opac/ebook_api/loggedin.js +++ b/Open-ILS/web/js/ui/default/opac/ebook_api/loggedin.js @@ -146,7 +146,9 @@ function updateCheckoutView() { if (x.download_url) { dl_td.innerHTML = '' + l_strings.download + ''; } - if (x.formats) { + if (x.download_redirect) { + dl_td.innerHTML = '' + l_strings.download + ''; + } else if (x.formats) { var select = dojo.create("select", { id: "download-format" }, dl_td); for (f in x.formats) { dojo.create("option", { value: x.formats[f], innerHTML: f }, select); @@ -319,6 +321,11 @@ function doCheckout() { new_xact.download_url = resp.download_url; dojo.create("a", { href: new_xact.download_url, innerHTML: l_strings.download }, dojo.byId('checkout-button-td')); new_xact.finish(); + } else if (resp.download_redirect) { + // Use download URL from checkout response, if available. + new_xact.download_redirect = resp.download_redirect; + dojo.create("a", { target: "_blank", href: new_xact.download_redirect, innerHTML: l_strings.download }, dojo.byId('checkout-button-td')); + new_xact.finish(); } else if (typeof resp.formats !== 'undefined') { // User must select download format from list of options. var select = dojo.create("select", { id: "download-format" }, dojo.byId('checkout-button-td')); -- 2.11.0