<chapter id="proxy">
- <!-- $Id: proxy.xml,v 1.1 2002-10-08 11:55:57 adam Exp $ -->
- <title>YAZ Proxy</title>
- <para>
- About YAZ Proxy.
- </para>
-</chapter>
+ <title>The YAZ Proxy</title>
+ <para>
+ The YAZ proxy is a transparent Z39.50-to-Z39.50 gateway. That is,
+ it is a Z39.50 server which has as its back-end a Z39.50 client
+ that forwards requests on to another server (known as the
+ <firstterm>backend target</firstterm>.)
+ </para>
+ <para>
+ The YAZ Proxy is useful for debugging Z39.50 software, logging
+ APDUs, redirecting Z39.50 packages through firewalls, etc.
+ Furthermore, it offers facilities that often
+ boost performance for connectionless Z39.50 clients such
+ as web gateways.
+ </para>
+ <para>
+ 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.
+ </para>
+
+ <section id="proxy-example">
+ <title>Example: Using the Proxy to Log APDUs</title>
+ <para>
+ 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.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ Suppose the server is running on <literal>foo.bar.com</literal>,
+ port 18398. Run the proxy on the machine of your choice, say
+ <literal>your.company.com</literal> like this:
+ </para>
+ <screen>
+ yaz-proxy -a - -t tcp:foo.bar.com:18398 tcp:@:9000
+ </screen>
+ <para>
+ (The <literal>-a -</literal> option requests APDU logging on
+ standard output, <literal>-t tcp:foo.bar.com:18398</literal>
+ specifies where the backend target is, and
+ <literal>tcp:@:9000</literal> tells the proxy to listen on port
+ 9000 and accept connections from any machine.)
+ </para>
+ <para>
+ Now change your client application's configuration so that instead
+ of connecting to <literal>foo.bar.com</literal> port 18398, it
+ connects to <literal>your.company.com</literal> 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:
+ </para>
+ <screen>
+ 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
+ }
+ }
+ }
+ }
+ }
+ </screen>
+ </section>
+
+ <section id="proxy-target">
+ <title>Specifying the Backend Target</title>
+ <para>
+ When the proxy accepts a Z39.50 client session, it
+ determines the backend target by the following rules:
+ <orderedlist>
+ <listitem>
+ <para> If the <literal>InitializeRequest</literal> PDU from the
+ client includes an
+ <link linkend="otherinfo-encoding"><literal>otherInfo</literal></link>
+ element with OID
+ <literal>1.2.840.10003.10.1000.81.1</literal>, then the
+ contents of that element specify the target to be used, in the
+ usual YAZ address format (typically
+ <literal>tcp:<parameter>hostname</parameter>:<parameter>port</parameter></literal>)
+ as described in
+ <ulink url="http://www.indexdata.dk/yaz/doc/comstack.addresses.php"
+ >the Addresses section of the YAZ manual</ulink>.
+ </para>
+ </listitem>
+ <listitem>
+ <para> Otherwise, the Proxy uses the default target, if one was
+ specified on the command-line with the <literal>-t</literal>
+ option.
+ </para>
+ </listitem>
+ <listitem>
+ <para> Otherwise, the proxy closes the connection with
+ the client.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+ </section>
+ <section id="proxy-keepalive">
+ <title>Keep-alive Facility for Stateless Clients</title>
+ <para>
+ Stateless clients such as web gateways may generate a cookie for a Z39.50
+ session which is sent to the proxy as part of PDUs.
+ In this case, the proxy will keep alive its Z39.50 session
+ to the backend target even when the connection from the client
+ to the proxy is closed. When the client contacts the
+ proxy again, and re-issues the same cookie, the proxy reuses the
+ Z39.50 connection with the backend target.
+ </para>
+ <para>
+ There is no
+ guarantee that the Z39.50 connection to the backend
+ target is kept forever: the proxy will shut it down after certain
+ idle time.
+ So in effect, the connection from the client's
+ point of view should be considered stateless, and the keep-alive
+ facility should be treated only as a performance booster.
+ </para>
+ <para>
+ Cookies may be passed in an
+ <link linkend="otherinfo-encoding"><literal>otherInfo</literal></link>
+ element with OID <literal>1.2.840.10003.10.1000.81.2</literal>.
+ </para>
+ </section>
+
+ <section id="proxy-cache">
+ <title>Query Caching</title>
+ <para>
+ Simple stateless clients often send identical Z39.50 searches
+ in a relatively short period of time (e.g. in order to produce a
+ results-list page, the next page,
+ a single full-record, etc). And for many targets, it's
+ much more expensive to produce a new result set than to
+ reuse an existing one.
+ </para>
+ <para>
+ The proxy tries to solve that by remembering the last query for each
+ backend target, so that if an identical query is received next, it
+ is turned into Present Requests rather than new Search Requests.
+ </para>
+ <note>
+ <para>
+ In a future we release will will probably allows for
+ an arbitrary-sized cache for targets supporting named result sets.
+ </para>
+ </note>
+ <para>
+ You can enable/disable query caching using option -o.
+ </para>
+ </section>
+
+ <section id="proxy-optimizations">
+ <title>Other Optimizations</title>
+ <para>
+ We've had some plans to support caching of result set records,
+ but this has not yet been implemented.
+ </para>
+ </section>
+
+ <section id="proxy-usage">
+ <title>Proxy Usage</title>
+ <para>
+ </para>
+ <refentry id="yaz-proxy">
+ &yaz-proxy-ref;
+ </refentry>
+ </section>
+ <section id="otherinfo-encoding"><title>OtherInformation Encoding</title>
+ <para>
+ The proxy uses the OtherInformation definition to carry
+ information about the target address and cookie.
+ </para>
+ <screen>
+ OtherInformation ::= [201] IMPLICIT SEQUENCE OF SEQUENCE{
+ category [1] IMPLICIT InfoCategory OPTIONAL,
+ information CHOICE{
+ characterInfo [2] IMPLICIT InternationalString,
+ binaryInfo [3] IMPLICIT OCTET STRING,
+ externallyDefinedInfo [4] IMPLICIT EXTERNAL,
+ oid [5] IMPLICIT OBJECT IDENTIFIER}}
+--
+ InfoCategory ::= SEQUENCE{
+ categoryTypeId [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
+ categoryValue [2] IMPLICIT INTEGER}
+ </screen>
+ <para>
+ The <literal>categoryTypeId</literal> is either
+ OID 1.2.840.10003.10.1000.81.1, 1.2.840.10003.10.1000.81.2
+ for proxy target and proxy cookie respectively. The
+ integer element <literal>category</literal> is set to 0.
+ The value proxy and cookie is stored in element
+ <literal>characterInfo</literal> of the <literal>information</literal>
+ choice.
+ </para>
+ </section>
+ </chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
- sgml-parent-document: "zebra.xml"
+ sgml-parent-document: "yaz++.xml"
sgml-local-catalogs: nil
sgml-namecase-general:t
End: