env["SERVER_PROTOCOL"] = req.ver
env["REQUEST_METHOD"] = req.method
env["REQUEST_URI"] = req.url
- try:
- env["PATH_INFO"] = unquoteurl(req.rest)
- except:
- env["PATH_INFO"] = req.rest
name = req.url
p = name.find('?')
if p >= 0:
else:
env["QUERY_STRING"] = ""
if name[-len(req.rest):] == req.rest:
+ # This is the same hack used in call*cgi.
name = name[:-len(req.rest)]
+ try:
+ pi = unquoteurl(req.rest)
+ except:
+ pi = req.rest
+ if name == '/':
+ # This seems to be normal CGI behavior, but see callcgi.c for
+ # details.
+ pi = "/" + pi
+ name = ""
env["SCRIPT_NAME"] = name
+ env["PATH_INFO"] = pi
if "Host" in req: env["SERVER_NAME"] = req["Host"]
if "X-Ash-Server-Port" in req: env["SERVER_PORT"] = req["X-Ash-Server-Port"]
if "X-Ash-Protocol" in req and req["X-Ash-Protocol"] == "https": env["HTTPS"] = "on"
char *qp, **env, *name;
int inp[2], outp[2];
pid_t pid;
- char *unqr;
+ char *pi;
pipe(inp);
pipe(outp);
if(getenv("HTTP_VERSION"))
putenv(sprintf2("SERVER_PROTOCOL=%s", getenv("HTTP_VERSION")));
putenv(sprintf2("REQUEST_METHOD=%s", method));
- unqr = unquoteurl(rest);
- putenv(sprintf2("PATH_INFO=%s", unqr?unqr:rest));
name = url;
/* XXX: This is an ugly hack (I think), but though I can think
* of several alternatives, none seem to be better. */
!strcmp(rest, url + strlen(url) - strlen(rest))) {
name = sprintf2("%.*s", (int)(strlen(url) - strlen(rest)), url);
}
+ if((pi = unquoteurl(rest)) == NULL)
+ pi = rest;
+ if(!strcmp(name, "/")) {
+ /*
+ * Normal CGI behavior appears to be to always let
+ * PATH_INFO begin with a slash and never let SCRIPT_NAME
+ * end with one. That conflicts, however, with some
+ * behaviors, such as "mounting" CGI applications on a
+ * directory element of the URI space -- a handler
+ * responding to "/foo/" would not be able to tell that it
+ * is not called "/foo", which makes a large difference,
+ * not least in relation to URI reconstruction and
+ * redirections. A common practical case is CGI-handled
+ * index files in directories. Therefore, this only
+ * handles the nonconditional case of the root directory
+ * and leaves other decisions to the previous handler
+ * handing over the request to callcgi. It is unclear if
+ * there is a better way to handle the problem.
+ */
+ name[0] = 0;
+ pi = sprintf2("/%s", pi);
+ }
+ putenv(sprintf2("PATH_INFO=%s", pi));
putenv(sprintf2("SCRIPT_NAME=%s", name));
putenv(sprintf2("QUERY_STRING=%s", qp?qp:""));
if(getenv("REQ_HOST"))
static void mkcgienv(struct hthead *req, struct charbuf *dst)
{
int i;
- char *url, *unq, *qp, *h, *p;
+ char *url, *pi, *tmp, *qp, *h, *p;
bufaddenv(dst, "SERVER_SOFTWARE", "ashd/%s", VERSION);
bufaddenv(dst, "GATEWAY_INTERFACE", "CGI/1.1");
bufaddenv(dst, "SERVER_PROTOCOL", "%s", req->ver);
bufaddenv(dst, "REQUEST_METHOD", "%s", req->method);
bufaddenv(dst, "REQUEST_URI", "%s", req->url);
- if((unq = unquoteurl(req->rest)) != NULL) {
- bufaddenv(dst, "PATH_INFO", unq);
- free(unq);
- } else {
- bufaddenv(dst, "PATH_INFO", req->rest);
- }
url = sstrdup(req->url);
if((qp = strchr(url, '?')) != NULL)
*(qp++) = 0;
* several alternatives, none seem to be better. */
if(*req->rest && (strlen(url) >= strlen(req->rest)) &&
!strcmp(req->rest, url + strlen(url) - strlen(req->rest))) {
- bufaddenv(dst, "SCRIPT_NAME", "%.*s", (int)(strlen(url) - strlen(req->rest)), url);
- } else {
- bufaddenv(dst, "SCRIPT_NAME", "%s", url);
- }
+ url[strlen(url) - strlen(req->rest)] = 0;
+ }
+ if((pi = unquoteurl(req->rest)) == NULL)
+ pi = sstrdup(req->rest);
+ if(!strcmp(url, "/")) {
+ /* This seems to be normal CGI behavior, but see callcgi.c for
+ * details. */
+ url[0] = 0;
+ pi = sprintf2("/%s", tmp = pi);
+ free(tmp);
+ }
+ bufaddenv(dst, "PATH_INFO", pi);
+ bufaddenv(dst, "SCRIPT_NAME", url);
bufaddenv(dst, "QUERY_STRING", "%s", qp?qp:"");
+ free(pi);
free(url);
if((h = getheader(req, "Host")) != NULL)
bufaddenv(dst, "SERVER_NAME", "%s", h);
static void mkcgienv(struct hthead *req, struct charbuf *dst)
{
int i;
- char *url, *unq, *qp, *h, *p;
+ char *url, *pi, *tmp, *qp, *h, *p;
bufaddenv(dst, "SERVER_SOFTWARE", "ashd/%s", VERSION);
bufaddenv(dst, "GATEWAY_INTERFACE", "CGI/1.1");
bufaddenv(dst, "SERVER_PROTOCOL", "%s", req->ver);
bufaddenv(dst, "REQUEST_METHOD", "%s", req->method);
bufaddenv(dst, "REQUEST_URI", "%s", req->url);
- if((unq = unquoteurl(req->rest)) != NULL) {
- bufaddenv(dst, "PATH_INFO", unq);
- free(unq);
- } else {
- bufaddenv(dst, "PATH_INFO", req->rest);
- }
url = sstrdup(req->url);
if((qp = strchr(url, '?')) != NULL)
*(qp++) = 0;
* several alternatives, none seem to be better. */
if(*req->rest && (strlen(url) >= strlen(req->rest)) &&
!strcmp(req->rest, url + strlen(url) - strlen(req->rest))) {
- bufaddenv(dst, "SCRIPT_NAME", "%.*s", (int)(strlen(url) - strlen(req->rest)), url);
- } else {
- bufaddenv(dst, "SCRIPT_NAME", "%s", url);
+ url[strlen(url) - strlen(req->rest)] = 0;
+ }
+ if((pi = unquoteurl(req->rest)) == NULL)
+ pi = sstrdup(req->rest);
+ if(!strcmp(url, "/")) {
+ /* This seems to be normal CGI behavior, but see callcgi.c for
+ * details. */
+ url[0] = 0;
+ pi = sprintf2("/%s", tmp = pi);
+ free(tmp);
}
+ bufaddenv(dst, "PATH_INFO", pi);
+ bufaddenv(dst, "SCRIPT_NAME", url);
bufaddenv(dst, "QUERY_STRING", "%s", qp?qp:"");
+ free(pi);
free(url);
if((h = getheader(req, "Host")) != NULL)
bufaddenv(dst, "SERVER_NAME", "%s", h);