f64df8332a2328c2fe6325dcd1cb0b9281586957 galt Thu Feb 10 01:55:48 2011 -0800 added alternate method for finding filesize via byterange, useful workaround for udc used against poorly configured remote apache servers diff --git src/lib/net.c src/lib/net.c index 54bb60c..6a72092 100644 --- src/lib/net.c +++ src/lib/net.c @@ -921,37 +921,37 @@ int netOpenHttpExt(char *url, char *method, char *optionalHeader) /* Return a file handle that will read the url. optionalHeader * may by NULL or may contain cookies and other info. */ { return netHttpConnect(url, method, "HTTP/1.0", "genome.ucsc.edu/net.c", optionalHeader); } static int netGetOpenHttp(char *url) /* Return a file handle that will read the url. */ { return netOpenHttpExt(url, "GET", NULL); } -int netUrlHead(char *url, struct hash *hash) +int netUrlHeadExt(char *url, char *method, struct hash *hash) /* Go get head and return status. Return negative number if * can't get head. If hash is non-null, fill it with header * lines with upper cased keywords for case-insensitive lookup, * including hopefully CONTENT-TYPE: . */ { -int sd = netOpenHttpExt(url, "HEAD", NULL); +int sd = netOpenHttpExt(url, method, NULL); int status = EIO; if (sd >= 0) { char *line, *word; struct lineFile *lf = lineFileAttach(url, TRUE, sd); if (lineFileNext(lf, &line, NULL)) { if (startsWith("HTTP/", line)) { word = nextWord(&line); word = nextWord(&line); if (word != NULL && isdigit(word[0])) { status = atoi(word); @@ -963,30 +963,68 @@ if (word == NULL) break; hashAdd(hash, strUpper(word), cloneString(skipLeadingSpaces(line))); } } } } } lineFileClose(&lf); } else status = errno; return status; } + +int netUrlHead(char *url, struct hash *hash) +/* Go get head and return status. Return negative number if + * can't get head. If hash is non-null, fill it with header + * lines with upper cased keywords for case-insensitive lookup, + * including hopefully CONTENT-TYPE: . */ +{ +return netUrlHeadExt(url, "HEAD", hash); +} + + +long long netUrlSizeByRangeResponse(char *url) +/* Use byteRange as a work-around alternate method to get file size (content-length). + * Return negative number if can't get. */ +{ +long long retVal = -1; +char rangeUrl[2048]; +safef(rangeUrl, sizeof(rangeUrl), "%s;byterange=0-0", url); +struct hash *hash = newHash(0); +int status = netUrlHeadExt(rangeUrl, "GET", hash); +if (status == 206) + { + char *rangeString = hashFindValUpperCase(hash, "Content-Range:"); + if (rangeString) + { + /* input pattern: Content-Range: bytes 0-99/2738262 */ + char *slash = strchr(rangeString,'/'); + if (slash) + { + retVal = atoll(slash+1); + } + } + } +hashFree(&hash); +return retVal; +} + + int netUrlOpenSockets(char *url, int *retCtrlSocket) /* Return socket descriptor (low-level file handle) for read()ing url data, * or -1 if error. * If retCtrlSocket is non-NULL and url is FTP, set *retCtrlSocket * to the FTP control socket which is left open for a persistent connection. * close(result) (and close(*retCtrlSocket) if applicable) when done. * If url is missing :// then it's just treated as a file. */ { if (stringIn("://", url) == NULL) return open(url, O_RDONLY); else { if (startsWith("http://",url) || startsWith("https://",url)) return netGetOpenHttp(url); else if (startsWith("ftp://",url))