17e9538e2611916d77bb2a8992b6b7e4ef201cd0
galt
  Sat Sep 12 12:24:09 2015 -0700
Using more efficient redirect method. Because the net functions do not make it easy to use HEAD instead of GET and save the header lines in a hash, without some major reworking of net.c, this is the best we can do.

diff --git src/lib/udc.c src/lib/udc.c
index 74b9d6e..caae2b2 100644
--- src/lib/udc.c
+++ src/lib/udc.c
@@ -381,54 +381,75 @@
     }
 if (rd == -1)
     errnoAbort("udcDataViaHttpOrFtp: error reading socket");
 if (ci == NULL)
     mustCloseFd(&sd);
 else
     ci->offset += total;
 return total;
 }
 
 boolean udcInfoViaHttp(char *url, struct udcRemoteFileInfo *retInfo)
 /* Gets size and last modified time of URL
  * and returns status of HEAD GET. */
 {
 verbose(4, "checking http remote info on %s\n", url);
-struct hash *hash = newHash(0);
-int status = netUrlHead(url, hash);
-if (status != 200  && status != 301 && status != 302)  
-    return FALSE;
-if (status == 301 && status == 302)
+int redirectCount = 0;
+struct hash *hash;
+int status;
+while (TRUE)
     {
-    int sd = netUrlOpen(url);
-    if (sd < 0)
+    hash = newHash(0);
+    status = netUrlHead(url, hash);
+    if (status == 200)
+	break;
+    if (status != 301 && status != 302)  
 	return FALSE;
-    int newSd = 0;
-    char *newUrl = NULL;
-    if (!netSkipHttpHeaderLinesHandlingRedirect(sd, url, &newSd, &newUrl))
+    ++redirectCount;
+    if (redirectCount > 5)
+	{
+	warn("code %d redirects: exceeded limit of 5 redirects, %s", status, url);
 	return  FALSE;
-    if (newUrl != NULL)
+	}
+    char *newUrl = cloneString(hashFindValUpperCase(hash, "Location:"));
+    struct netParsedUrl npu, newNpu;
+    /* Parse the old URL to make parts available for graft onto the redirected url. */
+    /* This makes redirection work with byterange urls and user:password@ */
+    netParseUrl(url, &npu);
+    netParseUrl(newUrl, &newNpu);
+    boolean updated = FALSE;
+    if (npu.byteRangeStart != -1)
 	{
-	sd = newSd;
-	url = newUrl;
-	retInfo->ci.redirUrl = newUrl; 
+	newNpu.byteRangeStart = npu.byteRangeStart;
+	newNpu.byteRangeEnd = npu.byteRangeEnd;
+	updated = TRUE;
 	}
-    close(sd);
-    // reread from the new redirected url
-    hash = newHash(0);
-    status = netUrlHead(url, hash);
+    if ((npu.user[0] != 0) && (newNpu.user[0] == 0))
+	{
+	safecpy(newNpu.user,     sizeof newNpu.user,     npu.user);
+	safecpy(newNpu.password, sizeof newNpu.password, npu.password);
+	updated = TRUE;
+	}
+    if (updated)
+	{
+	newUrl = urlFromNetParsedUrl(&newNpu);
 	}
+    url = newUrl;
+    retInfo->ci.redirUrl = url;
+    hashFree(&hash);
+    }
+
 char *sizeString = hashFindValUpperCase(hash, "Content-Length:");
 if (sizeString == NULL)
     {
     /* try to get remote file size by an alternate method */
     long long retSize = netUrlSizeByRangeResponse(url);
     if (retSize < 0)
 	{
     	hashFree(&hash);
 	errAbort("No Content-Length: returned in header for %s, can't proceed, sorry", url);
 	}
     retInfo->size = retSize;
     }
 else
     {
     retInfo->size = atoll(sizeString);