Dynamic websites
Static websites seem simple, but it is hard to avoid breaking
things even with those (see web design checklist). Dynamic ones
are certainly more complex, and there's more things to break
and/or overcomplicate. Below is an outline of relatively basic
technologies and tools that are sufficient for building a
typical dynamic website.
- DBMS
-
Most of the dynamic websites are essentially custom database
interfaces. Advanced DBMSes such as PostgreSQL provide
extensive tooling for access control and business logic
implementation: see Database Roles, GRANT, Row Security
Policies, Constraints, Server Programming. With a properly
designed database, a typical dynamic website only has to serve
as a bridge between a database and a web server. In case of
PostgreSQL, libpq is the client library, and bindings to it
are usually available. Though when a project is small enough,
it may be better to store structured files directly, without a
DBMS.
- CGI
-
CGI provides a simple interface between a web server and an
application. It can be used without any specialised libraries
(for instance, as implemented in bwchat), though more
convenient with those. There is FastCGI, an almost drop-in
alternative useful for optimisation. Web servers such as nginx
(which provide plenty of nice related functionality), and
possibly fcgiwrap, are the relevant software here. Among the
libraries are Perl's CGI.pm, Haskell's cgi and fastcgi
libraries.
- HTML forms
-
HTML forms specify how to serialise data for GET (where form
data goes into URI query, QUERY_STRING in CGI) and
POST (where form data goes into HTTP message body,
usually
stdin
with CGI)
requests. application/x-www-form-urlencoded can be (and often
is) used for both, though form's enctype
can be
changed for POST requests to use multipart/form-data. Parsing
of "urlencoded" data is easy to implement even in place, while
"multipart" parsing may better be done with a library, though
not sure if there are any prominent ones to highlight.
- HTML templates
-
I used to include XSLT for HTML templating here, which
integrates nicely with XHTML (or HTML 5's XML syntax) on one
side and DBMS-produced XML on the other, but since the
XML-based syntax is being phased out in HTML LS (see my HTML
notes for more on that), and XSLT produces a slightly
incorrect HTML in its HTML mode, it may be worthwhile to
consider other options now: possibly something like m4, or
HTML without templating, composed as a string.
- HTTP authentication
-
Standard HTTP authentication mechanisms include password-based
authentication, which is bearable when used over TLS. The
"Basic" scheme is trivial to handle with CGI by
base64-decoding HTTP_AUTHORIZATION, and using the
login and password directly for, for instance, DBMS
authentication. Base64 is easy to decode, can be implemented
in-place fairly easily, and widely supported. But it can also
be handled by a generic web server, such as nginx. Not
well-supported by most web browsers though: usually there is
not mechanism to forget or alter credentials, and their
handling with embedded objects and JS-based requests varies
from browser to browser.
- File manipulation
-
WebDAV does not integrate with plain HTML forms, but provides
capabilities for file manipulation, and can be useful for
HTTP-based APIs (possibly used by UIs other than web browsers
working with plain HTML), and can be handled by generic
software (e.g., nginx's http_dav module). Among other things,
one may process uploaded files asynchronously with
inotify(7)
(inotify-tools, systemd.path).
- SQL
-
Unless a project is small and well-defined (and stays that
way), it quickly becomes cumbersome to map different
combinations of parameters into SQL queries. A simpler
approach is to read a query template from a parameter, and
substitute other parameters into it (as I implemented
in pg×html). Potential slow custom queries can be dealt with
using timeouts and/or per-user time quotas. As another way to
provide a generic interface to the database, PostgREST is
useful for an HTTP-and-JSON-based interface, though for web
UIs, it aims JS-based ones.
While some dynamic websites may require different or additional
technologies (e.g., SPARQL instead of SQL, not an RDBMS at all,
or it may be crucial to adorn an authentication form), the
described tools would cover many cases, while keeping things
relatively simple. These are nice tools to use, avoiding
unnecessary abstractions on top of other abstractions, and/or
reimplementation of essentially the same things over and over
again.