cb99f0b11bdeee5dfa76064d38b6410da0f4a709 max Thu Sep 10 00:55:21 2026 -0700 Centralize CGI Content-Type printing in one cgiPrintContentType() helper Around 90 places across the tree hand-rolled the CGI response header, each with its own spelling: "Content-Type:" or "Content-type:", \n or \r\n, and the terminating blank line written as part of the same string, as a separate puts("\n") (which emits two newlines, so a stray blank line led the body) or as printf("\r\n\r\n") (two blank lines). A handful forgot the terminator entirely and relied on a following header to supply it. cgiPrintContentType() in lib/cheapcgi.c now writes the Content-Type line and the blank line that ends the header. Header lines are not ordered, so the callers that also send Status, Set-Cookie, Content-Disposition, Content-Length or X-Sendfile write those first and call this last to close the header; that keeps it to a single helper rather than a print-the-line / end-the-header pair that a caller can half-use. cart.c's existing httpHeaders list already worked this way. Only the CGI response path is touched. The dyStringPrintf("Content-type: ...") calls that build outgoing HTTP *requests* (genomeSpace, oauthLogin, eapMetaSync, edwWebAuthLogin, ga4ghToBed) are unrelated and left alone. Also fills out the apiKey error message in botDelay.c to say where to create a key and that keys are server-specific. No behavior change on the wire beyond dropping those stray blank lines and adding the missing newline after Retry-After. diff --git src/hg/sageVisCGI/sageVisCGI.c src/hg/sageVisCGI/sageVisCGI.c index 82477979a1c..e2988199cf9 100644 --- src/hg/sageVisCGI/sageVisCGI.c +++ src/hg/sageVisCGI/sageVisCGI.c @@ -1,280 +1,280 @@ /* Copyright (C) 2013 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ /** \page sageVisCGI.doxp sageVisCGI cgi program for viewing graphs of sage data used standalone or called by the hgc.c program in ~kent/src/hg/hgc/.
sageVisCGI creates graphs on the fly for the sage data of different
uniGene clusters. The clusters to be graphed are passed via cgi (or command
line) in the form u= Example
or http://genome-test.soe.ucsc.edu/cgi-bin/sageVisCGI?md=20&u=202&u=122566 .
\sa sageVisCGI.c
*/
#include "common.h"
#include "hCommon.h"
#include "dystring.h"
#include "sage.h"
#include "sageExp.h"
#include "gnuPlot2D.h"
#include "portable.h"
#include "jksql.h"
#include "dnautil.h"
#include "cheapcgi.h"
#include "htmshell.h"
#include "knownMore.h"
#include "hdb.h"
#include "genePred.h"
#include "hgConfig.h"
int maxDataVal =0;
int dataValCeiling;
/**
Just prints out the
sageVisCGI md=20 u=202 u=122566 > out.html
tag and filename
*/
void doPlotPrintOut(char *fileName)
{
printf( "
\n", fileName);
}
/**
* Appends one string to another without having to
* worry about going over. Assumes that the total length
* of dest is the strlen(dest) + 1. Wasteful if you want to
* use it lots of times in a row as it reallocates memory every time
*/
void dynamicStrncat(char **dest, const char *src)
{
ExpandArray(*dest, (strlen(*dest)+1), (strlen(*dest) +strlen(src) + 1));
strncat(*dest, src, strlen(src));
}
/**
Construct a graphPoint from data in sage and current index.
Assumes that the experiments are stored in order.
*/
struct graphPoint2D*createSageGraphPoint(struct sage *sg, int i)
{
struct graphPoint2D *gp = NULL;
char name[128];
sprintf(name, "Hs.%d", sg->uni);
AllocVar(gp);
gp->y = sg->meds[i-1];
if(gp->y > maxDataVal && gp->y < dataValCeiling)
maxDataVal = gp->y;
gp->x = i;
gp->name = cloneString(name);
gp->hName = cloneString(name);
gp->groupName = cloneString(name);
return gp;
}
/**
Uses the sage experiment data (sageExp) and sage data itself (sage)
to construct the basic gnuPlot2D data type, specifically creating the
graphPoint2D data lists for each element in sgList */
struct gnuPlot2D *createSagePlot(struct sageExp *seList, struct sage *sgList)
{
struct gnuPlot2D *gp = createGnuPlot2D();
struct sage *sg = NULL;
int i;
for(sg = sgList; sg != NULL; sg = sg->next)
{
struct graphPoint2D *gList = NULL;
for (i=0; i< sg->numExps; i++)
{
struct graphPoint2D *gTemp = NULL;
gTemp = createSageGraphPoint(sg, i+1);
slAddHead(&gList, gTemp);
}
gptAddGraphPointList(gp, gList, "linesp");
}
return gp;
}
/* Creates a string which tells gnuPlot what label to put on
xTics and where to put them. Will Chop "SAGE" from name if present */
char * constructXticsFromExps(struct sageExp *seList)
{
char *ret = cloneString("set xtics rotate(");
static char buff[256];
int count =1;
struct sageExp *se;
for(se = seList; se != NULL; se = se->next)
{
if(se->next == NULL)
sprintf(buff, " \"%d)%s\" %d ", count, strstr(se->exp,"SAGE_") ? strstr(se->exp,"_") : se->exp , count);
else
sprintf(buff, " \"%d)%s\" %d, ", count, strstr(se->exp,"SAGE_") ? strstr(se->exp, "_") : se->exp, count);
dynamicStrncat(&ret, buff);
count++;
}
dynamicStrncat(&ret, ")\n");
return ret;
}
/* Prints the header appropriate for the title
* passed in. Links html to chucks stylesheet for
* easier maintaince
*/
void chuckHtmlStart(char *title)
{
printf("\n%s", getCspMetaHeader());
//FIXME blueStyle should not be absolute to genome-test and should bae called by:
// webIncludeResourceFile("blueStyle.css");
printf("\n");
printf("