2 <title>The YAZ Proxy</title>
4 The YAZ proxy is a transparent Z39.50-to-Z39.50 gateway. That is,
5 it is a Z39.50 server which has as its back-end a Z39.50 client
6 that forwards requests on to another server (known as the
7 <firstterm>backend target</firstterm>.)
10 The YAZ Proxy is useful for debugging Z39.50 software, logging
11 APDUs, redirecting Z39.50 packages through firewalls, etc.
12 Furthermore, it offers facilities that often
13 boost performance for connectionless Z39.50 clients such
17 Unlike most other server software, the proxy runs single-threaded,
18 single-process. Every I/O operation
19 is non-blocking so it is very lightweight and extremely fast.
20 It does not store any state information on the hard drive,
21 except any log files you ask for.
24 <section id="proxy-example">
25 <title>Example: Using the Proxy to Log APDUs</title>
27 Suppose you use a commercial Z39.50 client for which you do not
28 have source code, and it's not behaving how you think it should
29 when running against some specific server that you have no control
30 over. One way to diagnose the problem is to find out what packets
31 (APDUs) are being sent and received, but not all client
32 applications have facilities to do APDU logging.
35 No problem. Run the proxy on a friendly machine, get it to log
36 APDUs, and point the errant client at the proxy instead of
37 directly at the server that's causing it problems.
40 Suppose the server is running on <literal>foo.bar.com</literal>,
41 port 18398. Run the proxy on the machine of your choice, say
42 <literal>your.company.com</literal> like this:
45 yaz-proxy -a - -t tcp:foo.bar.com:18398 tcp:@:9000
48 (The <literal>-a -</literal> option requests APDU logging on
49 standard output, <literal>-t tcp:foo.bar.com:18398</literal>
50 specifies where the backend target is, and
51 <literal>tcp:@:9000</literal> tells the proxy to listen on port
52 9000 and accept connections from any machine.)
55 Now change your client application's configuration so that instead
56 of connecting to <literal>foo.bar.com</literal> port 18398, it
57 connects to <literal>your.company.com</literal> port 9000, and
58 start it up. It will work exactly as usual, but all the packets
59 will be sent via the proxy, which will generate a log like this:
64 referenceId OCTETSTRING(len=4) 69 6E 69 74
65 protocolVersion BITSTRING(len=1)
66 options BITSTRING(len=2)
67 preferredMessageSize 1048576
68 maximumRecordSize 1048576
69 implementationId 'Mike Taylor (id=169)'
70 implementationName 'Net::Z3950.pm (Perl)'
71 implementationVersion '0.31'
75 referenceId OCTETSTRING(len=4) 69 6E 69 74
76 protocolVersion BITSTRING(len=1)
77 options BITSTRING(len=2)
78 preferredMessageSize 1048576
79 maximumRecordSize 1048576
82 implementationName 'GFS/YAZ / Zebra Information Server'
83 implementationVersion 'YAZ 1.9.1 / Zebra 1.3.3'
87 referenceId OCTETSTRING(len=1) 30
90 mediumSetPresentNumber 0
92 resultSetName 'default'
97 smallSetElementSetNames choice
101 mediumSetElementSetNames choice
104 preferredRecordSyntax OID: 1 2 840 10003 5 10
108 attributeSetId OID: 1 2 840 10003 3 1
116 general OCTETSTRING(len=7) 6D 69 6E 65 72 61 6C
125 <section id="proxy-target">
126 <title>Specifying the Backend Target</title>
128 When the proxy accepts a Z39.50 client session, it
129 determines the backend target by the following rules:
132 <para> If the <literal>InitializeRequest</literal> PDU from the
134 <link linkend="otherinfo-encoding"><literal>otherInfo</literal></link>
136 <literal>1.2.840.10003.10.1000.81.1</literal>, then the
137 contents of that element specify the target to be used, in the
138 usual YAZ address format (typically
139 <literal>tcp:<parameter>hostname</parameter>:<parameter>port</parameter></literal>)
141 <ulink url="http://www.indexdata.dk/yaz/doc/comstack.addresses.php"
142 >the Addresses section of the YAZ manual</ulink>.
146 <para> Otherwise, the Proxy uses the default target, if one was
147 specified on the command-line with the <literal>-t</literal>
152 <para> Otherwise, the proxy closes the connection with
159 <section id="proxy-keepalive">
160 <title>Keep-alive Facility for Stateless Clients</title>
162 Stateless clients such as web gateways may generate a cookie for a Z39.50
163 session which is sent to the proxy as part of PDUs.
164 In this case, the proxy will keep alive its Z39.50 session
165 to the backend target even when the connection from the client
166 to the proxy is closed. When the client contacts the
167 proxy again, and re-issues the same cookie, the proxy reuses the
168 Z39.50 connection with the backend target.
172 guarantee that the Z39.50 connection to the backend
173 target is kept forever: the proxy will shut it down after certain
175 So in effect, the connection from the client's
176 point of view should be considered stateless, and the keep-alive
177 facility should be treated only as a performance booster.
180 Cookies may be passed in an
181 <link linkend="otherinfo-encoding"><literal>otherInfo</literal></link>
182 element with OID <literal>1.2.840.10003.10.1000.81.2</literal>.
186 <section id="proxy-cache">
187 <title>Query Caching</title>
189 Simple stateless clients often send identical Z39.50 searches
190 in a relatively short period of time (e.g. in order to produce a
191 results-list page, the next page,
192 a single full-record, etc). And for many targets, it's
193 much more expensive to produce a new result set than to
194 reuse an existing one.
197 The proxy tries to solve that by remembering the last query for each
198 backend target, so that if an identical query is received next, it
199 is turned into Present Requests rather than new Search Requests.
203 In a future we release will will probably allows for
204 an arbitrary-sized cache for targets supporting named result sets.
208 You can enable/disable query caching using option -o.
212 <section id="proxy-optimizations">
213 <title>Other Optimizations</title>
215 We've had some plans to support caching of result set records,
216 but this has not yet been implemented.
220 <section id="proxy-usage">
221 <title>Proxy Usage</title>
224 <refentry id="yaz-proxy">
228 <section id="otherinfo-encoding"><title>OtherInformation Encoding</title>
230 The proxy uses the OtherInformation definition to carry
231 information about the target address and cookie.
234 OtherInformation ::= [201] IMPLICIT SEQUENCE OF SEQUENCE{
235 category [1] IMPLICIT InfoCategory OPTIONAL,
237 characterInfo [2] IMPLICIT InternationalString,
238 binaryInfo [3] IMPLICIT OCTET STRING,
239 externallyDefinedInfo [4] IMPLICIT EXTERNAL,
240 oid [5] IMPLICIT OBJECT IDENTIFIER}}
242 InfoCategory ::= SEQUENCE{
243 categoryTypeId [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
244 categoryValue [2] IMPLICIT INTEGER}
247 The <literal>categoryTypeId</literal> is either
248 OID 1.2.840.10003.10.1000.81.1, 1.2.840.10003.10.1000.81.2
249 for proxy target and proxy cookie respectively. The
250 integer element <literal>category</literal> is set to 0.
251 The value proxy and cookie is stored in element
252 <literal>characterInfo</literal> of the <literal>information</literal>
257 <!-- Keep this comment at the end of the file
262 sgml-minimize-attributes:nil
263 sgml-always-quote-attributes:t
266 sgml-parent-document: "yaz++.xml"
267 sgml-local-catalogs: nil
268 sgml-namecase-general:t