Althttpd

MIME type for index
Login

MIME type for index

(1) By sodface on 2022-07-29 12:03:40 [source]

I'm currently using "index" exclusively for cgi scripts and "index.html" for static pages. For consistency, I originally thought I could use "index" for both cgi and static since the former would be executable and the latter would not.

I've waited too long to post since I was last working on it, so now I'm only 95% sure without retesting, but I think the issue I had with a static file named "index" was the lack of a defined MIME type.

If that's the case, would it make sense to define "text/html" for "index" in althttpd.c? The current MIME type list seems to only look at the .suffix of the filename, which makes sense, but makes it harder for me to see where and what to add in the case of "index".

(2) By Stephan Beal (stephan) on 2022-07-29 15:34:51 in reply to 1 [link] [source]

For consistency, I originally thought I could use "index" for both cgi and static since the former would be executable and the latter would not.

IMO that would fall into the category of "poor practice" because of confusion it will cause for things like...

would it make sense to define "text/html" for "index" in althttpd.c?

i would argue no, as web-served files without an extension are mostly CGIs (in my experience, anyway) and it's up to the CGI to emit its own mimetype.

The current MIME type list seems to only look at the .suffix of the filename,

Looking at GetMimeType(), it does indeed assume that the filename contains a dot. To pick up extensionless files, that "could" be changed to something like:

z = ('.'==zName[i]) ? &zName[i+1] : zName /*i==0 in this case*/;
// or:
z = i>0 ? &zName[i+1] : zName;
// ^^^ noting that althttpd won't serve filenames which start with a dot

(untested!)

That, along with an "index" entry in the mimetype table, would give you the feature you're looking for (and would allow althttpd to guess the mimetype for makefiles).

(3) By sodface on 2022-07-30 00:14:46 in reply to 2 [link] [source]

Thanks for the reply Stephan.

and it's up to the CGI to emit its own mimetype.

Just to clarify, I believe that would still occur with a CGI or static "index" file, based solely on whether it is executable or not.

Testing with the opposite of my desired outcome for example, "index.html" as a static file (non-executable) is served by althttpd with a "Content-type: text/html" but if you make it executable it's now treated as CGI by althttpd and has to emit its own content type header as you noted.

But then we are left with unattractive paths like:

www.example.com/index.html/this/was/cgi

As it is now, my homegrown templating scripts just check if "index" exists and do not generate a static file. If index does not exist, then index.html is created.

I guess I'd rather it just always be index, and check whether it's executable or not. Not sure if that made any sense. Not a big enough deal that I want to run a patched althttpd for.

(4) By Stephan Beal (stephan) on 2022-07-30 00:41:54 in reply to 3 [link] [source]

Just to clarify, I believe that would still occur with a CGI or static "index" file, based solely on whether it is executable or not.

Now that you mention it... correct, if index is run as a CGI, althttpd won't ever output a mimetype for it (just confirmed via going through the code). Given that, i've got no objection to adding an "index" mimetype of text/html. Doing so would require the no-dot-required patch (or equivalent) from up-thread.

Would it be possible for you to try that out on your server and report back whether it causes any unforeseen issues?

(5.2) By sodface on 2022-07-30 03:17:57 edited from 5.1 in reply to 4 [link] [source]

adding an "index" mimetype of text/html.

I added the no-dot-required patch above, but it's not immediately clear to me what change to make to the mimetype list. At first I thought it would need to match a zero length suffix (which would mean all files without an extension would be text/html, not just index):

static const MimeTypeDef aMime[] = {
+  { "",           0, 0x00, "text/html"                        },
   { "ai",         2, 0x00, "application/postscript"           },

And then, still confused, I added the full filename:

   { "igs",        3, 0x00, "model/iges"                       },
+  { "index",      5, 0x00, "text/html"                        },
   { "ips",        3, 0x00, "application/x-ipscript"           },

In both cases firefox just tries to download the file and shows it as being "application/octet-stream;"

Sorry if I'm being dense here.

(6) By Stephan Beal (stephan) on 2022-07-30 03:46:04 in reply to 5.2 [link] [source]

In both cases firefox just tries to download the file and shows it as being "application/octet-stream;"

The second one, along with one of the two changes from my first response, ought to do it, but i'm on a tablet so can't try it out. i'll try it on Saturday sometime and get back to you.

(7) By sodface on 2022-07-30 13:09:00 in reply to 6 [link] [source]

The below patch is probably not the best code but seems to be working. More testing needed. I think the issue is that zName is the full path to the file, not just the base filename, so I added a test for '/'

--- src/althttpd.c
+++ althttpd.c
@@ -1688,6 +1688,7 @@
   { "ief",        3, 0x00, "image/ief"                        },
   { "iges",       4, 0x00, "model/iges"                       },
   { "igs",        3, 0x00, "model/iges"                       },
+  { "index",      5, 0x00, "text/html"                        },
   { "ips",        3, 0x00, "application/x-ipscript"           },
   { "ipx",        3, 0x00, "application/x-ipix"               },
   { "jad",        3, 0x00, "text/vnd.sun.j2me.app-descriptor" },
@@ -1825,8 +1826,8 @@
   { "zip",        3, 0x00, "application/zip"                  },
   };
 
-  for(i=nName-1; i>0 && zName[i]!='.'; i--){}
-  z = &zName[i+1];
+  for(i=nName-1; i>0 && zName[i]!='.' && zName[i]!='/'; i--){}
+  z = i>0 ? &zName[i+1] : zName;
   len = nName - i;
   if( len<(int)sizeof(zSuffix)-1 ){
     strcpy(zSuffix, z);

(8) By Stephan Beal (stephan) on 2022-07-30 16:44:56 in reply to 7 [link] [source]

I think the issue is that zName is the full path to the file, not just the base filename,

Aha! In that case the final change line needs to be something like:

z = (zName[i]=='.' || zName[i]=='/') ? &zName[i+1] : zName;

Still typing one-handed on the tablet, away from the computer, so can't easily verify that, though. The check for i>0 was suggested on the assumption that zName was only looking at the trailing file part of the name.

(9) By Stephan Beal (stephan) on 2022-07-30 17:43:31 in reply to 7 [link] [source]

More testing needed.

The following patch works for me. My previous untested attempt neglected to account for the extension's length.

Index: althttpd.c
==================================================================
--- althttpd.c
+++ althttpd.c
@@ -1686,10 +1686,11 @@
   { "html",       4, 0x00, "text/html"                        },
   { "ice",        3, 0x00, "x-conference/x-cooltalk"          },
   { "ief",        3, 0x00, "image/ief"                        },
   { "iges",       4, 0x00, "model/iges"                       },
   { "igs",        3, 0x00, "model/iges"                       },
+  { "index",      5, 0x00, "text/html"                        },
   { "ips",        3, 0x00, "application/x-ipscript"           },
   { "ipx",        3, 0x00, "application/x-ipix"               },
   { "jad",        3, 0x00, "text/vnd.sun.j2me.app-descriptor" },
   { "jar",        3, 0x00, "application/java-archive"         },
   { "jpeg",       4, 0x00, "image/jpeg"                       },
@@ -1829,13 +1830,18 @@
   { "xwd",        3, 0x00, "image/x-xwindowdump"              },
   { "xyz",        3, 0x00, "chemical/x-pdb"                   },
   { "zip",        3, 0x00, "application/zip"                  },
   };
 
-  for(i=nName-1; i>0 && zName[i]!='.'; i--){}
-  z = &zName[i+1];
+  for(i=nName-1; i>0 && zName[i]!='.' && zName[i]!='/'; i--){}
   len = nName - i;
+  if('.'==zName[i] || '/'==zName[i]){
+    z = &zName[i+1];
+    --len;
+  }else{
+    z = zName;
+  }
   if( len<(int)sizeof(zSuffix)-1 ){
     strcpy(zSuffix, z);
     for(i=0; zSuffix[i]; i++) zSuffix[i] = tolower(zSuffix[i]);
     first = 0;
     last = sizeof(aMime)/sizeof(aMime[0]);

As to whether or not that should be integrated into the main copy, i'm ambivalent. That's a decision for Richard.

(10) By sodface on 2022-07-30 21:43:07 in reply to 9 [link] [source]

The following patch works for me.

Works for me too! Thanks again Stephan.

That's a decision for Richard.

A bit more explanation for Richard or anyone interested. Though I have very little content on my site currently, I've had a lot of fun working on the mechanics of it and I'm relying on a few features of althttpd for the site to work properly. Mainly, the protected content directories (starting with a dash) but also the search order that althttpd uses when trying to answer a page request:

"/home", "/index", "/index.html", "/index.cgi"

I use ambiguous links like:

http://www.sodface.com/misc/qots-crew-gen/

Which makes althttpd look for a file in the order noted above. Since index.cgi is last, I'm using that as the page source generator.

Basically, if you make it all the way to index.cgi this is what it does:

  • Assembles a page.src file from fragments of html (template files)
  • Checks to see if "index" exists, if it does, just sources page.src
  • If "index" doesn't exist, source page.src but also tee it to index.html

This way althttpd should only get to index.cgi when you first create a page or you explicitly request it in the url in order to force a rebuild after a template change. For subsequent requests, "index" (in the case of cgi) or "index.html" (in the case of static content) will be found and returned first.

Adding a text/html mimetype for "index" would let me just use index everywhere, for both static and cgi, which to me would be a little more consistent and aesthetically pleasing.

Below is my current function that handles this. Note that more often that not, "index" is just a symlink to "index.cgi" so the $0 test determines whether to rebuild page.src from templates or just source the existing page.src.

__page_out()
{
	printf "%s\n\n" "Content-Type: text/html"
	if [ "$0" = "index.cgi" ]
	then
		__page_src
		if [ -e index ]; then
			source ./-src/page.src
		else
			source ./-src/page.src | tee index.html
		fi
	else
		[ ! -e ./-src/page.src ] && __page_src
		source ./-src/page.src
	fi
}