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/inc/blatServers.h src/hg/inc/blatServers.h
index d47f24c8677..60319925208 100644
--- src/hg/inc/blatServers.h
+++ src/hg/inc/blatServers.h
@@ -52,17 +52,38 @@
 
 void blatServersFreeList(struct blatServers **pList);
 /* Free a list of dynamically allocated blatServers's */
 
 void blatServersOutput(struct blatServers *el, FILE *f, char sep, char lastSep);
 /* Print out blatServers.  Separate fields with sep. Follow last field with lastSep. */
 
 #define blatServersTabOut(el,f) blatServersOutput(el,f,'\t','\n');
 /* Print out blatServers as a line in a tab-separated file. */
 
 #define blatServersCommaOut(el,f) blatServersOutput(el,f,',',',');
 /* Print out blatServers as a comma separated list including final comma. */
 
 /* -------------------------------- End autoSql Generated Code -------------------------------- */
 
+struct blatServerParams
+/* Parameters needed to connect to a gfServer and run alignments.
+ * Returned by findBlatServer(); shared by hgBlat and hubApi/blat. */
+    {
+    char *db;           /* Assembly database name. */
+    char *genome;       /* Human-readable genome name. */
+    char *host;         /* gfServer hostname. */
+    char *port;         /* gfServer port (string). */
+    char *nibDir;       /* Directory of .2bit / .nib sequence files. */
+    char *genomeDataDir;/* Dynamic-server root-relative directory, or NULL. */
+    boolean isTrans;    /* TRUE for translated (protein/rnax/dnax) queries. */
+    boolean isDynamic;  /* TRUE if served by a dynamic gfServer. */
+    };
+
+struct blatServerParams *findBlatServer(char *db, boolean isTrans);
+/* Return gfServer connection parameters for the given assembly, or NULL if
+ * none is configured.  Handles both hub and non-hub assemblies.
+ * The description-to-name fallback from hgBlat is included: if db is not
+ * found as a name in dbDb it is tried as a description.
+ * Caller should NOT free the returned struct. */
+
 #endif /* BLATSERVERS_H */