25a903639645b7bd2d783858023555c375dbc112 galt Tue May 17 18:08:51 2011 -0700 adding support for redirects to byterange urls diff --git src/lib/net.c src/lib/net.c index bf99f67..0d36230 100644 --- src/lib/net.c +++ src/lib/net.c @@ -472,30 +472,69 @@ if (sameWord(parsed->protocol,"ftp")) strcpy(parsed->port, "21"); } else { *t++ = 0; if (!isdigit(t[0])) errAbort("Non-numeric port name %s", t); safecpy(parsed->port, sizeof(parsed->port), t); } /* What's left is the host. */ safecpy(parsed->host, sizeof(parsed->host), s); } +char *urlFromNetParsedUrl(struct netParsedUrl *npu) +/* Build URL from netParsedUrl structure */ +{ +struct dyString *dy = newDyString(512); + +dyStringAppend(dy, npu->protocol); +dyStringAppend(dy, "://"); +if (npu->user[0] != 0) + { + dyStringAppend(dy, npu->user); + if (npu->password[0] != 0) + { + dyStringAppend(dy, ":"); + dyStringAppend(dy, npu->password); + } + dyStringAppend(dy, "@"); + } +dyStringAppend(dy, npu->host); +/* do not include port if it is the default */ +if (!( + (sameString(npu->protocol, "ftp" ) && sameString("21", npu->port)) || + (sameString(npu->protocol, "http" ) && sameString("80", npu->port)) || + (sameString(npu->protocol, "https") && sameString("443",npu->port)) + )) + { + dyStringAppend(dy, ":"); + dyStringAppend(dy, npu->port); + } +dyStringAppend(dy, npu->file); +if (npu->byteRangeStart != -1) + { + dyStringPrintf(dy, ";byterange=%lld-", (long long)npu->byteRangeStart); + if (npu->byteRangeEnd != -1) + dyStringPrintf(dy, "%lld", (long long)npu->byteRangeEnd); + } + +/* Clean up and return handle. */ +return dyStringCannibalize(&dy); +} /* this was cloned from rudp.c - move it later for sharing */ static boolean readReadyWait(int sd, int microseconds) /* Wait for descriptor to have some data to read, up to * given number of microseconds. */ { struct timeval tv; fd_set set; int readyCount; for (;;) { if (microseconds >= 1000000) { tv.tv_sec = microseconds/1000000; @@ -993,31 +1032,32 @@ /* Ask remote server for a file. */ char *urlForProxy = NULL; if (proxyUrl) { /* trim off the byterange part at the end of url because proxy does not understand it. */ urlForProxy = cloneString(url); char *x = strrchr(urlForProxy, ';'); if (x && startsWith(";byterange=", x)) *x = 0; } dyStringPrintf(dy, "%s %s %s\r\n", method, proxyUrl ? urlForProxy : npu.file, protocol); freeMem(urlForProxy); dyStringPrintf(dy, "User-Agent: %s\r\n", agent); /* do not need the 80 since it is the default */ -if (sameString("80",npu.port)) +if ((sameString(npu.protocol, "http" ) && sameString("80", npu.port)) || + (sameString(npu.protocol, "https") && sameString("443",npu.port))) dyStringPrintf(dy, "Host: %s\r\n", npu.host); else dyStringPrintf(dy, "Host: %s:%s\r\n", npu.host, npu.port); setAuthorization(npu, "Authorization", dy); if (proxyUrl) setAuthorization(pxy, "Proxy-Authorization", dy); dyStringAppend(dy, "Accept: */*\r\n"); if (npu.byteRangeStart != -1) { if (npu.byteRangeEnd != -1) dyStringPrintf(dy, "Range: bytes=%lld-%lld\r\n" , (long long)npu.byteRangeStart , (long long)npu.byteRangeEnd); else dyStringPrintf(dy, "Range: bytes=%lld-\r\n" @@ -1423,30 +1463,44 @@ /* we have a new url to try */ ++redirectCount; if (redirectCount > 5) { warn("code 30x redirects: exceeded limit of 5 redirects, %s", newUrl); success = FALSE; } else if (!startsWith("http://",newUrl) && !startsWith("https://",newUrl)) { warn("redirected to non-http(s): %s", newUrl); success = FALSE; } else { + struct netParsedUrl npu; + /* Parse the old URL to make parts available for graft onto the redirected url. */ + /* This makes redirection work with byterange urls */ + /* If needed we can preserve the user and password from the old url in a similar way. */ + netParseUrl(url, &npu); + if (npu.byteRangeStart != -1) + { + struct netParsedUrl newNpu; + netParseUrl(newUrl, &newNpu); + newNpu.byteRangeStart = npu.byteRangeStart; + newNpu.byteRangeEnd = npu.byteRangeEnd; + freeMem(newUrl); + newUrl = urlFromNetParsedUrl(&newNpu); + } sd = netUrlOpen(newUrl); if (sd < 0) { warn("Couldn't open %s", newUrl); success = FALSE; } } } if (!success) { /* failure after 0 to 5 redirects */ if (redirectCount > 0) freeMem(newUrl); return FALSE; } url = newUrl; @@ -1939,33 +1993,30 @@ else { char *newUrl = NULL; int newSd = 0; if (startsWith("http://",url) || startsWith("https://",url)) { if (!netSkipHttpHeaderLinesHandlingRedirect(pc->sd, urlExt, &newSd, &newUrl)) { warn("Error processing http response for %s", url); return FALSE; } if (newUrl) { /* Update sd with newSd, replace it with newUrl, etc. */ pc->sd = newSd; - warn("Redirects not supported at this time: %s re-directed to: %s", url, newUrl); - freeMem(newUrl); /* redirects with byterange do not work anyway */ - return FALSE; } } ++connOpen; } } } if (connOpen == 0) { warn("Unable to open any connections to download %s, can't proceed, sorry", url); return FALSE; }