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);