Commit Diff


commit - afc025ff600c11e5cbe8794b944b560492290cce
commit + e3ddf390950bf51d0c6c9cc6b931879006936e4c
blob - a9e08cc67cf25cecb7448cd23442cc0e47c60daa
blob + 8c067118f80a6563f880bce832a463c7c3d395dd
--- ChangeLog
+++ ChangeLog
@@ -1,6 +1,7 @@
 2021-02-06  Omar Polo  <op@omarpolo.com>
 
 	* parse.y (locopt): added ``block return'' and ``strip'' options
+	(servopt): add the ``entrypoint'' option
 
 2021-02-05  Omar Polo  <op@omarpolo.com>
 
blob - 58fa9cb3cf8c9d5473a90fbdd42e5fe025ab5fcc
blob + 012d5999170d7bbf5beb9f4db7dac75f3b744546
--- gmid.1
+++ gmid.1
@@ -230,7 +230,8 @@ A
 .Ic location
 section may include most of the server configuration rules
 except
-.Ic cert , Ic key , Ic root , Ic location No and Ic cgi .
+.Ic cert , Ic key , Ic root , Ic location No ,
+.Ic entrypoint No and Ic cgi .
 .It Ic block Op Ic return Ar code Op Ar meta
 Send a reply and close the connection;
 .Ar code
@@ -269,6 +270,11 @@ It's only considered for the
 .Ar meta
 parameter in the scope of a matching
 .Ic block return .
+.It Ic entrypoint Pa path
+Make the CGI script at
+.Pa path
+.Pq relative to the Ic root No directory
+handle all the requests for the current virtual host
 .El
 .Sh CGI
 When a request for an executable file matches the
blob - 1a1bd59dccdc46a5b479b6f829e38de5cbe506b3
blob + 8a9a52b65387862993e6fdcad3f98ec9eae63b08
--- gmid.c
+++ gmid.c
@@ -433,6 +433,7 @@ free_config(void)
 		free((char*)h->key);
 		free((char*)h->dir);
 		free((char*)h->cgi);
+		free((char*)h->entrypoint);
 
 		for (l = h->locations; l->match != NULL; ++l) {
 			free((char*)l->match);
blob - e4dd437546bf7bcc3b012601ce32c7d62a31fbfa
blob + 1701c98cdd2dc08328f952a0814f05bac533d295
--- gmid.h
+++ gmid.h
@@ -80,6 +80,7 @@ struct vhost {
 	const char	*key;
 	const char	*dir;
 	const char	*cgi;
+	const char	*entrypoint;
 	int		 dirfd;
 
 	/* the first location rule is always '*' and holds the default
blob - 04d902a39bbc4498fe9dc0cc29665682640ff3c1
blob + 8f233fbf8519b8205280cbca06e5098ccd387a91
--- lex.l
+++ lex.l
@@ -72,6 +72,7 @@ auto		return TAUTO;
 strip		return TSTRIP;
 block		return TBLOCK;
 return		return TRETURN;
+entrypoint	return TENTRYPOINT;
 
 [{}]		return *yytext;
 
blob - 77a3558f73c42d12b25629e5b75f251a8426c231
blob + c89ed5d1567a4175b895b116edaa627967a8e658
--- parse.y
+++ parse.y
@@ -125,6 +125,13 @@ servopt		: TCERT TSTRING		{ host->cert = ensure_absolu
 				memmove($2, $2+1, strlen($2));
 			host->cgi = $2;
 		}
+		| TENTRYPOINT TSTRING {
+			if (host->entrypoint != NULL)
+				yyerror("`entrypoint' specified more than once");
+			while (*$2 == '/')
+				memmove($2, $2+1, strlen($2));
+			host->entrypoint = $2;
+		}
 		| locopt
 		;
 
blob - b94e5c92c61eb3683e971ede87afa227fa542c6c
blob + 8a29ce505bfaecf01b6d65e0c7b73ee1d18d1b01
--- regress/Makefile
+++ regress/Makefile
@@ -38,7 +38,7 @@ testdata: fill-file
 	./sha testdata/bigfile testdata/bigfile.sha
 	printf "# hello world\n" > testdata/index.gmi
 	./sha testdata/index.gmi testdata/index.gmi.sha
-	cp hello slow err invalid serve-bigfile testdata/
+	cp hello slow err invalid serve-bigfile env testdata/
 	mkdir testdata/dir
 	cp hello testdata/dir
 	cp testdata/index.gmi testdata/dir/foo.gmi
blob - 4d53f1ccd29af150e22849189b82db6dd54b3649
blob + 9492b1d92e0ab68cca7f4ac7cd36fb69d7c7cfe9
--- regress/runtime
+++ regress/runtime
@@ -254,5 +254,15 @@ eq "$(head /bigfile)"		"40 %   10965 localhost test"
 echo OK GET /bigfile with strip and block
 
 check "should be running"
+
+# test the entrypoint
+
+config '' 'entrypoint "/env"'
+checkconf
+restart
 
+eq "$(head /foo/bar)"	"20 text/plain; lang=en"	"Unknown head for /foo/bar"
+eq "$(get /foo/bar|grep PATH_INFO)" "PATH_INFO=/foo/bar" "Unexpected PATH_INFO"
+echo OK GET /foo/bar with entrypoint
+
 quit
blob - ec44649f16b0fa2b951fc6dee6e1340cb06d3a40
blob + 33eda69a0184952292729558e39252c45628ecc0
--- server.c
+++ server.c
@@ -481,8 +481,15 @@ handle_open_conn(struct pollfd *fds, struct client *c)
 		return;
 	}
 
-	if (!apply_block_return(fds, c))
-		open_file(fds, c);
+	if (apply_block_return(fds, c))
+		return;
+
+	if (c->host->entrypoint != NULL) {
+		start_cgi(c->host->entrypoint, c->iri.path, fds, c);
+		return;
+	}
+
+	open_file(fds, c);
 }
 
 static void