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 @@ -1,68 +1,89 @@ /* blatServers.h was originally generated by the autoSql program, which also * generated blatServers.c and blatServers.sql. This header links the database and * the RAM representation of objects. */ #ifndef BLATSERVERS_H #define BLATSERVERS_H #define BLATSERVERS_NUM_COLS 6 extern char *blatServersCommaSepFieldNames; struct blatServers /* Description of online BLAT servers */ { struct blatServers *next; /* Next in singly linked list. */ char *db; /* Database name */ char *host; /* Host (machine) name */ int port; /* TCP/IP port on host */ signed char isTrans; /* 0 for nucleotide/1 for translated nucleotide */ signed char canPcr; /* 1 for use with PCR, 0 for not */ signed char dynamic; /* 1 for if gfServer is dynamic under xinetd, 0 for not */ }; void blatServersStaticLoad(char **row, struct blatServers *ret); /* Load a row from blatServers table into ret. The contents of ret will * be replaced at the next call to this function. */ struct blatServers *blatServersLoad(char **row); /* Load a blatServers from row fetched with select * from blatServers * from database. Dispose of this with blatServersFree(). */ struct blatServers *blatServersLoadAll(char *fileName); /* Load all blatServers from whitespace-separated file. * Dispose of this with blatServersFreeList(). */ struct blatServers *blatServersLoadAllByChar(char *fileName, char chopper); /* Load all blatServers from chopper separated file. * Dispose of this with blatServersFreeList(). */ #define blatServersLoadAllByTab(a) blatServersLoadAllByChar(a, '\t'); /* Load all blatServers from tab separated file. * Dispose of this with blatServersFreeList(). */ struct blatServers *blatServersCommaIn(char **pS, struct blatServers *ret); /* Create a blatServers out of a comma separated string. * This will fill in ret if non-null, otherwise will * return a new blatServers */ void blatServersFree(struct blatServers **pEl); /* Free a single dynamically allocated blatServers such as created * with blatServersLoad(). */ 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 */