75af658048fd25b17153e6fff08712e48f78f61a
hiram
  Thu Apr 4 10:19:55 2019 -0700
begin to think about error code returns refs #18869

diff --git src/hg/hubApi/apiUtils.c src/hg/hubApi/apiUtils.c
index 7b7936d..f9a9a82 100644
--- src/hg/hubApi/apiUtils.c
+++ src/hg/hubApi/apiUtils.c
@@ -1,150 +1,173 @@
 /* utility functions for data API business */
 
 #include "dataApi.h"
 
+#ifdef NOT
+static void jsonFinishOutput(int errorCode, char *errorString, struct jsonWrite *jw)
+/* potential output an error code other than 200 */
+{
+/* this is the first time any output to stdout has taken place for
+ * json output, therefore, start with the appropriate header
+ */
+puts("Content-Type:application/json");
+/* potentially with an error code return */
+if (errorCode)
+    {
+    char errString[2048];
+    safef(errString, sizeof(errString), "Status: %d %s",errorCode,errorString);
+    puts(errString);
+    }
+puts("\n");
+
+jsonWriteObjectEnd(jw);
+fputs(jw->dy->string,stdout);
+}
+#endif
+
 void apiErrAbort(char *format, ...)
 /* Issue an error message in json format, and exit(0) */
 {
 char errMsg[2048];
 va_list args;
 va_start(args, format);
 vsnprintf(errMsg, sizeof(errMsg), format, args);
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "error", errMsg);
+// jsonFinishOutput(400, "Bad Request", jw);
 jsonWriteObjectEnd(jw);
 fputs(jw->dy->string,stdout);
 exit(0);
 }
 
 struct jsonWrite *apiStartOutput()
 /* begin json output with standard header information for all requests */
 {
 time_t timeNow = time(NULL);
 // struct tm tm;
 // gmtime_r(&timeNow, &tm);
 struct jsonWrite *jw = jsonWriteNew();
 jsonWriteObjectStart(jw, NULL);
 // not recommended: jsonWriteString(jw, "apiVersion", "v"CGI_VERSION);
 // not needed jsonWriteString(jw, "source", "UCSantaCruz");
 jsonWriteDateFromUnix(jw, "downloadTime", (long long) timeNow);
 jsonWriteNumber(jw, "downloadTimeStamp", (long long) timeNow);
 if (debug)
     jsonWriteNumber(jw, "botDelay", (long long) botDelay);
 return jw;
 }
 
 int tableColumns(struct sqlConnection *conn, struct jsonWrite *jw, char *table,
    char ***nameReturn, char ***typeReturn)
 /* return the column names, and their MySQL data type, for the given table
  *  return number of columns (aka 'fields')
  */
 {
 // not needed jsonWriteListStart(jw, "columnNames");
 struct sqlFieldInfo *fi, *fiList = sqlFieldInfoGet(conn, table);
 int columnCount = slCount(fiList);
 char **namesReturn = NULL;
 char **typesReturn = NULL;
 AllocArray(namesReturn, columnCount);
 AllocArray(typesReturn, columnCount);
 int i = 0;
 for (fi = fiList; fi; fi = fi->next)
     {
     namesReturn[i] = cloneString(fi->field);
     typesReturn[i] = cloneString(fi->type);
     i++;
 // not needed     jsonWriteObjectStart(jw, NULL);
 // not needed     jsonWriteString(jw, fi->field, fi->type);
 // not needed     jsonWriteObjectEnd(jw);
     }
 // not needed jsonWriteListEnd(jw);
 *nameReturn = namesReturn;
 *typeReturn = namesReturn;
 return columnCount;
 }
 
 struct trackHub *errCatchTrackHubOpen(char *hubUrl)
 /* use errCatch around a trackHub open in case it fails */
 {
 struct trackHub *hub = NULL;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     hub = trackHubOpen(hubUrl, "");
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     apiErrAbort("error opening hubUrl: '%s', '%s'", hubUrl,  errCatch->message->string);
     }
 errCatchFree(&errCatch);
 return hub;
 }
 
 struct trackDb *obtainTdb(struct trackHubGenome *genome, char *db)
 /* return a full trackDb fiven the hub genome pointer, or ucsc database name */
 {
 struct trackDb *tdb = NULL;
 if (db)
     tdb = hTrackDb(db);
 else
     {
     tdb = trackHubTracksForGenome(genome->trackHub, genome);
     tdb = trackDbLinkUpGenerations(tdb);
     tdb = trackDbPolishAfterLinkup(tdb, genome->name);
     slSort(&tdb, trackDbCmp);
     }
 return tdb;
 }
 
 struct trackDb *findTrackDb(char *track, struct trackDb *tdb)
 /* search tdb structure for specific track, recursion on subtracks */
 {
 struct trackDb *trackFound = NULL;
 
 for (trackFound = tdb; trackFound; trackFound = trackFound->next)
     {
     if (trackFound->subtracks)
 	{
         struct trackDb *subTrack = findTrackDb(track, trackFound->subtracks);
 	if (subTrack)
 	    {
 	    if (sameOk(subTrack->track, track))
 		trackFound = subTrack;
 	    }
 	}
     if (sameOk(trackFound->track, track))
 	break;
     }
 return trackFound;
 }
 
 struct bbiFile *bigFileOpen(char *trackType, char *bigDataUrl)
 /* open bigDataUrl for correct trackType and error catch if failure */
 {
 struct bbiFile *bbi = NULL;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
 if (startsWith("bigBed", trackType))
     bbi = bigBedFileOpen(bigDataUrl);
 else if (startsWith("bigWig", trackType))
     bbi = bigWigFileOpen(bigDataUrl);
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     apiErrAbort("error opening bigFile URL: '%s', '%s'", bigDataUrl,  errCatch->message->string);
     }
 errCatchFree(&errCatch);
 return bbi;
 }
 
 int chromInfoCmp(const void *va, const void *vb)
 /* Compare to sort based on size */
 {
 const struct chromInfo *a = *((struct chromInfo **)va);
 const struct chromInfo *b = *((struct chromInfo **)vb);
 int dif;
 dif = (long) a->size - (long) b->size;
 return dif;
 }