1 /* $Id: sru_util.cpp,v 1.3 2006-12-28 13:26:06 marc Exp $
2 Copyright (c) 2005-2006, Index Data.
4 See the LICENSE file for details
7 #include "sru_util.hpp"
10 //#include <yaz/wrbuf.h>
11 //#include <yaz/querytowrbuf.h>
16 namespace mp = metaproxy_1;
18 // Doxygen doesn't like mp::gdu, so we use this instead
19 namespace mp_util = metaproxy_1::util;
23 bool mp_util::build_sru_debug_package(mp::Package &package)
25 Z_GDU *zgdu_req = package.request().get();
26 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
28 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
29 std::string content = mp_util::http_headers_debug(*http_req);
31 mp_util::http_response(package, content, http_code);
34 package.session().close();
39 bool mp_util::build_simple_explain(mp::Package &package,
41 Z_SRW_PDU *sru_pdu_res,
45 // z3950'fy recordPacking
46 int record_packing = Z_SRW_recordPacking_XML;
47 if (er_req && er_req->recordPacking && 's' == *(er_req->recordPacking))
48 record_packing = Z_SRW_recordPacking_string;
50 // getting database info
51 std::string database("Default");
52 if (er_req && er_req->database)
53 database = er_req->database;
55 // getting host and port info
56 std::string host = package.origin().listen_host();
57 std::string port = mp_util::to_string(package.origin().listen_port());
59 // overwriting host and port info if set from HTTP Host header
60 Z_GDU *zgdu_req = package.request().get();
61 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
63 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
66 std::string http_host_address
67 = mp_util::http_header_value(http_req->headers, "Host");
69 std::string::size_type i = http_host_address.rfind(":");
70 if (i != std::string::npos)
72 host.assign(http_host_address, 0, i);
73 port.assign(http_host_address, i + 1, std::string::npos);
78 // building SRU explain record
79 std::string explain_xml
82 " <serverInfo protocol='SRU'>\n"
85 + mp_util::to_string("</host>\n"
88 + mp_util::to_string("</port>\n"
91 + mp_util::to_string("</database>\n"
96 // preparing explain record insert
97 Z_SRW_explainResponse *sru_res = sru_pdu_res->u.explain_response;
99 // inserting one and only explain record
101 sru_res->record.recordPosition = odr_intdup(odr_en, 1);
102 sru_res->record.recordPacking = record_packing;
103 sru_res->record.recordSchema = "http://explain.z3950.org/dtd/2.0/";
104 sru_res->record.recordData_len = 1 + explain_xml.size();
105 sru_res->record.recordData_buf
106 = odr_strdupn(odr_en, (const char *)explain_xml.c_str(),
107 1 + explain_xml.size());
113 bool mp_util::build_sru_response(mp::Package &package,
116 const Z_SRW_PDU *sru_pdu_res,
118 const char *stylesheet)
121 // SRU request package translation to Z3950 package
123 // std::cout << *(const_cast<Z_SRW_PDU *>(sru_pdu_res)) << "\n";
125 // std::cout << "SRU empty\n";
128 Z_GDU *zgdu_req = package.request().get();
129 if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request)
131 Z_GDU *zgdu_res //= z_get_HTTP_Response(odr_en, 200);
132 = odr_en.create_HTTP_Response(package.session(),
133 zgdu_req->u.HTTP_Request,
136 // adding HTTP response code and headers
137 Z_HTTP_Response * http_res = zgdu_res->u.HTTP_Response;
138 //http_res->code = http_code;
140 std::string ctype("text/xml");
142 ctype += "; charset=";
146 z_HTTP_header_add(odr_en,
147 &http_res->headers, "Content-Type", ctype.c_str());
149 // packaging Z_SOAP into HTML response
150 static Z_SOAP_Handler soap_handlers[4] = {
151 {"http://www.loc.gov/zing/srw/", 0,
152 (Z_SOAP_fun) yaz_srw_codec},
153 {"http://www.loc.gov/zing/srw/v1.0/", 0,
154 (Z_SOAP_fun) yaz_srw_codec},
155 {"http://www.loc.gov/zing/srw/update/", 0,
156 (Z_SOAP_fun) yaz_ucp_codec},
161 // empty stylesheet means NO stylesheet
162 if (stylesheet && *stylesheet == '\0')
165 // encoding SRU package
167 soap->u.generic->p = (void*) sru_pdu_res;
169 z_soap_codec_enc_xsl(odr_en, &soap,
170 &http_res->content_buf, &http_res->content_len,
171 soap_handlers, charset, stylesheet);
174 package.response() = zgdu_res;
177 package.session().close();
183 Z_SRW_PDU * mp_util::decode_sru_request(mp::Package &package,
186 Z_SRW_PDU *sru_pdu_res,
191 Z_GDU *zgdu_req = package.request().get();
192 Z_SRW_PDU *sru_pdu_req = 0;
194 //assert((zgdu_req->which == Z_GDU_HTTP_Request));
196 //ignoring all non HTTP_Request packages
197 if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
201 Z_HTTP_Request* http_req = zgdu_req->u.HTTP_Request;
205 // checking if we got a SRU GET/POST/SOAP HTTP package
206 // closing connection if we did not ...
207 if (0 == yaz_sru_decode(http_req, &sru_pdu_req, &soap,
209 &(sru_pdu_res->u.response->diagnostics),
210 &(sru_pdu_res->u.response->num_diagnostics)))
212 if (sru_pdu_res->u.response->num_diagnostics)
214 //sru_pdu_res = sru_pdu_res_exp;
215 package.session().close();
220 else if (0 == yaz_srw_decode(http_req, &sru_pdu_req, &soap,
225 //sru_pdu_res = sru_pdu_res_exp;
226 package.session().close();
234 mp_util::check_sru_query_exists(mp::Package &package,
236 Z_SRW_PDU *sru_pdu_res,
237 Z_SRW_searchRetrieveRequest const *sr_req)
239 if( (sr_req->query_type == Z_SRW_query_type_cql && !sr_req->query.cql) )
241 yaz_add_srw_diagnostic(odr_en,
242 &(sru_pdu_res->u.response->diagnostics),
243 &(sru_pdu_res->u.response->num_diagnostics),
245 yaz_add_srw_diagnostic(odr_en,
246 &(sru_pdu_res->u.response->diagnostics),
247 &(sru_pdu_res->u.response->num_diagnostics),
248 10, "CQL query is empty");
251 if( (sr_req->query_type == Z_SRW_query_type_xcql && !sr_req->query.xcql) )
253 yaz_add_srw_diagnostic(odr_en,
254 &(sru_pdu_res->u.response->diagnostics),
255 &(sru_pdu_res->u.response->num_diagnostics),
256 10, "XCQL query is empty");
259 if( (sr_req->query_type == Z_SRW_query_type_pqf && !sr_req->query.pqf) )
261 yaz_add_srw_diagnostic(odr_en,
262 &(sru_pdu_res->u.response->diagnostics),
263 &(sru_pdu_res->u.response->num_diagnostics),
264 10, "PQF query is empty");
274 mp_util::build_esn_from_schema(mp::odr &odr_en,
280 Z_ElementSetNames *esn
281 = (Z_ElementSetNames *) odr_malloc(odr_en, sizeof(Z_ElementSetNames));
282 esn->which = Z_ElementSetNames_generic;
283 esn->u.generic = odr_strdup(odr_en, schema);
288 std::ostream& std::operator<<(std::ostream& os, Z_SRW_PDU& srw_pdu)
292 switch(srw_pdu.which) {
293 case Z_SRW_searchRetrieve_request:
294 os << " " << "searchRetrieveRequest";
296 Z_SRW_searchRetrieveRequest *sr = srw_pdu.u.request;
300 os << " " << (sr->database);
304 os << " " << *(sr->startRecord);
307 if (sr->maximumRecords)
308 os << " " << *(sr->maximumRecords);
311 if (sr->recordPacking)
312 os << " " << (sr->recordPacking);
316 if (sr->recordSchema)
317 os << " " << (sr->recordSchema);
321 switch (sr->query_type){
322 case Z_SRW_query_type_cql:
325 os << " " << sr->query.cql;
327 case Z_SRW_query_type_xcql:
330 case Z_SRW_query_type_pqf:
333 os << " " << sr->query.pqf;
339 case Z_SRW_searchRetrieve_response:
340 os << " " << "searchRetrieveResponse";
342 Z_SRW_searchRetrieveResponse *sr = srw_pdu.u.response;
345 if (! (sr->num_diagnostics))
348 if (sr->numberOfRecords)
349 os << " " << *(sr->numberOfRecords);
352 //if (sr->num_records)
353 os << " " << (sr->num_records);
356 if (sr->nextRecordPosition)
357 os << " " << *(sr->nextRecordPosition);
364 if (sr->diagnostics && sr->diagnostics->uri)
365 os << " " << (sr->diagnostics->uri);
368 if (sr->diagnostics && sr->diagnostics->message)
369 os << " " << (sr->diagnostics->message);
372 if (sr->diagnostics && sr->diagnostics->details)
373 os << " " << (sr->diagnostics->details);
382 case Z_SRW_explain_request:
383 os << " " << "explainRequest";
385 case Z_SRW_explain_response:
386 os << " " << "explainResponse";
388 case Z_SRW_scan_request:
389 os << " " << "scanRequest";
391 case Z_SRW_scan_response:
392 os << " " << "scanResponse";
394 case Z_SRW_update_request:
395 os << " " << "updateRequest";
397 case Z_SRW_update_response:
398 os << " " << "updateResponse";
401 os << " " << "UNKNOWN";
410 // mp_util::SRU::SRU_protocol_type
411 // mp_util::SRU::protocol(const Z_HTTP_Request &http_req) const
413 // const std::string mime_urlencoded("application/x-www-form-urlencoded");
414 // const std::string mime_text_xml("text/xml");
415 // const std::string mime_soap_xml("application/soap+xml");
417 // const std::string http_method(http_req.method);
418 // const std::string http_type
419 // = mp_util::http_header_value(http_req.headers, "Content-Type");
421 // if (http_method == "GET")
424 // if (http_method == "POST"
425 // && http_type == mime_urlencoded)
428 // if ( http_method == "POST"
429 // && (http_type == mime_text_xml
430 // || http_type == mime_soap_xml))
437 // mp_util::sru_protocol(const Z_HTTP_Request &http_req) const
439 // const std::string mime_urlencoded("application/x-www-form-urlencoded");
440 // const std::string mime_text_xml("text/xml");
441 // const std::string mime_soap_xml("application/soap+xml");
443 // const std::string http_method(http_req.method);
444 // const std::string http_type
445 // = mp_util::http_header_value(http_req.headers, "Content-Type");
447 // if (http_method == "GET")
450 // if (http_method == "POST"
451 // && http_type == mime_urlencoded)
452 // return "SRU POST";
454 // if ( http_method == "POST"
455 // && (http_type == mime_text_xml
456 // || http_type == mime_soap_xml))
457 // return "SRU SOAP";
463 // mp_util::debug_http(const Z_HTTP_Request &http_req) const
465 // std::string message("<html>\n<body>\n<h1>"
466 // "Metaproxy SRUtoZ3950 filter"
469 // message += "<h3>HTTP Info</h3><br/>\n";
470 // message += "<p>\n";
471 // message += "<b>Method: </b> " + std::string(http_req.method) + "<br/>\n";
472 // message += "<b>Version:</b> " + std::string(http_req.version) + "<br/>\n";
473 // message += "<b>Path: </b> " + std::string(http_req.path) + "<br/>\n";
475 // message += "<b>Content-Type:</b>"
476 // + mp_util::http_header_value(http_req.headers, "Content-Type")
478 // message += "<b>Content-Length:</b>"
479 // + mp_util::http_header_value(http_req.headers, "Content-Length")
481 // message += "</p>\n";
483 // message += "<h3>Headers</h3><br/>\n";
484 // message += "<p>\n";
485 // Z_HTTP_Header* header = http_req.headers;
487 // message += "<b>Header: </b> <i>"
488 // + std::string(header->name) + ":</i> "
489 // + std::string(header->value) + "<br/>\n";
490 // header = header->next;
492 // message += "</p>\n";
493 // message += "</body>\n</html>\n";
497 // void mp_util::http_response(metaproxy_1::Package &package,
498 // const std::string &content,
499 // int http_code) const
502 // Z_GDU *zgdu_req = package.request().get();
503 // Z_GDU *zgdu_res = 0;
506 // = odr.create_HTTP_Response(package.session(),
507 // zgdu_req->u.HTTP_Request,
510 // zgdu_res->u.HTTP_Response->content_len = content.size();
511 // zgdu_res->u.HTTP_Response->content_buf
512 // = (char*) odr_malloc(odr, zgdu_res->u.HTTP_Response->content_len);
514 // strncpy(zgdu_res->u.HTTP_Response->content_buf,
515 // content.c_str(), zgdu_res->u.HTTP_Response->content_len);
517 // //z_HTTP_header_add(odr, &hres->headers,
518 // // "Content-Type", content_type.c_str());
519 // package.response() = zgdu_res;
525 * indent-tabs-mode: nil
526 * c-file-style: "stroustrup"
528 * vim: shiftwidth=4 tabstop=8 expandtab