Add facility to record HTTP requests to Pazpar2
authorAdam Dickmeiss <adam@indexdata.dk>
Sat, 26 Mar 2011 20:18:49 +0000 (21:18 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Sat, 26 Mar 2011 20:18:49 +0000 (21:18 +0100)
The HTTP record facility is enabled by specifying option -R.

doc/pazpar2.xml
src/http.c
src/http.h
src/pazpar2.c
src/pazpar2_config.c
src/pazpar2_config.h

index 9e7b662..32b499c 100644 (file)
@@ -35,6 +35,7 @@
    <arg choice="opt"><option>-h <replaceable>ip:port</replaceable></option></arg>
    <arg choice="opt"><option>-l <replaceable>logfile</replaceable></option></arg>
    <arg choice="opt"><option>-p <replaceable>pidfile</replaceable></option></arg>
+   <arg choice="opt"><option>-R <replaceable>recfile</replaceable></option></arg>
    <arg choice="opt"><option>-t</option></arg>
    <arg choice="opt"><option>-u <replaceable>uid</replaceable></option></arg>
    <arg choice="opt"><option>-V</option></arg>
      </para>
     </listitem>
    </varlistentry>
+   <varlistentry>
+    <term><option>-R <replaceable>recfile</replaceable></option></term>
+    <listitem>
+     <para>
+      If this option is given, HTTP requests are logged to file named
+      <replaceable>recfile</replaceable>.
+     </para>
+    </listitem>
+   </varlistentry>
 
    <varlistentry>
     <term><option>-t</option></term>
index d93c874..1ce0aa4 100644 (file)
@@ -21,6 +21,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <config.h>
 #endif
 
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
 #include <stdio.h>
 #ifdef WIN32
 #include <winsock.h>
@@ -106,6 +110,7 @@ struct http_server
     int ref_count;
     http_sessions_t http_sessions;
     struct sockaddr_in *proxy_addr;
+    FILE *record_file;
 };
 
 struct http_channel_observer_s {
@@ -914,7 +919,18 @@ static void http_io(IOCHAN i, int event)
             }
             if (res <= 0)
             {
+#if HAVE_SYS_TIME_H
+                if (hc->http_server->record_file)
+                {
+                    struct timeval tv;
+                    gettimeofday(&tv, 0);
+                    fprintf(hc->http_server->record_file, "%lld %lld %lld 0\n",
+                            (long long) tv.tv_sec, (long long) tv.tv_usec,
+                            (long long) iochan_getfd(i));
+                }
+#endif
                 http_buf_destroy(hc->http_server, htbuf);
+                fflush(hc->http_server->record_file);
                 http_channel_destroy(i);
                 return;
             }
@@ -931,6 +947,22 @@ static void http_io(IOCHAN i, int event)
                     return;
                 // we have a complete HTTP request
                 nmem_reset(hc->nmem);
+#if HAVE_SYS_TIME_H
+                if (hc->http_server->record_file)
+                {
+                    struct timeval tv;
+                    int sz = 0;
+                    struct http_buf *hb;
+                    for (hb = hc->iqueue; hb; hb = hb->next)
+                        sz += hb->len;
+                    gettimeofday(&tv, 0);
+                    fprintf(hc->http_server->record_file, "%lld %lld %lld %d\n",
+                            (long long) tv.tv_sec, (long long) tv.tv_usec,
+                            (long long) iochan_getfd(i), sz);
+                    for (hb = hc->iqueue; hb; hb = hb->next)
+                        fwrite(hb->buf, 1, hb->len, hc->http_server->record_file);
+                }
+ #endif
                 if (!(hc->request = http_parse_request(hc, &hc->iqueue, reqlen)))
                 {
                     yaz_log(YLOG_WARN, "Failed to parse request");
@@ -1223,7 +1255,8 @@ static void http_accept(IOCHAN i, int event)
 }
 
 /* Create a http-channel listener, syntax [host:]port */
-int http_init(const char *addr, struct conf_server *server)
+int http_init(const char *addr, struct conf_server *server,
+              const char *record_fname)
 {
     IOCHAN c;
     int l;
@@ -1232,9 +1265,21 @@ int http_init(const char *addr, struct conf_server *server)
     int one = 1;
     const char *pp;
     short port;
+    FILE *record_file = 0;
 
     yaz_log(YLOG_LOG, "HTTP listener %s", addr);
 
+
+    if (record_fname)
+    {
+        record_file = fopen(record_fname, "wb");
+        if (!record_file)
+        {
+            yaz_log(YLOG_FATAL|YLOG_ERRNO, "fopen %s", record_fname);
+            return 1;
+        }
+    }
+
     memset(&myaddr, 0, sizeof myaddr);
     myaddr.sin_family = AF_INET;
     pp = strchr(addr, ':');
@@ -1286,6 +1331,7 @@ int http_init(const char *addr, struct conf_server *server)
 
     server->http_server = http_server_create();
 
+    server->http_server->record_file = record_file;
     server->http_server->listener_socket = l;
 
     c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT, "http_server");
@@ -1415,6 +1461,7 @@ http_server_t http_server_create(void)
     hs->http_buf_freelist_count = 0;
     /* Disable max check */
     hs->http_buf_freelist_max = 0;
+    hs->record_file = 0;
     return hs;
 }
 
@@ -1449,6 +1496,8 @@ void http_server_destroy(http_server_t hs)
             http_sessions_destroy(hs->http_sessions);
             xfree(hs->proxy_addr);
             yaz_mutex_destroy(&hs->mutex);
+            if (hs->record_file)
+                fclose(hs->record_file);
             xfree(hs);
         }
     }
index 9a00fee..63d8d88 100644 (file)
@@ -104,7 +104,8 @@ void http_mutex_init(struct conf_server *server);
 void http_server_destroy(http_server_t hs);
 
 void http_set_proxyaddr(const char *url, struct conf_server *ser);
-int http_init(const char *addr, struct conf_server *ser);
+int http_init(const char *addr, struct conf_server *ser,
+              const char *record_fname);
 void http_close_server(struct conf_server *ser);
 void http_addheader(struct http_response *r, 
                     const char *name, const char *value);
index 6680662..7f69902 100644 (file)
@@ -95,6 +95,7 @@ static int sc_main(
     const char *uid = 0;
     const char *listener_override = 0;
     const char *config_fname = 0;
+    const char *record_fname = 0;
     struct conf_config *config = 0;
     int test_mode = 0;
 
@@ -108,7 +109,7 @@ static int sc_main(
     yaz_log_init_prefix("pazpar2");
     yaz_log_xml_errors(0, YLOG_WARN);
 
-    while ((ret = options("dDf:h:l:p:tu:v:VX", argv, argc, &arg)) != -2)
+    while ((ret = options("dDf:h:l:p:R:tu:v:VX", argv, argc, &arg)) != -2)
     {
        switch (ret)
         {
@@ -131,6 +132,9 @@ static int sc_main(
         case 'p':
             pidfile = arg;
             break;
+        case 'R':
+            record_fname = arg;
+            break;
         case 't':
             test_mode = 1;
             break;
@@ -153,6 +157,7 @@ static int sc_main(
                     "    -h [host:]port          Listener port\n"
                     "    -l file                 Log to file\n"
                     "    -p pidfile              PID file\n"
+                    "    -R recfile              HTTP recording file\n"
                     "    -t                      Test configuration\n"
                     "    -u uid                  Change user to uid\n"
                     "    -V                      Show version\n"
@@ -197,7 +202,7 @@ static int sc_main(
                     "mode");
             return 1;
         }
-        ret = config_start_listeners(config, listener_override);
+        ret = config_start_listeners(config, listener_override, record_fname);
         if (ret)
             return ret; /* error starting http listener */
         
index 740ac9c..8b94b63 100644 (file)
@@ -1122,7 +1122,8 @@ void config_process_events(struct conf_config *conf)
 }
 
 int config_start_listeners(struct conf_config *conf,
-                           const char *listener_override)
+                           const char *listener_override,
+                           const char *record_fname)
 {
     struct conf_server *ser;
 
@@ -1149,7 +1150,7 @@ int config_start_listeners(struct conf_config *conf,
                 wrbuf_printf(w, "%d", ser->port);
             }
         }
-        r = http_init(wrbuf_cstr(w), ser);
+        r = http_init(wrbuf_cstr(w), ser, record_fname);
         wrbuf_destroy(w);
         if (r)
             return -1;
index 0bb9cbe..60d7793 100644 (file)
@@ -175,7 +175,8 @@ void service_incref(struct conf_service *service);
 void service_destroy(struct conf_service *service);
 
 int config_start_listeners(struct conf_config *conf,
-                           const char *listener_override);
+                           const char *listener_override,
+                           const char *record_fname);
 
 void config_stop_listeners(struct conf_config *conf);