Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/yaz
[yaz-moved-to-github.git] / src / url.c
index 3c2b361..ff7ff81 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -18,6 +18,7 @@ struct yaz_url {
     ODR odr_in;
     ODR odr_out;
     char *proxy;
+    int max_redirects;
 };
 
 yaz_url_t yaz_url_create(void)
@@ -26,6 +27,7 @@ yaz_url_t yaz_url_create(void)
     p->odr_in = odr_createmem(ODR_DECODE);
     p->odr_out = odr_createmem(ODR_ENCODE);
     p->proxy = 0;
+    p->max_redirects = 10;
     return p;
 }
 
@@ -48,6 +50,11 @@ void yaz_url_set_proxy(yaz_url_t p, const char *proxy)
         p->proxy = xstrdup(proxy);
 }
 
+void yaz_url_set_max_redirects(yaz_url_t p, int num)
+{
+    p->max_redirects = num;
+}
+
 static void extract_user_pass(NMEM nmem,
                               const char *uri,
                               char **uri_lean, char **http_user,
@@ -88,7 +95,7 @@ static void extract_user_pass(NMEM nmem,
 
 Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri,
                               const char *method,
-                              Z_HTTP_Header *headers,
+                              Z_HTTP_Header *user_headers,
                               const char *buf, size_t len)
 {
     Z_HTTP_Response *res = 0;
@@ -99,7 +106,6 @@ Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri,
         void *add;
         COMSTACK conn = 0;
         int code;
-        struct Z_HTTP_Header **last_header_entry;
         const char *location = 0;
         char *http_user = 0;
         char *http_pass = 0;
@@ -112,17 +118,25 @@ Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri,
         gdu = z_get_HTTP_Request_uri(p->odr_out, uri_lean, 0, p->proxy ? 1 : 0);
         gdu->u.HTTP_Request->method = odr_strdup(p->odr_out, method);
 
+        for ( ; user_headers; user_headers = user_headers->next)
+        {
+            /* prefer new Host over user-supplied Host */
+            if (!strcmp(user_headers->name, "Host"))
+                ;
+            /* prefer user-supplied User-Agent over YAZ' own */
+            else if (!strcmp(user_headers->name, "User-Agent"))
+                z_HTTP_header_set(p->odr_out, &gdu->u.HTTP_Request->headers,
+                                  user_headers->name, user_headers->value);
+            else
+                z_HTTP_header_add(p->odr_out, &gdu->u.HTTP_Request->headers,
+                                  user_headers->name, user_headers->value);
+        }
         if (http_user && http_pass)
             z_HTTP_header_add_basic_auth(p->odr_out,
                                          &gdu->u.HTTP_Request->headers,
                                          http_user, http_pass);
 
         res = 0;
-        last_header_entry = &gdu->u.HTTP_Request->headers;
-        while (*last_header_entry)
-            last_header_entry = &(*last_header_entry)->next;
-        *last_header_entry = headers; /* attach user headers */
-
         if (buf && len)
         {
             gdu->u.HTTP_Request->content_buf = (char *) buf;
@@ -182,7 +196,7 @@ Z_HTTP_Response *yaz_url_exec(yaz_url_t p, const char *uri,
             break;
         code = res->code;
         location = z_HTTP_header_lookup(res->headers, "Location");
-        if (++number_of_redirects < 10 &&
+        if (++number_of_redirects <= p->max_redirects &&
             location && (code == 301 || code == 302 || code == 307))
         {
             odr_reset(p->odr_out);