Let's serve

When we left off, we had one of the most inefficiently executed useless machines.

For Instances pt. 2

We can invalidate this observation by instantiating a webserver. This can be done by assigning HttpService() to any random name of the instances-map, like so:


() behaves similarly to {} in that it's a map. However, it's only occurrence is behind the name of a service, where it can be used for configuring.

You may attempt to run Geese, but you can expect it to bark at you on behalf of the HttpService, because you've not told it on what domain and port to listen for requests. Let's configure this now.


At the time of writing this, the HttpService uses the HttpListener supplied with Mono and .Net.

Let's assume we want to run the HTTP server on port 8080 of localhost. If it were to run there, we could access it in our browser at the URL http://localhost:8080/. Hold on to that feeling.

We can instruct the HttpService to deal with requests on that URL by putting it in an array called prefixes in its configuration ()'s. It would look like this:

Now run it and access the url http://localhost:8080/. You'll see a white page. If you try to access it using i.e. your network hostname or FQDN, you'll be welcomed by an error page because the server isn't configured to respond to that.

Fill up the void

The HttpService has a branch called 'http', where incoming requests come seeping out.


So why do you get a white page instead of an error? So soon as HttpService has parsed the HTTP request and tries to pass it on, it hits a Stub; no literally.

When the developer (that's you!) doesn't attach anything to a branch a Service has (like you did!), branches will be closed off by a 'stub'.

Stubs do nothing and hand the control back over to the originating service. In this case, that means a simple 200-response without additional headers or body will be returned.

Let's make the HttpService respond to the request with the contents of a file, regardless of what the request was. We can do this by attaching something to the 'http'-branch that's capable of writing data.

First, facilitate a map to put this branch, by suffixing HttpService() with a {}.

With this map, we may attach a service that's capable of writing data back, to the 'http'-branch. One service that can do this is the Template we discussed earlier.

Attach the Template to the http-branch by assigning a Template() to http_branch in the newly made map, like so:

We now have a simple tree structure consisting of an HttpService at the roots, branching into a Template.

You may notice that we never told the Template what file the actual template resides in. Geese notices this too when running it; it'll say something like:

Template produced an error on initialization: templatefile mandatory

Set the template-file by assigning f"index.html" to templatefile in the Template settings. Like so: (any other file should do fine too)

Run it. Hey, we're back at square one, but now we at least know how we got here.


Given that the Template-service doesn't do more than providing a template, one could argue wasting 15 characters on templatefile = is a bit inconvenient.

"Implied primary setting keys" may be the solution to this; find out how it works after the enclosed 'fun fact' (possibly on the left, or down here.)

Best practice

ApolloGeese and especially CLON have been designed to be concise and pragmatic with no shortcuts and a minimal potential cognitive payload. However, in some cases it's not entirely clear than the most pragmatic approach would be.

The concept of 'Implied primary setting keys' is one of those cases. Currently, explicitly stating primary setting keys is regarded as a slightly better practice because it's more explicit. You're not discouraged from implying them, however.

Template, among other Services, is a service that can be initialized with only a string expression within the configuring (). The templatefile-key is implied, because it's the primary setting for Templates. That's what makes it an implied primary setting key.

So, Template(f"index.html"); does the same as Template(templatefile = f"index.html"); - try it!