130388103d6579f91a15a0922b5f237b689894b6 chmalee Tue May 18 15:56:51 2021 -0700 Fix hgTracks web browser caching again. This time allow CGIs to specify their own HTTP headers, as of now only hgTracks prevents caching. refs #26627 diff --git src/hg/lib/cart.c src/hg/lib/cart.c index ce0c147..7327657 100644 --- src/hg/lib/cart.c +++ src/hg/lib/cart.c @@ -28,30 +28,32 @@ #include "geoMirror.h" #include "hubConnect.h" #include "trackHub.h" #include "cgiApoptosis.h" #include "customComposite.h" #include "regexHelper.h" #include "windowsToAscii.h" static char *sessionVar = "hgsid"; /* Name of cgi variable session is stored in. */ static char *positionCgiName = "position"; DbConnector cartDefaultConnector = hConnectCart; DbDisconnect cartDefaultDisconnector = hDisconnectCart; static boolean cartDidContentType = FALSE; +struct slPair *httpHeaders = NULL; // A list of headers to output before the content-type + static void hashUpdateDynamicVal(struct hash *hash, char *name, void *val) /* Val is a dynamically allocated (freeMem-able) entity to put * in hash. Override existing hash item with that name if any. * Otherwise make new hash item. */ { struct hashEl *hel = hashLookup(hash, name); if (hel == NULL) hashAdd(hash, name, val); else { freeMem(hel->val); hel->val = val; } } @@ -2279,48 +2281,59 @@ setenv("no_proxy", noProxy, TRUE); char *logProxy = cfgOption("logProxy"); if (logProxy) setenv("log_proxy", logProxy, TRUE); // if ignoreCookie is on the URL, don't check for cookies char *hguid = NULL; if (cgiOptionalString("ignoreCookie") == NULL) hguid = getCookieId(cookieName); char *hgsid = getSessionId(); struct cart *cart = cartNew(hguid, hgsid, exclude, oldVars); cartExclude(cart, sessionVar); return cart; } +static void addHttpHeaders() +/* CGIs can initialize the global variable httpHeaders to control their own HTTP + * headers. This allows, for example, to prevent web browser caching of hgTracks + * responses, but implicitly allow web browser caching everywhere else */ +{ +struct slPair *h; +for (h = httpHeaders; h != NULL; h = h->next) + { + printf("%s: %s\n", h->name, (char *)h->val); + } +} + struct cart *cartAndCookieWithHtml(char *cookieName, char **exclude, struct hash *oldVars, boolean doContentType) /* Load cart from cookie and session cgi variable. Write cookie * and optionally content-type part HTTP preamble to web page. Don't * write any HTML though. */ { // Note: early abort works fine but early warn does not htmlPushEarlyHandlers(); struct cart *cart = cartForSession(cookieName, exclude, oldVars); popWarnHandler(); popAbortHandler(); cartWriteCookie(cart, cookieName); if (doContentType && !cartDidContentType) { + addHttpHeaders(); puts("Content-Type:text/html"); - // disable web browsers from caching CGI responses: - puts("Cache-Control: no-cache"); puts("\n"); cartDidContentType = TRUE; } return cart; } struct cart *cartAndCookie(char *cookieName, char **exclude, struct hash *oldVars) /* Load cart from cookie and session cgi variable. Write cookie and * content-type part HTTP preamble to web page. Don't write any HTML though. */ { return cartAndCookieWithHtml(cookieName, exclude, oldVars, TRUE); } struct cart *cartAndCookieNoContent(char *cookieName, char **exclude,