As mentioned in the introduction the YAZ proxy has many uses. This chapter includes a few examples.
The YAZ Proxy is useful for debugging SRU/Z39.50 software, logging APDUs, redirecting Z39.50 packages through firewalls, etc. Furthermore, it offers facilities that often boost performance for connection-less Z39.50 clients such as web gateways.
Unlike most other server software, the proxy runs single-threaded, single-process. Every I/O operation is non-blocking so it is very lightweight and extremely fast. It does not store any state information on the hard drive, except any log files you ask for.
Example 3.1. Using the Proxy to Log APDUs
Suppose you use a commercial Z39.50 client for which you do not have source code, and it's not behaving how you think it should when running against some specific server that you have no control over. One way to diagnose the problem is to find out what packets (APDUs) are being sent and received, but not all client applications have facilities to do APDU logging.
No problem. Run the proxy on a friendly machine, get it to log APDUs, and point the errant client at the proxy instead of directly at the server that's causing it problems.
Suppose the server is running on foo.bar.com
,
port 18398. Run the proxy on the machine of your choice, say
your.company.com
like this:
yazproxy -a - -t tcp:foo.bar.com:18398 tcp:@:9000
(The -a -
option requests APDU logging on
standard output, -t tcp:foo.bar.com:18398
specifies where the backend target is, and
tcp:@:9000
tells the proxy to listen on port
9000 and accept connections from any machine.)
Now change your client application's configuration so that instead
of connecting to foo.bar.com
port 18398, it
connects to your.company.com
port 9000, and
start it up. It will work exactly as usual, but all the packets
will be sent via the proxy, which will generate a log like this:
decode choice initRequest { referenceId OCTETSTRING(len=4) 69 6E 69 74 protocolVersion BITSTRING(len=1) options BITSTRING(len=2) preferredMessageSize 1048576 maximumRecordSize 1048576 implementationId 'Mike Taylor (id=169)' implementationName 'Net::Z3950.pm (Perl)' implementationVersion '0.31' } encode choice initResponse { referenceId OCTETSTRING(len=4) 69 6E 69 74 protocolVersion BITSTRING(len=1) options BITSTRING(len=2) preferredMessageSize 1048576 maximumRecordSize 1048576 result TRUE implementationId '81' implementationName 'GFS/YAZ / Zebra Information Server' implementationVersion 'YAZ 1.9.1 / Zebra 1.3.3' } decode choice searchRequest { referenceId OCTETSTRING(len=1) 30 smallSetUpperBound 0 largeSetLowerBound 1 mediumSetPresentNumber 0 replaceIndicator TRUE resultSetName 'default' databaseNames { 'gils' } { smallSetElementSetNames choice generic 'F' } { mediumSetElementSetNames choice generic 'B' } preferredRecordSyntax OID: 1 2 840 10003 5 10 { query choice type_1 { attributeSetId OID: 1 2 840 10003 3 1 RPNStructure choice { simple choice attributesPlusTerm { attributes { } term choice general OCTETSTRING(len=7) 6D 69 6E 65 72 61 6C } } } } }
Example 3.2. Using a configuration file
In Example 3.1, “Using the Proxy to Log APDUs” the default backend server was specified by a command line option. The same proxy behavior can be achieved by creating a configuration with the following contents:
<?xml version="1.0"?> <proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/"> <target name="foo" default="1"> <url>foo.bar.com:18398</url> <log>client-apdu</log> </target> <target name="*"> </target> </proxy>
The proxy is started with
yazproxy -c config.xml @:9000
The last target section is used for all servers except foo. Had the the last section been omitted, then only foo could be reached via the proxy.
Example 3.3. Offering SRU/Z39.50 service
In order to offer SRU service we must be specify sufficient
information to allow the proxy to convert from SRU to Z39.50.
This involves translating CQL queries
to Type-1 (also called RPN/PQF), since most
Z39.50 servers do not support CQL. The conversion
is specified by the cql2rpn
element.
We must also ensure that the server can return at least one kind of XML record (Dublin-Core recommended).
An explain record for the SRU service must also be created.
The following is a relatively simple configuration file for
such a service. This service lives on indexdata.dk
,
port 9000. The database is gils
. The
backend server is also indexdata.dk
(port 210) as
given by url
.
The server may return USMARC/MARC21 (Z39.50/SRU) and MARCXML (SRU only) as specified by the syntax elements.
<?xml version="1.0"?> <proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/"> <target name="bagel"> <url>indexdata.dk</url> <target-timeout>240</target-timeout> <client-timeout>180</client-timeout> <attribute type="1" value="1-11,13-1016"/> <attribute type="1" value="*" error="114"/> <syntax type="usmarc"/> <syntax type="none"/> <syntax type="xml" marcxml="1" identifier="info:srw/schema/1/marcxml-v1.1" > <name>marcxml</name> </syntax> <syntax type="*" error="238"/> <preinit>0</preinit> <explain xmlns="http://explain.z3950.org/dtd/2.0/"> <serverInfo> <host>indexdata.dk</host> <port>9000</port> <database>gils</database> </serverInfo> </explain> <cql2rpn>pqf.properties</cql2rpn> </target> </proxy>
The conversion from CQL to RPN is specified by a file whose name,
relative to the working directory, is given in the
cql2rpn element.
A complete Bath/DC conversion file,
pqf.properties
is provided as part of the
yazproxy distribution in the etc
subdirectory.
Explain information is embedded in the configuration file. Note that in this example,only a few mandatory explain elements are specified. A well-behaving server should describe index sets, indexes, record schemas as well.