24 #include <sys/types.h>
33 #include <yaz/snprintf.h>
34 #include <yaz/yaz-util.h>
35 #include <yaz/malloc_info.h>
46 #define PAZPAR2_PROTOCOL_VERSION "1"
48 #define HTTP_COMMAND_RESPONSE_PREFIX "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
76 if (version && strcmp(version,
"")) {
77 version_no = atoi(version);
92 yaz_log(YLOG_DEBUG,
"%s http_sessions=%d", delta == 0 ?
"" :
93 (delta > 0 ?
"INC" :
"DEC"), sessions);
104 hs->
log_level = yaz_log_module_level(
"http");
118 nmem_destroy(s->
nmem);
121 yaz_mutex_destroy(&hs->
mutex);
138 NMEM
nmem = nmem_create();
142 sprintf(tmp_str,
"session#%u", sesid);
156 "http_session_timeout");
160 "HTTP session create. timeout chan=%p ses=%d",
171 int must_destroy = 0;
176 "HTTP session destroy");
197 nmem_destroy(s->
nmem);
202 "Destroy delayed. Active clients (%d-%d)",
210 struct pazpar2_error_msg {
214 static const struct pazpar2_error_msg ar[] = {
234 if (code == ar[i].code)
243 const char *addinfo,
const char *addinfo2)
246 WRBUF text = wrbuf_alloc();
247 const char *http_status =
"417";
248 const char *msg =
get_msg(code);
250 rs->
msg = nmem_strdup(c->
nmem, msg);
251 strcpy(rs->
code, http_status);
254 "<error code=\"%d\" msg=\"%s\">", (
int) code, msg);
257 wrbuf_xmlputs(text, addinfo);
260 wrbuf_xmlputs(text,
": ");
261 wrbuf_xmlputs(text, addinfo2);
264 wrbuf_puts(text,
"</error>");
266 yaz_log(YLOG_WARN,
"HTTP %s %s%s%s", http_status,
267 msg, addinfo ?
": " :
"" , addinfo ? addinfo :
"");
268 rs->
payload = nmem_strdup(c->
nmem, wrbuf_cstr(text));
277 error2(rs, code, addinfo, 0);
282 wrbuf_rewind(c->
wrbuf);
285 wrbuf_printf(c->
wrbuf,
"<%s>", command);
291 wrbuf_puts(c->
wrbuf,
"<status>OK</status>");
299 wrbuf_printf(c->
wrbuf,
"</%s>", command);
319 if (gettimeofday(&t, 0) < 0)
321 yaz_log(YLOG_WARN|YLOG_ERRNO,
"gettimeofday");
327 res = ((res << 8) | (seq & 0xff)) & ((1U << 31) - 1);
379 NMEM nmem = nmem_create();
382 if (strchr(a->
name,
'['))
390 nmem_strsplit(nmem,
"[]", a->
name, &res, &num);
407 yaz_log(YLOG_WARN,
"exit");
423 int ignored_content = 0;
428 if (yaz_strcmp_del(
"text/xml", content_type,
"; "))
439 root_n = xmlDocGetRootElement(doc);
464 "Ignoring content (Content-Type must be text/xml)");
465 if (!clear || *clear ==
'0')
474 wrbuf_printf(c->
wrbuf,
"<session>%d", sesid);
477 wrbuf_puts(c->
wrbuf,
".");
480 wrbuf_puts(c->
wrbuf,
"</session>"
483 wrbuf_printf(c->
wrbuf,
"<keepAlive>%d</keepAlive>\n",
509 if (yaz_strcmp_del(
"text/xml", content_type,
"; "))
512 "Ignoring content (Content-Type must be text/xml)");
525 root_n = xmlDocGetRootElement(doc);
547 const char *cmd_status)
564 wrbuf_printf(c->
wrbuf,
"<status>%s</status>\n", cmd_status);
565 wrbuf_printf(c->
wrbuf,
"<activeclients>%d</activeclients>\n", status);
577 const char *status = 0;
579 if (report && !strcmp(
"status", report))
584 "termlist watch released");
597 int report_status = 0;
598 int report_error = 0;
599 const char *status_message = 0;
602 if (report && !strcmp(
"error", report))
605 status_message =
"OK";
607 if (report && !strcmp(
"status", report))
610 status_message =
"OK";
616 if (block && !strcmp(
"1", block) && active_clients)
623 "multiple times on termlist block. Not supported!");
629 else if (report_status)
630 status_message =
"WARNING (Already blocked on termlist)";
633 "Ignoring termlist block. Return current result");
638 "Blocking on command termlist");
653 wrbuf_printf(c->
wrbuf,
"<http_count>%u</http_count>\n",
655 wrbuf_printf(c->
wrbuf,
"<http_nmem>%zu</http_nmem>\n",
656 nmem_total(s->
nmem) );
658 wrbuf_printf(c->
wrbuf,
"<session_nmem>%zu</session_nmem>\n", session_nmem);
687 const char *cmd_status)
702 wrbuf_printf(c->
wrbuf,
"<status>%s</status>", cmd_status);
707 "Empty bytarget Response. No targets found!");
708 for (i = 0; i < count; i++)
710 wrbuf_puts(c->
wrbuf,
"\n<target>");
712 wrbuf_puts(c->
wrbuf,
"<id>");
713 wrbuf_xmlputs(c->
wrbuf, ht[i].
id);
714 wrbuf_puts(c->
wrbuf,
"</id>\n");
718 wrbuf_puts(c->
wrbuf,
"<name>");
720 wrbuf_puts(c->
wrbuf,
"</name>\n");
723 wrbuf_printf(c->
wrbuf,
"<hits>" ODR_INT_PRINTF
"</hits>\n", ht[i].
hits);
724 wrbuf_printf(c->
wrbuf,
"<diagnostic>%d</diagnostic>\n",
728 wrbuf_puts(c->
wrbuf,
"<message>");
730 wrbuf_puts(c->
wrbuf,
"</message>\n");
731 wrbuf_puts(c->
wrbuf,
"<addinfo>");
734 wrbuf_puts(c->
wrbuf,
"</addinfo>\n");
737 wrbuf_printf(c->
wrbuf,
"<records>%d</records>\n",
739 wrbuf_printf(c->
wrbuf,
"<filtered>%d</filtered>\n", ht[i].
filtered);
742 wrbuf_printf(c->
wrbuf,
"<approximation>" ODR_INT_PRINTF
745 wrbuf_puts(c->
wrbuf,
"<state>");
747 wrbuf_puts(c->
wrbuf,
"</state>\n");
748 if (settings && *settings ==
'1')
750 wrbuf_puts(c->
wrbuf,
"<settings>\n");
752 wrbuf_puts(c->
wrbuf,
"</settings>\n");
756 wrbuf_puts(c->
wrbuf,
"<suggestions>");
758 wrbuf_puts(c->
wrbuf,
"</suggestions>");
762 wrbuf_puts(c->
wrbuf,
"<query_type>");
764 wrbuf_puts(c->
wrbuf,
"</query_type>\n");
765 wrbuf_puts(c->
wrbuf,
"<query_data>");
767 wrbuf_puts(c->
wrbuf,
"</query_data>\n");
769 wrbuf_puts(c->
wrbuf,
"</target>");
778 const char *status_message =
"OK";
782 "bytarget watch released");
788 "No Session found for released bytarget watch");
799 int report_error = 0;
800 int report_status = 0;
801 const char *status_message =
"OK";
804 if (report && !strcmp(
"error", report))
806 if (report && !strcmp(
"status", report))
813 if (block && !strcmp(
"1", block) && no_active)
820 "multiple times on bytarget block. Not supported!");
827 else if (report_status)
828 status_message =
"WARNING (Already blocked on bytarget)";
831 " Return current result.");
836 "Blocking on command bytarget");
855 if (!cmd->
brief && !(flags & 1))
857 for (md = ml[imeta]; md; md = md->
next)
861 for (i = 0; i < indent; i++)
863 wrbuf_printf(w,
"<md-%s", cmd->
name);
865 for (; attr; attr = attr->
next)
867 wrbuf_printf(w,
" %s=\"", attr->
name);
868 wrbuf_xmlputs(w, attr->
value);
889 wrbuf_puts(w,
"[can't represent]");
892 wrbuf_printf(w,
"</md-%s>\n", cmd->
name);
904 wrbuf_puts(w,
" <location id=\"");
906 wrbuf_puts(w,
"\"\n");
908 wrbuf_puts(w,
" name=\"");
909 wrbuf_xmlputs(w, *
name ?
name :
"Unknown");
910 wrbuf_puts(w,
"\" ");
912 wrbuf_puts(w,
"checksum=\"");
914 wrbuf_puts(w,
"\">\n");
917 wrbuf_puts(w,
" </location>\n");
939 wrbuf_write(c->
wrbuf, buf, sz);
953 wrbuf_write(c->
wrbuf, buf, sz);
980 unsigned flags = (snippets && *snippets ==
'1') ? 3 : 1;
990 wrbuf_rewind(c->
wrbuf);
1004 if (offsetstr || checksumstr)
1013 if (binarystr && *binarystr !=
'0')
1018 unsigned v = strtoul(checksumstr, 0, 10);
1019 for (i = 0; r; r = r->
next)
1027 int offset = atoi(offsetstr);
1028 for (i = 0; i < offset && r; r = r->
next, i++)
1057 wrbuf_puts(c->
wrbuf,
"\n <recid>");
1059 wrbuf_puts(c->
wrbuf,
"</recid>\n");
1062 wrbuf_puts(c->
wrbuf,
" <prevrecid>");
1064 wrbuf_puts(c->
wrbuf,
"</prevrecid>\n");
1068 wrbuf_puts(c->
wrbuf,
" <nextrecid>");
1070 wrbuf_puts(c->
wrbuf,
"</nextrecid>\n");
1072 wrbuf_printf(c->
wrbuf,
" <activeclients>%d</activeclients>\n",
1089 "record watch released");
1118 unsigned flags = (snippets && *snippets ==
'1') ? 2 : 0;
1124 Odr_int approx_hits;
1135 startn = atoi(start);
1155 wrbuf_printf(c->
wrbuf,
"\n<activeclients>%d</activeclients>\n", active);
1156 wrbuf_printf(c->
wrbuf,
"<merged>%d</merged>\n", total);
1157 wrbuf_printf(c->
wrbuf,
"<total>" ODR_INT_PRINTF
"</total>\n", total_hits);
1159 wrbuf_printf(c->
wrbuf,
"<approximation>" ODR_INT_PRINTF
1160 "</approximation>\n", approx_hits);
1162 wrbuf_printf(c->
wrbuf,
"<start>%d</start>\n", startn);
1163 wrbuf_printf(c->
wrbuf,
"<num>%d</num>\n", numn);
1165 for (i = 0; i < numn; i++)
1172 wrbuf_puts(c->
wrbuf,
"<hit>\n");
1174 for (ccount = 0, p = rl[i]->records; p; p = p->
next, ccount++)
1176 wrbuf_printf(c->
wrbuf,
" <count>%d</count>\n", ccount);
1177 if (strstr(sort,
"relevance"))
1179 wrbuf_printf(c->
wrbuf,
" <relevance>%d</relevance>\n",
1183 wrbuf_printf(c->
wrbuf,
" <relevance_info>\n");
1186 wrbuf_printf(c->
wrbuf,
" </relevance_info>\n");
1189 wrbuf_puts(c->
wrbuf,
" <recid>");
1191 wrbuf_puts(c->
wrbuf,
"</recid>\n");
1192 wrbuf_puts(c->
wrbuf,
"</hit>\n");
1207 "show watch released");
1229 int report_error = 0;
1231 if (block_error && !strcmp(
"1", block_error))
1250 if (!strcmp(block,
"preferred")
1259 "Blocking on command show (preferred targets)");
1266 " multiple times on show (preferred targets) block."
1271 "show (preferred targets)");
1277 "Ignoring show(preferred) block."
1278 " Returning current result");
1289 " multiple times on show block. Not supported!");
1298 " Returning current result");
1303 "Blocking on command show");
1337 const char *addinfo = 0;
1338 const char *addinfo2 = 0;
1351 if (!yaz_utf8_check(query))
1369 &addinfo, &addinfo2, sp, mergekey, rank);
1372 error2(rs, code, addinfo, addinfo2);
1402 wrbuf_printf(c->
wrbuf,
"\n <activeclients>%d</activeclients>\n", clients);
1403 wrbuf_printf(c->
wrbuf,
" <hits>" ODR_INT_PRINTF
"</hits>\n", stat.
num_hits);
1409 wrbuf_printf(c->
wrbuf,
" <idle>%d</idle>\n", stat.
num_idle);
1412 wrbuf_printf(c->
wrbuf,
" <progress>%.2f</progress>\n", progress);
1430 char yaz_version_str[20];
1431 char yaz_sha1_str[42];
1434 wrbuf_puts(c->
wrbuf,
"\n <version>\n");
1435 wrbuf_puts(c->
wrbuf,
" <pazpar2");
1436 #ifdef PAZPAR2_VERSION_SHA1
1439 wrbuf_puts(c->
wrbuf,
">");
1441 wrbuf_puts(c->
wrbuf,
"</pazpar2>\n");
1443 yaz_version(yaz_version_str, yaz_sha1_str);
1444 wrbuf_puts(c->
wrbuf,
" <yaz compiled=\"");
1445 wrbuf_xmlputs(c->
wrbuf, YAZ_VERSION);
1446 wrbuf_puts(c->
wrbuf,
"\" sha1=\"");
1447 wrbuf_xmlputs(c->
wrbuf, yaz_sha1_str);
1448 wrbuf_puts(c->
wrbuf,
"\">");
1449 wrbuf_xmlputs(c->
wrbuf, yaz_version_str);
1450 wrbuf_puts(c->
wrbuf,
"</yaz>\n");
1452 wrbuf_puts(c->
wrbuf,
" </version>\n");
1455 char hostname_str[64];
1456 if (gethostname(hostname_str,
sizeof(hostname_str)) == 0)
1458 wrbuf_puts(c->
wrbuf,
" <host>");
1459 wrbuf_xmlputs(c->
wrbuf, hostname_str);
1460 wrbuf_puts(c->
wrbuf,
"</host>\n");
1466 wrbuf_malloc_info(c->
wrbuf);
1469 if (nmem_get_status(buf,
sizeof(buf) - 1) == 0)
1470 wrbuf_puts(c->
wrbuf, buf);
1506 http_addheader(rs,
"Cache-Control",
"no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
int clients_get_count(void)
const char * client_get_id(struct client *cl)
int client_show_raw_begin(struct client *cl, int position, const char *syntax, const char *esn, void *data, void(*error_handler)(void *data, const char *addinfo), void(*record_handler)(void *data, const char *buf, size_t sz), int binary, const char *nativesyntax)
struct session_database * client_get_database(struct client *cl)
#define PAZPAR2_VERSION_SHA1
IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags, const char *name)
void iochan_destroy(IOCHAN chan)
int iochan_add(iochan_man_t man, IOCHAN chan, int slack)
#define iochan_settimeout(i, t)
#define iochan_activity(i)
#define iochan_getdata(i)
#define iochan_setdata(i, d)
struct http_response * http_create_response(struct http_channel *c)
const char * http_lookup_header(struct http_header *header, const char *name)
void http_remove_observer(http_channel_observer_t obs)
const char * http_argbyname(struct http_request *r, const char *name)
void http_send_response(struct http_channel *ch)
void http_close_server(struct conf_server *server)
void http_addheader(struct http_response *r, const char *name, const char *value)
http_channel_observer_t http_add_observer(struct http_channel *c, void *data, http_channel_destroy_t des)
struct http_channel * http_channel_observer_chan(http_channel_observer_t obs)
static struct http_session * locate_session(struct http_channel *c)
static void cmd_record(struct http_channel *c)
int http_session_use(int delta)
static void bytarget_result_ready(void *data)
http_sessions_t http_sessions_create(void)
int get_version(struct http_request *rq)
void http_session_destroy(struct http_session *s)
static void cmd_record_ready(void *data)
static void show_raw_record_ok_binary(void *data, const char *buf, size_t sz)
static void apply_local_setting(void *client_data, struct setting *set)
static void error2(struct http_response *rs, enum pazpar2_error_code code, const char *addinfo, const char *addinfo2)
static void termlist_result_ready(void *data)
static void show_record(struct http_channel *c, struct http_session *s)
void(* fun)(struct http_channel *c)
static void cmd_ping(struct http_channel *c)
#define PAZPAR2_PROTOCOL_VERSION
static void cmd_bytarget(struct http_channel *c)
struct http_session * http_session_create(struct conf_service *service, http_sessions_t http_sessions, unsigned int sesid)
void http_sessions_destroy(http_sessions_t hs)
static void session_timeout(IOCHAN i, int event)
void http_command(struct http_channel *c)
static void termlist_response(struct http_channel *c, struct http_session *s, const char *cmd_status)
static void cmd_termlist(struct http_channel *c)
static void cmd_service(struct http_channel *c)
static void write_subrecord(struct record *r, WRBUF w, struct conf_service *service, unsigned flags, int indent)
static void show_raw_record_ok(void *data, const char *buf, size_t sz)
void show_raw_reset(void *data, struct http_channel *c, void *data2)
static void cmd_settings(struct http_channel *c)
static void response_open_ok(struct http_channel *c, const char *command)
static void cmd_init(struct http_channel *c)
static void response_close(struct http_channel *c, const char *command)
static void response_open_command(struct http_channel *c, const char *command)
static void cmd_info(struct http_channel *c)
size_t session_get_memory_status(struct session *session)
static void cmd_stat(struct http_channel *c)
static void cmd_session_status(struct http_channel *c)
static void cmd_search(struct http_channel *c)
static void release_session(struct http_channel *c, struct http_session *session)
static void error(struct http_response *rs, enum pazpar2_error_code code, const char *addinfo)
static void cmd_stop(struct http_channel *c)
static void bytarget_response(struct http_channel *c, struct http_session *s, const char *cmd_status)
static const char * get_msg(enum pazpar2_error_code code)
#define HTTP_COMMAND_RESPONSE_PREFIX
static int g_http_sessions
static void show_raw_record_error(void *data, const char *addinfo)
static void write_metadata(WRBUF w, struct conf_service *service, struct record_metadata **ml, unsigned flags, int indent)
static int process_settings(struct session *se, struct http_request *rq, struct http_response *rs)
static void show_records_ready(void *data)
static void cmd_exit(struct http_channel *c)
unsigned int make_sessionid(void)
static void cmd_show(struct http_channel *c)
static void show_records(struct http_channel *c, struct http_session *s, int active)
static YAZ_MUTEX g_http_session_mutex
static void session_status(struct http_channel *c, struct http_session *s)
struct parameters global_parameters
struct conf_service * locate_service(struct conf_server *server, const char *service_id)
void info_services(struct conf_server *server, WRBUF w)
struct conf_service * service_create(struct conf_server *server, xmlNode *node)
void pazpar2_mutex_create(YAZ_MUTEX *p, const char *name)
struct reclist_sortparms * reclist_parse_sortparms(NMEM nmem, const char *parms, struct conf_service *service)
int reclist_get_num_records(struct reclist *l)
const char * session_setting_oneval(struct session_database *db, int offset)
enum pazpar2_error_code session_search(struct session *se, const char *query, const char *startrecs, const char *maxrecs, const char *filter, const char *limit, const char **addinfo, const char **addinfo2, struct reclist_sortparms *sp, const char *mergekey, const char *rank)
void session_stop(struct session *se)
void session_apply_setting(struct session *se, const char *dbname, const char *name, const char *value)
void session_sort(struct session *se, struct reclist_sortparms *sp, const char *mergekey, const char *rank)
struct session * session_create(NMEM nmem, struct conf_service *service, unsigned session_id)
void session_init_databases(struct session *se)
void show_range_stop(struct session *se, struct record_cluster **recs)
int session_set_watch(struct session *s, int what, session_watchfun fun, void *data, struct http_channel *chan)
void statistics(struct session *se, struct statistics *stat)
struct hitsbytarget * get_hitsbytarget(struct session *se, int *count, NMEM nmem)
void perform_termlist(struct http_channel *c, struct session *se, const char *name, int num, int version)
int sessions_get_count(void)
struct record_cluster ** show_range_start(struct session *se, struct reclist_sortparms *sp, int start, int *num, int *total, Odr_int *sumhits, Odr_int *approx_hits, void(*show_records_ready)(void *data), struct http_channel *chan)
void session_destroy(struct session *se)
void show_single_stop(struct session *se, struct record_cluster *rec)
void session_log(struct session *s, int level, const char *fmt,...)
int session_active_clients(struct session *s)
int session_is_preferred_clients_ready(struct session *s)
struct record_cluster * show_single_start(struct session *se, const char *id, struct record_cluster **prev_r, struct record_cluster **next_r)
#define SESSION_WATCH_BYTARGET
@ PAZPAR2_MISSING_PARAMETER
@ PAZPAR2_MALFORMED_PARAMETER_VALUE
@ PAZPAR2_HITCOUNTS_FAILED
@ PAZPAR2_MALFORMED_PARAMETER_ENCODING
@ PAZPAR2_NOT_IMPLEMENTED
@ PAZPAR2_ALREADY_BLOCKED
@ PAZPAR2_MALFORMED_SETTING
#define SESSION_WATCH_TERMLIST
#define SESSION_WATCH_SHOW
#define SESSION_WATCH_SHOW_PREF
#define SESSION_WATCH_RECORD
int settings_read_node_x(xmlNode *n, void *client_data, void(*fun)(void *client_data, struct setting *set))
struct conf_server * server
struct conf_metadata * metadata
struct http_argument * next
struct http_request * request
http_sessions_t http_sessions
struct http_response * response
struct conf_server * server
struct http_header * headers
struct http_argument * arguments
struct http_channel * channel
http_sessions_t http_sessions
struct session * psession
struct http_session * next
struct http_session * session_list
struct record_metadata ** metadata
struct record_metadata ** metadata
struct conf_service * service
struct data_types::@3 text
struct data_types::@4 number