A server-side web framework written in Forth

World Wild Web

The year is 1991. The World Wide Web has just seen public release. 1991 looks to ease your interactions with the new web using cutting edge programming techniques in Forth (well, Gforth).

Logging In

Getting started in 1991 is easy.

All you need to do is include 1991.fs into your Forth source file. Next, you can define your public routes using the /1991 word. Once your routes are all layed out, start the server using 1991:.

\ app.fs
\ Load 1991.
include 1991.fs

\ Define our route handlers.
: handle-/ ( -- addr u )
    \ Any string returned by the handler
    \ will be output to the browser.
    s" Hello, 1991." ;

\ Set up our routes.
/1991 / handle-/

\ Start the server on port 8080.
8080 1991:

You can run the server using gforth app.fs.

Logging In II: Logging In, Deeper

Route Wildcards (Fuzzy Routing / URL Mapping)

If you want to specify that some part of a route is a wildcard (accepts any value), then you can wrap some named value in <chevrons>. 1991 will accept any URL that matches your wildcard pattern, setting the internal value of whatever you place between the chevrons to whatever is actually requested.

In the example below, <uid> specifies that we're willing to accept any (non-empty) value in its place which we'd like to access using the name uid.

\ wildcards.fs
\ Load 1991.
include 1991.fs

\ Define our route handler.
: handle-wildcard-route ( -- addr u )
    s" contents of the route request: " get-query-string s+ ;

\ Set up our route.
/1991 /users/<uid> handle-wildcard-route

\ We can set up multiple wildcards too (must be slash-separated).
/1991 /users/<uid>/posts/<pid> handle-wildcard-route

\ Start server on port 8080.
8080 1991:

All wildcards are treated similar to query string arguments. As such, wildcards can be retrieved using get-query-string.

In the example above, visiting http://localhost:8080/users/urlysses will result in the following query string: uid=urlysses.

File Serving

Use a public/ directory to act as a basic fileserver. Whenever a requested URL doesn't resolve through the registered routes, 1991 will attempt to find the requested route within your specified public directory.

\ public.fs
\ Load 1991.
include 1991.fs

\ Specify the location of our public directory.
\ Anything in the public/ directory within the
\ same dir as this source file will resolve.
\ You can change "public" to anything you want
\ as long as it matches your directory name.
sourcedir s" public" s+ set-public-path

\ We can set mimetypes using the `filetype:` word.
\ In the case below, we want .mp4 files to be served
\ with the content-type video/mp4.
s" video/mp4" filetype: mp4

\ Start the server on port 8080.
8080 1991:

In the above example, If we have a file public/my-video.mp4, then it will be available through http://localhost:8080/my-video.mp4.


1991 offers basic templating through views.

In order to get started, you should specify the views/ path. Notice the trailing slash, which differs from how we define public.

Once you've specified your views/ directory, you can write views/ files to it. This can be any kind of file, honestly. The benefit offered by views/ is the ability to use basic templating. You can write any valid Forth code within opening (<$ ) and closing ( $>) tags. Additionally, you can use the import word to import other views into your view.

\ views.fs
\ Load 1991.
include 1991.fs

\ Specify the location of our views directory.
sourcedir s" views/" s+ set-view-path

\ Define some words we'll use within
\ our view.
: page-title ( -- addr u )
    s" Dynamic page title" ;
: ten-lines ( -- )
    10 0 do
        s" line " i s>d <# #s #> s+
        s" <br>" s+
    loop ;

\ Use render-view to output the contents
\ of a file in the views/ directory.
: handle-/
    s" v-index.html" render-view ;

/1991 / handle-/

\ Start the server on port 8080.
8080 1991:
\ views/index.html
<!DOCTYPE html>
        <meta charset="utf-8">
        <title><$ page-title $type $></title>
        <$ ten-lines $>
        <$ s" imported-view.html" import $>
\ views/imported-view.html
It's possible to import view files from within other view files. This is from <code>views/imported-view.html</code>

Wait, what?

Why is 1991: post-fix when /1991 is pre-fix?

Forth is a (mostly) post-fix notation language. So, for example, you'd write two plus two as 2 2 +. This is the language's natural and immediate notation. Along those lines, 1991: is an immediate word——running it results in immediate action. As such, we use Forth's post-fix notation to set the port and start the server immediately. Alternately, /1991 doesn't exactly have immediate effect per se. All it does is tell 1991 that any request to /path should be handled by path-handler. As such, we opt to write non-immediate code using pre-fix notation.

You're using Gforth, which came out in 1992. Also, it's 2017.

Okay. But Fredric Jameson establishes that in postmodernism we have experienced a weakening sense of historisity such that what is, what was, and what will be all exist as presents in time. 1970, 1991, 1992, and 2017 all happen simultaneously. Hence developers working on new projects while still coding in decades-old text editors. They write the future in the past and are made present in so doing.

GET 1991