Re: patch: adding httpd implicit file extensions

2021-02-27 Thread Bruce Hill

On 2/27/21 3:10 AM, Stuart Henderson wrote:

I might be missing something but doesn't this do the same?

 location not found match "/(.*)" {
 request rewrite "/%1.html"
 }


Nope, you're not missing anything, I wasn't aware you could do this.
This *does* actually solve my problem, although it should be

location not found match "/(.+)"

(with `.+` instead of `.*`) in order for it to work properly with
`index.html`. I guess my patch is pretty unnecessary :)

On 2/27/21 3:10 AM, Stuart Henderson wrote:

Custom error pages sound useful indeed.


My patch for that is actually quite small (including a slight tweak to
the default font). It hardcodes the error file path to `/.html` (e.g. /var/www/htdocs/404.html) and if that
file exists, it uses that file's contents instead of a hardcoded error
string. It's not very configurable, but it gets the job done:

Index: server_http.c
===
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.143
diff -u -p -u -p -r1.143 server_http.c
--- server_http.c   5 Jan 2021 19:56:11 -   1.143
+++ server_http.c   27 Feb 2021 23:31:13 -
@@ -848,6 +848,8 @@ server_abort_http(struct client *clt, un
char buf[IBUF_READ_SIZE];
char*escapedmsg = NULL;
int  bodylen;
+   char err_path[PATH_MAX];
+   FILE*f;
 
 	if (code == 0) {

server_close(clt, "dropped");
@@ -925,14 +927,25 @@ server_abort_http(struct client *clt, un
 
 	/* A CSS stylesheet allows minimal customization by the user */

style = "body { background-color: white; color: black; font-family: "
-   "'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; }\n"
+   "sans-serif; }\n"
"hr { border: 0; border-bottom: 1px dashed; }\n"
"@media (prefers-color-scheme: dark) {\n"
"body { background-color: #1E1F21; color: #EEEFF1; }\n"
"a { color: #BAD7FF; }\n}";
 
+	/* Check for error document HTML file */

+   bodylen = 0;
+   if (snprintf(err_path, sizeof(err_path), "%s/%d.html", srv_conf->root,
+   code) != -1 && (f = fopen(err_path, "r")) != NULL) {
+   fseek(f, 0, SEEK_END);
+   bodylen = ftell(f);
+   fseek(f, 0, SEEK_SET);
+   body = calloc(bodylen + 1, sizeof(char));
+   bodylen = body ? fread(body, sizeof(char), bodylen, f) : 0;
+   }
+
/* Generate simple HTML error document */
-   if ((bodylen = asprintf(,
+   if (bodylen == 0 && (bodylen = asprintf(,
"\n"
"\n"
"\n"



Re: patch: adding httpd implicit file extensions

2021-02-27 Thread Stuart Henderson
On 2021/02/26 15:38, Bruce Hill wrote:
> Hello, this is my first time contributing to openbsd and this mailing
> list, so please excuse any newbie blunders. I recently switched my
> personal website to use httpd with statically generated HTML files, but
> was unhappy to find that my HTML files could only be accessed by exact
> filename, including the ".html" at the end. My site previously ran on
> Apache with rewrite rules to ensure that "example.com/foo" would serve
> the file "/foo.html" (when "/foo" didn't exist). I wanted to keep my
> original URLs working and I aesthetically prefer URLs without ".html"
> suffixes, so I looked around for different options with httpd. The best
> option I could find was to create symbolic links from "/foo" to
> "/foo.html" and set the default media type to text/html, but this
> solution was cumbersome (I had to maintain all the symbolic links) and
> had undesirable side effects (all extensionless files were treated as
> text/html instead of text/plain).
> 
> I decided instead to look into modifying httpd to support implicit file
> extensions. My basic idea was to add a configurable setting called
> `implicit extension`. When a file is not found and the file doesn't
> already have the implicit extension, then httpd will look for the same
> filename but with the implicit extension added at the end, and reroute
> to that file if it exists. This neatly solves my problem by adding
> `implicit extension ".html"` to the top of my /etc/httpd.conf file, and
> `implicit extension ".php"` to the section of my website that uses PHP
> scripts. For simplicity (and because my website doesn't use both HTML
> and PHP in the same subdomain), I opted to only support a single
> implicit extension per config block, though in the future, supporting
> globs as implicit extensions might also be nice(e.g. `implicit extension
> ".{html,php}"`).

I might be missing something but doesn't this do the same?

location not found match "/(.*)" {
request rewrite "/%1.html"
}

> I've been running the code on my personal website for a while now
> without any issues. If this patch is accepted, I also have a separate
> small patch that displays custom HTTP error pages if you have a
> /[] file (e.g. /404 or /404.html), which
> works well in conjunction with this patch.

Custom error pages sound useful indeed.

> I'm happy to take any feedback or criticism on both the idea and my
> implementation patch below. Hopefully other people find this useful as
> well!
> 
> - Bruce Hill
> 
> 
> Index: config.c
> ===
> RCS file: /cvs/src/usr.sbin/httpd/config.c,v
> retrieving revision 1.61
> diff -u -p -u -p -r1.61 config.c
> --- config.c  21 Sep 2020 09:42:07 -  1.61
> +++ config.c  26 Feb 2021 23:30:18 -
> @@ -568,6 +568,13 @@ config_getserver_config(struct httpd *en
>   >default_type, sizeof(struct media_type));
>   }
> + f = SRVFLAG_IMPLICIT_EXT;
> + if ((srv_conf->flags & f) == 0) {
> + srv_conf->flags |= parent->flags & f;
> + memcpy(_conf->implicit_extension,
> + >implicit_extension, 
> sizeof(parent->implicit_extension));
> + }
> +
>   f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE;
>   if ((srv_conf->flags & f) == 0) {
>   srv_conf->flags |= parent->flags & f;
> Index: httpd.h
> ===
> RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
> retrieving revision 1.153
> diff -u -p -u -p -r1.153 httpd.h
> --- httpd.h   29 Oct 2020 12:30:52 -  1.153
> +++ httpd.h   26 Feb 2021 23:30:19 -
> @@ -57,6 +57,7 @@
>  #define HTTPD_REALM_MAX  255
>  #define HTTPD_LOCATION_MAX   255
>  #define HTTPD_DEFAULT_TYPE   { "bin", "application", "octet-stream", NULL }
> +#define HTTPD_IMPLICIT_EXT   ""
>  #define HTTPD_LOGVIS VIS_NL|VIS_TAB|VIS_CSTYLE
>  #define HTTPD_TLS_CERT   "/etc/ssl/server.crt"
>  #define HTTPD_TLS_KEY"/etc/ssl/private/server.key"
> @@ -391,6 +392,7 @@ SPLAY_HEAD(client_tree, client);
>  #define SRVFLAG_DEFAULT_TYPE 0x0080
>  #define SRVFLAG_PATH_REWRITE 0x0100
>  #define SRVFLAG_NO_PATH_REWRITE  0x0200
> +#define SRVFLAG_IMPLICIT_EXT 0x0400
>  #define SRVFLAG_LOCATION_FOUND   0x4000
>  #define SRVFLAG_LOCATION_NOT_FOUND 0x8000
> @@ -399,8 +401,8 @@ SPLAY_HEAD(client_tree, client);
>   "\05ROOT\06LOCATION\07FCGI\10NO_FCGI\11LOG\12NO_LOG"\
>   "\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG"  \
>   "\21AUTH\22NO_AUTH\23BLOCK\24NO_BLOCK\25LOCATION_MATCH" \
> - "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31PATH\32NO_PATH" \
> - "\37LOCATION_FOUND\40LOCATION_NOT_FOUND"
> + 

Re: patch: adding httpd implicit file extensions

2021-02-27 Thread Matthias Pressfreund


On 2021-02-27 00:38, Bruce Hill wrote:
> Hello, this is my first time contributing to openbsd and this mailing
> list, so please excuse any newbie blunders. I recently switched my
> personal website to use httpd with statically generated HTML files, but
> was unhappy to find that my HTML files could only be accessed by exact
> filename, including the ".html" at the end. My site previously ran on
> Apache with rewrite rules to ensure that "example.com/foo" would serve
> the file "/foo.html" (when "/foo" didn't exist). I wanted to keep my
> original URLs working and I aesthetically prefer URLs without ".html"
> suffixes, so I looked around for different options with httpd. The best
> option I could find was to create symbolic links from "/foo" to
> "/foo.html" and set the default media type to text/html, but this
> solution was cumbersome (I had to maintain all the symbolic links) and
> had undesirable side effects (all extensionless files were treated as
> text/html instead of text/plain).
> 

Hello, wouldn't the following serve for what you want?


location not found match "^/scripts/(.*)$" {
request rewrite "/scripts/%1.php"
}

location not found match "^/(.*)$" {
request rewrite "/%1.html"
}



patch: adding httpd implicit file extensions

2021-02-26 Thread Bruce Hill

Hello, this is my first time contributing to openbsd and this mailing
list, so please excuse any newbie blunders. I recently switched my
personal website to use httpd with statically generated HTML files, but
was unhappy to find that my HTML files could only be accessed by exact
filename, including the ".html" at the end. My site previously ran on
Apache with rewrite rules to ensure that "example.com/foo" would serve
the file "/foo.html" (when "/foo" didn't exist). I wanted to keep my
original URLs working and I aesthetically prefer URLs without ".html"
suffixes, so I looked around for different options with httpd. The best
option I could find was to create symbolic links from "/foo" to
"/foo.html" and set the default media type to text/html, but this
solution was cumbersome (I had to maintain all the symbolic links) and
had undesirable side effects (all extensionless files were treated as
text/html instead of text/plain).

I decided instead to look into modifying httpd to support implicit file
extensions. My basic idea was to add a configurable setting called
`implicit extension`. When a file is not found and the file doesn't
already have the implicit extension, then httpd will look for the same
filename but with the implicit extension added at the end, and reroute
to that file if it exists. This neatly solves my problem by adding
`implicit extension ".html"` to the top of my /etc/httpd.conf file, and
`implicit extension ".php"` to the section of my website that uses PHP
scripts. For simplicity (and because my website doesn't use both HTML
and PHP in the same subdomain), I opted to only support a single
implicit extension per config block, though in the future, supporting
globs as implicit extensions might also be nice(e.g. `implicit extension
".{html,php}"`).

I've been running the code on my personal website for a while now
without any issues. If this patch is accepted, I also have a separate
small patch that displays custom HTTP error pages if you have a
/[] file (e.g. /404 or /404.html), which
works well in conjunction with this patch.

I'm happy to take any feedback or criticism on both the idea and my
implementation patch below. Hopefully other people find this useful as
well!

- Bruce Hill


Index: config.c
===
RCS file: /cvs/src/usr.sbin/httpd/config.c,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 config.c
--- config.c21 Sep 2020 09:42:07 -  1.61
+++ config.c26 Feb 2021 23:30:18 -
@@ -568,6 +568,13 @@ config_getserver_config(struct httpd *en
>default_type, sizeof(struct media_type));
}
 
+		f = SRVFLAG_IMPLICIT_EXT;

+   if ((srv_conf->flags & f) == 0) {
+   srv_conf->flags |= parent->flags & f;
+   memcpy(_conf->implicit_extension,
+   >implicit_extension, 
sizeof(parent->implicit_extension));
+   }
+
f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE;
if ((srv_conf->flags & f) == 0) {
srv_conf->flags |= parent->flags & f;
Index: httpd.h
===
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.153
diff -u -p -u -p -r1.153 httpd.h
--- httpd.h 29 Oct 2020 12:30:52 -  1.153
+++ httpd.h 26 Feb 2021 23:30:19 -
@@ -57,6 +57,7 @@
 #define HTTPD_REALM_MAX255
 #define HTTPD_LOCATION_MAX 255
 #define HTTPD_DEFAULT_TYPE { "bin", "application", "octet-stream", NULL }
+#define HTTPD_IMPLICIT_EXT ""
 #define HTTPD_LOGVIS   VIS_NL|VIS_TAB|VIS_CSTYLE
 #define HTTPD_TLS_CERT "/etc/ssl/server.crt"
 #define HTTPD_TLS_KEY  "/etc/ssl/private/server.key"
@@ -391,6 +392,7 @@ SPLAY_HEAD(client_tree, client);
 #define SRVFLAG_DEFAULT_TYPE   0x0080
 #define SRVFLAG_PATH_REWRITE   0x0100
 #define SRVFLAG_NO_PATH_REWRITE0x0200
+#define SRVFLAG_IMPLICIT_EXT   0x0400
 #define SRVFLAG_LOCATION_FOUND 0x4000
 #define SRVFLAG_LOCATION_NOT_FOUND 0x8000
 
@@ -399,8 +401,8 @@ SPLAY_HEAD(client_tree, client);

"\05ROOT\06LOCATION\07FCGI\10NO_FCGI\11LOG\12NO_LOG"  \
"\14SYSLOG\15NO_SYSLOG\16TLS\17ACCESS_LOG\20ERROR_LOG"\
"\21AUTH\22NO_AUTH\23BLOCK\24NO_BLOCK\25LOCATION_MATCH"   \
-   "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31PATH\32NO_PATH" \
-   "\37LOCATION_FOUND\40LOCATION_NOT_FOUND"
+   "\26SERVER_MATCH\27SERVER_HSTS\30DEFAULT_TYPE\31PATH\32NO_PATH"   \
+   "\33IMPLICIT_EXTENSION\37LOCATION_FOUND\40LOCATION_NOT_FOUND"
 
 #define TCPFLAG_NODELAY		0x01

 #define TCPFLAG_NNODELAY   0x02
@@ -481,6 +483,7 @@ struct server_config {
char accesslog[PATH_MAX];
char errorlog[PATH_MAX];
struct media_typedefault_type;
+   char