SOAP and SRU
Introduction
&yaz; uses a very simple implementation of
SOAP that only,
currenly, supports what is sufficient to offer SRU SOAP functionality.
The implementation uses the
tree API of
libxml2 to encode and decode SOAP packages.
Like the Z39.50 ASN.1 module, the &yaz; SRU implementation uses
simple C structs to represent SOAP packages as well as
HTTP packages.
HTTP
&yaz; only offers HTTP as transport carrier for SOAP, but it is
relatively easy to change that.
The following definition of Z_GDU (Generic Data
Unit) allows for both HTTP and Z39.50 in one packet.
#include <yaz/zgdu.h>
#define Z_GDU_Z3950 1
#define Z_GDU_HTTP_Request 2
#define Z_GDU_HTTP_Response 3
typedef struct {
int which;
union {
Z_APDU *z3950;
Z_HTTP_Request *HTTP_Request;
Z_HTTP_Response *HTTP_Response;
} u;
} Z_GDU ;
The corresponding Z_GDU encoder/decoder is z_GDU.
The z3950 is any of the known BER encoded Z39.50
APDUs.
HTTP_Request and HTTP_Response
is the HTTP Request and Response respectively.
SOAP Packages
Every SOAP package in &yaz; is represented as follows:
#include <yaz/soap.h>
typedef struct {
char *fault_code;
char *fault_string;
char *details;
} Z_SOAP_Fault;
typedef struct {
int no;
char *ns;
void *p;
} Z_SOAP_Generic;
#define Z_SOAP_fault 1
#define Z_SOAP_generic 2
#define Z_SOAP_error 3
typedef struct {
int which;
union {
Z_SOAP_Fault *fault;
Z_SOAP_Generic *generic;
Z_SOAP_Fault *soap_error;
} u;
const char *ns;
} Z_SOAP;
The fault and soap_error
arms represent both a SOAP fault - struct
Z_SOAP_Fault. Any other generic
(valid) package is represented by Z_SOAP_Generic.
The ns as part of Z_SOAP
is the namespace for SOAP itself and reflects the SOAP
version. For version 1.1 it is
http://schemas.xmlsoap.org/soap/envelope/,
for version 1.2 it is
http://www.w3.org/2001/06/soap-envelope.
int z_soap_codec(ODR o, Z_SOAP **pp,
char **content_buf, int *content_len,
Z_SOAP_Handler *handlers);
The content_buf and content_len
is XML buffer and length of buffer respectively.
The handlers is a list of SOAP codec
handlers - one handler for each service namespace. For SRU SOAP, the
namespace would be http://www.loc.gov/zing/srw/v1.0/.
When decoding, the z_soap_codec
inspects the XML content
and tries to match one of the services namespaces of the
supplied handlers. If there is a match a handler function
is invoked which decodes that particular SOAP package.
If successful, the returned Z_SOAP package will be
of type Z_SOAP_Generic.
Member no is
set the offset of handler that matched; ns
is set to namespace of matching handler; the void pointer
p is set to the C data structure assocatiated
with the handler.
When a NULL namespace is met (member ns bwlow),
that specifies end-of-list.
Each handler is defined as follows:
typedef struct {
char *ns;
void *client_data;
Z_SOAP_fun f;
} Z_SOAP_Handler;
The ns is namespace of service associated with
handler f. client_data
is user-defined data which is passed to handler.
The prototype for a SOAP service handler is:
int handler(ODR o, void * ptr, void **handler_data,
void *client_data, const char *ns);
The o specifies the mode (decode/encode)
as usual. The second argument, ptr,
is a libxml2 tree node pointer (xmlNodePtr)
and is a pointer to the Body element
of the SOAP package. The handler_data
is an opaque pointer to a C definitions associated with the
SOAP service. client_data is the pointer
which was set as part of the Z_SOAP_handler.
Finally, ns the service namespace.
SRU
SRU SOAP is just one implementation of a SOAP handler as described
in the previous section.
The encoder/decoder handler for SRU is defined as
follows:
#include <yaz/srw.h>
int yaz_srw_codec(ODR o, void * pptr,
Z_SRW_GDU **handler_data,
void *client_data, const char *ns);
Here, Z_SRW_GDU is either
searchRetrieveRequest or a searchRetrieveResponse.
The xQuery and xSortKeys are not handled yet by
the SRW implementation of &yaz;. Explain is also missing.
Future versions of &yaz; will include these features.
The definition of searchRetrieveRequest is:
typedef struct {
#define Z_SRW_query_type_cql 1
#define Z_SRW_query_type_xcql 2
#define Z_SRW_query_type_pqf 3
int query_type;
union {
char *cql;
char *xcql;
char *pqf;
} query;
#define Z_SRW_sort_type_none 1
#define Z_SRW_sort_type_sort 2
#define Z_SRW_sort_type_xSort 3
int sort_type;
union {
char *none;
char *sortKeys;
char *xSortKeys;
} sort;
int *startRecord;
int *maximumRecords;
char *recordSchema;
char *recordPacking;
char *database;
} Z_SRW_searchRetrieveRequest;
Please observe that data of type xsd:string is represented
as a char pointer (char *). A null pointer
means that the element is absent.
Data of type xsd:integer is representd as a pointer to
an int (int *). Again, a null pointer
us used for absent elements.
The SearchRetrieveResponse has the following definition.
typedef struct {
int * numberOfRecords;
char * resultSetId;
int * resultSetIdleTime;
Z_SRW_record *records;
int num_records;
Z_SRW_diagnostic *diagnostics;
int num_diagnostics;
int *nextRecordPosition;
} Z_SRW_searchRetrieveResponse;
The num_records and num_diagnostics
is number of returned records and diagnostics respectively and also
correspond to the "size of" arrays records
and diagnostics.
A retrieval record is defined as follows:
typedef struct {
char *recordSchema;
char *recordData_buf;
int recordData_len;
int *recordPosition;
} Z_SRW_record;
The record data is defined as a buffer of some length so that
data can be of any type. SRW 1.0 currenly doesn't allow for this
(only XML), but future versions might do.
And, a diagnostic as:
typedef struct {
int *code;
char *details;
} Z_SRW_diagnostic;