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/<type> (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 <noreply@anthropic.com>

diff --git src/hg/hubApi/makefile src/hg/hubApi/makefile
index 2db42eba4db..59688ba34a1 100644
--- src/hg/hubApi/makefile
+++ src/hg/hubApi/makefile
@@ -1,26 +1,26 @@
 kentSrc = ../..
 include ../../inc/common.mk
 
 cgiApi = /usr/local/apache/cgi-bin-api
 
 L += ${HALLIBS} $(MYSQLLIBS) -lm
 MYLIBDIR = ../../lib/${MACHTYPE}
-MYLIBS =  $(MYLIBDIR)/jkhgapcgi.a $(MYLIBDIR)/jkhgap.a ${MYLIBDIR}/jkweb.a
+MYLIBS =  $(MYLIBDIR)/jkhgapcgi.a $(MYLIBDIR)/jkhgap.a $(MYLIBDIR)/jkOwnLib.a ${MYLIBDIR}/jkweb.a
 
 A = hubApi
-O = hubApi.o getData.o apiUtils.o list.o search.o findGenome.o liftOver.o
+O = hubApi.o getData.o apiUtils.o list.o search.o findGenome.o liftOver.o blat.o
 
 A = hubApi
 
 include ../../inc/cgi_build_rules.mk
 
 compile:: $O
 	${CC} $O ${MYLIBS} ${L}
 	mv ${AOUT} $A${EXE}
 
 # building your own sandbox also copies result to cgiApi directory
 # if it exists
 
 my::
 	if [ -d ${cgiApi} ]; then rm -f ${cgiApi}/$A; cp -p ${CGI_BIN_USER}/$A ${cgiApi}/$A; fi