06b0009211c47fc85787ac3d9bb8a55652c13556
galt
  Thu Jul 20 11:39:39 2023 -0700
HTTP/1.1 without persistent connections. Addresses complaints that byterange headers should not be used with old HTTP/1.0, or that HTTP/1.0 should no longer be used. fixes #31774

diff --git src/lib/net.c src/lib/net.c
index 0795279..0f50bae7 100644
--- src/lib/net.c
+++ src/lib/net.c
@@ -1259,41 +1259,41 @@
     /* make a pipe (fds go in pipefd[0] and pipefd[1])  */
     if (pipe(params->pipefd) != 0)
 	errAbort("netGetOpenFtpSockets: failed to create pipe: %s", strerror(errno));
     int rc;
     rc = pthread_create(&params->thread, NULL, sendFtpDataToPipeThread, (void *)params);
     if (rc)
 	{
 	errAbort("Unexpected error %d from pthread_create(): %s",rc,strerror(rc));
 	}
 
     return params->pipefd[0];
     }
 }
 
 
-int connectNpu(struct netParsedUrl npu, char *url, boolean noProxy)
+int connectNpu(struct netParsedUrl npu, char *url, boolean noProxy, char *httpProtocol)
 /* 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), noProxy);
+    sd = netConnectHttps(npu.host, atoi(npu.port), noProxy, httpProtocol);
     }
 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];
@@ -1328,49 +1328,51 @@
  * 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
  * Cert verification control via hg.conf httpsCertCheck or env var https_cert_check
  * Cert verify domains exception white-list via hg.conf httpsCertCheckDomainExceptions or env var https_cert_check_domain_exceptions
  * Return data socket, or -1 if error.*/
 {
 struct netParsedUrl npu;
 struct netParsedUrl pxy;
 struct dyString *dy = dyStringNew(512);
 int sd = -1;
 /* Parse the URL and connect. */
 netParseUrl(url, &npu);
 
+
+
 boolean noProxy = checkNoProxy(npu.host);
 char *proxyUrl = getenv("http_proxy");
 if (sameString(npu.protocol, "https"))
     proxyUrl = NULL;
 if (noProxy)
     proxyUrl = NULL;
 if (proxyUrl)
     {
     netParseUrl(proxyUrl, &pxy);
     if (!sameString(pxy.protocol, "http"))
 	errAbort("Unknown proxy protocol %s in %s.", pxy.protocol, proxyUrl);
-    sd = connectNpu(pxy, url, noProxy);
+    sd = connectNpu(pxy, url, noProxy, protocol);
     char *logProxy = getenv("log_proxy");
     if (sameOk(logProxy,"on"))
 	verbose(1, "%s via proxy %s\n", url, proxyUrl);
     }
 else
     {
-    sd = connectNpu(npu, url, noProxy);
+    sd = connectNpu(npu, url, noProxy, protocol);
     }
 if (sd < 0)
     return -1;
 
 /* 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);
@@ -1398,47 +1400,50 @@
     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"
 		       , (long long)npu.byteRangeStart);
     }
 
 if (optionalHeader)
     dyStringAppend(dy, optionalHeader);
+if (sameString(protocol, "HTTP/1.1"))
+    dyStringAppend(dy, "Connection: close\r\n");  // NON-persistent HTTP 1.1 connection
 
 /* finish off the header with final blank line */
 dyStringAppend(dy, "\r\n");
 
 mustWriteFd(sd, dy->string, dy->stringSize);
 
+
 /* Clean up and return handle. */
 dyStringFree(&dy);
 return sd;
 }
 
 
 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);
+return netHttpConnect(url, method, "HTTP/1.1", "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 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, method, NULL);