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</title>
162 The keep-alive is a facility where the proxy keeps the connection to the
163 backend - even if the client closes the connection to the proxy.
166 If a new or another client connects to the proxy again and requests the
167 same backend it will be reassigned to this backend. In this case, the
168 proxy sends an initialize response directly to the client and an
169 initialize handshake with the backend is omitted.
172 When a client reconnects, query and record caching works better, if the
173 proxy assigns it to the same backend as before. And the result set
174 (if any) is re-used. To achive this, Index Data defined a session
175 cookie which identifies the backend session.
178 The cookie is defined by the client and is sent as part of the
179 Initialize Request and passed in an
180 <link linkend="otherinfo-encoding"><literal>otherInfo</literal></link>
181 element with OID <literal>1.2.840.10003.10.1000.81.2</literal>.
184 Clients that do not send a cookie as part of the initialize request
185 may still better performance, since the init handshake is saved.
189 <section id="query-cache">
190 <title>Query Caching</title>
192 Simple stateless clients often send identical Z39.50 searches
193 in a relatively short period of time (e.g. in order to produce a
194 results-list page, the next page,
195 a single full-record, etc). And for many targets, it's
196 much more expensive to produce a new result set than to
197 reuse an existing one.
200 The proxy tries to solve that by remembering the last query for each
201 backend target, so that if an identical query is received next, it
202 is turned into Present Requests rather than new Search Requests.
206 In a future we release will will probably allows for
207 an arbitrary-sized cache for targets supporting named result sets.
211 You can enable/disable query caching using option -o.
215 <section id="record-cache">
216 <title>Record Caching</title>
218 As an option, the proxy may also cache result set records for the
220 The proxy takes into account the Record Syntax and CompSpec.
221 The CompSpec includes simple element set names as well.
225 <section id="query-validation">
226 <title>Query Validation</title>
231 <section id="record-validation">
232 <title>Record Syntax Validation</title>
237 <section id="other-optimizations">
238 <title>Other Optimizations</title>
240 We've had some plans to support global caching of result set records,
241 but this has not yet been implemented.
245 <section id="proxy-usage">
246 <title>Proxy Usage</title>
249 <refentry id="yaz-proxy">
253 <section id="otherinfo-encoding"><title>OtherInformation Encoding</title>
255 The proxy uses the OtherInformation definition to carry
256 information about the target address and cookie.
259 OtherInformation ::= [201] IMPLICIT SEQUENCE OF SEQUENCE{
260 category [1] IMPLICIT InfoCategory OPTIONAL,
262 characterInfo [2] IMPLICIT InternationalString,
263 binaryInfo [3] IMPLICIT OCTET STRING,
264 externallyDefinedInfo [4] IMPLICIT EXTERNAL,
265 oid [5] IMPLICIT OBJECT IDENTIFIER}}
267 InfoCategory ::= SEQUENCE{
268 categoryTypeId [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
269 categoryValue [2] IMPLICIT INTEGER}
272 The <literal>categoryTypeId</literal> is either
273 OID 1.2.840.10003.10.1000.81.1, 1.2.840.10003.10.1000.81.2
274 for proxy target and proxy cookie respectively. The
275 integer element <literal>category</literal> is set to 0.
276 The value proxy and cookie is stored in element
277 <literal>characterInfo</literal> of the <literal>information</literal>
282 <!-- Keep this comment at the end of the file
287 sgml-minimize-attributes:nil
288 sgml-always-quote-attributes:t
291 sgml-parent-document: "yaz++.xml"
292 sgml-local-catalogs: nil
293 sgml-namecase-general:t