src/lib/net.c 1.80
1.80 2010/04/14 07:42:06 galt
Adding support for http(s) proxy
Index: src/lib/net.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/net.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -b -B -U 4 -r1.79 -r1.80
--- src/lib/net.c 10 Mar 2010 23:41:17 -0000 1.79
+++ src/lib/net.c 14 Apr 2010 07:42:06 -0000 1.80
@@ -803,56 +803,95 @@
return pipefd[0];
}
}
+
+int connectNpu(struct netParsedUrl npu, char *url)
+/* Connect using NetParsedUrl. */
+{
+int sd = -1;
+if (sameString(npu.protocol, "http"))
+ {
+ sd = netConnect(npu.host, atoi(npu.port));
+ }
+else if (sameString(npu.protocol, "https"))
+ {
+ sd = netConnectHttps(npu.host, atoi(npu.port));
+ }
+else
+ {
+ errAbort("netHttpConnect: url (%s) is not for http.", url);
+ return -1; /* never gets here, fixes compiler complaint */
+ }
+return sd;
+}
+
+void setAuthorization(struct netParsedUrl npu, char *authHeader, struct dyString *dy)
+/* Set the specified authorization header with BASIC auth base64-encoded user and password */
+{
+if (!sameString(npu.user,""))
+ {
+ char up[256];
+ char *b64up = NULL;
+ safef(up, sizeof(up), "%s:%s", npu.user, npu.password);
+ b64up = base64Encode(up, strlen(up));
+ dyStringPrintf(dy, "%s: Basic %s\r\n", authHeader, b64up);
+ freez(&b64up);
+ }
+}
+
int netHttpConnect(char *url, char *method, char *protocol, char *agent, char *optionalHeader)
/* Parse URL, connect to associated server on port, and send most of
* the request to the server. If specified in the url send user name
* and password too. Typically the "method" will be "GET" or "POST"
* and the agent will be the name of your program or
* library. optionalHeader may be NULL or contain additional header
* lines such as cookie info.
+ * Proxy support via hg.conf httpProxy or env var http_proxy
* Return data socket, or -1 if error.*/
{
struct netParsedUrl npu;
+struct netParsedUrl pxy;
struct dyString *dy = newDyString(512);
int sd = -1;
-
/* Parse the URL and connect. */
netParseUrl(url, &npu);
-if (sameString(npu.protocol, "http"))
- {
- sd = netConnect(npu.host, atoi(npu.port));
- }
-else if (sameString(npu.protocol, "https"))
+
+char *proxyUrl = getenv("http_proxy");
+
+if (proxyUrl)
{
- sd = netConnectHttps(npu.host, atoi(npu.port));
+ netParseUrl(proxyUrl, &pxy);
+ sd = connectNpu(pxy, url);
}
else
{
- errAbort("netHttpConnect: url (%s) is not for http.", url);
- return -1; /* never gets here, fixes compiler complaint */
+ sd = connectNpu(npu, url);
}
if (sd < 0)
return -1;
/* Ask remote server for a file. */
-dyStringPrintf(dy, "%s %s %s\r\n", method, npu.file, protocol);
+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))
dyStringPrintf(dy, "Host: %s\r\n", npu.host);
else
dyStringPrintf(dy, "Host: %s:%s\r\n", npu.host, npu.port);
-if (!sameString(npu.user,""))
- {
- char up[256];
- char *b64up = NULL;
- safef(up, sizeof(up), "%s:%s", npu.user, npu.password);
- b64up = base64Encode(up, strlen(up));
- dyStringPrintf(dy, "Authorization: Basic %s\r\n", b64up);
- freez(&b64up);
- }
+setAuthorization(npu, "Authorization", dy);
+if (proxyUrl)
+ setAuthorization(pxy, "Proxy-Authorization", dy);
dyStringAppend(dy, "Accept: */*\r\n");
if (npu.byteRangeStart != -1)
{
if (npu.byteRangeEnd != -1)
@@ -999,8 +1038,13 @@
char *sep = NULL;
char *headerName = NULL;
char *headerVal = NULL;
boolean redirect = FALSE;
+
+boolean mustUseProxy = FALSE; /* User must use proxy 305 error*/
+char *proxyLocation = NULL;
+boolean mustUseProxyAuth = FALSE; /* User must use proxy authentication 407 error*/
+
while(TRUE)
{
i = 0;
while (TRUE)
@@ -1046,8 +1090,16 @@
&& ((code[2] >= '0' && code[2] <= '3') || code[2] == '7') && code[3] == 0)
{
redirect = TRUE;
}
+ else if (sameString(code, "305"))
+ {
+ mustUseProxy = TRUE;
+ }
+ else if (sameString(code, "407"))
+ {
+ mustUseProxyAuth = TRUE;
+ }
else if (!(sameString(code, "200") || sameString(code, "206")))
{
warn("%s: %s %s\n", url, code, line);
return FALSE;
@@ -1068,10 +1120,20 @@
if (sameWord(headerName,"Location"))
{
if (redirect)
*redirectedUrl = cloneString(headerVal);
+ if (mustUseProxy)
+ proxyLocation = cloneString(headerVal);
}
}
+if (mustUseProxy || mustUseProxyAuth)
+ {
+ warn("%s: %s error. Use Proxy%s. Location = %s\n", url,
+ mustUseProxy ? "" : " Authentication",
+ mustUseProxy ? "305" : "407",
+ proxyLocation ? proxyLocation : "not given");
+ return FALSE;
+ }
return TRUE;
}