2197f6d5208aff4c48ccbe42e61a116d988ac392 max Tue May 19 08:23:54 2026 -0700 hubApi: add /blat endpoint with apiKey gating, format=hgblat, and known-agent bypass New src/hg/hubApi/blat.c implements /blat/ (dna, protein, transRna, transDna, guess) backed by the same gfServer logic as hgBlat. Key details: - Requires an apiKey for rate-limiting; botException() and botExceptionUserAgent() exempt IPs/user-agents in hg.conf (same policy as captcha bypass elsewhere in the browser stack). - Invalid apiKey returns a clean JSON 403 rather than an HTML 500 (pre-validated in hubApi.c main() before hgBotDelayTimeFrac runs). - Extra bot-delay fraction (default 0.3, 10x hubApi default) is configurable via hubApi.blatDelayFraction in hg.conf. - format=text/psl -> PSL text; format=hgblat -> byte-for-byte hgBlat?output=json shape; jsonOutputArrays=1 -> hubApi envelope with arrays (parallel to getData behaviour); default -> objects. - botExceptionUserAgent() carved out of cart.c's static isUserAgentException() into botDelay.c so non-cart callers can use it. - Cross-reference comments added in hgBlat.c and blat.c noting the shared logic so fixes get applied to both. refs #36315 Co-Authored-By: Claude Sonnet 4.6 diff --git src/hg/inc/botDelay.h src/hg/inc/botDelay.h index 882163a7e31..d29f9c64818 100644 --- src/hg/inc/botDelay.h +++ src/hg/inc/botDelay.h @@ -1,43 +1,46 @@ /* botDelay - contact bottleneck server and sleep * for a little bit if IP address looks like it is * being just too demanding. */ /* Copyright (C) 2004 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ int botDelayTime(char *host, int port, char *ip); /* Figure out suggested delay time for ip address in * milliseconds. */ char *botDelayWarningMsg(char *ip, int millis); /* return the string for the default botDelay message * not all users of botDelay want the message to go to stderr * return it for their own use case */ void botDelayMessage(char *ip, int millis); /* Print out message saying why you are stalled. */ int hgBotDelayTime(); /* Get suggested delay time from cgi using the standard penalty. */ int hgBotDelayTimeFrac(double fraction); /* Get suggested delay time from cgi using the specified fraction of the standard penalty. */ extern int botDelayMillis; boolean earlyBotCheck(long enteredMainTime, char *cgiName, double delayFrac, int warnMs, int exitMs, char *exitType); /* for use before the CGI has started any * output or setup the cart of done any MySQL operations. The boolean * return is used later in the CGI after it has done all its setups and * started output so it can issue the warning. Pass in delayFrac 0.0 * to use the default 1.0, pass in 0 for warnMs and exitMs to use defaults, * and exitType is either 'html' or 'json' to do that type of exit output in * the case of hogExit(); */ int hgBotDelayCurrWarnMs(); /* get number of millis that are tolerated until a warning is shown on the most recent call to earlyBotCheck */ boolean botException(); /* check if the remote ip address is on the exceptions list */ + +boolean botExceptionUserAgent(); +/* Return TRUE if HTTP_USER_AGENT matches a noCaptchaAgent. pattern in hg.conf. */