This patch arose because I tried to run a wiki inside https instead of http. The key problem is that the "Location:" HTTP header must specify an absolute URI, which means that whoever decides to do a redirect must know not only the "pathname" and the hostname but also the "scheme" (http or https) and the port number. According to the current design this information must be propagated not only throughout httpd.c but also out to the helper programs via exec(). I've been running essentially this code for two years, and this patch is based on merging in the intervening changes from sources, rebuilding, and testing briefly. However, I should state that there are many features of httpd which I don't use, e.g., httpd.rewrite or any of the magic programs such as the man-page generator (though I have exercised wikipost). Reference: /n/sources/patch/applied/httpd-schemes Date: Mon Jun 23 05:21:00 CES 2008 Signed-off-by: davide+p9@cs.cmu.edu --- /sys/include/httpd.h Sat Jun 7 00:05:27 2008 +++ /sys/include/httpd.h Sat Jun 7 00:05:26 2008 @@ -196,6 +196,9 @@ void *private; /* for the library clients */ void (*replog)(HConnect*, char*, ...); /* called when reply sent */ + char *scheme; /* "http" vs. "https" */ + char *port; /* may be arbitrary, i.e., neither 80 nor 443 */ + HttpReq req; HttpHead head; --- /sys/src/cmd/ip/httpd/httpd.c Sat Jun 7 00:05:32 2008 +++ /sys/src/cmd/ip/httpd/httpd.c Thu Jul 15 23:40:40 2010 @@ -142,7 +142,7 @@ } static HConnect* -mkconnect(void) +mkconnect(char *scheme, char *port) { HConnect *c; @@ -150,6 +150,8 @@ c->hpos = c->header; c->hstop = c->header; c->replog = writelog; + c->scheme = scheme; + c->port = port; return c; } @@ -168,7 +170,7 @@ HSPriv *hp; HConnect *c; NetConnInfo *nci; - char ndir[NETPATHLEN], dir[NETPATHLEN], *p; + char ndir[NETPATHLEN], dir[NETPATHLEN], *p, *scheme; int ctl, nctl, data, t, ok, spotchk; TLSconn conn; @@ -221,7 +223,10 @@ if (certchain != nil) conn.chain = certchain; data = tlsServer(data, &conn); - } + scheme = "https"; + }else + scheme = "http"; + if(data < 0){ syslog(0, HTTPLOG, "can't open %s/data: %r", ndir); exits(nil); @@ -234,7 +239,7 @@ close(nctl); nci = getnetconninfo(ndir, -1); - c = mkconnect(); + c = mkconnect(scheme, nci->lserv); hp = mkhspriv(); hp->remotesys = nci->rsys; hp->remoteserv = nci->rserv; @@ -346,7 +351,9 @@ return -1; } hp = c->private; - execl(c->xferbuf, magic, "-d", hmydomain, "-w", webroot, "-r", hp->remotesys, "-N", netdir, "-b", hb, + execl(c->xferbuf, magic, "-s", c->scheme, "-d", hmydomain, + "-p", c->port, "-w", webroot, + "-r", hp->remotesys, "-N", netdir, "-b", hb, "-L", logfd0, logfd1, "-R", c->header, c->req.meth, vers, uri, c->req.search, nil); logit(c, "no magic %s uri %s", magic, uri); --- /sys/src/cmd/ip/httpd/init.c Sat Jun 7 00:05:36 2008 +++ /sys/src/cmd/ip/httpd/init.c Sat Jun 7 00:05:35 2008 @@ -4,9 +4,9 @@ #include "httpsrv.h" void -usage(void) +usage(char *progname) { - fprint(2, "usage: httpd [-b inbuf] [-d domain] [-r remoteip] [-w webroot] [-N netdir] [-R reqline] [-L logfd0 logfd1] method version uri [search]\n"); + fprint(2, "usage: %s [-b inbuf] [-d domain] [-p localport] [-r remoteip] [-s uri-scheme] [-w webroot] [-N netdir] [-R reqline] [-L logfd0 logfd1] method version uri [search]\n", progname); exits("usage"); } @@ -20,12 +20,14 @@ HConnect* init(int argc, char **argv) { - char *s, *vs; + char *s, *vs, *progname; hinit(&connect.hin, 0, Hread); hinit(&connect.hout, 1, Hwrite); hmydomain = nil; connect.replog = writelog; + connect.scheme = "http"; + connect.port = "80"; connect.private = &priv; priv.remotesys = nil; priv.remoteserv = nil; @@ -33,6 +35,7 @@ fmtinstall('H', httpfmt); fmtinstall('U', hurlfmt); netdir = "/net"; + progname = argv[0]; ARGBEGIN{ case 'b': s = ARGF(); @@ -42,9 +45,15 @@ case 'd': hmydomain = ARGF(); break; + case 'p': + connect.port = ARGF(); + break; case 'r': priv.remotesys = ARGF(); break; + case 's': + connect.scheme = ARGF(); + break; case 'w': webroot = ARGF(); break; @@ -54,21 +63,21 @@ case 'L': s = ARGF(); if(s == nil) - usage(); + usage(progname); logall[0] = strtol(s, nil, 10); s = ARGF(); if(s == nil) - usage(); + usage(progname); logall[1] = strtol(s, nil, 10); break; case 'R': s = ARGF(); if(s == nil) - usage(); + usage(progname); snprint((char*)connect.header, sizeof(connect.header), "%s", s); break; default: - usage(); + usage(progname); }ARGEND if(priv.remotesys == nil) @@ -87,7 +96,7 @@ syslog(0, HTTPLOG, nil); if(argc != 4 && argc != 3) - usage(); + usage(progname); connect.req.meth = argv[0]; --- /sys/src/libhttpd/parsereq.c Sat Jun 7 00:05:41 2008 +++ /sys/src/libhttpd/parsereq.c Sat Jun 7 00:05:40 2008 @@ -144,12 +144,15 @@ urihost = nil; if(uri[0] != '/'){ - if(cistrncmp(uri, "http://", 7) != 0){ + if(cistrncmp(uri, "http://", 7) == 0) + uri += 5; /* skip http: */ + else if (cistrncmp(uri, "https://", 8) == 0) + uri += 6; /* skip https: */ + else{ ss.s1 = nil; ss.s2 = nil; return ss; } - uri += 5; /* skip http: */ } /* --- /sys/src/libhttpd/redirected.c Sat Jun 7 00:05:46 2008 +++ /sys/src/libhttpd/redirected.c Sat Jun 7 00:05:46 2008 @@ -7,9 +7,11 @@ hredirected(HConnect *c, char *how, char *uri) { Hio *hout; - char *s, *ss, *host; + char *s, *ss, *scheme, *host, sayport[NETPATHLEN]; int n; + scheme = c->scheme ? c->scheme : "http"; + host = c->head.host; if(strchr(uri, ':')){ host = ""; @@ -24,6 +26,11 @@ *s = '/'; } + if((strcmp(scheme, "http") == 0 && (atoi(c->port) == 80)) || (strcmp(scheme, "https") == 0 && (atoi(c->port) == 443)) || strchr(host, ':')) + sayport[0] = '\0'; + else + snprint(sayport, sizeof(sayport), ":%s", c->port); + n = snprint(c->xferbuf, HBufSize, "Redirection\r\n" "

Redirection

\r\n" @@ -38,7 +45,7 @@ if(host == nil || host[0] == 0) hprint(hout, "Location: %U\r\n", uri); else - hprint(hout, "Location: http://%U%U\r\n", host, uri); + hprint(hout, "Location: %s://%U%s%U\r\n", scheme, host, sayport, uri); if(c->head.closeit) hprint(hout, "Connection: close\r\n"); else if(!http11(c)) @@ -52,7 +59,7 @@ if(host == nil || host[0] == 0) c->replog(c, "Reply: %s\nRedirect: %U\n", how, uri); else - c->replog(c, "Reply: %s\nRedirect: http://%U%U\n", how, host, uri); + c->replog(c, "Reply: %s\nRedirect: %s://%U%s%U\n", how, scheme, host, sayport, uri); } return hflush(hout); }