a7ad12187330204f9657482c84bebc349905bcc0 chmalee Tue May 27 16:22:26 2025 -0700 Make hgApi use the cart. This makes db=hub_id work on requests to allow genark bigGenePred zoomToExon/Codon to work, refs #35799 diff --git src/hg/hgApi/hgApi.c src/hg/hgApi/hgApi.c index 25236948dab..bab23310ca7 100644 --- src/hg/hgApi/hgApi.c +++ src/hg/hgApi/hgApi.c @@ -1,249 +1,262 @@ /* Copyright (C) 2013 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ /* hgApi - provide a JSON based API to the browser. Required CGI parameters: db: assembly cmd: command (see below) Optional CGI parameters: jsonp: if present, the returned json is wrapped in a call to the value of the jsonp parameter (e.g. "jsonp=parseResponse"). Supported commands: defaultPos: default position for this assembly metaDb: return list of values for metaDb parameter hgt_mdbVal: return metaDb value control - see code for details tableMetadata: returns an html table with metadata for track parameter **** DEPRECATED: Not currently used in GB codonToPos: returns genomic position for given codon; parameters: codon, table and name (which is gene name). codonToPos: returns genomic position for given exon; parameters: exon, table and name (which is gene name). */ #include "common.h" #include "hdb.h" #include "mdb.h" #include "cheapcgi.h" #include "htmshell.h" #include "hPrint.h" #include "dystring.h" #include "hui.h" #include "search.h" #include "cv.h" #include "api.h" #include "chromAlias.h" #include "bigBed.h" #include "trackHub.h" +#include "cart.h" -int main(int argc, char *argv[]) +struct hash *oldVars = NULL; + +void doMiddle(struct cart *cart) { long enteredMainTime = clock1000(); struct dyString *output = dyStringNew(10000); setUdcCacheDir(); -cgiSpoof(&argc, argv); pushWarnHandler(htmlVaBadRequestAbort); pushAbortHandler(htmlVaBadRequestAbort); char *database = cgiString("db"); char *cmd = cgiString("cmd"); char *jsonp = cgiOptionalString("jsonp"); if (!trackHubDatabase(database) && !hDbExists(database)) errAbort("Invalid database '%s'", database); if (!strcmp(cmd, "defaultPos")) { dyStringPrintf(output, "{\"pos\": \"%s\"}", hDefaultPos(database)); } else if (!strcmp(cmd, "metaDb")) { // Return list of values for given metaDb var // e.g. http://genome.ucsc.edu/hgApi?db=hg18&cmd=metaDb&var=cell struct sqlConnection *conn = hAllocConn(database); boolean metaDbExists = sqlTableExists(conn, "metaDb"); if (metaDbExists) { char *var = cgiOptionalString("var"); if (!var) errAbort("Missing var parameter"); boolean fileSearch = (cgiOptionalInt("fileSearch",0) == 1); struct slPair *pairs = mdbValLabelSearch(conn, var, MDB_VAL_STD_TRUNCATION, FALSE, !fileSearch, fileSearch); struct slPair *pair; dyStringPrintf(output, "[\n"); for (pair = pairs; pair != NULL; pair = pair->next) { if (pair != pairs) dyStringPrintf(output, ",\n"); dyStringPrintf(output, "['%s','%s']", javaScriptLiteralEncode(mdbPairLabel(pair)), javaScriptLiteralEncode(mdbPairVal(pair))); } dyStringPrintf(output, "\n]\n"); } else errAbort("Assembly does not support metaDb"); } // TODO: move to lib since hgTracks and hgApi share #define METADATA_VALUE_PREFIX "hgt_mdbVal" else if (startsWith(METADATA_VALUE_PREFIX, cmd)) { // Returns metaDb value control: drop down or free text, with or without help link. // e.g. http://genome.ucsc.edu/hgApi?db=hg18&cmd=hgt_mdbVal3&var=cell // TODO: Move guts to lib, so that hgTracks::searchTracks.c and hgApi.c can share struct sqlConnection *conn = hAllocConn(database); boolean metaDbExists = sqlTableExists(conn, "metaDb"); if (metaDbExists) { char *var = cgiOptionalString("var"); if (!var) errAbort("Missing var parameter"); int ix = atoi(cmd+strlen(METADATA_VALUE_PREFIX)); // 1 based index if (ix == 0) // errAbort("Unsupported 'cmd' parameter"); enum cvSearchable searchBy = cvSearchMethod(var); char name[128]; safef(name,sizeof name,"%s%i",METADATA_VALUE_PREFIX,ix); if (searchBy == cvSearchBySingleSelect || searchBy == cvSearchByMultiSelect) { boolean fileSearch = (cgiOptionalInt("fileSearch",0) == 1); struct slPair *pairs = mdbValLabelSearch(conn, var, MDB_VAL_STD_TRUNCATION, FALSE, !fileSearch, fileSearch); if (slCount(pairs) > 0) { char *dropDownHtml = cgiMakeSelectDropList((searchBy == cvSearchByMultiSelect), name, pairs, NULL, ANYLABEL, "mdbVal", "change", "findTracksMdbValChanged(this);", "min-width: 200px; font-size: .9em;", NULL); if (dropDownHtml) { dyStringAppend(output,dropDownHtml); freeMem(dropDownHtml); } slPairFreeList(&pairs); } } else if (searchBy == cvSearchByFreeText) { dyStringPrintf(output,"", name, name); jsOnEventById("change", name, "findTracksMdbValChanged(this);"); } else if (searchBy == cvSearchByWildList) { dyStringPrintf(output,"", name, name); jsOnEventById("change", name, "findTracksMdbValChanged(this);"); } else if (searchBy == cvSearchByDateRange || searchBy == cvSearchByIntegerRange) { // TO BE IMPLEMENTED } else errAbort("Metadata variable not searchable"); dyStringPrintf(output," ",ix); } else errAbort("Assembly does not support metaDb"); } else if (!strcmp(cmd, "tableMetadata")) { // returns an html table with metadata for a given track char *trackName = cgiOptionalString("track"); boolean showLonglabel = (NULL != cgiOptionalString("showLonglabel")); boolean showShortLabel = (NULL != cgiOptionalString("showShortLabel")); if (trackName != NULL) { // hTrackDbForTrackAndAncestors avoids overhead of getting whole track list! struct trackDb *tdb = hTrackDbForTrackAndAncestors(database, trackName); if (tdb != NULL) { char * html = metadataAsHtmlTable(database,tdb,showLonglabel,showShortLabel); if (html) { dyStringAppend(output,html); freeMem(html); } else dyStringPrintf(output,"No metadata found for track %s.",trackName); } else dyStringPrintf(output,"Track %s not found",trackName); } else dyStringAppend(output,"No track variable found"); } else if (sameString(cmd, "codonToPos") || sameString(cmd, "exonToPos")) { char query[256]; struct sqlResult *sr; char **row; struct genePred *gp = NULL; char *name = cgiString("name"); char *table = cgiString("table"); char *chrom = cgiString("chrom"); int num = cgiInt("num"); - struct sqlConnection *conn; + struct sqlConnection *conn = NULL; if (!trackHubDatabase(database)) conn = hAllocConn(database); struct trackDb *tdb = tdbForTrack(database, table, NULL); if (sameString(tdb->type, "genePred")) { sqlSafef(query, sizeof(query), "select name, chrom, strand, txStart, txEnd, cdsStart, cdsEnd, exonCount, exonStarts, exonEnds from %s where name = '%s' and chrom='%s'", table, name, chrom); sr = sqlGetResult(conn, query); row = sqlNextRow(sr); gp = genePredLoad(row); sqlFreeResult(&sr); } else if (sameString(tdb->type, "bigGenePred") || startsWith("bigGenePred", tdb->type)) // makes knownGene work { // TODO: what bigBed types can we even support? bigBed12 at a minimum for the blocks? // bigPsl should work maybe? // for now just support genePred and bigGenePred char *fileName = bbiNameFromSettingOrTable(tdb, conn, tdb->table); struct bbiFile *bbi = bigBedFileOpenAlias(fileName, chromAliasFindAliases); int fieldIx; struct bptFile *bpt = bigBedOpenExtraIndex(bbi, "name", &fieldIx); struct lm *lm = lmInit(0); struct bigBedInterval *bbList = bigBedNameQuery(bbi, bpt, fieldIx, name, lm); if (bbList) gp = (struct genePred *)genePredFromBigGenePred(chrom, bbList); } if (!gp) dyStringPrintf(output, "{\"error\": \"Couldn't find item: %s\"}", name); boolean found; int start, end; if (sameString(cmd, "codonToPos")) found = codonToPos(gp, num, &start, &end); else found = exonToPos(gp, num, &start, &end); if (found) dyStringPrintf(output, "{\"pos\": \"%s:%d-%d\"}", gp->chrom, start + 1, end); else dyStringPrintf(output, "{\"error\": \"%d is an invalid %s for this gene\"}", num, sameString(cmd, "codonToPos") ? "codon" : "exon"); hFreeConn(&conn); } else { warn("unknown cmd: %s",cmd); errAbort("Unsupported 'cmd' parameter"); } apiOut(dyStringContents(output), jsonp); cgiExitTime("hgApi", enteredMainTime); +} + +/* Null terminated list of CGI Variables we don't want to save + * permanently. */ +char *excludeVars[] = {"fileSearch", "var", "showShortLabel", "showLongLabel", "track", "table", "name", "chrom", "cmd", "num", NULL,}; + +int main(int argc, char *argv[]) +/* Process command line. */ +{ +cgiSpoof(&argc, argv); +cartEmptyShellNoContent(doMiddle, hUserCookie(), excludeVars, oldVars); return 0; }