"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
"Omar Polo" <op@omarpolo.com>
Subject:
Re: make gotwebd serve its own static files
To:
Stefan Sperling <stsp@stsp.name>
Cc:
gameoftrees@openbsd.org
Date:
Tue, 07 Oct 2025 17:14:29 +0200

Download raw body.

Thread
Stefan Sperling <stsp@stsp.name> wrote:
> Because gotwebd's FastCGI socket can be reached over TCP, the web server
> and gotwebd do not necessarily need to run on the same machine.
> 
> However, pages won't render properly unless the web server provides
> the static files needed to render the page (.css, .png, etc.).

I just realized that for gothub we could actually serve the assets from
the outside, saving one round-trip to the vm.  (assuming we find a way
to deal with verision changes).  anyway

> This patch adds support to gotwebd for serving these files directly,
> and updates the documentation accordingly. This fixes FastCGI over
> TCP to gotwebd running on remote machines, and also makes local setups
> simpler since we no longer need to fiddle with web server location
> match syntax to get the files served correctly.
> 
> 
> ok?

ok op@ with one nit below.

> make gotwebd serve its own static files if not they are not served by httpd
> 
> This makes it possible to forward FastCGI requests to a remote gotwebd over
> TCP without requiring the local webserver to host gotwebd's static files.
> 
> M  gotwebd/auth.c            |   13+   0-
> M  gotwebd/config.c          |    2+   0-
> M  gotwebd/gotweb.c          |  153+   2-
> M  gotwebd/gotwebd.8         |   55+  20-
> M  gotwebd/gotwebd.conf.5    |  103+   0-
> M  gotwebd/gotwebd.h         |    6+   0-
> M  gotwebd/pages.tmpl        |   13+   8-
> M  gotwebd/parse.y           |  106+   3-
> M  include/got_error.h       |    1+   0-
> M  lib/error.c               |    1+   0-
> M  regress/gotwebd/Makefile  |    1+   0-
> 
> 11 files changed, 454 insertions(+), 33 deletions(-)
> 
> commit - 0982109a05d9bfe118c5979cce77395365ceba4a
> commit + c309f46155fedeef7089b4fdd4007e53d88c2979
> blob - 9da9ece32167915acfad39d45ed3fec2efd09cbe
> blob + a63bc5110b0be05423cf4da5de4837ec9c0ad94e
> --- gotwebd/auth.c
> +++ gotwebd/auth.c
> @@ -17,6 +17,7 @@
>   */
>  
>  #include <sys/queue.h>
> +#include <sys/tree.h>
>  
>  #include <errno.h>
>  #include <event.h>
> @@ -34,6 +35,7 @@
>  #include "got_error.h"
>  #include "got_reference.h"
>  #include "got_object.h"
> +#include "got_path.h"
>  
>  #include "gotwebd.h"
>  #include "log.h"
> @@ -451,6 +453,17 @@ process_request(struct request *c)
>  		goto done;
>  	}
>  
> +	/*
> +	 * Static gotwebd assets (images, CSS, ...) are not protected
> +	 * by authentication.
> +	 */
> +	if (got_path_cmp(srv->gotweb_url_path, c->fcgi_params.document_uri,
> +	    strlen(srv->gotweb_url_path),
> +	    strlen(c->fcgi_params.document_uri)) != 0) {
> +		forward_request(c);
> +		return;
> +	}
> +
>  	auth_config = srv->auth_config;
>  	if (c->fcgi_params.qs.path[0] != '\0') {
>  		repo = gotweb_get_repository(srv, c->fcgi_params.qs.path);
> blob - e1514e1edc7175e78aa0a0cf6ec183f55c300360
> blob + df4f8a49c87aba1c7a3e19f855d4000f47a90003
> --- gotwebd/config.c
> +++ gotwebd/config.c
> @@ -51,6 +51,8 @@ config_init(struct gotwebd *env)
>  	int i;
>  
>  	strlcpy(env->httpd_chroot, D_HTTPD_CHROOT, sizeof(env->httpd_chroot));
> +	strlcpy(env->htdocs_path, D_HTDOCS_PATH, sizeof(env->htdocs_path));
> +	strlcpy(env->gotweb_url_path, "/", sizeof(env->gotweb_url_path));
>  
>  	env->prefork = GOTWEBD_NUMPROC;
>  	TAILQ_INIT(&env->servers);
> blob - 56f89783fe3d444b674bbc92188b4ce4a7f237fc
> blob + 755ad3573eb6c6a0227db5614b45d844b9382190
> --- gotwebd/gotweb.c
> +++ gotwebd/gotweb.c
> @@ -259,11 +259,117 @@ gotweb_log_request(struct request *c)
>  	free(document_uri);
>  }
>  
> +const struct got_error *
> +gotweb_serve_htdocs(struct request *c)
> +{
> +	const struct got_error *error = NULL;
> +	struct server *srv = c->srv;;
> +	struct gotwebd_fcgi_params *p = &c->fcgi_params;
> +	char *document_uri = p->document_uri;
> +	char *request_path = NULL;
> +	char *child_path = NULL;
> +	char *ondisk_path = NULL;
> +	int fd = -1;
> +	const char *mime_type;

could you please set this to a default, catch-all value, like
application/octet-stream?  because...

> [...]
> +	ext = strrchr(ondisk_path, '.');
> +	if (ext) {
> +		if (strcmp(ext, ".css") == 0)
> +			mime_type = "text/css";
> +		if (strcmp(ext, ".png") == 0)
> +			mime_type = "image/png";
> +		if (strcmp(ext, ".svg") == 0)
> +			mime_type = "image/svg+xml";
> +		if (strcmp(ext, ".txt") == 0)
> +			mime_type = "text/plain";
> +		if (strcmp(ext, ".xml") == 0)
> +			mime_type = "text/xml";

...here might still be unset and

> +	}
> +
> +	if (gotweb_reply(c, 200, mime_type, NULL) == -1) {

ooops =)

I know it's very unlikely, since (should) control the files in
/var/www/htdocs/gotwebd.

BUT, given that you've forgot about favicon.ico and site.webmanifest, I
guess it's a nice guardrail as well =)

> +		error = got_error(GOT_ERR_IO);
> +		goto done;
> +	}
> +
> +	if (template_flush(c->tp) == -1) {
> +		error = got_error(GOT_ERR_IO);
> +		goto done;
> +	}
> +
> +	for (;;) {
> +		uint8_t buf[BUF];
> +		ssize_t r;
> +
> +		r = read(fd, buf, sizeof(buf));
> +		if (r == -1) {
> +			error = got_error_from_errno("read");
> +			goto done;
> +		}
> +		if (r == 0)
> +			break;
> +	
> +		if (fcgi_write(c, buf, r) == -1) {
> +			error = got_error(GOT_ERR_IO);
> +			goto done;
> +		}
> +	}
> +done:
> +	if (fd != -1 && close(fd) == -1 && error == NULL)
> +		error = got_error_from_errno("close");
> +	free(request_path);
> +	free(child_path);
> +	free(ondisk_path);
> +	return error;
> +}
> +


Thanks,
Omar Polo