USMARC to MARCXML conversion. Check for reconfigure in more places
[yazpp-moved-to-github.git] / doc / proxy.xml
1 <chapter id="proxy">
2  <title>The YAZ Proxy</title>
3   <para>
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>.)
8   </para>
9   <para>
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
14    as web gateways.
15   </para>
16   <para>
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.
22   </para>
23
24   <section id="proxy-example">
25    <title>Example: Using the Proxy to Log APDUs</title>
26    <para>
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.
33    </para>
34    <para>
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.
38    </para>
39    <para>
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:
43    </para>
44    <screen>
45     yaz-proxy -a - -t tcp:foo.bar.com:18398 tcp:@:9000
46    </screen>
47    <para>
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.)
53    </para>
54    <para>
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:
60    </para>
61    <screen>
62     decode choice
63     initRequest {
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'
72     }
73     encode choice
74     initResponse {
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
80         result TRUE
81         implementationId '81'
82         implementationName 'GFS/YAZ / Zebra Information Server'
83         implementationVersion 'YAZ 1.9.1 / Zebra 1.3.3'
84     }
85     decode choice
86     searchRequest {
87         referenceId OCTETSTRING(len=1) 30
88         smallSetUpperBound 0
89         largeSetLowerBound 1
90         mediumSetPresentNumber 0
91         replaceIndicator TRUE
92         resultSetName 'default'
93         databaseNames {
94             'gils'
95         }
96         {
97             smallSetElementSetNames choice
98             generic 'F'
99         }
100         {
101             mediumSetElementSetNames choice
102             generic 'B'
103         }
104         preferredRecordSyntax OID: 1 2 840 10003 5 10
105         {
106             query choice
107             type_1 {
108                 attributeSetId OID: 1 2 840 10003 3 1
109                 RPNStructure choice
110                 {
111                     simple choice
112                     attributesPlusTerm {
113                         attributes {
114                         }
115                         term choice
116                         general OCTETSTRING(len=7) 6D 69 6E 65 72 61 6C
117                     }
118                 }
119             }
120         }
121     }
122    </screen>
123   </section>
124
125   <section id="proxy-target">
126    <title>Specifying the Backend Target</title>
127    <para>
128     When the proxy accepts a Z39.50 client session, it
129     determines the backend target by the following rules:
130     <orderedlist>
131      <listitem>
132       <para> If the <literal>InitializeRequest</literal> PDU from the
133        client includes an 
134        <link linkend="otherinfo-encoding"><literal>otherInfo</literal></link>
135        element with OID
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>)
140        as described in
141        <ulink url="http://www.indexdata.dk/yaz/doc/comstack.addresses.php"
142         >the Addresses section of the YAZ manual</ulink>.
143       </para>
144      </listitem>
145      <listitem>
146       <para> Otherwise, the Proxy uses the default target, if one was
147        specified on the command-line with the <literal>-t</literal>
148        option.
149       </para>
150      </listitem>
151      <listitem>
152       <para> Otherwise, the proxy closes the connection with
153        the client.
154       </para>
155      </listitem>
156     </orderedlist>
157    </para>
158   </section>
159   <section id="proxy-keepalive">
160    <title>Keep-alive Facility</title>
161    <para>
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.
164    </para>
165    <para>
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.
170    </para>
171    <para>
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.
176    </para>
177    <para>
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>.
182    </para>
183    <para>
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.
186    </para>
187   </section>
188
189   <section id="query-cache">
190    <title>Query Caching</title>
191    <para>
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.
198    </para>
199    <para>
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.
203    </para>
204    <note>
205     <para>
206      In a future we release will will probably allows for
207      an arbitrary-sized cache for targets supporting named result sets.
208     </para>
209    </note>
210    <para>
211     You can enable/disable query caching using option -o.
212    </para>
213   </section>
214   
215
216   <section id="record-cache">
217   <title>Record Caching</title>
218   <para>
219   As an option, the proxy may also cache result set records for the
220   last search.
221   The proxy takes into account the Record Syntax and CompSpec.
222   The CompSpec includes simple element set names as well.
223   </para>
224   </section>
225
226   <section id="query-validation">
227   <title>Query Validation</title>
228   <para>
229   </para>
230   </section>
231
232   <section id="record-validation">
233   <title>Record Syntax Validation</title>
234   <para>
235   </para>
236   </section>
237
238   <section id="other-optimizations">
239    <title>Other Optimizations</title>
240      <para>
241      We've had some plans to support global caching of result set records,
242     but this has not yet been implemented.
243    </para>
244   </section>
245
246   <section id="proxy-usage">
247    <title>Proxy Usage</title>
248    <para>
249    </para>
250    <refentry id="yaz-proxy">
251     &yaz-proxy-ref;
252    </refentry>
253   </section>
254   <section id="otherinfo-encoding"><title>OtherInformation Encoding</title>
255    <para>
256     The proxy uses the OtherInformation definition to carry
257     information about the target address and cookie.
258    </para>
259    <screen>
260   OtherInformation   ::= [201] IMPLICIT SEQUENCE OF SEQUENCE{
261     category           [1]   IMPLICIT InfoCategory OPTIONAL, 
262     information        CHOICE{
263       characterInfo            [2]  IMPLICIT InternationalString,
264       binaryInfo               [3]  IMPLICIT OCTET STRING,
265       externallyDefinedInfo    [4]  IMPLICIT EXTERNAL,
266       oid                      [5]  IMPLICIT OBJECT IDENTIFIER}}
267 --
268   InfoCategory ::= SEQUENCE{
269       categoryTypeId   [1]   IMPLICIT OBJECT IDENTIFIER OPTIONAL,
270       categoryValue    [2]   IMPLICIT INTEGER}
271   </screen>
272    <para>
273     The <literal>categoryTypeId</literal> is either
274     OID 1.2.840.10003.10.1000.81.1, 1.2.840.10003.10.1000.81.2
275     for proxy target and proxy cookie respectively. The
276     integer element <literal>category</literal> is set to 0.
277     The value proxy and cookie is stored in element
278     <literal>characterInfo</literal> of the <literal>information</literal>
279     choice.
280    </para>
281   </section>
282  </chapter>
283  <!-- Keep this comment at the end of the file
284  Local variables:
285  mode: sgml
286  sgml-omittag:t
287  sgml-shorttag:t
288  sgml-minimize-attributes:nil
289  sgml-always-quote-attributes:t
290  sgml-indent-step:1
291  sgml-indent-data:t
292  sgml-parent-document: "yaz++.xml"
293  sgml-local-catalogs: nil
294  sgml-namecase-general:t
295  End:
296  -->