Skip to content

Commit 9757499

Browse files
MIT LibrariesMIT Libraries
MIT Libraries
authored and
MIT Libraries
committed
Revisions for implementing SQL lookup in place of the X-server
0 parents  commit 9757499

6 files changed

+598
-0
lines changed

api_adapter.template

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
#!/usr/bin/perl
2+
3+
#--------------------------------------------------------------
4+
# 12-05-2014 Rich Wenger, MIT Libraries
5+
# This script provides Aleph services to an external server.
6+
#--------------------------------------------------------------
7+
8+
use strict;
9+
use warnings;
10+
use HTTP::Request;
11+
use LWP::UserAgent;
12+
use Switch;
13+
use POSIX;
14+
use Time::Local;
15+
16+
my $rest_port = 'PORT';
17+
my @whitelist = (WHITELIST);
18+
#-----------------------------------------------------------------
19+
# Only accept connections from authorized IP addresses.
20+
#-----------------------------------------------------------------
21+
if (!grep /$ENV{REMOTE_ADDR}/, @whitelist) {
22+
print STDERR "*** $0: Unauthorized access attempt from $ENV{REMOTE_ADDR} ***\n";
23+
print "Content-type: text/html\n\n";
24+
print "Unathorized access";
25+
exit;
26+
}
27+
28+
#--------------------------------------------------------------------------------------------
29+
# $debug and $parameter_trace are for diagnostic purposes and will normally be set to 0.
30+
# $id_translation will be set to 1 as a default. Setting it to 0 disables the translation
31+
# of alternate identifiers to Aleph ids by the adapter.
32+
#--------------------------------------------------------------------------------------------
33+
my $debug = 0;
34+
my $parameter_trace = 0;
35+
my $id_translation = 1;
36+
my $sql_lookup = 0;
37+
38+
#------------------------------------------------------------------------
39+
# Local base URLs for the Aleph X-server and the RESTful API.
40+
#------------------------------------------------------------------------
41+
my $x_base_url = 'http://localhost/X?';
42+
my $r_base_url = "http://localhost:$rest_port";
43+
44+
#-------------------------------------
45+
# Headers and XML constants.
46+
#-------------------------------------
47+
my $xml_header = "Content-type: text/xml\n\n";
48+
my $html_header = "Content-type: text/html\n\n";
49+
my $xml_prolog = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
50+
51+
my $version_xml = join '',
52+
'<version>',
53+
'<ilsInstitutionName>INSTNAME</ilsInstitutionName>',
54+
'<ilsVersion>ALEPHVER</ilsVersion>',
55+
'<locale>en_US</locale>',
56+
'<timeZone>TIMEZONE</timeZone>',
57+
'<timeZoneCode>TZCODE</timeZoneCode>',
58+
'<timeZoneGMT>TZGMT</timeZoneGMT>',
59+
'<currencyCode>CURRENCY</currencyCode>',
60+
'</version>';
61+
62+
my $printline = '';
63+
my $putdata;
64+
my $postdata;
65+
66+
#----------------------------------------------------
67+
# Valid parameters in Aleph RESTful URLs
68+
#----------------------------------------------------
69+
my @allowed_groups = ('patron','ilsinstance','record');
70+
my @allowed_categories = ('patroninformation','circulationactions','record','patronstatus','items','holds');
71+
my @patinfo_functions = ('address','password');
72+
my @circ_functions = ('loans','requests','cash');
73+
my @patstatus_functions = ('blocks','registration');
74+
my @allowed_subfunctions = ('holds','photocopies','acquisitionrequests','ill','bookings');
75+
76+
#--------------------------------
77+
# Valid HTTP methods
78+
#--------------------------------
79+
my @allowed_methods = ('get','post','put','delete');
80+
81+
#----------------------------------------------------------------------------
82+
# Get the RESTful URL components.
83+
# @parms will contain the RESTful nodes between slashes.
84+
# @args will contain any key=value pairs from the end of the URI.
85+
#----------------------------------------------------------------------------
86+
my @parms = split /\//, (split /\?parm1=/, lc $ENV{'REQUEST_URI'})[0];
87+
splice @parms,0,2;
88+
my @args = split /\&/, (split /\?/, $parms[$#parms])[1];
89+
if (grep /\?/, $parms[$#parms]) {
90+
$parms[$#parms] =~ s/\?(.*)$//go;
91+
}
92+
93+
my ($group, $patron_id, $category, $function, $subfunction) = '';
94+
($group, $patron_id, $category, $function, $subfunction) = @parms;
95+
if (!grep /$group/, @allowed_groups) {
96+
print "$html_header invalid group $group";
97+
exit;
98+
}
99+
if (!grep /$category/, @allowed_categories) {
100+
print "$html_header invalid category $category";
101+
exit;
102+
}
103+
104+
#----------------------------------------------------------------------------------------
105+
# $method will contain one of the HTTP commands: GET, POST, PUT, DELETE, etc.
106+
# They are stored here in lower case for later use as method calls to LWP.
107+
#----------------------------------------------------------------------------------------
108+
my $method = lc $ENV{'REQUEST_METHOD'};
109+
110+
#------------------------------------------------------------------------------
111+
# This paragraph is for diagnostic purposes only. It writes parameters
112+
# and arguments to the Apache log (STDERR) and exits.
113+
#------------------------------------------------------------------------------
114+
if ($parameter_trace) {
115+
print "$html_header";
116+
foreach my $x (@parms) { print "parm: $x<br>"; }
117+
if (@args) {
118+
foreach my $x (@args) { print "args: $x<br>"; }
119+
}
120+
if ($debug) {
121+
my $printline = join '',
122+
"*** Group: $group ***\n",
123+
"*** Patron id: $patron_id ***\n",
124+
"*** Category: $category ***\n",
125+
"*** Function: $function ***\n",
126+
"*** Subfunction: $subfunction ***\n";
127+
print STDERR $printline;
128+
}
129+
exit;
130+
}
131+
132+
#----------------------------------------------------------------------------
133+
# This section handles the request for Aleph version information.
134+
# The Aleph REST API does not support this operation.
135+
#----------------------------------------------------------------------------
136+
if ($group eq 'ilsinstance') {
137+
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
138+
my $timezone = $isdst ? 'Eastern Daylight Time' : 'Eastern Standard Time';
139+
my $tzcode = $isdst ? 'EDT' : 'EST';
140+
141+
my @aleph_info = `./get_aleph_info.csh`;
142+
my $version = (split ',', $aleph_info[0])[2];
143+
my $aleph_version = (split ' ', $version)[1];
144+
my $currency = $aleph_info[3];
145+
chomp $currency;
146+
147+
my @t = localtime(time);
148+
my $gmt_offset_in_hours = (timegm(@t) - timelocal(@t)) / 3600;
149+
150+
my $version_string = $version_xml;
151+
$version_string =~ s/ALEPHVER/$aleph_version/;
152+
$version_string =~ s/TIMEZONE/$timezone/;
153+
$version_string =~ s/TZCODE/$tzcode/;
154+
$version_string =~ s/TZGMT/$gmt_offset_in_hours/;
155+
$version_string =~ s/CURRENCY/$currency/;
156+
157+
$printline = join '', $xml_prolog, $version_string;
158+
}
159+
160+
else {
161+
#----------------------------------------------------------------------
162+
# Instantiate a user agent for use in calling the REST API.
163+
#----------------------------------------------------------------------
164+
my $ua = LWP::UserAgent->new;
165+
166+
my $request_uri = $ENV{'REQUEST_URI'};
167+
my $response = '';
168+
my $aleph_id = '';
169+
if ($group eq 'patron' && $id_translation) {
170+
if (!$sql_lookup) {
171+
#---------------------------------------------------------------------
172+
# Incoming identifer requires translation. Since $sql_lookup
173+
# is not set, convert it to an Aleph id via bor-by-key
174+
# x-server function,
175+
#---------------------------------------------------------------------
176+
my $info_prefix = "op=bor-by-key&bor_id=$patron_id";
177+
my $rest_url = join '', $x_base_url, $info_prefix;
178+
print STDERR "*** Bor-by-key URL: $rest_url ***\n" if $debug;
179+
$response = $ua->get($rest_url);
180+
$aleph_id = &extract_alephid($response);
181+
print STDERR "*** Aleph id: $aleph_id ***\n" if $debug;
182+
print STDERR "*** Patron id: $patron_id ***\n" if $debug;
183+
print STDERR "*** request_uri before: $request_uri ***\n" if $debug;
184+
$request_uri =~ s/$patron_id/$aleph_id/ig;
185+
print STDERR "*** request_uri after: $request_uri ***\n" if $debug;
186+
}
187+
else {
188+
#---------------------------------------------------------------------
189+
# Incoming identifer requires translation. Since $sql_lookup
190+
# is on, convert it to an Aleph id via SQL lookup.
191+
#---------------------------------------------------------------------
192+
$aleph_id = `./sql_lookup.csh $patron_id`;
193+
print STDERR "*** Aleph id from SQL: $aleph_id ***\n" if $debug;
194+
$request_uri =~ s/$patron_id/$aleph_id/ig;
195+
}
196+
}
197+
198+
if (grep /$method/, @allowed_methods) {
199+
#-----------------------------------
200+
# Optional local programming can be inserted here by uncommenting the
201+
# switch structure below
202+
#-----------------------------------
203+
#switch ($category) {
204+
# case ('patroninformation') {
205+
# # local code here
206+
# }
207+
# case ('patronstatus') {
208+
# # local code here
209+
# }
210+
# case ('circulationactions') {
211+
# # local code here
212+
# }
213+
# case ('record') {
214+
# # local code here
215+
# }
216+
# case ('items') {
217+
# # local code here
218+
# }
219+
# }
220+
#-----------------------------------
221+
# Default passthrough.
222+
#-----------------------------------
223+
my $rest_url = join '', $r_base_url, $request_uri;
224+
print STDERR "*** $category: $rest_url ***\n" if $debug;
225+
print STDERR "*** Method: $method ***\n" if $debug;
226+
my $request;
227+
switch ($method) {
228+
case ('get') {
229+
$request = HTTP::Request->new(GET => $rest_url);
230+
}
231+
case ('post') {
232+
read(STDIN, $putdata, $ENV{'CONTENT_LENGTH'});
233+
my $h = HTTP::Headers->new(Content_Type => 'text/xml');
234+
$request = HTTP::Request->new('POST', $rest_url, $h, $putdata);
235+
}
236+
case ('put') {
237+
read(STDIN, $putdata, $ENV{'CONTENT_LENGTH'});
238+
my $h = HTTP::Headers->new(Content_Type => 'text/xml');
239+
$request = HTTP::Request->new('PUT', $rest_url, $h, $putdata);
240+
}
241+
case ('delete') {
242+
$request = HTTP::Request->new(DELETE => $rest_url);
243+
}
244+
}
245+
$response = $ua->request($request);
246+
$printline = $response->content;
247+
#------------------------------------------------------------
248+
# Remove the port number from any URLs in the XML.
249+
#------------------------------------------------------------
250+
$printline =~ s/localhost:$rest_port/$ENV{'HTTP_HOST'}/go;
251+
}
252+
else {
253+
#------------------------------------------------------------------
254+
# HTTP method is not supported. Return failure message
255+
#------------------------------------------------------------------
256+
$printline = join '', $xml_prolog, "<note>HTTP command $method is restricted or invalid</note>";
257+
}
258+
}
259+
260+
#-----------------------------------------------------------------------------------------
261+
# Return the content to the caller.
262+
# The following 'if' statement is required to ameliorate the Aleph REST API's
263+
# inexplicable practice of returning HTML in certain error conditions.
264+
#-----------------------------------------------------------------------------------------
265+
print STDERR "*** printline: $printline ***\n" if $debug;
266+
if (grep /<html>/, $printline) { print "$html_header" }
267+
else { print "$xml_header" }
268+
print $printline;
269+
exit;
270+
271+
#------------------------- subroutines --------------------------
272+
sub extract_alephid {
273+
my $xml_ref = pop;
274+
my @temp = split '<\/internal\-id>', (split '<internal\-id>', $xml_ref->content)[1];
275+
return $temp[0];
276+
}

get_aleph_info.template

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/tcsh
2+
source /exlibris/aleph/VER/alephm/.cshrc >/dev/null
3+
ver
4+
echo $local_currency

0 commit comments

Comments
 (0)