Commit Diff


commit - f5dc7eddd7ac6cf06d7092e9526691b566850b50
commit + e872053b20d763005a398200c638c923aebd04e1
blob - e681e1b5bb39bf3e023e0ca22acdf7218c249daa
blob + 2219ecb5114fbc8afc04b620a93f808831b3b029
--- fcgi.c
+++ fcgi.c
@@ -371,12 +371,37 @@ fcgi_error(struct bufferevent *bev, short err, void *d
 	c->type = REQUEST_DONE;
 }
 
+static void
+path_translate(const char *path, struct location *loc, struct location *rloc,
+    char *buf, size_t len)
+{
+	const char *root, *sufx;
+
+	buf[0] = '\0';
+
+	if (*loc->dir != '\0')
+		root = loc->dir;
+	else if (*rloc->dir != '\0')
+		root = rloc->dir;
+	else
+		return;
+
+	sufx = "";
+	if (*root != '\0')
+		sufx = root[strlen(root) - 1] == '/' ? "" : "/";
+
+	while (*path == '/')
+		path++;
+
+	snprintf(buf, len, "%s%s%s", root, sufx, path);
+}
+
 void
 fcgi_req(struct client *c, struct location *loc)
 {
-	char		 buf[22], path[GEMINI_URL_LEN];
+	char		 buf[22], path[GEMINI_URL_LEN], path_tr[PATH_MAX];
 	char		*scriptname, *qs;
-	const char	*stripped;
+	const char	*stripped, *port;
 	size_t		 l;
 	time_t		 tim;
 	struct tm	 tminfo;
@@ -384,6 +409,16 @@ fcgi_req(struct client *c, struct location *loc)
 
 	fcgi_begin_request(c->cgibev);
 
+	stripped = strip_path(c->iri.path, loc->fcgi_strip);
+	if (*stripped != '/')
+		snprintf(path, sizeof(path), "/%s", stripped);
+	else
+		strlcpy(path, stripped, sizeof(path));
+
+	port = c->iri.host;
+	if (port == NULL || *port == '\0')
+		port = "1965";
+
 	scriptname = "";
 	TAILQ_FOREACH(p, &loc->params, envs) {
 		if (!strcmp(p->name, "SCRIPT_NAME")) {
@@ -392,35 +427,36 @@ fcgi_req(struct client *c, struct location *loc)
 		}
 	}
 
-	stripped = strip_path(c->iri.path, loc->fcgi_strip);
-	if (*stripped != '/')
-		snprintf(path, sizeof(path), "/%s", stripped);
-	else
-		strlcpy(path, stripped, sizeof(path));
-
 	l = strlen(scriptname);
 	while (l > 0 && scriptname[l - 1] == '/')
 		l--;
 	if (!strncmp(scriptname, path, l) && (path[l] == '/' ||
 	    path[l] == '\0')) {
 		fcgi_send_param(c->cgibev, "PATH_INFO", &path[l]);
+		path_translate(&path[l], loc, TAILQ_FIRST(&c->host->locations),
+		    path_tr, sizeof(path_tr));
 		path[l] = '\0';
 		fcgi_send_param(c->cgibev, "SCRIPT_NAME", path);
 	} else {
+		path_translate(stripped, loc, TAILQ_FIRST(&c->host->locations),
+		    path_tr, sizeof(path_tr));
 		fcgi_send_param(c->cgibev, "PATH_INFO", stripped);
 		fcgi_send_param(c->cgibev, "SCRIPT_NAME", scriptname);
 	}
 
 	fcgi_send_param(c->cgibev, "GATEWAY_INTERFACE", "CGI/1.1");
-	fcgi_send_param(c->cgibev, "GEMINI_URL_PATH", c->iri.path);
+	fcgi_send_param(c->cgibev, "PATH_TRANSLATED", path_tr);
 	fcgi_send_param(c->cgibev, "QUERY_STRING", c->iri.query);
 	fcgi_send_param(c->cgibev, "REMOTE_ADDR", c->rhost);
 	fcgi_send_param(c->cgibev, "REMOTE_HOST", c->rhost);
-	fcgi_send_param(c->cgibev, "REQUEST_METHOD", "");
+	fcgi_send_param(c->cgibev, "REQUEST_METHOD", "GET");
 	fcgi_send_param(c->cgibev, "SERVER_NAME", c->iri.host);
+	fcgi_send_param(c->cgibev, "SERVER_PORT", port);
 	fcgi_send_param(c->cgibev, "SERVER_PROTOCOL", "GEMINI");
 	fcgi_send_param(c->cgibev, "SERVER_SOFTWARE", GMID_VERSION);
 
+	fcgi_send_param(c->cgibev, "GEMINI_URL_PATH", c->iri.path);
+
 	if (*c->iri.query != '\0' &&
 	    strchr(c->iri.query, '=') == NULL &&
 	    (qs = strdup(c->iri.query)) != NULL) {
blob - 5738e72613a9504aec57e8694007461b164bdeb5
blob + fc7845222690e79ccee09f573e33cfa8eebab720
--- gmid.conf.5
+++ gmid.conf.5
@@ -11,7 +11,7 @@
 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.Dd July 24, 2023
+.Dd August 18, 2023
 .Dt GMID.CONF 5
 .Os
 .Sh NAME
@@ -326,25 +326,25 @@ leading path components from the
 .Pp
 The FastCGI handler will be given the following variables by default:
 .Bl -tag -width 24m
-.It Ev GATEWAY_INTERFACE
-.Dq CGI/1.1
-.It Ev GEMINI_DOCUMENT_ROOT
-The root directory of the virtual host.
-.It Ev GEMINI_SCRIPT_FILENAME
-Full path to the FastCGI script being executed.
-.It Ev GEMINI_URL
-The full IRI of the request.
+.\" .It Ev GEMINI_DOCUMENT_ROOT
+.\" The root directory of the virtual host.
 .It Ev GEMINI_URL_PATH
-The path of the request.
+Full path of the request.
 .It Ev GEMINI_SEARCH_STRING
 The decoded
 .Ev QUERY_STRING
 if defined in the request and if it doesn't contain any unencoded
 .Sq =
 characters, otherwise unset.
+.It Ev GATEWAY_INTERFACE
+.Dq CGI/1.1
+.It Ev AUTH_TYPE
+The string "Certificate" if the client used a certificate, otherwise
+unset.
 .It Ev PATH_INFO
 The portion of the requested path that is derived from the the IRI
-path hierarchy following the part that identifies the script itself.
+path hierarchy following
+.Ev SCRIPT_NAME .
 Can be unset.
 .It Ev PATH_TRANSLATED
 Present if and only if
@@ -362,9 +362,17 @@ The URL-encoded search or parameter string.
 Textual representation of the client IP.
 .It Ev REQUEST_METHOD
 This is present only for RFC3875 (CGI) compliance.
-It's always set to the empty string.
+It's always set to
+.Dq GET .
 .It Ev SCRIPT_NAME
 The virtual URI path to the script.
+Since it's impossible to determine in all cases the correct
+.Ev SCRIPT_NAME
+programmatically
+.Nm gmid
+assumes it's the empty string.
+It is recommended to manually specify this parameter when serving a
+sub-tree of a virtual host via FastCGI.
 .It Ev SERVER_NAME
 The name of the server
 .It Ev SERVER_PORT
@@ -374,9 +382,6 @@ The port the server is listening on.
 .It Ev SERVER_SOFTWARE
 The name and version of the server, i.e.
 .Dq gmid/1.8.4
-.It Ev AUTH_TYPE
-The string "Certificate" if the client used a certificate, otherwise
-unset.
 .It Ev REMOTE_USER
 The subject of the client certificate if provided, otherwise unset.
 .It Ev TLS_CLIENT_ISSUER